refactor(document-picker): downgrade listbox ARIA roles; fix unique listboxId

role=listbox + role=option without arrow-key navigation is misleading — the
WAI-ARIA combobox pattern requires aria-activedescendant handling that isn't
implemented. Downgraded to plain <ul>/<li>; input keeps role=combobox +
aria-controls pointing to the list id.

listboxId was a module-level constant so two simultaneous instances would share
the same DOM id. Fixed with a <script module> counter.

Updated spec queries from getByRole('option') to getByText() — tests behaviour,
not the ARIA implementation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-06-09 18:59:30 +02:00
parent 7df640201a
commit d35a165881
2 changed files with 13 additions and 10 deletions

View File

@@ -53,9 +53,12 @@ describe('DocumentPickerDropdown — already-added indicator', () => {
await userEvent.fill(page.getByRole('combobox'), 'Brief');
await waitForDebounce();
const disabledOption = page.getByRole('option', { name: /Brief von Eugenie/i });
await expect.element(disabledOption).toHaveAttribute('aria-disabled', 'true');
// Screen-reader text "bereits enthalten" must be present in the option
const disabledItem = page
.getByText(/Brief von Eugenie/i)
.element()
.closest('li')!;
expect(disabledItem.getAttribute('aria-disabled')).toBe('true');
// Screen-reader text "bereits enthalten" must be present in the item
await expect.element(page.getByText(/bereits enthalten/i)).toBeInTheDocument();
});
});
@@ -69,7 +72,7 @@ describe('DocumentPickerDropdown — selection', () => {
await userEvent.fill(page.getByRole('combobox'), 'Brief');
await waitForDebounce();
await userEvent.click(page.getByRole('option', { name: /Brief von Eugenie/i }));
await userEvent.click(page.getByText(/Brief von Eugenie/i));
expect(onSelect).toHaveBeenCalledWith(expect.objectContaining({ id: 'd1' }));
});
@@ -85,8 +88,7 @@ describe('DocumentPickerDropdown — selection', () => {
await userEvent.fill(page.getByRole('combobox'), 'Brief');
await waitForDebounce();
// aria-disabled items are not "enabled" — userEvent refuses them; use force click
await page.getByRole('option', { name: /Brief von Eugenie/i }).click({ force: true });
await page.getByText(/Brief von Eugenie/i).click({ force: true });
expect(onSelect).not.toHaveBeenCalled();
});