From b1e16af62dbda6535a432b3824c78f8b80130b99 Mon Sep 17 00:00:00 2001 From: Amit Haridas Date: Fri, 5 Jun 2026 16:00:58 +0530 Subject: [PATCH] feat(renderer): AppHeader wired to command store - toggle sidebar/preview buttons dispatch through command store - new 'shortcuts.show' command (Keyboard icon, opens shortcuts panel later) - AppHeader.test.tsx updated: registers matching commands in beforeEach - integration test fixed: 'Open folder' button now matches 2 (toolbar + sidebar) - 155/155 tests pass --- src/renderer/components/layout/AppHeader.tsx | 23 ++++++++++--- tests/component/layout/AppHeader.test.tsx | 34 ++++++++++++++++++++ tests/integration/phase5-smoke.test.tsx | 6 ++-- 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/renderer/components/layout/AppHeader.tsx b/src/renderer/components/layout/AppHeader.tsx index 78a6359..24f4a09 100644 --- a/src/renderer/components/layout/AppHeader.tsx +++ b/src/renderer/components/layout/AppHeader.tsx @@ -1,10 +1,12 @@ -import { PanelLeft, PanelRight } from 'lucide-react'; +import { PanelLeft, PanelRight, Keyboard } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { ThemeToggle } from '@/components/theme-toggle'; import { useAppStore } from '@/stores/app-store'; +import { useCommandStore } from '@/stores/command-store'; export function AppHeader() { - const { sidebarVisible, previewVisible, toggleSidebar, togglePreview } = useAppStore(); + const { sidebarVisible, previewVisible } = useAppStore(); + const dispatch = useCommandStore((s) => s.dispatch); return (
@@ -21,7 +23,8 @@ export function AppHeader() { size="icon" aria-label="Toggle sidebar" aria-pressed={sidebarVisible} - onClick={toggleSidebar} + data-testid="header-toggle-sidebar" + onClick={() => dispatch('view.toggleSidebar')} > @@ -30,12 +33,22 @@ export function AppHeader() { size="icon" aria-label="Toggle preview" aria-pressed={previewVisible} - onClick={togglePreview} + data-testid="header-toggle-preview" + onClick={() => dispatch('view.togglePreview')} > +
); -} \ No newline at end of file +} diff --git a/tests/component/layout/AppHeader.test.tsx b/tests/component/layout/AppHeader.test.tsx index a656f87..98ec1ec 100644 --- a/tests/component/layout/AppHeader.test.tsx +++ b/tests/component/layout/AppHeader.test.tsx @@ -4,11 +4,21 @@ import userEvent from '@testing-library/user-event'; import { ThemeProvider } from '@/components/theme-provider'; import { AppHeader } from '@/components/layout/AppHeader'; import { useAppStore } from '@/stores/app-store'; +import { useCommandStore } from '@/stores/command-store'; describe('AppHeader', () => { beforeEach(() => { localStorage.clear(); useAppStore.setState({ sidebarVisible: true, previewVisible: true, zenMode: false }); + useCommandStore.setState({ handlers: {} }); + // Mirror what AppShell registers so dispatching actually does something. + useCommandStore.getState().register('view.toggleSidebar', () => { + useAppStore.getState().toggleSidebar(); + }); + useCommandStore.getState().register('view.togglePreview', () => { + useAppStore.getState().togglePreview(); + }); + useCommandStore.getState().register('shortcuts.show', () => {}); }); it('renders the app title', () => { @@ -30,4 +40,28 @@ describe('AppHeader', () => { await userEvent.click(btn); expect(useAppStore.getState().sidebarVisible).toBe(false); }); + + it('toggles preview when preview button clicked', async () => { + render( + + + + ); + const btn = screen.getByRole('button', { name: /toggle preview/i }); + await userEvent.click(btn); + expect(useAppStore.getState().previewVisible).toBe(false); + }); + + it('disables-shortcut button dispatches shortcuts.show', async () => { + render( + + + + ); + const btn = screen.getByTestId('header-shortcuts'); + await userEvent.click(btn); + // No observable side effect; the command was registered as a no-op. + // The test passes if no error is thrown and the click is processed. + expect(btn).toBeInTheDocument(); + }); }); \ No newline at end of file diff --git a/tests/integration/phase5-smoke.test.tsx b/tests/integration/phase5-smoke.test.tsx index 0a8f7ae..957c344 100644 --- a/tests/integration/phase5-smoke.test.tsx +++ b/tests/integration/phase5-smoke.test.tsx @@ -71,9 +71,11 @@ describe('Phase 5 integration', () => { it('opening a folder via the Open Folder button populates the tree', async () => { render(); - const openBtn = screen.getByRole('button', { name: /open folder/i }); + // Two buttons share the "Open folder" name (toolbar + sidebar). + // Either one triggers the same command, so click the first match. + const buttons = screen.getAllByRole('button', { name: /open folder/i }); await act(async () => { - fireEvent.click(openBtn); + fireEvent.click(buttons[0]); }); // After openFolder, the tree should have children const state = useFileStore.getState();