import { afterEach, describe, expect, it, vi } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; import { page } from 'vitest/browser'; import Page from './+page.svelte'; const tick = () => new Promise((r) => setTimeout(r, 0)); vi.mock('$app/navigation', () => ({ goto: vi.fn() })); const makePerson = (overrides = {}) => ({ id: '1', firstName: 'Max', lastName: 'Mustermann', ...overrides }); const emptyData = { user: undefined, canWrite: true, canAnnotate: false, q: '', persons: [] }; const dataWithPersons = { ...emptyData, persons: [makePerson()] }; afterEach(cleanup); // ─── Rendering ──────────────────────────────────────────────────────────────── describe('Persons page – rendering', () => { it('renders the search input', async () => { render(Page, { data: emptyData }); await expect.element(page.getByRole('textbox')).toBeInTheDocument(); }); it('pre-fills the search input from data.q', async () => { render(Page, { data: { ...emptyData, q: 'Müller' } }); await expect.element(page.getByRole('textbox')).toHaveValue('Müller'); }); it('shows empty state when no persons', async () => { render(Page, { data: emptyData }); await expect.element(page.getByText('Keine Personen gefunden')).toBeInTheDocument(); }); it('renders person cards', async () => { render(Page, { data: dataWithPersons }); await expect.element(page.getByText('Max Mustermann')).toBeInTheDocument(); }); it('links person card to detail page', async () => { render(Page, { data: dataWithPersons }); await expect .element(page.getByRole('link', { name: /Max Mustermann/ })) .toHaveAttribute('href', '/persons/1'); }); }); // ─── Keystroke preservation (issue #34) ────────────────────────────────────── describe('Persons page – search input keystroke preservation', () => { it('does not overwrite the search input while the user is focused and stale data arrives', async () => { const { rerender } = render(Page, { data: emptyData }); const input = page.getByRole('textbox'); // User types "abc" — input is focused await input.click(); await input.fill('abc'); // Simulate a navigation completing with stale data (q='a') while the user is still typing await rerender({ data: { ...emptyData, q: 'a' } }); await tick(); // Input must still show what the user typed, not the stale URL value await expect.element(input).toHaveValue('abc'); }); });