boardgame-core/tests/commands/command.log.test.ts

279 lines
9.2 KiB
TypeScript

import { describe, it, expect, beforeEach } from 'vitest';
import { CommandLog, createCommandLog } from '../../src/commands/CommandLog';
import { Command, CommandActionType, CommandExecutionResult, StepResult } from '../../src/commands/Command';
describe('CommandLog', () => {
let log: CommandLog;
beforeEach(() => {
log = createCommandLog();
});
const sampleCommand: Command = {
id: 'test-command',
name: 'Test Command',
steps: [
{ action: CommandActionType.CreateMeeple, params: { id: 'm1', color: 'red' } },
],
};
const sampleResult: CommandExecutionResult = {
success: true,
executedSteps: 1,
totalSteps: 1,
};
const sampleStepResults: StepResult[] = [
{
stepIndex: 0,
action: CommandActionType.CreateMeeple,
success: true,
params: { id: 'm1', color: 'red' },
},
];
describe('log', () => {
it('should log a command execution', () => {
log.log(sampleCommand, sampleResult, sampleStepResults);
const entries = log.getEntries();
expect(entries.length).toBe(1);
expect(entries[0].commandId).toBe('test-command');
expect(entries[0].commandName).toBe('Test Command');
expect(entries[0].result.success).toBe(true);
});
it('should add timestamp to log entry', () => {
const beforeTime = Date.now();
log.log(sampleCommand, sampleResult, sampleStepResults);
const afterTime = Date.now();
const entry = log.getEntries()[0];
expect(entry.timestamp).toBeGreaterThanOrEqual(beforeTime);
expect(entry.timestamp).toBeLessThanOrEqual(afterTime);
});
it('should log multiple entries', () => {
log.log(sampleCommand, sampleResult, sampleStepResults);
log.log(sampleCommand, sampleResult, sampleStepResults);
log.log(sampleCommand, sampleResult, sampleStepResults);
expect(log.getEntries().length).toBe(3);
});
});
describe('getFilteredEntries', () => {
it('should filter by commandId', () => {
const command1: Command = { ...sampleCommand, id: 'cmd-1', name: 'Command 1' };
const command2: Command = { ...sampleCommand, id: 'cmd-2', name: 'Command 2' };
log.log(command1, sampleResult, sampleStepResults);
log.log(command2, sampleResult, sampleStepResults);
log.log(command1, sampleResult, sampleStepResults);
const filtered = log.getFilteredEntries({ commandId: 'cmd-1' });
expect(filtered.length).toBe(2);
});
it('should filter by success status', () => {
const successResult: CommandExecutionResult = { success: true, executedSteps: 1, totalSteps: 1 };
const failResult: CommandExecutionResult = { success: false, executedSteps: 0, totalSteps: 1, error: 'Failed' };
log.log(sampleCommand, successResult, sampleStepResults);
log.log(sampleCommand, failResult, []);
log.log(sampleCommand, successResult, sampleStepResults);
const failed = log.getFilteredEntries({ success: false });
expect(failed.length).toBe(1);
const successful = log.getFilteredEntries({ success: true });
expect(successful.length).toBe(2);
});
it('should filter by time range', () => {
const startTime = Date.now();
log.log(sampleCommand, sampleResult, sampleStepResults);
// 模拟时间流逝
const midTime = Date.now() + 100;
// 手动创建一个带时间戳的条目来测试时间过滤
const entries = log.getEntries();
expect(entries[0].timestamp).toBeGreaterThanOrEqual(startTime);
});
});
describe('getCommandHistory', () => {
it('should return history for a specific command', () => {
const command1: Command = { ...sampleCommand, id: 'cmd-1', name: 'Command 1' };
const command2: Command = { ...sampleCommand, id: 'cmd-2', name: 'Command 2' };
log.log(command1, sampleResult, sampleStepResults);
log.log(command2, sampleResult, sampleStepResults);
log.log(command1, sampleResult, sampleStepResults);
const history = log.getCommandHistory('cmd-1');
expect(history.length).toBe(2);
});
});
describe('getFailedCommands', () => {
it('should return only failed commands', () => {
const successResult: CommandExecutionResult = { success: true, executedSteps: 1, totalSteps: 1 };
const failResult: CommandExecutionResult = { success: false, executedSteps: 0, totalSteps: 1, error: 'Error' };
log.log(sampleCommand, successResult, sampleStepResults);
log.log(sampleCommand, failResult, []);
log.log(sampleCommand, successResult, sampleStepResults);
const failed = log.getFailedCommands();
expect(failed.length).toBe(1);
expect(failed[0].result.success).toBe(false);
});
});
describe('getSuccessfulCommands', () => {
it('should return only successful commands', () => {
const successResult: CommandExecutionResult = { success: true, executedSteps: 1, totalSteps: 1 };
const failResult: CommandExecutionResult = { success: false, executedSteps: 0, totalSteps: 1, error: 'Error' };
log.log(sampleCommand, successResult, sampleStepResults);
log.log(sampleCommand, failResult, []);
log.log(sampleCommand, successResult, sampleStepResults);
const successful = log.getSuccessfulCommands();
expect(successful.length).toBe(2);
});
});
describe('clear', () => {
it('should clear all log entries', () => {
log.log(sampleCommand, sampleResult, sampleStepResults);
log.log(sampleCommand, sampleResult, sampleStepResults);
expect(log.getEntries().length).toBe(2);
log.clear();
expect(log.getEntries().length).toBe(0);
});
});
describe('exportToJson', () => {
it('should export logs as JSON string', () => {
log.log(sampleCommand, sampleResult, sampleStepResults);
const json = log.exportToJson();
const parsed = JSON.parse(json);
expect(Array.isArray(parsed)).toBe(true);
expect(parsed.length).toBe(1);
expect(parsed[0].commandId).toBe('test-command');
});
});
describe('getCount', () => {
it('should return the number of log entries', () => {
expect(log.getCount()).toBe(0);
log.log(sampleCommand, sampleResult, sampleStepResults);
expect(log.getCount()).toBe(1);
log.log(sampleCommand, sampleResult, sampleStepResults);
expect(log.getCount()).toBe(2);
});
});
describe('getLastEntry', () => {
it('should return the last log entry', () => {
const command1: Command = { ...sampleCommand, id: 'cmd-1', name: 'First' };
const command2: Command = { ...sampleCommand, id: 'cmd-2', name: 'Last' };
log.log(command1, sampleResult, sampleStepResults);
log.log(command2, sampleResult, sampleStepResults);
const lastEntry = log.getLastEntry();
expect(lastEntry).not.toBeNull();
expect(lastEntry?.commandId).toBe('cmd-2');
});
it('should return null when log is empty', () => {
const lastEntry = log.getLastEntry();
expect(lastEntry).toBeNull();
});
});
describe('Queue management', () => {
describe('enqueue', () => {
it('should add command to queue', () => {
const queued = log.enqueue(sampleCommand);
expect(queued.id).toBe('test-command');
expect(log.getQueueLength()).toBe(1);
});
it('should set initial status to Pending', () => {
const queued = log.enqueue(sampleCommand);
expect(queued.status).toBe('pending');
});
});
describe('dequeue', () => {
it('should remove and return the first command from queue', () => {
const command1: Command = { ...sampleCommand, id: 'cmd-1' };
const command2: Command = { ...sampleCommand, id: 'cmd-2' };
log.enqueue(command1);
log.enqueue(command2);
const dequeued = log.dequeue();
expect(dequeued?.command.id).toBe('cmd-1');
expect(log.getQueueLength()).toBe(1);
});
it('should return null when queue is empty', () => {
const dequeued = log.dequeue();
expect(dequeued).toBeNull();
});
});
describe('updateQueueStatus', () => {
it('should update command status in queue', () => {
log.enqueue(sampleCommand);
log.updateQueueStatus('test-command', 'executing');
const queue = log.getQueue();
expect(queue[0].status).toBe('executing');
});
it('should set executedAt and result when status is Completed', () => {
const result: CommandExecutionResult = { success: true, executedSteps: 1, totalSteps: 1 };
log.enqueue(sampleCommand);
const beforeTime = Date.now();
log.updateQueueStatus('test-command', 'completed', result);
const afterTime = Date.now();
const queue = log.getQueue();
expect(queue[0].status).toBe('completed');
expect(queue[0].result).toEqual(result);
expect(queue[0].executedAt).toBeGreaterThanOrEqual(beforeTime);
expect(queue[0].executedAt).toBeLessThanOrEqual(afterTime);
});
});
describe('clearQueue', () => {
it('should clear all queued commands', () => {
log.enqueue(sampleCommand);
log.enqueue(sampleCommand);
expect(log.getQueueLength()).toBe(2);
log.clearQueue();
expect(log.getQueueLength()).toBe(0);
});
});
});
});