import { render, screen, waitForElementToBeRemoved } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { CheckboxSelect } from '../CheckboxSelect'; import styles from '@patternfly/react-styles/css/components/Badge/badge'; test('renders checkbox select with options', async () => { const initialOptions = [ { content: 'Option 1', value: 'option1' }, { content: 'Option 2', value: 'option2' }, { content: 'Option 3', value: 'option3' } ]; const user = userEvent.setup(); render(); const toggle = screen.getByRole('button', { name: 'Filter by status' }); await user.click(toggle); const option1 = screen.getByRole('checkbox', { name: 'Option 1' }); const option2 = screen.getByRole('checkbox', { name: 'Option 2' }); const option3 = screen.getByRole('checkbox', { name: 'Option 3' }); expect(option1).toBeInTheDocument(); expect(option2).toBeInTheDocument(); expect(option3).toBeInTheDocument(); }); test('selects options when clicked', async () => { const initialOptions = [ { content: 'Option 1', value: 'option1' }, { content: 'Option 2', value: 'option2' }, { content: 'Option 3', value: 'option3' } ]; const user = userEvent.setup(); render(); const toggle = screen.getByRole('button', { name: 'Filter by status' }); await user.click(toggle); const option1 = screen.getByRole('checkbox', { name: 'Option 1' }); expect(option1).not.toBeChecked(); await user.click(option1); expect(option1).toBeChecked(); }); test('deselects options when an already selected option is clicked', async () => { const initialOptions = [ { content: 'Option 1', value: 'option1' }, { content: 'Option 2', value: 'option2' }, { content: 'Option 3', value: 'option3' } ]; const user = userEvent.setup(); render(); const toggle = screen.getByRole('button', { name: 'Filter by status' }); await user.click(toggle); const option1 = screen.getByRole('checkbox', { name: 'Option 1' }); await user.click(option1); await user.click(option1); expect(option1).not.toBeChecked(); }); test('calls the onSelect callback with the selected value when an option is selected', async () => { const initialOptions = [ { content: 'Option 1', value: 'option1' }, { content: 'Option 2', value: 'option2' }, { content: 'Option 3', value: 'option3' } ]; const user = userEvent.setup(); const onSelectMock = jest.fn(); render(); const toggle = screen.getByRole('button', { name: 'Filter by status' }); await user.click(toggle); const option1 = screen.getByRole('checkbox', { name: 'Option 1' }); await user.click(option1); expect(onSelectMock).toHaveBeenCalledTimes(1); expect(onSelectMock).toHaveBeenCalledWith(expect.anything(), 'option1'); }); test('does not call the onSelect callback when no options are selected', async () => { const initialOptions = [ { content: 'Option 1', value: 'option1' }, { content: 'Option 2', value: 'option2' }, { content: 'Option 3', value: 'option3' } ]; const user = userEvent.setup(); const onSelectMock = jest.fn(); render(); const toggle = screen.getByRole('button', { name: 'Filter by status' }); await user.click(toggle); expect(onSelectMock).not.toHaveBeenCalled(); }); test('toggles the select menu when the toggle button is clicked', async () => { const initialOptions = [ { content: 'Option 1', value: 'option1' }, { content: 'Option 2', value: 'option2' }, { content: 'Option 3', value: 'option3' } ]; const user = userEvent.setup(); render(); const toggleButton = screen.getByRole('button', { name: 'Filter by status' }); await user.click(toggleButton); expect(screen.getByRole('menu')).toBeInTheDocument(); await user.click(toggleButton); await waitForElementToBeRemoved(() => screen.queryByRole('menu')); expect(screen.queryByRole('menu')).not.toBeInTheDocument(); }); test('displays custom toggle content', async () => { const initialOptions = [ { content: 'Option 1', value: 'option1' }, { content: 'Option 2', value: 'option2' }, { content: 'Option 3', value: 'option3' } ]; render(); const toggleButton = screen.getByRole('button', { name: 'Custom Toggle' }); expect(toggleButton).toBeInTheDocument(); }); test('Passes toggleWidth', () => { const initialOptions = [ { content: 'Option 1', value: 'option1' }, { content: 'Option 2', value: 'option2' }, { content: 'Option 3', value: 'option3' } ]; render(); const toggleButton = screen.getByRole('button', { name: 'Custom Toggle' }); expect(toggleButton).toHaveAttribute('style', 'width: 500px;'); }); test('Passes additional toggleProps', () => { const initialOptions = [ { content: 'Option 1', value: 'option1' }, { content: 'Option 2', value: 'option2' }, { content: 'Option 3', value: 'option3' } ]; render( ); const toggleButton = screen.getByRole('button', { name: 'Custom Toggle' }); expect(toggleButton).toHaveAttribute('id', 'toggle'); }); test('calls the onToggle callback when the select opens or closes', async () => { const initialOptions = [ { content: 'Option 1', value: 'option1' }, { content: 'Option 2', value: 'option2' }, { content: 'Option 3', value: 'option3' } ]; const user = userEvent.setup(); const onToggleMock = jest.fn(); render(); const toggle = screen.getByRole('button', { name: 'Filter by status' }); await user.click(toggle); expect(onToggleMock).toHaveBeenCalledTimes(1); expect(onToggleMock).toHaveBeenCalledWith(true); await user.click(toggle); expect(onToggleMock).toHaveBeenCalledTimes(2); expect(onToggleMock).toHaveBeenCalledWith(false); }); test('does not call the onToggle callback when the toggle is not clicked', async () => { const initialOptions = [ { content: 'Option 1', value: 'option1' }, { content: 'Option 2', value: 'option2' }, { content: 'Option 3', value: 'option3' } ]; const onToggleMock = jest.fn(); render(); expect(onToggleMock).not.toHaveBeenCalled(); }); test('disables the select when isDisabled prop is true', async () => { const initialOptions = [ { content: 'Option 1', value: 'option1' }, { content: 'Option 2', value: 'option2' }, { content: 'Option 3', value: 'option3' } ]; const user = userEvent.setup(); render(); const toggleButton = screen.getByRole('button', { name: 'Filter by status' }); expect(toggleButton).toBeDisabled(); await user.click(toggleButton); expect(screen.queryByRole('menu')).not.toBeInTheDocument(); }); test('passes other SelectOption props to the SelectOption component', async () => { const initialOptions = [{ content: 'Option 1', value: 'option1', isDisabled: true }]; const user = userEvent.setup(); render(); const toggle = screen.getByRole('button', { name: 'Filter by status' }); await user.click(toggle); const option1 = screen.getByRole('checkbox', { name: 'Option 1' }); expect(option1).toBeDisabled(); }); test('displays the badge count when options are selected', async () => { const initialOptions = [ { content: 'Option 1', value: 'option1' }, { content: 'Option 2', value: 'option2' }, { content: 'Option 3', value: 'option3' } ]; const user = userEvent.setup(); render(); const toggle = screen.getByRole('button', { name: 'Filter by status' }); await user.click(toggle); const option1 = screen.getByRole('checkbox', { name: 'Option 1' }); expect(screen.queryByText('1')).not.toBeInTheDocument(); await user.click(option1); expect(screen.getByText('1')).toHaveClass(styles.badge, 'pf-m-read'); });