import { channel_game_move, channel_leave_game, channel_listen_game_events, channel_new_game, channel_on_game_start, channel_on_user_connection_change, } from "@mancala/core"; import { GameManager } from "../../src/game/GameManager"; import { GameStoreImpl } from "../../src/game/gamestore/GameStoreImpl"; import { MatchMakerImpl } from "../../src/matchmaker/MatchMakerImpl"; import { BackendGame } from "../../src/models/Game"; import { FakeRtmt } from "./FakeRtmt"; const ALICE = { id: "kc:alice", name: "alice", isGuest: false }; const BOB = { id: "kc:bob", name: "bob", isGuest: false }; const CAROL = { id: "kc:carol", name: "carol", isGuest: false }; describe("GameManager", () => { let rtmt: FakeRtmt; let gameStore: GameStoreImpl; beforeEach(() => { rtmt = new FakeRtmt(); gameStore = new GameStoreImpl(); new GameManager({ rtmt, gameStore, matchMaker: new MatchMakerImpl({ rtmt }) }); [ALICE, BOB, CAROL].forEach((user) => rtmt.connect(user)); }); const startGame = (): BackendGame => { rtmt.receive(ALICE.id, channel_new_game); rtmt.receive(BOB.id, channel_new_game); const game = gameStore.getGameByUser(ALICE.id); if (!game) throw new Error("game did not start"); return game; }; it("sends the connection info once when a game starts", () => { startGame(); expect(rtmt.messagesTo(ALICE.id, channel_on_game_start)).toHaveLength(1); expect(rtmt.messagesTo(ALICE.id, channel_on_user_connection_change)).toHaveLength(1); }); it("removes a game from memory when a player leaves", () => { const game = startGame(); rtmt.receive(ALICE.id, channel_leave_game); expect(gameStore.get(game.id)).toBeUndefined(); expect(gameStore.getGameByUser(BOB.id)).toBeUndefined(); }); it("removes a game from memory when it ends by the rules", () => { const game = startGame(); // Alice has a single stone in her last pit, next to her store; playing it empties her side. const aliceIsPlayer1 = game.mancalaGame.player1Id === ALICE.id; const board = game.mancalaGame.board; board.pits.forEach((pit) => (pit.stoneCount = 0)); board.pits[aliceIsPlayer1 ? 5 : 12].stoneCount = 1; board.pits[aliceIsPlayer1 ? 7 : 0].stoneCount = 1; game.mancalaGame.turnPlayerId = ALICE.id; rtmt.receive(ALICE.id, channel_game_move, { index: 5 }); expect(game.mancalaGame.state).toBe("ended"); expect(gameStore.get(game.id)).toBeUndefined(); }); it("stops counting a spectator who disconnects", () => { const game = startGame(); rtmt.receive(CAROL.id, channel_listen_game_events, game.id); expect(game.spectatorIds).toEqual([CAROL.id]); expect(gameStore.getSpeactatingGameIdsByUser(CAROL.id)).toEqual([game.id]); rtmt.disconnect(CAROL.id); expect(game.spectatorIds).toEqual([]); }); });