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('');
});
});