From 8495f0e2e63f0fc7442db7a64193e30e79c3c248 Mon Sep 17 00:00:00 2001 From: Test Date: Mon, 2 Mar 2026 23:05:03 +0100 Subject: [PATCH] test: add theme command registry tests and minor fixes --- src/components/CommandPalette.tsx | 2 +- src/components/SearchPanel.tsx | 1 - src/hooks/useCommandRegistry.test.ts | 40 ++++++++++++++++++++++++++++ src/hooks/useThemeManager.ts | 1 - 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/components/CommandPalette.tsx b/src/components/CommandPalette.tsx index 08c805ea..ba360460 100644 --- a/src/components/CommandPalette.tsx +++ b/src/components/CommandPalette.tsx @@ -51,7 +51,7 @@ export function CommandPalette({ open, commands, onClose }: CommandPaletteProps) useEffect(() => { if (open) { setQuery('') // eslint-disable-line react-hooks/set-state-in-effect -- reset on open - setSelectedIndex(0) // eslint-disable-line react-hooks/set-state-in-effect -- reset on open + setSelectedIndex(0) setTimeout(() => inputRef.current?.focus(), 50) } }, [open]) diff --git a/src/components/SearchPanel.tsx b/src/components/SearchPanel.tsx index 093bc7dc..29ede4a3 100644 --- a/src/components/SearchPanel.tsx +++ b/src/components/SearchPanel.tsx @@ -209,7 +209,6 @@ function SearchContent({ onMouseEnter={() => onHover(i)} >
- {/* eslint-disable-next-line react-hooks/static-components -- icon from static map lookup */} {result.title} {noteType && ( diff --git a/src/hooks/useCommandRegistry.test.ts b/src/hooks/useCommandRegistry.test.ts index 1f3b2d34..78493c16 100644 --- a/src/hooks/useCommandRegistry.test.ts +++ b/src/hooks/useCommandRegistry.test.ts @@ -437,6 +437,46 @@ describe('useCommandRegistry', () => { const groups = new Set(result.current.map(c => c.group)) expect(groups).toContain('Appearance') }) + + it('generates open-theme commands for each theme when onOpenTheme is provided', () => { + const onOpenTheme = vi.fn() + const { result } = renderHook(() => useCommandRegistry(makeConfig({ + themes: themeFixtures, activeThemeId: 'default', onOpenTheme, + }))) + const openDefault = result.current.find(c => c.id === 'open-theme-default') + const openDark = result.current.find(c => c.id === 'open-theme-dark') + expect(openDefault).toBeDefined() + expect(openDefault!.label).toBe('Edit Default Theme') + expect(openDefault!.group).toBe('Appearance') + expect(openDefault!.enabled).toBe(true) + expect(openDark).toBeDefined() + expect(openDark!.label).toBe('Edit Dark Theme') + }) + + it('omits open-theme commands when onOpenTheme is not provided', () => { + const { result } = renderHook(() => useCommandRegistry(makeConfig({ + themes: themeFixtures, activeThemeId: 'default', + }))) + expect(result.current.find(c => c.id === 'open-theme-default')).toBeUndefined() + expect(result.current.find(c => c.id === 'open-theme-dark')).toBeUndefined() + }) + + it('calls onOpenTheme with correct themeId when open-theme command executes', () => { + const onOpenTheme = vi.fn() + const { result } = renderHook(() => useCommandRegistry(makeConfig({ + themes: themeFixtures, activeThemeId: 'default', onOpenTheme, + }))) + result.current.find(c => c.id === 'open-theme-dark')!.execute() + expect(onOpenTheme).toHaveBeenCalledWith('dark') + }) + + it('open-theme command is always enabled regardless of active theme', () => { + const onOpenTheme = vi.fn() + const { result } = renderHook(() => useCommandRegistry(makeConfig({ + themes: themeFixtures, activeThemeId: 'default', onOpenTheme, + }))) + expect(result.current.find(c => c.id === 'open-theme-default')!.enabled).toBe(true) + }) }) }) diff --git a/src/hooks/useThemeManager.ts b/src/hooks/useThemeManager.ts index 95d3d2e3..3ef828ea 100644 --- a/src/hooks/useThemeManager.ts +++ b/src/hooks/useThemeManager.ts @@ -296,7 +296,6 @@ export function useThemeManager( const entry = entries.find(e => e.path === activeThemeId) if (!entry || !isEntryRemoved(entry)) return clearTheme() - // eslint-disable-next-line react-hooks/set-state-in-effect -- sync fallback when active theme is deleted setActiveThemeId(null) if (vaultPath) tauriCall('set_active_theme', { vaultPath, themeId: null }).catch(() => {}) }, [entries, activeThemeId, clearTheme, vaultPath, setActiveThemeId])