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.queryByText('testing custom')).toBeNull();
});
test('renders expanded 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' })).toHaveClass('pf-m-placeholder');
});
test('does not apply the placeholder class when 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"');
});