diff --git a/src/components/Sidebar.test.tsx b/src/components/Sidebar.test.tsx index 281a63fb..0aaf776f 100644 --- a/src/components/Sidebar.test.tsx +++ b/src/components/Sidebar.test.tsx @@ -1,8 +1,20 @@ import { render, screen, fireEvent } from '@testing-library/react' -import { describe, it, expect, vi } from 'vitest' +import { describe, it, expect, vi, beforeEach } from 'vitest' import { Sidebar } from './Sidebar' import type { VaultEntry, SidebarSelection } from '../types' +// Mock localStorage for section visibility tests +const localStorageMock = (() => { + let store: Record = {} + return { + getItem: (key: string) => store[key] ?? null, + setItem: (key: string, value: string) => { store[key] = value }, + removeItem: (key: string) => { delete store[key] }, + clear: () => { store = {} }, + } +})() +Object.defineProperty(globalThis, 'localStorage', { value: localStorageMock, writable: true }) + const mockEntries: VaultEntry[] = [ { path: '/vault/project/build-app.md', @@ -369,4 +381,97 @@ describe('Sidebar', () => { expect(projectLabels.length).toBe(1) }) }) + + describe('customize section visibility', () => { + beforeEach(() => { + localStorageMock.clear() + }) + + it('renders a "Customize sections" button', () => { + render( {}} />) + expect(screen.getByTitle('Customize sections')).toBeInTheDocument() + }) + + it('opens popover with toggle for each section when clicking customize button', () => { + render( {}} />) + fireEvent.click(screen.getByTitle('Customize sections')) + expect(screen.getByText('Show in sidebar')).toBeInTheDocument() + expect(screen.getByLabelText('Toggle Projects')).toBeInTheDocument() + expect(screen.getByLabelText('Toggle People')).toBeInTheDocument() + expect(screen.getByLabelText('Toggle Topics')).toBeInTheDocument() + }) + + it('hides a section when its toggle is clicked off', () => { + render( {}} />) + // People section should be visible initially + expect(screen.getByText('Alice')).toBeInTheDocument() + + // Open customize popover and toggle People off + fireEvent.click(screen.getByTitle('Customize sections')) + fireEvent.click(screen.getByLabelText('Toggle People')) + + // People section and its items should be gone + expect(screen.queryByText('Alice')).not.toBeInTheDocument() + }) + + it('re-shows a section when its toggle is clicked on again', () => { + render( {}} />) + + // Hide People + fireEvent.click(screen.getByTitle('Customize sections')) + fireEvent.click(screen.getByLabelText('Toggle People')) + expect(screen.queryByText('Alice')).not.toBeInTheDocument() + + // Show People again + fireEvent.click(screen.getByLabelText('Toggle People')) + expect(screen.getByText('Alice')).toBeInTheDocument() + }) + + it('persists hidden sections in localStorage', () => { + const { unmount } = render( {}} />) + fireEvent.click(screen.getByTitle('Customize sections')) + fireEvent.click(screen.getByLabelText('Toggle Events')) + unmount() + + // Verify localStorage was updated + const stored = JSON.parse(localStorage.getItem('laputa-hidden-sections') || '[]') + expect(stored).toContain('Event') + }) + + it('restores hidden sections from localStorage on mount', () => { + localStorage.setItem('laputa-hidden-sections', JSON.stringify(['Person', 'Event'])) + render( {}} />) + + // People and Events sections should be hidden + expect(screen.queryByText('Alice')).not.toBeInTheDocument() + expect(screen.queryByText('Kickoff Meeting')).not.toBeInTheDocument() + + // Other sections should still be visible + expect(screen.getByText('Build Laputa App')).toBeInTheDocument() + expect(screen.getByText('Software Development')).toBeInTheDocument() + }) + + it('does not affect All Notes or other sidebar filters when sections are hidden', () => { + localStorage.setItem('laputa-hidden-sections', JSON.stringify(['Project', 'Person'])) + render( {}} />) + + // Top nav items still present + expect(screen.getByText('All Notes')).toBeInTheDocument() + expect(screen.getByText('Favorites')).toBeInTheDocument() + }) + + it('closes popover when clicking outside', () => { + render( +
+
outside
+ {}} /> +
+ ) + fireEvent.click(screen.getByTitle('Customize sections')) + expect(screen.getByText('Show in sidebar')).toBeInTheDocument() + + fireEvent.mouseDown(screen.getByTestId('outside')) + expect(screen.queryByText('Show in sidebar')).not.toBeInTheDocument() + }) + }) })