wrapping trigger + content.
const container = trigger.closest('div')!;
// Type "c" → should highlight Cherry.
fireEvent.keyDown(container, { key: 'c' });
const cherry = screen.getByRole('menuitem', { name: /cherry/i });
expect(cherry.getAttribute('data-highlighted')).toBe('true');
// Advance past the typeahead reset buffer.
act(() => { vi.advanceTimersByTime(700); });
// Type "b" → should jump to Banana.
fireEvent.keyDown(container, { key: 'b' });
const banana = screen.getByRole('menuitem', { name: /banana/i });
expect(banana.getAttribute('data-highlighted')).toBe('true');
expect(cherry.getAttribute('data-highlighted')).toBeNull();
});
/* ─── compositional API smoke test ────────────────────────────────── */
it('compositional API: Root + Trigger + Content + Item renders and selects', () => {
const onSel = vi.fn();
render(
Open
Group
onSel('copy')} shortcut="⌘C">Copy
onSel('delete')}>Delete
,
);
expect(screen.getByTestId('dropdown-header')).toBeTruthy();
expect(screen.getByTestId('dropdown-separator')).toBeTruthy();
const shortcut = screen.getByTestId('dropdown-shortcut');
expect(shortcut.textContent).toBe('⌘C');
fireEvent.click(screen.getByRole('menuitem', { name: /delete/i }));
expect(onSel).toHaveBeenCalledWith('delete');
});
it('destructive item gets red tone class', () => {
render(
Open
{}}>Delete
,
);
const del = screen.getByRole('menuitem', { name: /delete/i });
expect(del.className).toMatch(/text-retro-red/);
});
/* ─── v2.1 prop-inheritance migration: DOM props reach the