chore: add more tests
This commit is contained in:
@@ -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
@@ -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);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user