import * as React from 'react'; import { configure, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { Select } from '../Select'; import { SelectOption, SelectOptionObject } from '../SelectOption'; import { SelectGroup } from '../SelectGroup'; import { SelectVariant, SelectDirection } from '../selectConstants'; import { KeyTypes } from '../../../../helpers'; class User implements SelectOptionObject { private firstName: string; private lastName: string; private title: string; constructor(title: string, firstName: string, lastName: string) { this.title = title; this.firstName = firstName; this.lastName = lastName; } toString = (): string => `${this.title}: ${this.firstName} ${this.lastName}`; compareTo = (value: string): boolean => this.toString().includes(value); } const selectOptions = [ , , , ]; const selectOptionsCustom = [ , , ]; // Update testId accessor since data-testid is not passed to the parent component of Select configure({ testIdAttribute: 'data-ouia-component-id' }); describe('Select', () => { describe('single select', () => { test('renders closed successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); test('renders disabled successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); test('renders expanded successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); test('renders expanded in strict mode successfully', () => { const consoleError = jest.spyOn(console, 'error'); const { asFragment } = render( ); expect(consoleError).not.toHaveBeenCalled(); expect(asFragment()).toMatchSnapshot(); }); test('renders expanded successfully with custom objects', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); }); test('renders up direction successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); describe('custom select filter', () => { test('filters properly', async () => { const customFilter = (e: React.ChangeEvent, value: string) => { let input: RegExp; try { input = new RegExp(e.target.value, 'i'); } catch (err) { input = new RegExp(e.target.value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i'); } const typeaheadFilteredChildren = e.target.value !== '' ? selectOptions.filter((child: React.ReactNode) => input.test((child as React.ReactElement).props.value)) : selectOptions; return typeaheadFilteredChildren; }; const user = userEvent.setup(); render( ); await user.type(screen.getByTestId('test-id').querySelector('input'), 'r'); expect(screen.getByText('Mr')).toBeInTheDocument(); expect(screen.getByText('Mrs')).toBeInTheDocument(); expect(screen.getByText('Other')).toBeInTheDocument(); }); }); test('renders select groups successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); }); test('renders select with favorites successfully', () => { const selectOptionsFavorites = [ , , , ]; const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); describe('checkbox select', () => { test('renders closed successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); test('renders checkbox select selections properly', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); test('renders checkbox select selections properly when isCheckboxSelectionBadgeHidden is true', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); test('renders expanded successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); test('renders expanded with filtering successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); test('renders expanded successfully with custom objects', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); test('renders checkbox select groups successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); }); describe('typeahead select', () => { test('renders closed successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); test('renders expanded successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); test('renders selected successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); test('test select existing option on a non-creatable select', async () => { const user = userEvent.setup(); render( ); const input = screen.getByTestId('test-id').querySelector('input'); await user.type(input, 'Other'); await user.type(input, `{${KeyTypes.Enter}}`); expect(screen.getByText('Other')).toBeVisible(); }); }); describe('typeahead multi select', () => { test('renders closed successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); test('renders expanded successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); test('renders selected successfully', () => { const { asFragment } = render( ); expect(asFragment()).toMatchSnapshot(); }); }); describe('API', () => { test('click on item', async () => { const mockToggle = jest.fn(); const mockSelect = jest.fn(); const user = userEvent.setup(); render( ); await user.click(screen.getByRole('option', { name: 'Mr' })); expect(mockToggle).not.toHaveBeenCalled(); expect(mockSelect).toHaveBeenCalled(); }); test('children only, no console error', () => { const myMock = jest.fn(); global.console = { ...global.console, error: myMock }; render( ); expect(myMock).not.toHaveBeenCalled(); }); }); describe('toggle icon', () => { const ToggleIcon =
Icon
; test('select single', () => { render( ); expect(screen.getByText('Icon')).toBeInTheDocument(); }); test('select checkbox', () => { render( ); expect(screen.getByText('Icon')).toBeInTheDocument(); }); test('typeahead select', () => { render( ); expect(screen.getByText('Icon')).toBeInTheDocument(); }); test('typeahead multi select', () => { render( ); expect(screen.getByText('Icon')).toBeInTheDocument(); }); }); describe('select with custom content', () => { test('renders closed successfully', () => { render(); expect(screen.getByText('testing custom')).toBeInTheDocument(); }); }); describe('select with placeholder', () => { test('applies the placeholder class when not selected', () => { render( ); expect(screen.getByRole('button', { name: 'Options menu' })).not.toHaveClass('pf-m-placeholder'); }); }); test('applies focus styling to the create option when reached via keyboard navigation', async () => { const user = userEvent.setup(); render( ); const input = screen.getByRole('textbox'); await user.type(input, `a{${KeyTypes.ArrowDown}}`); const createOption = screen.getByRole('option', { name: 'Create "a"' }); expect(createOption.parentElement).toHaveClass('pf-m-focus'); }); test('appends create option to list of options', async () => { const user = userEvent.setup(); render( ); const input = screen.getByRole('textbox'); await user.type(input, `m`); const createOption = screen.getAllByRole('option')[3]; expect(createOption).toHaveTextContent('Create "m"'); }); test('prepends create option to list of options if isCreateOptionOnTop flag is set', async () => { const user = userEvent.setup(); render( ); const input = screen.getByRole('textbox'); await user.type(input, `m`); const createOption = screen.getAllByRole('option')[0]; expect(createOption).toHaveTextContent('Create "m"'); });