import { describe, it, expect, vi, beforeEach } from 'vitest' import { render, screen, fireEvent } from '@testing-library/react' import { NoteSearchList } from './NoteSearchList' import type { NoteSearchResultItem } from './NoteSearchList' // jsdom doesn't implement scrollIntoView Element.prototype.scrollIntoView = vi.fn() interface TestItem extends NoteSearchResultItem { id: string } const items: TestItem[] = [ { id: '1', title: 'Alpha Project', noteType: 'Project', typeColor: 'var(--accent-blue)' }, { id: '2', title: 'Beta Notes' }, { id: '3', title: 'Gamma Experiment', noteType: 'Experiment' }, ] describe('NoteSearchList', () => { const onItemClick = vi.fn() const onItemHover = vi.fn() beforeEach(() => { vi.clearAllMocks() }) it('renders all items with titles', () => { render( item.id} onItemClick={onItemClick} />, ) expect(screen.getByText('Alpha Project')).toBeInTheDocument() expect(screen.getByText('Beta Notes')).toBeInTheDocument() expect(screen.getByText('Gamma Experiment')).toBeInTheDocument() }) it('shows type badge when noteType is present', () => { render( item.id} onItemClick={onItemClick} />, ) expect(screen.getByText('Project')).toBeInTheDocument() expect(screen.getByText('Experiment')).toBeInTheDocument() }) it('does not show type badge when noteType is absent', () => { render( item.id} onItemClick={onItemClick} />, ) expect(screen.getByText('Beta Notes')).toBeInTheDocument() // No badge element should exist expect(screen.queryByText('Note')).not.toBeInTheDocument() }) it('applies typeColor to badge when provided', () => { render( item.id} onItemClick={onItemClick} />, ) const badge = screen.getByText('Project') expect(badge.style.color).toBe('var(--accent-blue)') }) it('shows empty message when no items', () => { render( ''} onItemClick={onItemClick} emptyMessage="No matching notes" />, ) expect(screen.getByText('No matching notes')).toBeInTheDocument() }) it('shows default empty message', () => { render( ''} onItemClick={onItemClick} />, ) expect(screen.getByText('No results')).toBeInTheDocument() }) it('calls onItemClick when an item is clicked', () => { render( item.id} onItemClick={onItemClick} />, ) fireEvent.click(screen.getByText('Beta Notes')) expect(onItemClick).toHaveBeenCalledWith(items[1], 1) }) it('calls onItemHover when mouse enters an item', () => { render( item.id} onItemClick={onItemClick} onItemHover={onItemHover} />, ) fireEvent.mouseEnter(screen.getByText('Gamma Experiment')) expect(onItemHover).toHaveBeenCalledWith(2) }) it('highlights selected item with accent background', () => { render( item.id} onItemClick={onItemClick} />, ) const selectedItem = screen.getByText('Beta Notes').closest('div')! expect(selectedItem.className).toContain('bg-accent') const unselectedItem = screen.getByText('Alpha Project').closest('div')! expect(unselectedItem.className).not.toContain('bg-accent') }) it('calls scrollIntoView on the selected item', () => { const scrollMock = vi.fn() Element.prototype.scrollIntoView = scrollMock const { rerender } = render( item.id} onItemClick={onItemClick} />, ) scrollMock.mockClear() rerender( item.id} onItemClick={onItemClick} />, ) expect(scrollMock).toHaveBeenCalledWith({ block: 'nearest' }) }) })