import { describe, expect, it, vi, afterEach } from 'vitest'; import { cleanup, render } from 'vitest-browser-svelte'; import { page } from 'vitest/browser'; import DisambiguationPicker from './DisambiguationPicker.svelte'; import type { components } from '$lib/generated/api'; type PersonHint = components['schemas']['PersonHint']; afterEach(() => cleanup()); const persons: PersonHint[] = [ { id: 'w1', displayName: 'Walter Raddatz' }, { id: 'w2', displayName: 'Walter Müller' } ]; const multiProps = { persons, heading: 'Person auswählen', showCue: true }; function pressEscape() { (document.activeElement as HTMLElement).dispatchEvent( new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }) ); } describe('DisambiguationPicker', () => { it('opens the picker and shows a select option per ambiguous person', async () => { render(DisambiguationPicker, { ...multiProps, onSelect: vi.fn() }); await page.getByRole('button', { name: /Mehrere Personen gefunden/ }).click(); await expect .element(page.getByRole('button', { name: 'Walter Raddatz auswählen' })) .toBeInTheDocument(); await expect .element(page.getByRole('button', { name: 'Walter Müller auswählen' })) .toBeInTheDocument(); }); it('moves focus into the picker list on open', async () => { render(DisambiguationPicker, { ...multiProps, onSelect: vi.fn() }); await page.getByRole('button', { name: /Mehrere Personen gefunden/ }).click(); await expect .element(page.getByRole('button', { name: 'Walter Raddatz auswählen' })) .toHaveFocus(); }); it('returns focus to the trigger when closed with Escape', async () => { render(DisambiguationPicker, { ...multiProps, onSelect: vi.fn() }); const trigger = page.getByRole('button', { name: /Mehrere Personen gefunden/ }); await trigger.click(); await expect .element(page.getByRole('button', { name: 'Walter Raddatz auswählen' })) .toHaveFocus(); pressEscape(); await expect.element(trigger).toHaveFocus(); }); it('does not call onSelect when dismissed without choosing', async () => { const onSelect = vi.fn(); render(DisambiguationPicker, { ...multiProps, onSelect }); await page.getByRole('button', { name: /Mehrere Personen gefunden/ }).click(); await expect .element(page.getByRole('button', { name: 'Walter Raddatz auswählen' })) .toHaveFocus(); pressEscape(); expect(onSelect).not.toHaveBeenCalled(); }); it('calls onSelect with the chosen person', async () => { const onSelect = vi.fn(); render(DisambiguationPicker, { ...multiProps, onSelect }); await page.getByRole('button', { name: /Mehrere Personen gefunden/ }).click(); await page.getByRole('button', { name: 'Walter Müller auswählen' }).click(); expect(onSelect).toHaveBeenCalledWith(persons[1]); }); it('renders the supplied heading as a visible panel heading', async () => { render(DisambiguationPicker, { persons: [{ id: 'c1', displayName: 'Clara Cramer' }], heading: 'Meintest du Clara Cramer?', showCue: false, onSelect: vi.fn() }); await page.getByRole('button', { name: 'Meintest du Clara Cramer?' }).click(); await expect.element(page.getByText('Meintest du Clara Cramer?')).toBeVisible(); }); it('suppresses the cue when showCue is false', async () => { render(DisambiguationPicker, { persons: [{ id: 'c1', displayName: 'Clara Cramer' }], heading: 'Meintest du Clara Cramer?', showCue: false, onSelect: vi.fn() }); await expect.element(page.getByText('(auswählen…)')).not.toBeInTheDocument(); }); it('shows the cue when showCue is true', async () => { render(DisambiguationPicker, { ...multiProps, onSelect: vi.fn() }); await expect.element(page.getByText('(auswählen…)')).toBeVisible(); }); it('announces the did-you-mean heading as the trigger accessible name for a single suggestion', async () => { render(DisambiguationPicker, { persons: [{ id: 'c1', displayName: 'Clara Cramer' }], heading: 'Meintest du Clara Cramer?', showCue: false, onSelect: vi.fn() }); await expect .element(page.getByRole('button', { name: 'Meintest du Clara Cramer?' })) .toBeInTheDocument(); }); it('keeps the multiple-people trigger accessible name for two or more suggestions', async () => { render(DisambiguationPicker, { ...multiProps, onSelect: vi.fn() }); await expect .element(page.getByRole('button', { name: /Mehrere Personen gefunden/ })) .toBeInTheDocument(); }); });