diff --git a/packages/arcade_lobby/seed/scripts/tests/arcade.cases.json b/packages/arcade_lobby/seed/scripts/tests/arcade.cases.json new file mode 100644 index 000000000..cd1495508 --- /dev/null +++ b/packages/arcade_lobby/seed/scripts/tests/arcade.cases.json @@ -0,0 +1,55 @@ +{ + "matchmaking": { + "assign_bucket": [ + { "party_size": 1, "expected": "solo", "desc": "Solo player gets solo bucket" }, + { "party_size": 2, "expected": "duo", "desc": "Duo gets duo bucket" }, + { "party_size": 3, "expected": "solo", "desc": "Trio gets solo bucket (not 4)" }, + { "party_size": 4, "expected": "squad", "desc": "Full squad gets squad bucket" }, + { "party_size": 5, "expected": "squad", "desc": "5+ players get squad bucket" }, + { "party_size": null, "expected": "solo", "desc": "Nil size defaults to solo" } + ] + }, + "permissions": { + "can_create_tournament": [ + { "role": "public", "expected": false, "desc": "Public users cannot create tournaments" }, + { "role": "admin", "expected": true, "desc": "Admins can create tournaments" }, + { "role": "god", "expected": true, "desc": "God users can create tournaments" }, + { "role": "supergod", "expected": true, "desc": "Supergod users can create tournaments" }, + { "role": null, "expected": false, "desc": "Nil role defaults to public" } + ] + }, + "queue_metrics": { + "summarize": [ + { + "queues": [], + "expected_players": 0, + "expected_wait": 0, + "desc": "Empty queue list" + }, + { + "queues": [{"players": 10, "waitSeconds": 30}], + "expected_players": 10, + "expected_wait": 30, + "desc": "Single queue" + }, + { + "queues": [ + {"players": 5, "waitSeconds": 10}, + {"players": 15, "waitSeconds": 60} + ], + "expected_players": 20, + "expected_wait": 60, + "desc": "Multiple queues aggregate" + }, + { + "queues": [ + {"players": null, "waitSeconds": null}, + {"players": 5, "waitSeconds": 30} + ], + "expected_players": 5, + "expected_wait": 30, + "desc": "Handles nil values" + } + ] + } +} diff --git a/packages/forum_forge/seed/scripts/tests/permissions.test.lua b/packages/forum_forge/seed/scripts/tests/permissions.test.lua new file mode 100644 index 000000000..4e4f40de3 --- /dev/null +++ b/packages/forum_forge/seed/scripts/tests/permissions.test.lua @@ -0,0 +1,87 @@ +-- Forum Forge permissions and functionality tests +-- Uses lua_test framework with parameterized test cases + +describe("Forum Permissions", function() + local cases = load_cases("permissions.cases.json") + + describe("can_post", function() + local can_post = require("can_post") + + it_each(cases.can_post, "$desc", function(tc) + local user = { role = tc.role } + local result = can_post(user) + expect(result).toBe(tc.expected) + end) + end) + + describe("can_moderate", function() + local can_moderate = require("can_moderate") + + it_each(cases.can_moderate, "$desc", function(tc) + local user = { role = tc.role } + local result = can_moderate(user) + expect(result).toBe(tc.expected) + end) + end) +end) + +describe("Content Moderation", function() + local cases = load_cases("permissions.cases.json") + + describe("flag_post", function() + local flag_post = require("flag_post") + + it_each(cases.flag_post, "$desc", function(tc) + local post = { content = tc.content } + local result = flag_post(post) + expect(result.flagged).toBe(tc.expected_flagged) + if tc.expected_reasons then + expect(#result.reasons).toBe(tc.expected_reasons) + end + end) + + it("flags posts over 5000 characters", function() + local long_content = string.rep("a", 5001) + local post = { content = long_content } + local result = flag_post(post) + expect(result.flagged).toBe(true) + expect(#result.reasons).toBe(1) + expect(result.reasons[1]).toContain("5000 characters") + end) + end) +end) + +describe("Thread Ranking", function() + local cases = load_cases("permissions.cases.json") + + describe("rank_thread", function() + local rank_thread = require("rank_thread") + + it_each(cases.rank_thread, "$desc", function(tc) + local thread = { + replyCount = tc.replyCount, + likeCount = tc.likeCount, + lastReplyAt = tc.lastReplyAt + } + local score = rank_thread(thread) + expect(score >= tc.expected_min).toBe(true) + end) + + it("calculates score correctly: (replies * 2) + likes + (recency / 1000000)", function() + local thread = { + replyCount = 10, + likeCount = 5, + lastReplyAt = 2000000 + } + local score = rank_thread(thread) + -- 10 * 2 + 5 + 2 = 27 + expect(score).toBe(27) + end) + + it("handles missing fields with defaults", function() + local thread = {} + local score = rank_thread(thread) + expect(score).toBe(0) + end) + end) +end) diff --git a/packages/irc_webchat/seed/scripts/tests/chat.cases.json b/packages/irc_webchat/seed/scripts/tests/chat.cases.json new file mode 100644 index 000000000..e5efc0e98 --- /dev/null +++ b/packages/irc_webchat/seed/scripts/tests/chat.cases.json @@ -0,0 +1,40 @@ +{ + "handle_command": { + "help_command": [ + { "command": "/help", "expected_contains": "Available commands", "desc": "Help shows commands" }, + { "command": "/HELP", "expected_contains": "Available commands", "desc": "Help is case insensitive" } + ], + "users_command": [ + { "command": "/users", "users": ["Alice", "Bob"], "expected_contains": "Alice, Bob", "desc": "Lists online users" }, + { "command": "/users", "users": [], "expected_contains": "Online users (0)", "desc": "Empty user list" } + ], + "clear_command": [ + { "command": "/clear", "expected_type": "command", "expected_message": "CLEAR_MESSAGES", "desc": "Clear returns command type" } + ], + "me_command": [ + { "command": "/me waves", "username": "TestUser", "expected_contains": "waves", "desc": "Me action with text" }, + { "command": "/me", "expected_contains": "Usage:", "desc": "Me without action shows usage" } + ], + "unknown_command": [ + { "command": "/invalid", "expected_contains": "Unknown command", "desc": "Unknown command error" }, + { "command": "/test123", "expected_contains": "Type /help", "desc": "Suggests help for unknown" } + ] + }, + "format_time": [ + { "timestamp": 0, "expected_format": "HH:MM", "desc": "Epoch timestamp" }, + { "timestamp": 1609459200000, "expected_contains": ":", "desc": "Valid timestamp formats" }, + { "timestamp": 1609502400000, "expected_contains": ":", "desc": "Afternoon timestamp" } + ], + "send_message": [ + { "channelId": "ch1", "username": "Alice", "userId": "u1", "message": "Hello", "desc": "Basic message creation" }, + { "channelId": "general", "username": "Bot", "userId": "bot1", "message": "System alert", "desc": "System message" } + ], + "user_events": { + "join": [ + { "username": "Alice", "channelId": "ch1", "expected_type": "join", "desc": "User join event" } + ], + "leave": [ + { "username": "Bob", "channelId": "ch1", "expected_type": "leave", "desc": "User leave event" } + ] + } +} diff --git a/packages/irc_webchat/seed/scripts/tests/chat.test.lua b/packages/irc_webchat/seed/scripts/tests/chat.test.lua new file mode 100644 index 000000000..a5665a4b0 --- /dev/null +++ b/packages/irc_webchat/seed/scripts/tests/chat.test.lua @@ -0,0 +1,103 @@ +-- IRC Webchat functionality tests +-- Uses lua_test framework with parameterized test cases + +describe("IRC Commands", function() + local cases = load_cases("chat.cases.json") + local handle_command = require("handle_command") + + describe("help command", function() + it_each(cases.handle_command.help_command, "$desc", function(tc) + local result = handle_command(tc.command, "ch1", "TestUser", {}) + expect(result.message).toContain(tc.expected_contains) + end) + end) + + describe("users command", function() + it_each(cases.handle_command.users_command, "$desc", function(tc) + local result = handle_command(tc.command, "ch1", "TestUser", tc.users) + expect(result.message).toContain(tc.expected_contains) + end) + end) + + describe("clear command", function() + it_each(cases.handle_command.clear_command, "$desc", function(tc) + local result = handle_command(tc.command, "ch1", "TestUser", {}) + expect(result.type).toBe(tc.expected_type) + expect(result.message).toBe(tc.expected_message) + end) + end) + + describe("me command", function() + it_each(cases.handle_command.me_command, "$desc", function(tc) + local username = tc.username or "TestUser" + local result = handle_command(tc.command, "ch1", username, {}) + expect(result.message).toContain(tc.expected_contains) + end) + end) + + describe("unknown commands", function() + it_each(cases.handle_command.unknown_command, "$desc", function(tc) + local result = handle_command(tc.command, "ch1", "TestUser", {}) + expect(result.message).toContain(tc.expected_contains) + end) + end) +end) + +describe("Time Formatting", function() + local format_time = require("format_time") + + it("formats time with AM/PM", function() + local result = format_time(1609459200000) -- 12:00 AM UTC + expect(result).toContain(":") + expect(result:match("[AP]M")).toBeTruthy() + end) + + it("handles midnight correctly", function() + -- Midnight should show as 12:XX AM + local midnight = 1609459200000 -- Jan 1, 2021 00:00 UTC + local result = format_time(midnight) + expect(result).toContain("12:") + end) +end) + +describe("Message Creation", function() + local cases = load_cases("chat.cases.json") + local send_message = require("send_message") + + it_each(cases.send_message, "$desc", function(tc) + local result = send_message(tc.channelId, tc.username, tc.userId, tc.message) + expect(result.channelId).toBe(tc.channelId) + expect(result.username).toBe(tc.username) + expect(result.userId).toBe(tc.userId) + expect(result.message).toBe(tc.message) + expect(result.type).toBe("message") + expect(result.id).toBeTruthy() + expect(result.timestamp).toBeTruthy() + end) +end) + +describe("User Events", function() + local cases = load_cases("chat.cases.json") + + describe("user join", function() + local user_join = require("user_join") + + it_each(cases.user_events.join, "$desc", function(tc) + local result = user_join(tc.username, tc.channelId) + expect(result.type).toBe(tc.expected_type) + expect(result.username).toBe(tc.username) + expect(result.channelId).toBe(tc.channelId) + end) + end) + + describe("user leave", function() + local user_leave = require("user_leave") + + it_each(cases.user_events.leave, "$desc", function(tc) + local result = user_leave(tc.username, tc.channelId) + expect(result.type).toBe(tc.expected_type) + expect(result.username).toBe(tc.username) + expect(result.channelId).toBe(tc.channelId) + end) + end) +end)