import { describe, it, expect, afterEach } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; import { page } from 'vitest/browser'; import ReaderHeaderBar from './ReaderHeaderBar.svelte'; afterEach(() => { cleanup(); }); describe('ReaderHeaderBar', () => { it('renders a link to /documents with document count', async () => { render(ReaderHeaderBar, { name: 'Anna', documents: 42, persons: 7, stories: 3 }); const link = page.getByRole('link', { name: /42/ }); await expect.element(link).toHaveAttribute('href', '/documents'); }); it('renders a link to /persons with person count', async () => { render(ReaderHeaderBar, { name: 'Anna', documents: 42, persons: 7, stories: 3 }); const link = page.getByRole('link', { name: /7/ }); await expect.element(link).toHaveAttribute('href', '/persons'); }); it('renders a link to /geschichten with story count', async () => { render(ReaderHeaderBar, { name: 'Anna', documents: 42, persons: 7, stories: 3 }); const link = page.getByRole('link', { name: /3/ }); await expect.element(link).toHaveAttribute('href', '/geschichten'); }); it('documents stat link has min-h-[44px] for touch target', async () => { render(ReaderHeaderBar, { name: 'Anna', documents: 42, persons: 7, stories: 3 }); const link = page.getByRole('link', { name: /42/ }); const cls = ((await link.element()) as HTMLElement).className; expect(cls).toMatch(/min-h-\[44px\]/); }); it('persons stat link has min-h-[44px] for touch target', async () => { render(ReaderHeaderBar, { name: 'Anna', documents: 42, persons: 7, stories: 3 }); const link = page.getByRole('link', { name: /7/ }); const cls = ((await link.element()) as HTMLElement).className; expect(cls).toMatch(/min-h-\[44px\]/); }); it('stories stat link has min-h-[44px] for touch target', async () => { render(ReaderHeaderBar, { name: 'Anna', documents: 42, persons: 7, stories: 3 }); const link = page.getByRole('link', { name: /3/ }); const cls = ((await link.element()) as HTMLElement).className; expect(cls).toMatch(/min-h-\[44px\]/); }); it('shows "—" when counts are null', async () => { render(ReaderHeaderBar, { name: 'Anna', documents: null, persons: null, stories: null }); const wrapper = page.getByRole('banner'); const text = ((await wrapper.element()) as HTMLElement).textContent; expect(text?.match(/—/g)?.length).toBeGreaterThanOrEqual(3); }); it('time label uses text-ink class for morning hour', async () => { render(ReaderHeaderBar, { name: 'Anna', documents: 1, persons: 1, stories: 1, hour: 8 }); const timeLabel = page.getByText(/Morgen/i); await expect.element(timeLabel).toBeInTheDocument(); const cls = ((await timeLabel.element()) as HTMLElement).className; expect(cls).toMatch(/\btext-ink\b/); }); it('shows afternoon label for hour 14', async () => { render(ReaderHeaderBar, { name: 'Anna', documents: 1, persons: 1, stories: 1, hour: 14 }); const timeLabel = page.getByText(/Mittag/i); await expect.element(timeLabel).toBeInTheDocument(); }); it('shows evening label for hour 20', async () => { render(ReaderHeaderBar, { name: 'Anna', documents: 1, persons: 1, stories: 1, hour: 20 }); const timeLabel = page.getByText(/Abend/i); await expect.element(timeLabel).toBeInTheDocument(); }); it('welcome line contains the user name', async () => { render(ReaderHeaderBar, { name: 'Anna', documents: 1, persons: 1, stories: 1, hour: 8 }); const welcome = page.getByText(/Anna/); await expect.element(welcome).toBeInTheDocument(); }); it('wrapper uses bg-surface (CSS-variable-backed, dark-mode-aware)', async () => { render(ReaderHeaderBar, { name: 'Anna', documents: 1, persons: 1, stories: 1 }); const wrapper = page.getByRole('banner'); const cls = ((await wrapper.element()) as HTMLElement).className; expect(cls).toMatch(/\bbg-surface\b/); }); it('renders a vertical divider with bg-line class', async () => { render(ReaderHeaderBar, { name: 'Anna', documents: 1, persons: 1, stories: 1 }); const wrapper = page.getByRole('banner'); const el = (await wrapper.element()) as HTMLElement; const divider = el.querySelector('[aria-hidden="true"]'); expect(divider).not.toBeNull(); expect(divider!.className).toMatch(/bg-line/); }); });