255 lines
6.9 KiB
TypeScript
255 lines
6.9 KiB
TypeScript
import { describe, it, expect, beforeEach } from 'vitest';
|
|
import { CommandRegistry, createCommandRegistry } from '../../src/commands/CommandRegistry';
|
|
import type { CliCommand } from '../../src/commands/CliCommand';
|
|
|
|
describe('CommandRegistry', () => {
|
|
let registry: CommandRegistry;
|
|
|
|
beforeEach(() => {
|
|
registry = createCommandRegistry();
|
|
});
|
|
|
|
const sampleCommand: CliCommand = {
|
|
name: 'test',
|
|
description: 'Test command',
|
|
usage: 'test <arg>',
|
|
args: [
|
|
{ name: 'arg', description: 'Test argument', required: true },
|
|
],
|
|
handler: (args) => {
|
|
return [
|
|
{
|
|
action: 'createMeeple',
|
|
params: { id: args.positional[0], color: 'red' },
|
|
},
|
|
];
|
|
},
|
|
};
|
|
|
|
describe('register', () => {
|
|
it('should register a command', () => {
|
|
registry.register(sampleCommand);
|
|
|
|
expect(registry.has('test')).toBe(true);
|
|
expect(registry.get('test')).toBe(sampleCommand);
|
|
});
|
|
|
|
it('should register multiple commands', () => {
|
|
const cmd1: CliCommand = {
|
|
name: 'cmd1',
|
|
description: 'Command 1',
|
|
usage: 'cmd1',
|
|
handler: () => [],
|
|
};
|
|
const cmd2: CliCommand = {
|
|
name: 'cmd2',
|
|
description: 'Command 2',
|
|
usage: 'cmd2',
|
|
handler: () => [],
|
|
};
|
|
|
|
registry.registerAll([cmd1, cmd2]);
|
|
|
|
expect(registry.has('cmd1')).toBe(true);
|
|
expect(registry.has('cmd2')).toBe(true);
|
|
expect(registry.getCount()).toBe(2);
|
|
});
|
|
});
|
|
|
|
describe('get', () => {
|
|
it('should return undefined for non-existent command', () => {
|
|
const cmd = registry.get('non-existent');
|
|
expect(cmd).toBeUndefined();
|
|
});
|
|
|
|
it('should return existing command', () => {
|
|
registry.register(sampleCommand);
|
|
const cmd = registry.get('test');
|
|
expect(cmd?.name).toBe('test');
|
|
});
|
|
});
|
|
|
|
describe('unregister', () => {
|
|
it('should remove a command', () => {
|
|
registry.register(sampleCommand);
|
|
expect(registry.has('test')).toBe(true);
|
|
|
|
registry.unregister('test');
|
|
expect(registry.has('test')).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('getAll', () => {
|
|
it('should return all registered commands', () => {
|
|
registry.register(sampleCommand);
|
|
|
|
const cmd2: CliCommand = {
|
|
name: 'cmd2',
|
|
description: 'Command 2',
|
|
usage: 'cmd2',
|
|
handler: () => [],
|
|
};
|
|
registry.register(cmd2);
|
|
|
|
const all = registry.getAll();
|
|
expect(all.length).toBe(2);
|
|
expect(all.map((c) => c.name)).toEqual(['test', 'cmd2']);
|
|
});
|
|
});
|
|
|
|
describe('execute', () => {
|
|
it('should execute a command successfully', () => {
|
|
registry.register(sampleCommand);
|
|
|
|
const result = registry.execute('test meeple-1');
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.steps.length).toBe(1);
|
|
expect(result.steps[0].action).toBe('createMeeple');
|
|
expect(result.steps[0].params).toEqual({ id: 'meeple-1', color: 'red' });
|
|
});
|
|
|
|
it('should return error for unknown command', () => {
|
|
const result = registry.execute('unknown arg1');
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('Unknown command');
|
|
expect(result.steps).toEqual([]);
|
|
});
|
|
|
|
it('should return error for missing required argument', () => {
|
|
registry.register(sampleCommand);
|
|
|
|
const result = registry.execute('test');
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('Missing required argument');
|
|
});
|
|
|
|
it('should execute command with flags', () => {
|
|
const cmdWithFlags: CliCommand = {
|
|
name: 'move',
|
|
description: 'Move command',
|
|
usage: 'move <id> [--to=region]',
|
|
args: [
|
|
{ name: 'id', description: 'ID', required: true },
|
|
],
|
|
flags: [
|
|
{ name: 'to', description: 'Target', type: 'string' },
|
|
],
|
|
handler: (args) => {
|
|
return [
|
|
{
|
|
action: 'movePlacement',
|
|
params: {
|
|
placementId: args.positional[0],
|
|
targetRegionId: args.flags.to,
|
|
},
|
|
},
|
|
];
|
|
},
|
|
};
|
|
registry.register(cmdWithFlags);
|
|
|
|
const result = registry.execute('move p1 --to=board');
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.steps[0].params).toEqual({
|
|
placementId: 'p1',
|
|
targetRegionId: 'board',
|
|
});
|
|
});
|
|
|
|
it('should handle command with optional args', () => {
|
|
const cmdOptional: CliCommand = {
|
|
name: 'draw',
|
|
description: 'Draw cards',
|
|
usage: 'draw [count]',
|
|
args: [
|
|
{ name: 'count', description: 'Count', required: false, default: '1' },
|
|
],
|
|
handler: (args) => {
|
|
return [];
|
|
},
|
|
};
|
|
registry.register(cmdOptional);
|
|
|
|
const result = registry.execute('draw');
|
|
expect(result.success).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('help', () => {
|
|
beforeEach(() => {
|
|
registry.register({
|
|
name: 'move',
|
|
description: 'Move a placement',
|
|
usage: 'move <id> <target>',
|
|
args: [
|
|
{ name: 'id', description: 'Placement ID', required: true },
|
|
{ name: 'target', description: 'Target region', required: true },
|
|
],
|
|
flags: [
|
|
{ name: 'key', description: 'Slot key', type: 'string', alias: 'k' },
|
|
],
|
|
handler: () => [],
|
|
});
|
|
|
|
registry.register({
|
|
name: 'flip',
|
|
description: 'Flip a placement',
|
|
usage: 'flip <id>',
|
|
args: [
|
|
{ name: 'id', description: 'Placement ID', required: true },
|
|
],
|
|
handler: () => [],
|
|
});
|
|
});
|
|
|
|
it('should show all commands help', () => {
|
|
const help = registry.help();
|
|
|
|
expect(help).toContain('Available commands');
|
|
expect(help).toContain('move');
|
|
expect(help).toContain('flip');
|
|
expect(help).toContain('help <command>');
|
|
});
|
|
|
|
it('should show specific command help', () => {
|
|
const help = registry.help('move');
|
|
|
|
expect(help).toContain('Command: move');
|
|
expect(help).toContain('Move a placement');
|
|
expect(help).toContain('Arguments:');
|
|
expect(help).toContain('Flags:');
|
|
});
|
|
|
|
it('should show error for unknown command help', () => {
|
|
const help = registry.help('unknown');
|
|
expect(help).toContain('Unknown command');
|
|
});
|
|
|
|
it('should show command with alias', () => {
|
|
const help = registry.help('move');
|
|
expect(help).toContain('-k,');
|
|
});
|
|
});
|
|
|
|
describe('clear', () => {
|
|
it('should clear all commands', () => {
|
|
registry.register(sampleCommand);
|
|
registry.register({
|
|
name: 'cmd2',
|
|
description: 'Command 2',
|
|
usage: 'cmd2',
|
|
handler: () => [],
|
|
});
|
|
|
|
expect(registry.getCount()).toBe(2);
|
|
registry.clear();
|
|
expect(registry.getCount()).toBe(0);
|
|
expect(registry.getAll()).toEqual([]);
|
|
});
|
|
});
|
|
});
|