/** * 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); }); }); });