import { render, screen, fireEvent } from '@testing-library/react' import { describe, it, expect, vi } from 'vitest' import { FolderTree } from './FolderTree' import type { FolderNode, SidebarSelection } from '../types' const mockFolders: FolderNode[] = [ { name: 'projects', path: 'projects', children: [ { name: 'laputa', path: 'projects/laputa', children: [] }, { name: 'portfolio', path: 'projects/portfolio', children: [] }, ], }, { name: 'areas', path: 'areas', children: [] }, { name: 'journal', path: 'journal', children: [] }, ] const defaultSelection: SidebarSelection = { kind: 'filter', filter: 'all' } describe('FolderTree', () => { it('renders nothing when folders is empty', () => { const { container } = render( , ) expect(container.firstChild).toBeNull() }) it('renders FOLDERS header and top-level folders', () => { render() expect(screen.getByText('FOLDERS')).toBeInTheDocument() expect(screen.getByText('projects')).toBeInTheDocument() expect(screen.getByText('areas')).toBeInTheDocument() expect(screen.getByText('journal')).toBeInTheDocument() }) it('expands children when clicking the folder chevron', () => { render() expect(screen.queryByText('laputa')).not.toBeInTheDocument() fireEvent.click(screen.getByLabelText('Expand projects')) expect(screen.getByText('laputa')).toBeInTheDocument() expect(screen.getByText('portfolio')).toBeInTheDocument() }) it('calls onSelect with folder kind when clicking a folder row', () => { const onSelect = vi.fn() render() fireEvent.click(screen.getByTestId('folder-row:projects')) expect(onSelect).toHaveBeenCalledWith({ kind: 'folder', path: 'projects' }) }) it('collapses section when clicking the FOLDERS header', () => { render() expect(screen.getByText('projects')).toBeInTheDocument() fireEvent.click(screen.getByText('FOLDERS')) expect(screen.queryByText('projects')).not.toBeInTheDocument() }) it('highlights the selected folder row', () => { const selection: SidebarSelection = { kind: 'folder', path: 'areas' } render() expect(screen.getByTestId('folder-row:areas').className).toContain('text-primary') }) it('opens the create-folder input from the header action', () => { render( , ) fireEvent.click(screen.getByTestId('create-folder-btn')) expect(screen.getByTestId('new-folder-input')).toBeInTheDocument() }) it('starts rename on folder double-click', () => { const onStartRenameFolder = vi.fn() render( , ) fireEvent.doubleClick(screen.getByTestId('folder-row:areas')) expect(onStartRenameFolder).toHaveBeenCalledWith('areas') }) it('shows inline rename and delete actions for folders', () => { const onDeleteFolder = vi.fn() const onStartRenameFolder = vi.fn() const onSelect = vi.fn() render( , ) fireEvent.click(screen.getByTestId('rename-folder-btn:projects')) fireEvent.click(screen.getByTestId('delete-folder-btn:projects')) expect(onSelect).toHaveBeenNthCalledWith(1, { kind: 'folder', path: 'projects' }) expect(onStartRenameFolder).toHaveBeenCalledWith('projects') expect(onSelect).toHaveBeenNthCalledWith(2, { kind: 'folder', path: 'projects' }) expect(onDeleteFolder).toHaveBeenCalledWith('projects') }) it('shows the rename input when a folder is being renamed', () => { render( , ) expect(screen.getByTestId('rename-folder-input')).toBeInTheDocument() }) it('opens a context menu with a delete action on right-click', () => { const onDeleteFolder = vi.fn() render( , ) fireEvent.contextMenu(screen.getByText('projects')) expect(screen.getByTestId('folder-context-menu')).toBeInTheDocument() fireEvent.click(screen.getByTestId('delete-folder-menu-item')) expect(onDeleteFolder).toHaveBeenCalledWith('projects') }) })