import { describe, expect, it, vi } from 'vitest'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { Combobox } from './combobox'; const options = [ { label: 'Next.js', value: 'next' }, { label: 'Remix', value: 'remix' }, { label: 'Astro', value: 'astro' }, ]; describe('Combobox', () => { it('shows the placeholder until something is selected', () => { render(); expect(screen.getByRole('combobox')).toHaveTextContent('Pick one'); }); it('selects an option and reports the value', async () => { const onValueChange = vi.fn(); render(); await userEvent.click(screen.getByRole('combobox')); await userEvent.click(await screen.findByRole('option', { name: 'Remix' })); expect(onValueChange).toHaveBeenCalledWith('remix'); expect(screen.getByRole('combobox')).toHaveTextContent('Remix'); }); it('filters the list as you type', async () => { render(); await userEvent.click(screen.getByRole('combobox')); await userEvent.type(await screen.findByPlaceholderText('Search'), 'ast'); expect(screen.getByRole('option', { name: 'Astro' })).toBeInTheDocument(); expect(screen.queryByRole('option', { name: 'Remix' })).not.toBeInTheDocument(); }); it('shows the empty message when nothing matches', async () => { render( ); await userEvent.click(screen.getByRole('combobox')); await userEvent.type(await screen.findByPlaceholderText('Search'), 'zzz'); expect(await screen.findByText('Nothing here')).toBeInTheDocument(); }); it('clears the selection when the selected option is chosen again', async () => { const onValueChange = vi.fn(); render(); // Scoped to the option, not the text: the trigger shows the same label. await userEvent.click(screen.getByRole('combobox')); await userEvent.click(await screen.findByRole('option', { name: 'Next.js' })); expect(onValueChange).toHaveBeenCalledWith(''); }); });