import { describe, it, expect, beforeEach, vi } from 'vitest'; import { CommandRegistry, getCommandRegistry, resetCommandRegistry, } from '../../../src/commands/registry.js'; import type { Command } from '../../../src/commands/types.js'; // Mock loader vi.mock('../../../src/commands/loader.js', () => ({ commandLoader: { loadFromDirectory: vi.fn().mockResolvedValue([]), getUserCommandsDir: vi.fn().mockReturnValue('/mock/user/commands'), getProjectCommandsDir: vi.fn().mockReturnValue('/mock/project/commands'), }, })); // Mock builtin commands vi.mock('../../../src/commands/builtin/index.js', () => ({ builtinCommands: [ { name: 'test-builtin', description: '内置测试命令', template: '测试模板 $ARGUMENTS', source: 'builtin', }, ], })); describe('CommandRegistry - Command 注册表', () => { let registry: CommandRegistry; beforeEach(() => { resetCommandRegistry(); registry = new CommandRegistry(); }); describe('register - 注册', () => { it('成功注册 Command', () => { const command: Command = { name: 'test', description: '测试', template: '模板', source: 'user', }; registry.register(command); expect(registry.has('test')).toBe(true); }); it('高优先级可以覆盖低优先级', () => { const builtin: Command = { name: 'same', description: '内置版本', template: '内置模板', source: 'builtin', }; const project: Command = { name: 'same', description: '项目版本', template: '项目模板', source: 'project', }; registry.register(builtin); registry.register(project); const result = registry.get('same'); expect(result?.source).toBe('project'); expect(result?.description).toBe('项目版本'); }); it('低优先级不能覆盖高优先级', () => { const project: Command = { name: 'same', description: '项目版本', template: '项目模板', source: 'project', }; const builtin: Command = { name: 'same', description: '内置版本', template: '内置模板', source: 'builtin', }; registry.register(project); registry.register(builtin); const result = registry.get('same'); expect(result?.source).toBe('project'); }); }); describe('get - 获取', () => { it('获取存在的 Command', () => { const command: Command = { name: 'test', description: '测试', template: '模板', source: 'user', }; registry.register(command); const result = registry.get('test'); expect(result).toBeDefined(); expect(result?.name).toBe('test'); }); it('获取不存在的 Command 返回 undefined', () => { const result = registry.get('non-existent'); expect(result).toBeUndefined(); }); }); describe('search - 搜索', () => { beforeEach(() => { const commands: Command[] = [ { name: 'review', description: '代码审查', template: '审查模板', source: 'builtin', }, { name: 'test', description: '运行测试', template: '测试模板', source: 'builtin', }, { name: 'deploy/staging', description: '部署到 staging', template: '部署模板', source: 'project', }, ]; for (const cmd of commands) { registry.register(cmd); } }); it('按名称精确匹配', () => { const results = registry.search('review'); expect(results.length).toBeGreaterThan(0); expect(results[0].command.name).toBe('review'); expect(results[0].score).toBe(100); }); it('按名称前缀匹配', () => { const results = registry.search('deploy'); expect(results.length).toBeGreaterThan(0); expect(results[0].command.name).toBe('deploy/staging'); }); it('按描述匹配', () => { const results = registry.search('代码'); expect(results.length).toBeGreaterThan(0); expect(results[0].command.name).toBe('review'); }); it('限制结果数量', () => { const results = registry.search('', 1); expect(results.length).toBeLessThanOrEqual(1); }); }); describe('list - 列表', () => { it('返回所有 Commands 的摘要', () => { const command: Command = { name: 'test', description: '测试', template: '模板', source: 'user', }; registry.register(command); const list = registry.list(); expect(list.length).toBe(1); expect(list[0].name).toBe('test'); expect(list[0].description).toBe('测试'); expect(list[0].source).toBe('user'); }); it('按名称排序', () => { const commands: Command[] = [ { name: 'zebra', description: '', template: '', source: 'user' }, { name: 'alpha', description: '', template: '', source: 'user' }, { name: 'beta', description: '', template: '', source: 'user' }, ]; for (const cmd of commands) { registry.register(cmd); } const list = registry.list(); expect(list[0].name).toBe('alpha'); expect(list[1].name).toBe('beta'); expect(list[2].name).toBe('zebra'); }); }); describe('getStats - 统计', () => { it('返回正确的统计信息', () => { const commands: Command[] = [ { name: 'b1', description: '', template: '', source: 'builtin' }, { name: 'b2', description: '', template: '', source: 'builtin' }, { name: 'u1', description: '', template: '', source: 'user' }, { name: 'p1', description: '', template: '', source: 'project' }, ]; for (const cmd of commands) { registry.register(cmd); } const stats = registry.getStats(); expect(stats.total).toBe(4); expect(stats.bySource.builtin).toBe(2); expect(stats.bySource.user).toBe(1); expect(stats.bySource.project).toBe(1); }); }); }); describe('getCommandRegistry - 全局注册表', () => { beforeEach(() => { resetCommandRegistry(); }); it('返回单例实例', () => { const registry1 = getCommandRegistry(); const registry2 = getCommandRegistry(); expect(registry1).toBe(registry2); }); it('resetCommandRegistry 重置实例', () => { const registry1 = getCommandRegistry(); resetCommandRegistry(); const registry2 = getCommandRegistry(); expect(registry1).not.toBe(registry2); }); });