diff --git a/src/hooks/commands/typeCommands.ts b/src/hooks/commands/typeCommands.ts index 7819dcfc..4d1dcddf 100644 --- a/src/hooks/commands/typeCommands.ts +++ b/src/hooks/commands/typeCommands.ts @@ -27,7 +27,7 @@ export function buildTypeCommands( const plural = pluralizeType(canonicalType) const commands: CommandAction[] = [] - if (canonicalType.toLowerCase() !== 'note') { + if (!['note', 'type'].includes(canonicalType.toLowerCase())) { commands.push({ id: `new-${slug}`, label: `New ${canonicalType}`, group: 'Note' as const, keywords: ['new', 'create', canonicalType.toLowerCase()], diff --git a/src/hooks/useCommandRegistry.test.ts b/src/hooks/useCommandRegistry.test.ts index 02b428f8..f76de77c 100644 --- a/src/hooks/useCommandRegistry.test.ts +++ b/src/hooks/useCommandRegistry.test.ts @@ -262,6 +262,36 @@ describe('useCommandRegistry', () => { shortcut: '⌘N', }) }) + + it('keeps a single canonical New Type command when the Type definition exists', () => { + const onCreateType = vi.fn() + const onCreateNoteOfType = vi.fn() + const config = makeConfig({ + onCreateType, + onCreateNoteOfType, + entries: [ + { path: '/type-definition.md', title: 'Type', isA: 'Type' }, + { path: '/recipe-definition.md', title: 'Recipe', isA: 'Type' }, + ], + }) + const { result } = renderHook(() => useCommandRegistry(config)) + + const newTypeCommands = result.current.filter(command => command.label === 'New Type') + + expect(newTypeCommands).toHaveLength(1) + expect(newTypeCommands[0]).toMatchObject({ + id: 'create-type', + group: 'Note', + }) + expect(findCommand(result.current, 'list-type')).toMatchObject({ + label: 'List Types', + group: 'Navigation', + }) + + newTypeCommands[0].execute() + expect(onCreateType).toHaveBeenCalledOnce() + expect(onCreateNoteOfType).not.toHaveBeenCalled() + }) }) describe('pluralizeType', () => { diff --git a/tests/smoke/command-palette-new-note-dedupe.spec.ts b/tests/smoke/command-palette-new-note-dedupe.spec.ts index 635d7073..7738ed55 100644 --- a/tests/smoke/command-palette-new-note-dedupe.spec.ts +++ b/tests/smoke/command-palette-new-note-dedupe.spec.ts @@ -23,4 +23,23 @@ test.describe('Command palette new note command dedupe', () => { await expect(page.getByText('Create New Note', { exact: true })).toHaveCount(0) await expect(page.getByText('New note', { exact: true })).toHaveCount(0) }) + + test('searching new ty shows one canonical New Type command and opens the type dialog', async ({ page }) => { + await openCommandPalette(page) + + const commandInput = page.locator('input[placeholder="Type a command..."]') + await commandInput.fill('new ty') + + const newTypeRow = page + .locator('div.mx-1.flex.cursor-pointer') + .filter({ has: page.getByText('New Type', { exact: true }) }) + + await expect(newTypeRow).toHaveCount(1) + + await page.keyboard.press('Enter') + await expect(page.getByText('Create New Type', { exact: true })).toBeVisible() + + await page.keyboard.press('Escape') + await expect(page.getByText('Create New Type', { exact: true })).not.toBeVisible() + }) })