import assert from 'node:assert/strict' import { renderToStaticMarkup } from 'react-dom/server' import { CapabilityPicker, capabilitySelectionKey, detectCapabilitySlashTrigger, filterCapabilityItems, resolveCapabilityPickerKey, type CapabilityPickerItem } from '../src/renderer/src/workbuddy/composer/CapabilityPicker' const items: CapabilityPickerItem[] = [ { id: 'skill:review', name: '代码审查', description: '检查实现缺陷与风险', kind: 'skill' }, { id: 'mcp-server', name: 'postgres', description: '查询本地数据库', kind: 'mcp' }, { id: 'compact', name: 'compact', description: '压缩当前上下文', kind: 'command' } ] const checks: string[] = [] const check = (name: string, actual: unknown, expected: unknown): void => { assert.deepEqual(actual, expected, name) checks.push(name) } check('empty query preserves registration order', filterCapabilityItems(items, ''), items) check('filter matches names and IDs case-insensitively', filterCapabilityItems(items, '/POST').map(item => item.id), ['mcp-server']) check('filter matches descriptions', filterCapabilityItems(items, '上下文').map(item => item.id), ['compact']) check('filter matches kind labels', filterCapabilityItems(items, '命令').map(item => item.id), ['compact']) check('multiple terms must all match', filterCapabilityItems(items, '数据库 本地').map(item => item.id), ['mcp-server']) check('selection identity includes kind', capabilitySelectionKey({ id: 'compact', kind: 'command' }), 'command:compact') check('slash at input start is detected', detectCapabilitySlashTrigger('/comp', 5, items), { start: 0, end: 5, query: 'comp' }) const independent = '请使用 /mcp' check('independent slash token is detected', detectCapabilitySlashTrigger(independent, independent.length, items), { start: 4, end: independent.length, query: 'mcp' }) check('plain slash opens the catalog when items exist', detectCapabilitySlashTrigger('/', 1, items), { start: 0, end: 1, query: '' }) for (const value of ['https://example.com/a', 'src/renderer/file.ts', 'C:\\work\\file.ts', '/Users/me/file.txt', 'file:///tmp/a']) { check('path or URL does not trigger: ' + value, detectCapabilitySlashTrigger(value, value.length, items), null) } check('unknown leading token is rejected when catalog is available', detectCapabilitySlashTrigger('/Users', 6, items), null) check('slash inside ordinary text is not independent', detectCapabilitySlashTrigger('path/compact', 12, items), null) check('IME composition suppresses Enter', resolveCapabilityPickerKey({ key: 'Enter', isComposing: true, itemCount: 3, activeIndex: 1 }), { type: 'none' }) check('IME keyCode 229 suppresses selection', resolveCapabilityPickerKey({ key: 'Enter', keyCode: 229, itemCount: 3, activeIndex: 1 }), { type: 'none' }) check('ArrowDown wraps', resolveCapabilityPickerKey({ key: 'ArrowDown', itemCount: 3, activeIndex: 2 }), { type: 'move', index: 0 }) check('ArrowUp wraps', resolveCapabilityPickerKey({ key: 'ArrowUp', itemCount: 3, activeIndex: 0 }), { type: 'move', index: 2 }) check('Home and End select boundaries', [resolveCapabilityPickerKey({ key: 'Home', itemCount: 3, activeIndex: 2 }), resolveCapabilityPickerKey({ key: 'End', itemCount: 3, activeIndex: 0 })], [{ type: 'move', index: 0 }, { type: 'move', index: 2 }]) check('Enter selects the active item', resolveCapabilityPickerKey({ key: 'Enter', itemCount: 3, activeIndex: 1 }), { type: 'select', index: 1 }) check('Escape closes', resolveCapabilityPickerKey({ key: 'Escape', itemCount: 3, activeIndex: 1 }), { type: 'close' }) check('Enter is ignored on an empty result', resolveCapabilityPickerKey({ key: 'Enter', itemCount: 0, activeIndex: 0 }), { type: 'none' }) const html = renderToStaticMarkup( undefined} onClose={() => undefined} /> ) check('SSR renders combobox and listbox', [html.includes('role="combobox"'), html.includes('role="listbox"')], [true, true]) check('SSR exposes type labels', ['技能', 'MCP', '命令'].every(label => html.includes(label)), true) check('SSR marks selected identity', html.includes('aria-selected="true"'), true) check('SSR renders descriptions', html.includes('检查实现缺陷与风险'), true) check('SSR seeds external query', renderToStaticMarkup( undefined} onClose={() => undefined} query="compact" />).includes('data-kind="command"'), true) check('SSR renders explicit empty state', renderToStaticMarkup( undefined} onClose={() => undefined} query="missing" />).includes('没有匹配的能力'), true) console.log(JSON.stringify({ result: 'PASS', checks: checks.length }))