Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 4m7s
CI / OCR Service Tests (pull_request) Successful in 35s
CI / Backend Unit Tests (pull_request) Failing after 3m18s
CI / Unit & Component Tests (push) Failing after 4m2s
CI / OCR Service Tests (push) Successful in 37s
CI / Backend Unit Tests (push) Failing after 3m25s
text-ink uses --c-ink which is #012851 in light and #f0efe9 in dark, responding to both @media and [data-theme='dark'] via CSS variable — no extra token needed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
100 lines
4.2 KiB
TypeScript
100 lines
4.2 KiB
TypeScript
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/);
|
|
});
|
|
});
|