Files
web-cad/frontend/tests/commandRegistry.test.ts
T

260 lines
7.9 KiB
TypeScript
Raw Normal View History

/**
* commandRegistry Tests Command lookup, autocomplete, categories
*/
import { describe, it, expect, beforeEach } from 'vitest';
import { CommandRegistry } from '../src/services/commandRegistry';
import type { CommandDefinition } from '../src/services/commandRegistry';
describe('CommandRegistry', () => {
let registry: CommandRegistry;
beforeEach(() => {
registry = new CommandRegistry();
});
describe('lookup by name', () => {
it('should find LINE by name', () => {
const cmd = registry.lookup('LINE');
expect(cmd).not.toBeNull();
expect(cmd!.name).toBe('LINE');
expect(cmd!.toolId).toBe('line');
});
it('should find CIRCLE by name', () => {
const cmd = registry.lookup('CIRCLE');
expect(cmd).not.toBeNull();
expect(cmd!.name).toBe('CIRCLE');
});
it('should find RECT by name', () => {
const cmd = registry.lookup('RECT');
expect(cmd).not.toBeNull();
expect(cmd!.name).toBe('RECT');
});
it('should find UNDO by name', () => {
const cmd = registry.lookup('UNDO');
expect(cmd).not.toBeNull();
expect(cmd!.category).toBe('meta');
});
it('should be case insensitive', () => {
const cmd = registry.lookup('line');
expect(cmd).not.toBeNull();
expect(cmd!.name).toBe('LINE');
});
it('should trim whitespace', () => {
const cmd = registry.lookup(' LINE ');
expect(cmd).not.toBeNull();
expect(cmd!.name).toBe('LINE');
});
});
describe('lookup by alias', () => {
it('should find LINE by alias L', () => {
const cmd = registry.lookup('L');
expect(cmd).not.toBeNull();
expect(cmd!.name).toBe('LINE');
});
it('should find CIRCLE by alias C', () => {
const cmd = registry.lookup('C');
expect(cmd).not.toBeNull();
expect(cmd!.name).toBe('CIRCLE');
});
it('should find RECT by alias R', () => {
const cmd = registry.lookup('R');
expect(cmd).not.toBeNull();
expect(cmd!.name).toBe('RECT');
});
it('should find MOVE by alias M', () => {
const cmd = registry.lookup('M');
expect(cmd).not.toBeNull();
expect(cmd!.name).toBe('MOVE');
});
it('should find ERASE by alias E and DEL', () => {
expect(registry.lookup('E')!.name).toBe('ERASE');
expect(registry.lookup('DEL')!.name).toBe('ERASE');
});
it('should find POLYLINE by alias PL', () => {
const cmd = registry.lookup('PL');
expect(cmd).not.toBeNull();
expect(cmd!.name).toBe('POLYLINE');
});
it('should find German alias LINIE for LINE', () => {
const cmd = registry.lookup('LINIE');
expect(cmd).not.toBeNull();
expect(cmd!.name).toBe('LINE');
});
});
describe('lookup unknown command', () => {
it('should return null for unknown command', () => {
expect(registry.lookup('UNKNOWN')).toBeNull();
});
it('should return null for empty string', () => {
expect(registry.lookup('')).toBeNull();
});
it('should return null for random text', () => {
expect(registry.lookup('XYZABC')).toBeNull();
});
});
describe('getToolId', () => {
it('should return toolId for LINE', () => {
expect(registry.getToolId('LINE')).toBe('line');
});
it('should return toolId for CIRCLE alias C', () => {
expect(registry.getToolId('C')).toBe('circle');
});
it('should return null for meta commands like UNDO', () => {
expect(registry.getToolId('UNDO')).toBeNull();
});
it('should return null for unknown command', () => {
expect(registry.getToolId('UNKNOWN')).toBeNull();
});
});
describe('getLabel', () => {
it('should return label for LINE', () => {
const label = registry.getLabel('LINE');
expect(label).not.toBeNull();
expect(label).toContain('Linie');
});
it('should return label for alias L', () => {
const label = registry.getLabel('L');
expect(label).not.toBeNull();
expect(label).toContain('Linie');
});
it('should return null for unknown command', () => {
expect(registry.getLabel('UNKNOWN')).toBeNull();
});
});
describe('getAllCommands', () => {
it('should return all command definitions', () => {
const all = registry.getAllCommands();
expect(all.length).toBeGreaterThan(10);
});
it('should include LINE, CIRCLE, RECT, MOVE, UNDO', () => {
const all = registry.getAllCommands();
const names = all.map(c => c.name);
expect(names).toContain('LINE');
expect(names).toContain('CIRCLE');
expect(names).toContain('RECT');
expect(names).toContain('MOVE');
expect(names).toContain('UNDO');
});
});
describe('autocomplete', () => {
it('should return exact match first', () => {
const results = registry.autocomplete('L');
expect(results.length).toBeGreaterThan(0);
// Exact alias match 'L' should be LINE (priority 1)
expect(results[0].name).toBe('LINE');
});
it('should return commands starting with input', () => {
const results = registry.autocomplete('LI');
expect(results.length).toBeGreaterThan(0);
const names = results.map(c => c.name);
expect(names).toContain('LINE');
});
it('should return empty for empty input', () => {
expect(registry.autocomplete('')).toEqual([]);
});
it('should return max 10 results', () => {
const results = registry.autocomplete('A');
expect(results.length).toBeLessThanOrEqual(10);
});
it('should match aliases', () => {
const results = registry.autocomplete('PL');
expect(results.length).toBeGreaterThan(0);
const names = results.map(c => c.name);
expect(names).toContain('POLYLINE');
});
it('should match case-insensitively', () => {
const results = registry.autocomplete('line');
expect(results.length).toBeGreaterThan(0);
expect(results[0].name).toBe('LINE');
});
});
describe('getAllNames', () => {
it('should return all names and aliases in uppercase', () => {
const names = registry.getAllNames();
expect(names.length).toBeGreaterThan(10);
expect(names.every(n => n === n.toUpperCase())).toBe(true);
});
it('should include LINE and alias L', () => {
const names = registry.getAllNames();
expect(names).toContain('LINE');
expect(names).toContain('L');
});
});
describe('categories', () => {
it('should have draw category commands', () => {
const all = registry.getAllCommands();
const draw = all.filter(c => c.category === 'draw');
expect(draw.length).toBeGreaterThan(5);
const names = draw.map(c => c.name);
expect(names).toContain('LINE');
expect(names).toContain('CIRCLE');
});
it('should have modify category commands', () => {
const all = registry.getAllCommands();
const modify = all.filter(c => c.category === 'modify');
expect(modify.length).toBeGreaterThan(5);
const names = modify.map(c => c.name);
expect(names).toContain('MOVE');
expect(names).toContain('ROTATE');
});
it('should have view category commands', () => {
const all = registry.getAllCommands();
const view = all.filter(c => c.category === 'view');
expect(view.length).toBeGreaterThan(0);
const names = view.map(c => c.name);
expect(names).toContain('PAN');
expect(names).toContain('ZOOM');
});
it('should have meta category commands', () => {
const all = registry.getAllCommands();
const meta = all.filter(c => c.category === 'meta');
expect(meta.length).toBeGreaterThan(0);
const names = meta.map(c => c.name);
expect(names).toContain('UNDO');
expect(names).toContain('REDO');
});
it('should have special category commands', () => {
const all = registry.getAllCommands();
const special = all.filter(c => c.category === 'special');
expect(special.length).toBeGreaterThan(0);
});
});
});