diff --git a/tests/core/game-host.test.ts b/tests/core/game-host.test.ts index f365a78..4d250ec 100644 --- a/tests/core/game-host.test.ts +++ b/tests/core/game-host.test.ts @@ -342,4 +342,72 @@ describe('GameHost', () => { expect(host.activePromptSchema.value).toBeNull(); }); }); + + describe('full game', () => { + it('should run a complete game of tic-tac-toe with X winning diagonally', async () => { + const { host } = createTestHost(); + + // Initial state + expect(host.state.value.currentPlayer).toBe('X'); + expect(host.state.value.winner).toBeNull(); + expect(host.state.value.turn).toBe(0); + expect(Object.keys(host.state.value.parts).length).toBe(0); + + // X wins diagonally: (0,0), (1,1), (2,2) + // O plays: (0,1), (2,1) + const moves = [ + 'play X 0 0', // turn 1: X + 'play O 0 1', // turn 2: O + 'play X 1 1', // turn 3: X + 'play O 2 1', // turn 4: O + 'play X 2 2', // turn 5: X wins! + ]; + + // Track prompt events in a queue + const promptEvents: PromptEvent[] = []; + host.commands.on('prompt', (e) => { + promptEvents.push(e); + }); + + // Start setup command (runs game loop until completion) + const setupPromise = host.commands.run('setup'); + + for (let i = 0; i < moves.length; i++) { + // Wait until the next prompt event arrives + while (i >= promptEvents.length) { + await new Promise(r => setTimeout(r, 10)); + } + + const promptEvent = promptEvents[i]; + expect(promptEvent.schema.name).toBe('play'); + + // Submit the move + const error = host.onInput(moves[i]); + expect(error).toBeNull(); + } + + // Wait for setup to complete (game ended with winner) + const result = await setupPromise; + expect(result.success).toBe(true); + if (result.success) { + expect(result.result.winner).toBe('X'); + } + + // Final state checks + expect(host.state.value.winner).toBe('X'); + expect(host.state.value.currentPlayer).toBe('X'); + expect(Object.keys(host.state.value.parts).length).toBe(5); + + // Verify winning diagonal + const parts = Object.values(host.state.value.parts); + const xPieces = parts.filter(p => p.player === 'X'); + expect(xPieces).toHaveLength(3); + expect(xPieces.some(p => JSON.stringify(p.position) === JSON.stringify([0, 0]))).toBe(true); + expect(xPieces.some(p => JSON.stringify(p.position) === JSON.stringify([1, 1]))).toBe(true); + expect(xPieces.some(p => JSON.stringify(p.position) === JSON.stringify([2, 2]))).toBe(true); + + host.dispose(); + expect(host.status.value).toBe('disposed'); + }); + }); });