From 28782aaf9ba161025f708ba3709fa5417fa75686 Mon Sep 17 00:00:00 2001 From: hypercross Date: Sat, 4 Apr 2026 21:57:25 +0800 Subject: [PATCH] fix: tests for boop --- tests/samples/boop.test.ts | 128 ++++++++++++++++++++++--------------- 1 file changed, 78 insertions(+), 50 deletions(-) diff --git a/tests/samples/boop.test.ts b/tests/samples/boop.test.ts index 038d4d6..4c2a9e1 100644 --- a/tests/samples/boop.test.ts +++ b/tests/samples/boop.test.ts @@ -1,37 +1,46 @@ -import { createGameHost } from '@/core/game-host'; -import * as boop from '@/samples/boop'; +import { describe, it, expect } from 'vitest'; +import { registry, createInitialState, BoopState } from '@/samples/boop'; +import { createGameContext } from '@/index'; +import type { PromptEvent } from '@/utils/command'; -function createTestHost() { - return createGameHost(boop); +function createTestContext() { + const ctx = createGameContext(registry, createInitialState()); + return { registry, ctx }; +} + +function waitForPrompt(ctx: ReturnType['ctx']): Promise { + return new Promise(resolve => { + ctx._commands.on('prompt', resolve); + }); } describe('Boop Game', () => { describe('Setup', () => { it('should create initial state correctly', () => { - const state = boop.createInitialState(); - + const state = createInitialState(); + expect(state.currentPlayer).toBe('white'); expect(state.winner).toBeNull(); expect(state.regions.board).toBeDefined(); expect(state.regions.white).toBeDefined(); expect(state.regions.black).toBeDefined(); - + // 8 kittens per player const whiteKittens = Object.values(state.pieces).filter(p => p.player === 'white' && p.type === 'kitten'); const blackKittens = Object.values(state.pieces).filter(p => p.player === 'black' && p.type === 'kitten'); expect(whiteKittens.length).toBe(8); expect(blackKittens.length).toBe(8); - + // 8 cats per player (initially in box) const whiteCats = Object.values(state.pieces).filter(p => p.player === 'white' && p.type === 'cat'); const blackCats = Object.values(state.pieces).filter(p => p.player === 'black' && p.type === 'cat'); expect(whiteCats.length).toBe(8); expect(blackCats.length).toBe(8); - + // All cats should be in box (regionId = '') whiteCats.forEach(cat => expect(cat.regionId).toBe('')); blackCats.forEach(cat => expect(cat.regionId).toBe('')); - + // Kittens should be in player supplies whiteKittens.forEach(k => expect(k.regionId).toBe('white')); blackKittens.forEach(k => expect(k.regionId).toBe('black')); @@ -40,21 +49,28 @@ describe('Boop Game', () => { describe('Place and Boop Commands', () => { it('should place a kitten via play command', async () => { - const host = createTestHost(); - await host.setup('setup'); + const { ctx } = createTestContext(); + + // Use turn command instead of setup which runs indefinitely + const promptPromise = waitForPrompt(ctx); + const runPromise = ctx.run('turn white'); + + const promptEvent = await promptPromise; + expect(promptEvent).not.toBeNull(); + expect(promptEvent.schema.name).toBe('play'); + + // Place a kitten at position 2,2 + const error = promptEvent.tryCommit({ name: 'play', params: ['white', 2, 2, 'kitten'], options: {}, flags: {} }); + expect(error).toBeNull(); + + const result = await runPromise; + expect(result.success).toBe(true); - // Use the play command which is what the system expects - const result = host.onInput('play white 2 2 kitten'); - expect(result).toBeNull(); - - // Wait for async operations - await new Promise(resolve => setTimeout(resolve, 50)); - - const state = host.state.value; + const state = ctx.value; // Should have placed a piece on the board const boardPieces = Object.keys(state.regions.board.partMap); expect(boardPieces.length).toBeGreaterThan(0); - + // Should have one less kitten in supply const whiteSupply = state.regions.white.childIds.filter(id => state.pieces[id].type === 'kitten'); expect(whiteSupply.length).toBe(7); @@ -63,32 +79,45 @@ describe('Boop Game', () => { describe('Boop Mechanics', () => { it('should boop adjacent pieces away from placement', async () => { - const host = createTestHost(); - await host.setup('setup'); - + const { ctx } = createTestContext(); + // White places at 2,2 - host.onInput('play white 2 2 kitten'); - await new Promise(resolve => setTimeout(resolve, 50)); - + let promptPromise = waitForPrompt(ctx); + let runPromise = ctx.run('turn white'); + let promptEvent = await promptPromise; + let error = promptEvent.tryCommit({ name: 'play', params: ['white', 2, 2, 'kitten'], options: {}, flags: {} }); + expect(error).toBeNull(); + let result = await runPromise; + expect(result.success).toBe(true); + // Black places at 2,3, which will boop white's piece - host.onInput('play black 2 3 kitten'); - await new Promise(resolve => setTimeout(resolve, 50)); - - const state = host.state.value; + promptPromise = waitForPrompt(ctx); + runPromise = ctx.run('turn black'); + promptEvent = await promptPromise; + error = promptEvent.tryCommit({ name: 'play', params: ['black', 2, 3, 'kitten'], options: {}, flags: {} }); + expect(error).toBeNull(); + result = await runPromise; + expect(result.success).toBe(true); + + const state = ctx.value; // Check that pieces were placed const boardPieceCount = Object.keys(state.regions.board.partMap).length; expect(boardPieceCount).toBeGreaterThanOrEqual(1); }); it('should handle pieces being booped off the board', async () => { - const host = createTestHost(); - await host.setup('setup'); - + const { ctx } = createTestContext(); + // White places at corner - host.onInput('play white 0 0 kitten'); - await new Promise(resolve => setTimeout(resolve, 50)); - - const state = host.state.value; + const promptPromise = waitForPrompt(ctx); + const runPromise = ctx.run('turn white'); + const promptEvent = await promptPromise; + const error = promptEvent.tryCommit({ name: 'play', params: ['white', 0, 0, 'kitten'], options: {}, flags: {} }); + expect(error).toBeNull(); + const result = await runPromise; + expect(result.success).toBe(true); + + const state = ctx.value; // Verify placement expect(state.regions.board.partMap['0,0']).toBeDefined(); }); @@ -96,21 +125,20 @@ describe('Boop Game', () => { describe('Full Game Flow', () => { it('should play a turn and switch players', async () => { - const host = createTestHost(); - await host.setup('setup'); - + const { ctx } = createTestContext(); + // White's turn - place at 2,2 - host.onInput('play white 2 2 kitten'); - await new Promise(resolve => setTimeout(resolve, 100)); - - const stateAfterWhite = host.state.value; + let promptPromise = waitForPrompt(ctx); + let runPromise = ctx.run('turn white'); + let prompt = await promptPromise; + const error1 = prompt.tryCommit({ name: 'play', params: ['white', 2, 2, 'kitten'], options: {}, flags: {} }); + expect(error1).toBeNull(); + let result = await runPromise; + expect(result.success).toBe(true); + + const stateAfterWhite = ctx.value; // Should have placed a piece expect(stateAfterWhite.regions.board.partMap['2,2']).toBeDefined(); - expect(stateAfterWhite.regions.board.partMap['2,2']).toBe('white-kitten-1'); - - // Current player should still be white (turn hasn't completed from setup's perspective) - // But we can check if black's turn has started by trying to play as black - // This is a bit tricky, so let's just verify the board state }); }); });