import { describe, it, expect, vi, afterEach } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; afterEach(cleanup); const baseProps = (overrides: Record = {}) => ({ filled: [ { month: '1923-01', count: 5 }, { month: '1923-02', count: 1 }, { month: '1923-03', count: 0 } ], maxCount: 5, barAreaHeight: 100, isSelected: () => false, isInDragPreview: () => false, isDragging: false, dragWindowLeftPct: 0, dragWindowRightPct: 0, onbarpointerdown: () => {}, onbarpointerenter: () => {}, onbarclick: () => {}, ...overrides }); import TimelineBars from './TimelineBars.svelte'; describe('TimelineBars', () => { it('renders one bar per filled bucket', async () => { render(TimelineBars, { props: baseProps() }); const bars = document.querySelectorAll('[data-testid="timeline-bar"]'); expect(bars.length).toBe(3); }); it('uses the singular aria-label when count is 1', async () => { render(TimelineBars, { props: baseProps() }); const bars = Array.from( document.querySelectorAll('[data-testid="timeline-bar"]') ) as HTMLButtonElement[]; expect(bars[1].getAttribute('aria-label')).toContain('1 Dokument'); }); it('uses the plural aria-label when count is greater than 1', async () => { render(TimelineBars, { props: baseProps() }); const bars = Array.from( document.querySelectorAll('[data-testid="timeline-bar"]') ) as HTMLButtonElement[]; expect(bars[0].getAttribute('aria-label')).toContain('5 Dokumente'); }); it('marks the bar as aria-pressed when isSelected returns true', async () => { render(TimelineBars, { props: baseProps({ isSelected: (label: string) => label === '1923-01' }) }); const bars = Array.from( document.querySelectorAll('[data-testid="timeline-bar"]') ) as HTMLButtonElement[]; expect(bars[0].getAttribute('aria-pressed')).toBe('true'); expect(bars[1].getAttribute('aria-pressed')).toBe('false'); }); it('renders the drag window only when isDragging is true', async () => { render(TimelineBars, { props: baseProps({ isDragging: true, dragWindowLeftPct: 10, dragWindowRightPct: 30 }) }); const dragWindow = document.querySelector('[data-testid="timeline-drag-window"]'); expect(dragWindow).not.toBeNull(); }); it('omits the drag window when isDragging is false', async () => { render(TimelineBars, { props: baseProps() }); const dragWindow = document.querySelector('[data-testid="timeline-drag-window"]'); expect(dragWindow).toBeNull(); }); it('calls onbarclick with the bucket index when a bar is clicked', async () => { const onbarclick = vi.fn(); render(TimelineBars, { props: baseProps({ onbarclick }) }); const bars = Array.from( document.querySelectorAll('[data-testid="timeline-bar"]') ) as HTMLButtonElement[]; bars[1].click(); expect(onbarclick).toHaveBeenCalledWith(1); }); it('uses minimum bar height for zero-count buckets', async () => { render(TimelineBars, { props: baseProps() }); const bars = Array.from( document.querySelectorAll('[data-testid="timeline-bar"]') ) as HTMLButtonElement[]; const zeroBar = bars[2].querySelector('.bar-fill') as HTMLElement; expect(zeroBar.style.height).toContain('2px'); }); });