From bd9569992b9b269c8b23810176debbd42f7b51b7 Mon Sep 17 00:00:00 2001 From: hypercross Date: Thu, 2 Apr 2026 15:20:34 +0800 Subject: [PATCH] fix: fix tic tac toe test --- src/samples/tic-tac-toe.ts | 4 +- tests/samples/tic-tac-toe.test.ts | 113 ++++++++++++++---------------- 2 files changed, 54 insertions(+), 63 deletions(-) diff --git a/src/samples/tic-tac-toe.ts b/src/samples/tic-tac-toe.ts index 23cb59c..2b4e722 100644 --- a/src/samples/tic-tac-toe.ts +++ b/src/samples/tic-tac-toe.ts @@ -16,8 +16,8 @@ const WINNING_LINES: number[][][] = [ [[0, 2], [1, 1], [2, 0]], ]; -type PlayerType = 'X' | 'O'; -type WinnerType = PlayerType | 'draw' | null; +export type PlayerType = 'X' | 'O'; +export type WinnerType = PlayerType | 'draw' | null; type TicTacToePart = Part & { player: PlayerType }; diff --git a/tests/samples/tic-tac-toe.test.ts b/tests/samples/tic-tac-toe.test.ts index d27c5a5..129f358 100644 --- a/tests/samples/tic-tac-toe.test.ts +++ b/tests/samples/tic-tac-toe.test.ts @@ -1,6 +1,14 @@ import { describe, it, expect } from 'vitest'; -import {registry, checkWinner, isCellOccupied, placePiece, createInitialState, TicTacToeState} from '../../src/samples/tic-tac-toe'; -import {Entity, entity} from "../../src/utils/entity"; +import { + registry, + checkWinner, + isCellOccupied, + placePiece, + createInitialState, + TicTacToeState, + WinnerType, PlayerType +} from '../../src/samples/tic-tac-toe'; +import {Entity} from "../../src/utils/entity"; import {createGameContext} from "../../src"; import type { PromptEvent } from '../../src/utils/command'; @@ -13,23 +21,6 @@ function getState(ctx: ReturnType['ctx']): Entity, id: string, row: number, col: number, player: 'X' | 'O') { - const board = state.value.board; - const part = { - id, - region: board, - position: [row, col], - player, - }; - const e = entity(id, part); - state.produce(draft => { - draft.parts.push(e); - board.produce(boardDraft => { - boardDraft.children.push(e); - }); - }); -} - function waitForPrompt(ctx: ReturnType['ctx']): Promise { return new Promise(resolve => { ctx.commands.on('prompt', resolve); @@ -49,11 +40,11 @@ describe('TicTacToe - helper functions', () => { const { ctx } = createTestContext(); const state = getState(ctx); - addPiece(state, 'piece-1', 0, 0, 'X'); - addPiece(state, 'piece-2', 1, 0, 'O'); - addPiece(state, 'piece-3', 0, 1, 'X'); - addPiece(state, 'piece-4', 1, 1, 'O'); - addPiece(state, 'piece-5', 0, 2, 'X'); + placePiece(state, 0, 0, 'X'); + placePiece(state, 1, 0, 'O'); + placePiece(state, 0, 1, 'X'); + placePiece(state, 1, 1, 'O'); + placePiece(state, 0, 2, 'X'); expect(checkWinner(state)).toBe('X'); }); @@ -62,12 +53,12 @@ describe('TicTacToe - helper functions', () => { const { ctx } = createTestContext(); const state = getState(ctx); - addPiece(state, 'piece-1', 2, 0, 'X'); - addPiece(state, 'piece-2', 1, 0, 'O'); - addPiece(state, 'piece-3', 2, 1, 'X'); - addPiece(state, 'piece-4', 1, 1, 'O'); - addPiece(state, 'piece-5', 0, 0, 'X'); - addPiece(state, 'piece-6', 1, 2, 'O'); + placePiece(state, 2, 0, 'X'); + placePiece(state, 1, 0, 'O'); + placePiece(state, 2, 1, 'X'); + placePiece(state, 1, 1, 'O'); + placePiece(state, 0, 0, 'X'); + placePiece(state, 1, 2, 'O'); expect(checkWinner(state)).toBe('O'); }); @@ -76,11 +67,11 @@ describe('TicTacToe - helper functions', () => { const { ctx } = createTestContext(); const state = getState(ctx); - addPiece(state, 'piece-1', 0, 0, 'X'); - addPiece(state, 'piece-2', 0, 1, 'O'); - addPiece(state, 'piece-3', 1, 0, 'X'); - addPiece(state, 'piece-4', 1, 1, 'O'); - addPiece(state, 'piece-5', 2, 0, 'X'); + placePiece(state, 0, 0, 'X'); + placePiece(state, 0, 1, 'O'); + placePiece(state, 1, 0, 'X'); + placePiece(state, 1, 1, 'O'); + placePiece(state, 2, 0, 'X'); expect(checkWinner(state)).toBe('X'); }); @@ -89,11 +80,11 @@ describe('TicTacToe - helper functions', () => { const { ctx } = createTestContext(); const state = getState(ctx); - addPiece(state, 'piece-1', 0, 0, 'X'); - addPiece(state, 'piece-2', 0, 1, 'O'); - addPiece(state, 'piece-3', 1, 1, 'X'); - addPiece(state, 'piece-4', 0, 2, 'O'); - addPiece(state, 'piece-5', 2, 2, 'X'); + placePiece(state, 0, 0, 'X'); + placePiece(state, 0, 1, 'O'); + placePiece(state, 1, 1, 'X'); + placePiece(state, 0, 2, 'O'); + placePiece(state, 2, 2, 'X'); expect(checkWinner(state)).toBe('X'); }); @@ -102,12 +93,12 @@ describe('TicTacToe - helper functions', () => { const { ctx } = createTestContext(); const state = getState(ctx); - addPiece(state, 'piece-1', 0, 0, 'X'); - addPiece(state, 'piece-2', 0, 2, 'O'); - addPiece(state, 'piece-3', 1, 0, 'X'); - addPiece(state, 'piece-4', 1, 1, 'O'); - addPiece(state, 'piece-5', 1, 2, 'X'); - addPiece(state, 'piece-6', 2, 0, 'O'); + placePiece(state, 0, 0, 'X'); + placePiece(state, 0, 2, 'O'); + placePiece(state, 1, 0, 'X'); + placePiece(state, 1, 1, 'O'); + placePiece(state, 1, 2, 'X'); + placePiece(state, 2, 0, 'O'); expect(checkWinner(state)).toBe('O'); }); @@ -116,9 +107,9 @@ describe('TicTacToe - helper functions', () => { const { ctx } = createTestContext(); const state = getState(ctx); - addPiece(state, 'piece-1', 0, 0, 'X'); - addPiece(state, 'piece-2', 0, 1, 'O'); - addPiece(state, 'piece-3', 1, 2, 'X'); + placePiece(state, 0, 0, 'X'); + placePiece(state, 0, 1, 'O'); + placePiece(state, 1, 2, 'X'); expect(checkWinner(state)).toBeNull(); }); @@ -131,10 +122,10 @@ describe('TicTacToe - helper functions', () => { [0, 0, 'X'], [0, 1, 'O'], [0, 2, 'X'], [1, 0, 'X'], [1, 1, 'O'], [1, 2, 'O'], [2, 0, 'O'], [2, 1, 'X'], [2, 2, 'X'], - ]; + ] as [number, number, PlayerType][]; drawPositions.forEach(([r, c, p], i) => { - addPiece(state, 'piece-' + (i + 1), r, c, p); + placePiece(state, r, c, p); }); expect(checkWinner(state)).toBe('draw'); @@ -152,7 +143,7 @@ describe('TicTacToe - helper functions', () => { it('should return true for occupied cell', () => { const { ctx } = createTestContext(); const state = getState(ctx); - addPiece(state, 'piece-1', 1, 1, 'X'); + placePiece(state, 1, 1, 'X'); expect(isCellOccupied(state, 1, 1)).toBe(true); }); @@ -160,7 +151,7 @@ describe('TicTacToe - helper functions', () => { it('should return false for different cell', () => { const { ctx } = createTestContext(); const state = getState(ctx); - addPiece(state, 'piece-1', 0, 0, 'X'); + placePiece(state, 0, 0, 'X'); expect(isCellOccupied(state, 1, 1)).toBe(false); }); @@ -226,7 +217,7 @@ describe('TicTacToe - game flow', () => { const { ctx } = createTestContext(); const promptPromise = waitForPrompt(ctx); - const runPromise = ctx.commands.run('turn X 1'); + const runPromise = ctx.commands.run<{winner: WinnerType}>('turn X 1'); const promptEvent = await promptPromise; expect(promptEvent).not.toBeNull(); @@ -245,7 +236,7 @@ describe('TicTacToe - game flow', () => { const { ctx } = createTestContext(); const promptPromise = waitForPrompt(ctx); - const runPromise = ctx.commands.run('turn X 1'); + const runPromise = ctx.commands.run<{winner: WinnerType}>('turn X 1'); const promptEvent1 = await promptPromise; promptEvent1.resolve({ name: 'play', params: ['O', 1, 1], options: {}, flags: {} }); @@ -264,10 +255,10 @@ describe('TicTacToe - game flow', () => { const { ctx } = createTestContext(); const state = getState(ctx); - addPiece(state, 'piece-0', 1, 1, 'O'); + placePiece(state, 1, 1, 'O'); const promptPromise = waitForPrompt(ctx); - const runPromise = ctx.commands.run('turn X 1'); + const runPromise = ctx.commands.run<{winner: WinnerType}>('turn X 1'); const promptEvent1 = await promptPromise; promptEvent1.resolve({ name: 'play', params: ['X', 1, 1], options: {}, flags: {} }); @@ -286,7 +277,7 @@ describe('TicTacToe - game flow', () => { const { ctx } = createTestContext(); let promptPromise = waitForPrompt(ctx); - let runPromise = ctx.commands.run('turn X 1'); + let runPromise = ctx.commands.run<{winner: WinnerType}>('turn X 1'); let prompt = await promptPromise; prompt.resolve({ name: 'play', params: ['X', 0, 0], options: {}, flags: {} }); let result = await runPromise; @@ -339,16 +330,16 @@ describe('TicTacToe - game flow', () => { { id: 'p6', pos: [0, 1], player: 'O' }, { id: 'p7', pos: [2, 1], player: 'X' }, { id: 'p8', pos: [1, 2], player: 'O' }, - ]; + ] as { id: string, pos: [number, number], player: PlayerType}[]; for (const { id, pos, player } of pieces) { - addPiece(state, id, pos[0], pos[1], player); + placePiece(state, pos[0], pos[1], player); } expect(checkWinner(state)).toBeNull(); const promptPromise = waitForPrompt(ctx); - const runPromise = ctx.commands.run('turn X 9'); + const runPromise = ctx.commands.run<{winner: WinnerType}>('turn X 9'); const prompt = await promptPromise; prompt.resolve({ name: 'play', params: ['X', 1, 1], options: {}, flags: {} }); const result = await runPromise;