chore: add more tests

This commit is contained in:
2026-04-06 16:11:26 +08:00
parent 6cfb3b6df8
commit 6352977791
8 changed files with 633 additions and 5 deletions
+118
View File
@@ -515,4 +515,122 @@ describe('GameHost', () => {
expect(host.activePromptPlayer.value).toBeNull();
});
});
describe('tryAnswerPrompt', () => {
it('should answer prompt with valid arguments', async () => {
const { host } = createTestHost();
const promptPromise = waitForPromptEvent(host);
const runPromise = host.start();
const promptEvent = await promptPromise;
expect(promptEvent.schema.name).toBe('play');
// Use tryAnswerPrompt with the prompt def
const { prompts } = await import('@/samples/tic-tac-toe');
const error = host.tryAnswerPrompt(prompts.play, 'X', 1, 1);
expect(error).toBeNull();
// Wait for next prompt and cancel
const nextPromptPromise = waitForPromptEvent(host);
const nextPrompt = await nextPromptPromise;
nextPrompt.cancel('test cleanup');
try {
await runPromise;
} catch (e) {
const error = e as Error;
expect(error.message).toBe('test cleanup');
}
});
it('should reject invalid arguments', async () => {
const { host } = createTestHost();
const promptPromise = waitForPromptEvent(host);
const runPromise = host.start();
const promptEvent = await promptPromise;
// Use tryAnswerPrompt with invalid position
const { prompts } = await import('@/samples/tic-tac-toe');
const error = host.tryAnswerPrompt(prompts.play, 'X', 5, 5);
expect(error).not.toBeNull();
promptEvent.cancel('test cleanup');
try {
await runPromise;
} catch (e) {
const error = e as Error;
expect(error.message).toBe('test cleanup');
}
});
});
describe('addInterruption and clearInterruptions', () => {
it('should add interruption promise to state', async () => {
const { host } = createTestHost();
let resolveInterruption: () => void;
const interruptionPromise = new Promise<void>(resolve => {
resolveInterruption = resolve;
});
// Add interruption
host.addInterruption(interruptionPromise);
// Start the game - produceAsync should wait for interruption
const promptPromise = waitForPromptEvent(host);
const runPromise = host.start();
const promptEvent = await promptPromise;
// Resolve interruption
resolveInterruption!();
// Cancel and cleanup
promptEvent.cancel('test cleanup');
try {
await runPromise;
} catch {
// Expected
}
});
it('should clear all pending interruptions', async () => {
const { host } = createTestHost();
let resolveInterruption1: () => void;
let resolveInterruption2: () => void;
const interruptionPromise1 = new Promise<void>(resolve => {
resolveInterruption1 = resolve;
});
const interruptionPromise2 = new Promise<void>(resolve => {
resolveInterruption2 = resolve;
});
// Add multiple interruptions
host.addInterruption(interruptionPromise1);
host.addInterruption(interruptionPromise2);
// Clear all interruptions
host.clearInterruptions();
// Start the game - should not wait for cleared interruptions
const promptPromise = waitForPromptEvent(host);
const runPromise = host.start();
const promptEvent = await promptPromise;
promptEvent.cancel('test cleanup');
try {
await runPromise;
} catch {
// Expected
}
// Original interruption promises should still be pending
// (they were cleared, not resolved)
});
});
});
+57 -1
View File
@@ -1,5 +1,5 @@
import { describe, it, expect } from 'vitest';
import { createGameContext, createGameCommandRegistry, IGameContext } from '@/core/game';
import { createGameContext, createGameCommandRegistry, createPromptDef, IGameContext, PromptDef } from '@/core/game';
import type { PromptEvent, Command } from '@/utils/command';
type MyState = {
@@ -132,3 +132,59 @@ describe('createGameCommand', () => {
}
});
});
describe('createPromptDef', () => {
it('should create a PromptDef with string schema', () => {
const promptDef = createPromptDef<[string, number]>('play <player> <score:number>');
expect(promptDef).toBeDefined();
expect(promptDef.schema).toBe('play <player> <score:number>');
});
it('should create a PromptDef with CommandSchema object', () => {
const schemaObj = {
name: 'test',
params: [],
options: {},
flags: {}
};
const promptDef = createPromptDef<[]>(schemaObj);
expect(promptDef.schema).toEqual(schemaObj);
});
it('should be usable with game.prompt', async () => {
const registry = createGameCommandRegistry<{ score: number }>();
registry.register('test-prompt', async function(ctx) {
const promptDef = createPromptDef<[number]>('input <value:number>');
const result = await ctx.prompt(
promptDef,
(value) => {
if (value < 0) throw 'Value must be positive';
return value;
}
);
return result;
});
const ctx = createGameContext(registry, { score: 0 });
const promptPromise = new Promise<PromptEvent>(resolve => {
ctx._commands.on('prompt', resolve);
});
const runPromise = ctx.run('test-prompt');
const promptEvent = await promptPromise;
expect(promptEvent.schema.name).toBe('input');
const error = promptEvent.tryCommit({ name: 'input', params: [42], options: {}, flags: {} });
expect(error).toBeNull();
const result = await runPromise;
expect(result.success).toBe(true);
if (result.success) {
expect(result.result).toBe(42);
}
});
});
+46 -1
View File
@@ -1,5 +1,5 @@
import { describe, it, expect } from 'vitest';
import { createRegion, applyAlign, shuffle, moveToRegion, type Region, type RegionAxis } from '@/core/region';
import { createRegion, createRegionAxis, applyAlign, shuffle, moveToRegion, type Region, type RegionAxis } from '@/core/region';
import { createRNG } from '@/utils/rng';
import { type Part } from '@/core/part';
@@ -304,3 +304,48 @@ describe('Region', () => {
});
});
});
describe('createRegionAxis', () => {
it('should create axis with name only', () => {
const axis = createRegionAxis('x');
expect(axis.name).toBe('x');
expect(axis.min).toBeUndefined();
expect(axis.max).toBeUndefined();
expect(axis.align).toBeUndefined();
});
it('should create axis with min and max', () => {
const axis = createRegionAxis('y', 0, 10);
expect(axis.name).toBe('y');
expect(axis.min).toBe(0);
expect(axis.max).toBe(10);
});
it('should create axis with align start', () => {
const axis = createRegionAxis('x', 0, 5, 'start');
expect(axis.name).toBe('x');
expect(axis.min).toBe(0);
expect(axis.max).toBe(5);
expect(axis.align).toBe('start');
});
it('should create axis with align end', () => {
const axis = createRegionAxis('x', undefined, 10, 'end');
expect(axis.name).toBe('x');
expect(axis.max).toBe(10);
expect(axis.align).toBe('end');
});
it('should create axis with align center', () => {
const axis = createRegionAxis('x', 0, 10, 'center');
expect(axis.name).toBe('x');
expect(axis.min).toBe(0);
expect(axis.max).toBe(10);
expect(axis.align).toBe('center');
});
});