import { render, screen } from '@testing-library/react'; import { describe, it, expect, vi, beforeEach } from 'vitest'; import userEvent from '@testing-library/user-event'; import { Select } from './select'; describe('Select Component', () => { const mockOnChange = vi.fn(); const options = [ { value: 'option1', label: 'Option 1' }, { value: 'option2', label: 'Option 2' }, { value: 'option3', label: 'Option 3' }, ]; beforeEach(() => { vi.clearAllMocks(); }); it('renders select trigger correctly', () => { render( ); const triggers = screen.getAllByRole('button'); const trigger = triggers.find((btn) => btn.textContent?.includes('Select an option...'), ) || triggers[0]; await user.click(trigger); await waitFor(() => { expect(screen.getByText('Option 1')).toBeInTheDocument(); }); }); it('displays selected value for single select', () => { render( , ); expect(screen.getByText('2 selected')).toBeInTheDocument(); }); it('calls onChange when option is selected in single mode', async () => { const user = userEvent.setup(); render(); const triggers = screen.getAllByRole('button'); const trigger = triggers.find((btn) => btn.textContent?.includes('Select an option...'), ) || triggers[0]; await user.click(trigger); await waitFor(() => { expect(screen.getByText('Option 1')).toBeInTheDocument(); }); const option1 = screen.getByText('Option 1'); await user.click(option1); expect(mockOnChange).toHaveBeenCalledWith(['option1']); }); it('toggles option selection in multi mode', async () => { const user = userEvent.setup(); render( ); const triggers = screen.getAllByRole('button'); const trigger = triggers.find((btn) => btn.textContent?.includes('Select an option...'), ) || triggers[0]; await user.click(trigger); await waitFor(() => { expect(screen.getByPlaceholderText('Search...')).toBeInTheDocument(); }); // Attendre que les options soient rendues await waitFor(() => { expect(screen.getAllByRole('menuitem').length).toBeGreaterThan(0); }); const searchInput = screen.getByPlaceholderText('Search...'); await user.type(searchInput, 'Option 1'); await waitFor( () => { const menuItems = screen.getAllByRole('menuitem'); const option1Item = menuItems.find((item) => item.textContent?.includes('Option 1'), ); expect(option1Item).toBeInTheDocument(); const option2Item = menuItems.find((item) => item.textContent?.includes('Option 2'), ); expect(option2Item).not.toBeInTheDocument(); }, { timeout: 2000 }, ); }); it('displays grouped options', async () => { const user = userEvent.setup(); const groupedOptions = [ { value: 'opt1', label: 'Option 1', group: 'Group 1' }, { value: 'opt2', label: 'Option 2', group: 'Group 1' }, { value: 'opt3', label: 'Option 3', group: 'Group 2' }, ]; render(, ); const triggers = screen.getAllByRole('button'); const trigger = triggers.find((btn) => btn.textContent?.includes('Select an option...'), ) || triggers[0]; await user.click(trigger); await waitFor(() => { expect(screen.getByPlaceholderText('Search...')).toBeInTheDocument(); }); const searchInput = screen.getByPlaceholderText('Search...'); await user.type(searchInput, 'Apple'); expect(screen.getByText('Apple')).toBeInTheDocument(); expect(screen.queryByText('Banana')).not.toBeInTheDocument(); expect(screen.queryByText('Carrot')).not.toBeInTheDocument(); }); it('shows checkmark for selected option in single mode', async () => { const user = userEvent.setup(); render( , ); const triggers = screen.getAllByRole('button'); const trigger = triggers.find((btn) => btn.textContent?.includes('1 selected')) || triggers[0]; await user.click(trigger); await waitFor(() => { const option1 = screen.getByText('Option 1').closest('[role="menuitem"]'); const checkbox = option1?.querySelector('.border'); expect(checkbox).toBeInTheDocument(); }); }); it('disables option when disabled prop is true', async () => { const user = userEvent.setup(); const optionsWithDisabled = [ { value: 'opt1', label: 'Option 1' }, { value: 'opt2', label: 'Option 2', disabled: true }, ]; render(, ); const triggers = screen.getAllByRole('button'); const trigger = triggers.find((btn) => btn.textContent?.includes('Option 1'), ); const clearButton = trigger?.querySelector('svg'); expect(clearButton).toBeInTheDocument(); if (clearButton) { await user.click(clearButton); expect(mockOnChange).toHaveBeenCalledWith(''); } }); it('clears all selections in multi mode', async () => { const user = userEvent.setup(); render( ); const triggers = screen.getAllByRole('button'); const trigger = triggers.find((btn) => btn.textContent?.includes('Select an option...'), ) || triggers[0]; await user.click(trigger); await waitFor(() => { expect(screen.getByPlaceholderText('Search...')).toBeInTheDocument(); }); const searchInput = screen.getByPlaceholderText('Search...'); await user.type(searchInput, 'nonexistent'); await waitFor(() => { expect(screen.getByText('No options found')).toBeInTheDocument(); }); }); it('renders hidden input with name attribute', () => { render( , ); const hiddenInput = document.querySelector( 'input[type="hidden"][name="test-select"]', ); expect(hiddenInput).toBeInTheDocument(); expect(hiddenInput).toHaveValue('option1,option2'); }); it('disables select when disabled prop is true', () => { render(