Skip to content

Commit

Permalink
chore: move autosuggest tests from Enzyme to RTL (#2611)
Browse files Browse the repository at this point in the history
Co-authored-by: Mena Hassan <mhassan@axim.org>
  • Loading branch information
cintnguyen and httpsmenahassan authored Sep 12, 2023
1 parent f75dfbc commit 23b83c5
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 112 deletions.
4 changes: 3 additions & 1 deletion src/Form/FormAutosuggest.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ function FormAutosuggest({
const iconToggle = (
<IconButton
className="pgn__form-autosuggest__icon-button"
data-testid="autosuggest_iconbutton"
src={isMenuClosed ? KeyboardArrowDown : KeyboardArrowUp}
iconAs={Icon}
size="sm"
Expand Down Expand Up @@ -230,6 +231,7 @@ function FormAutosuggest({
onChange={handleOnChange}
onClick={handleClick}
trailingElement={iconToggle}
data-testid="autosuggest_textbox_input"
{...props}
/>

Expand All @@ -253,7 +255,7 @@ function FormAutosuggest({
>
{isLoading ? (
<div className="pgn__form-autosuggest__dropdown-loading">
<Spinner animation="border" variant="dark" screenReaderText={screenReaderText} />
<Spinner animation="border" variant="dark" screenReaderText={screenReaderText} data-testid="autosuggest_loading_spinner" />
</div>
) : state.dropDownItems.length > 0 && state.dropDownItems}
</ul>
Expand Down
3 changes: 2 additions & 1 deletion src/Form/FormAutosuggestOption.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ function FormAutosuggestOption({
return (
<MenuItem
as="li"
data-testid="autosuggest_optionitem"
role="option"
tabindex="-1"
tabIndex="-1"
onClick={onClick}
className={classNames(className, 'dropdown-item')}
{...props}
Expand Down
245 changes: 135 additions & 110 deletions src/Form/tests/FormAutosuggest.test.jsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,12 @@
import React from 'react';
import { mount } from 'enzyme';
import { act } from 'react-dom/test-utils';
import PropTypes from 'prop-types';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import { IntlProvider } from 'react-intl';
import FormAutosuggest from '../FormAutosuggest';
import FormAutosuggestOption from '../FormAutosuggestOption';

const createDocumentListenersMock = () => {
const listeners = {};
const handler = (domEl, e) => listeners?.[e]?.({ target: domEl });

document.addEventListener = jest.fn((e, fn) => { listeners[e] = fn; });
document.removeEventListener = jest.fn(e => { delete listeners[e]; });

return {
click: domEl => handler(domEl, 'click'),
};
};

function FormAutosuggestWrapper(props) {
return (
<IntlProvider locale="en" messages={{}}>
Expand All @@ -25,141 +15,176 @@ function FormAutosuggestWrapper(props) {
);
}

describe('FormAutosuggest', () => {
afterEach(() => {
jest.clearAllMocks();
});

const onSelected = jest.fn();
const onClick = jest.fn();

const container = mount(
function FormAutosuggestTestComponent(props) {
return (
<FormAutosuggestWrapper
name="FormAutosuggest"
floatingLabel="floatingLabel text"
helpMessage="Example help message"
errorMessageText="Example error message"
onSelected={onSelected}
onSelected={props.onSelected}
>
<FormAutosuggestOption>Option 1</FormAutosuggestOption>
<FormAutosuggestOption onClick={onClick}>Option 2</FormAutosuggestOption>
<FormAutosuggestOption onClick={props.onClick}>Option 2</FormAutosuggestOption>
<FormAutosuggestOption>Learn from more than 160 member universities</FormAutosuggestOption>
</FormAutosuggestWrapper>,
</FormAutosuggestWrapper>
);
}

FormAutosuggestTestComponent.defaultProps = {
onSelected: jest.fn(),
onClick: jest.fn(),
};

FormAutosuggestTestComponent.propTypes = {
/** Specifies onSelected event handler. */
onSelected: PropTypes.func,
/** Specifies onClick event handler. */
onClick: PropTypes.func,
};

describe('render behavior', () => {
it('renders component without error', () => {
render(<FormAutosuggestWrapper />);
});

describe('render behavior', () => {
it('renders component without error', () => {
mount(<FormAutosuggestWrapper />);
});
it('renders without loading state', () => {
const { queryByTestId } = render(<FormAutosuggestTestComponent />);
const spinner = queryByTestId('autosuggest_loading_spinner');
expect(spinner).not.toBeInTheDocument();
});

it('render with loading state', () => {
const { queryByTestId } = render(<FormAutosuggestWrapper isLoading />);
const spinner = queryByTestId('autosuggest_loading_spinner');
expect(spinner).toBeInTheDocument();
});

it('render without loading state', () => {
expect(container.exists('.pgn__form-autosuggest__dropdown-loading')).toBe(false);
expect(container.props().isLoading).toBeUndefined();
});
it('renders the auto-populated value if it exists', () => {
render(<FormAutosuggestWrapper value="Test Value" />);
expect(screen.getByDisplayValue('Test Value')).toBeInTheDocument();
});

it('render with loading state', () => {
const wrapper = mount(<FormAutosuggestWrapper isLoading />);
it('renders component with options', () => {
const { getByTestId, queryAllByTestId } = render(<FormAutosuggestTestComponent />);
const input = getByTestId('autosuggest_textbox_input');
userEvent.click(input);
const list = queryAllByTestId('autosuggest_optionitem');
expect(list.length).toBe(3);
});

expect(wrapper.exists('.pgn__form-autosuggest__dropdown-loading')).toBe(true);
expect(wrapper.props().isLoading).toBe(true);
});
it('renders with error msg', () => {
const { getByText, getByTestId } = render(<FormAutosuggestTestComponent />);
const input = getByTestId('autosuggest_textbox_input');

it('renders the auto-populated value if it exists', () => {
const wrapper = mount(<FormAutosuggestWrapper value="Test Value" />);
// if you click into the input and click outside, you should see the error message
userEvent.click(input);
userEvent.click(document.body);

expect(wrapper.find('input').instance().value).toEqual('Test Value');
expect(wrapper.props().value).toEqual('Test Value');
});
const formControlFeedback = getByText('Example error message');

it('renders component with options', () => {
container.find('input').simulate('click');
const optionsList = container.find('.pgn__form-autosuggest__dropdown').find('li');
expect(formControlFeedback).toBeInTheDocument();
});
});

expect(optionsList.length).toEqual(3);
});
describe('controlled behavior', () => {
it('sets input value based on clicked option', () => {
const { getByText, getByTestId } = render(<FormAutosuggestTestComponent />);
const input = getByTestId('autosuggest_textbox_input');

it('renders with error msg', () => {
container.find('input').simulate('click');
act(() => {
const event = new Event('click', { bubbles: true });
document.dispatchEvent(event);
});
container.update();
const formControlFeedback = container.find('FormControlFeedback');
userEvent.click(input);
const menuItem = getByText('Option 1');
userEvent.click(menuItem);

expect(formControlFeedback.text()).toEqual('Example error message');
});
expect(input.value).toEqual('Option 1');
});

describe('controlled behavior', () => {
it('selects option', () => {
container.find('input').simulate('click');
container.find('.pgn__form-autosuggest__dropdown').find('li')
.at(0).simulate('click');
it('calls onSelected based on clicked option', () => {
const onSelected = jest.fn();
const { getByText, getByTestId } = render(<FormAutosuggestTestComponent onSelected={onSelected} />);
const input = getByTestId('autosuggest_textbox_input');

expect(container.find('input').instance().value).toEqual('Option 1');
expect(onSelected).toHaveBeenCalledWith('Option 1');
expect(onSelected).toHaveBeenCalledTimes(1);
});
userEvent.click(input);
const menuItem = getByText('Option 1');
userEvent.click(menuItem);

it('when a function is passed to onClick, it is called', () => {
container.find('input').simulate('change', { target: { value: 'Option 2' } });
container.find('.pgn__form-autosuggest__dropdown').find('li')
.at(0).simulate('click');
expect(onSelected).toHaveBeenCalledWith('Option 1');
expect(onSelected).toHaveBeenCalledTimes(1);
});

expect(onClick).toHaveBeenCalledTimes(1);
});
it('calls the function passed to onClick when an option with it is selected', () => {
const onClick = jest.fn();
const { getByText, getByTestId } = render(<FormAutosuggestTestComponent onClick={onClick} />);
const input = getByTestId('autosuggest_textbox_input');

it('when a function is not passed to onClick, it is not called', () => {
container.find('input').simulate('change', { target: { value: 'Option 1' } });
container.find('.pgn__form-autosuggest__dropdown').find('li')
.at(0).simulate('click');
userEvent.click(input);
const menuItem = getByText('Option 2');
userEvent.click(menuItem);

expect(onClick).toHaveBeenCalledTimes(0);
});
expect(onClick).toHaveBeenCalledTimes(1);
});

it('options list depends on empty field value', () => {
container.find('input').simulate('change', { target: { value: '' } });
it('does not call onClick when an option without it is selected', () => {
const onClick = jest.fn();
const { getByText, getByTestId } = render(<FormAutosuggestTestComponent onClick={onClick} />);
const input = getByTestId('autosuggest_textbox_input');

expect(container.find('input').instance().value).toEqual('');
});
userEvent.click(input);
const menuItem = getByText('Option 1');
userEvent.click(menuItem);

it('options list depends on filled field value', () => {
container.find('input').simulate('change', { target: { value: 'option 1' } });
expect(onClick).toHaveBeenCalledTimes(0);
});

expect(container.find('.pgn__form-autosuggest__dropdown').find('li').length).toEqual(1);
expect(onSelected).toHaveBeenCalledTimes(0);
});
it('filters dropdown based on typed field value with one match', () => {
const { getByTestId, queryAllByTestId } = render(<FormAutosuggestTestComponent />);
const input = getByTestId('autosuggest_textbox_input');

it('toggles options list', () => {
const dropdownContainer = '.pgn__form-autosuggest__dropdown';
userEvent.click(input);
userEvent.type(input, 'Option 1');

expect(container.find(dropdownContainer).find('li').length).toEqual(1);
const list = queryAllByTestId('autosuggest_optionitem');
expect(list.length).toBe(1);
});

container.find('button.pgn__form-autosuggest__icon-button').simulate('click');
expect(container.find(dropdownContainer).find('li').length).toEqual(0);
it('toggles options list', () => {
const { getByTestId, queryAllByTestId } = render(<FormAutosuggestTestComponent />);
const dropdownBtn = getByTestId('autosuggest_iconbutton');

container.find('button.pgn__form-autosuggest__icon-button').simulate('click');
expect(container.find(dropdownContainer).find('li').length).toEqual(1);
});
userEvent.click(dropdownBtn);
const list = queryAllByTestId('autosuggest_optionitem');
expect(list.length).toBe(3);

it('shows options list depends on field value', () => {
container.find('input').simulate('change', { target: { value: '1' } });
userEvent.click(dropdownBtn);
const updatedList = queryAllByTestId('autosuggest_optionitem');
expect(updatedList.length).toBe(0);

expect(container.find('.pgn__form-autosuggest__dropdown').find('li').length).toEqual(2);
});
userEvent.click(dropdownBtn);
const reopenedList = queryAllByTestId('autosuggest_optionitem');
expect(reopenedList.length).toBe(3);
});

it('closes options list on click outside', () => {
const fireEvent = createDocumentListenersMock();
const dropdownContainer = '.pgn__form-autosuggest__dropdown';
it('filters dropdown based on typed field value with multiple matches', () => {
const { getByTestId, queryAllByTestId } = render(<FormAutosuggestTestComponent />);
const input = getByTestId('autosuggest_textbox_input');

userEvent.click(input);
userEvent.type(input, '1');

const list = queryAllByTestId('autosuggest_optionitem');
expect(list.length).toBe(2);
});

container.find('input').simulate('click');
expect(container.find(dropdownContainer).find('li').length).toEqual(2);
it('closes options list on click outside', () => {
const { getByTestId, queryAllByTestId } = render(<FormAutosuggestTestComponent />);
const input = getByTestId('autosuggest_textbox_input');

act(() => { fireEvent.click(document.body); });
container.update();
userEvent.click(input);
const list = queryAllByTestId('autosuggest_optionitem');
expect(list.length).toBe(3);

expect(container.find(dropdownContainer).find('li').length).toEqual(0);
});
userEvent.click(document.body);
const updatedList = queryAllByTestId('autosuggest_optionitem');
expect(updatedList.length).toBe(0);
});
});

0 comments on commit 23b83c5

Please sign in to comment.