import { describe, it, expect, beforeEach } from "bun:test"; import { RoomManager } from "./RoomManager"; import { gameRegistry } from "@shared/games/registry"; import { chessPlugin } from "@shared/games/chess/plugin"; // Register chess plugin for tests if (!gameRegistry.get("chess")) { gameRegistry.register(chessPlugin); } describe("RoomManager", () => { let manager: RoomManager; beforeEach(() => { manager = new RoomManager(); }); describe("createRoom", () => { it("should create a room and return its id", () => { const result = manager.createRoom("chess", "player1"); expect(result.ok).toBe(true); if (result.ok) { expect(result.roomId).toBeDefined(); expect(typeof result.roomId).toBe("string"); } }); it("should reject unknown game type", () => { const result = manager.createRoom("unknown-game", "player1"); expect(result.ok).toBe(false); }); it("should add creator as first player", () => { const result = manager.createRoom("chess", "player1"); if (result.ok) { const room = manager.getRoom(result.roomId); expect(room?.players).toContain("player1"); expect(room?.host).toBe("player1"); expect(room?.status).toBe("waiting"); } }); }); describe("joinRoom", () => { it("should add a player to a waiting room", () => { const create = manager.createRoom("chess", "player1"); if (!create.ok) throw new Error("Failed to create room"); const join = manager.joinRoom(create.roomId, "player2", "player"); expect(join.ok).toBe(true); if (join.ok) { expect(join.joinedAs).toBe("player"); } }); it("should auto-start when room reaches maxPlayers", () => { const create = manager.createRoom("chess", "player1"); if (!create.ok) throw new Error("Failed to create room"); manager.joinRoom(create.roomId, "player2", "player"); const room = manager.getRoom(create.roomId); expect(room?.status).toBe("playing"); expect(room?.state).toBeDefined(); }); it("should allow joining as spectator when game is playing", () => { const create = manager.createRoom("chess", "player1"); if (!create.ok) throw new Error("Failed to create room"); manager.joinRoom(create.roomId, "player2", "player"); const spec = manager.joinRoom(create.roomId, "spectator1", "spectator"); expect(spec.ok).toBe(true); }); it("should downgrade to spectator when joining full room as player", () => { const create = manager.createRoom("chess", "player1"); if (!create.ok) throw new Error("Failed to create room"); manager.joinRoom(create.roomId, "player2", "player"); const result = manager.joinRoom(create.roomId, "player3", "player"); expect(result.ok).toBe(true); if (result.ok) { expect(result.joinedAs).toBe("spectator"); } }); it("should reject joining nonexistent room", () => { const result = manager.joinRoom("fake-id", "player1", "player"); expect(result.ok).toBe(false); }); }); describe("handleAction", () => { it("should apply a valid game action", () => { const create = manager.createRoom("chess", "player1"); if (!create.ok) throw new Error("Failed to create room"); manager.joinRoom(create.roomId, "player2", "player"); const result = manager.handleAction(create.roomId, "player1", { type: "move", from: "e2", to: "e4" }); expect(result.ok).toBe(true); }); it("should reject action from spectator", () => { const create = manager.createRoom("chess", "player1"); if (!create.ok) throw new Error("Failed to create room"); manager.joinRoom(create.roomId, "player2", "player"); manager.joinRoom(create.roomId, "spectator1", "spectator"); const result = manager.handleAction(create.roomId, "spectator1", { type: "move", from: "e2", to: "e4" }); expect(result.ok).toBe(false); }); }); describe("leaveRoom", () => { it("should remove a player from the room", () => { const create = manager.createRoom("chess", "player1"); if (!create.ok) throw new Error("Failed to create room"); manager.leaveRoom(create.roomId, "player1"); // Room is deleted when last player leaves a waiting room const room = manager.getRoom(create.roomId); expect(room).toBeUndefined(); }); it("should remove a spectator from the room", () => { const create = manager.createRoom("chess", "player1"); if (!create.ok) throw new Error("Failed to create room"); manager.joinRoom(create.roomId, "player2", "player"); manager.joinRoom(create.roomId, "spec1", "spectator"); manager.leaveRoom(create.roomId, "spec1"); const room = manager.getRoom(create.roomId); expect(room?.spectators.has("spec1")).toBe(false); }); }); describe("listRooms", () => { it("should return summaries of all rooms", () => { manager.createRoom("chess", "player1"); manager.createRoom("chess", "player2"); const rooms = manager.listRooms(); expect(rooms.length).toBe(2); expect(rooms[0].gameSlug).toBe("chess"); expect(rooms[0].status).toBe("waiting"); }); it("should filter by game type", () => { manager.createRoom("chess", "player1"); const rooms = manager.listRooms("chess"); expect(rooms.length).toBe(1); const empty = manager.listRooms("blackjack"); expect(empty.length).toBe(0); }); }); });