75 lines
2.9 KiB
TypeScript
75 lines
2.9 KiB
TypeScript
|
|
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([]);
|
||
|
|
});
|
||
|
|
});
|