Skip to content

Commit

Permalink
chore: move autosuggest test from Enzyme to RTL
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 8, 2023
1 parent 9338f87 commit 47739c5
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 110 deletions.
1 change: 1 addition & 0 deletions src/Form/FormAutosuggest.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ function FormAutosuggest({
onChange={handleOnChange}
onClick={handleClick}
trailingElement={iconToggle}
data-testid="autosuggest_textbox_input"
{...props}
/>

Expand Down
2 changes: 1 addition & 1 deletion src/Form/FormAutosuggestOption.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function FormAutosuggestOption({
<MenuItem
as="li"
role="option"
tabindex="-1"
tabIndex="-1"
onClick={onClick}
className={classNames(className, 'dropdown-item')}
{...props}
Expand Down
245 changes: 136 additions & 109 deletions src/Form/tests/FormAutosuggest.test.jsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
import React from 'react';
import { mount } from 'enzyme';
import { act } from 'react-dom/test-utils';
import PropTypes from 'prop-types';
import { render, screen, fireEvent } from '@testing-library/react';
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 +14,179 @@ 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>
);
}

describe('render behavior', () => {
it('renders component without error', () => {
mount(<FormAutosuggestWrapper />);
});
FormAutosuggestTestComponent.defaultProps = {
onSelected: jest.fn(),
onClick: jest.fn(),
};

it('render without loading state', () => {
expect(container.exists('.pgn__form-autosuggest__dropdown-loading')).toBe(false);
expect(container.props().isLoading).toBeUndefined();
});
FormAutosuggestTestComponent.propTypes = {
/** Specifies onSelected event handler. */
onSelected: PropTypes.func,
/** Specifies onClick event handler. */
onClick: PropTypes.func,
};

it('render with loading state', () => {
const wrapper = mount(<FormAutosuggestWrapper isLoading />);
describe('render behavior', () => {
it('renders component without error', () => {
render(<FormAutosuggestWrapper />);
});

expect(wrapper.exists('.pgn__form-autosuggest__dropdown-loading')).toBe(true);
expect(wrapper.props().isLoading).toBe(true);
});
it('renders without loading state', () => {
const { container } = render(<FormAutosuggestTestComponent />);
expect(container.querySelector('.pgn__form-autosuggest__dropdown-loading')).toBeNull();
});

it('renders the auto-populated value if it exists', () => {
const wrapper = mount(<FormAutosuggestWrapper value="Test Value" />);
it('render with loading state', () => {
const { container } = render(<FormAutosuggestWrapper isLoading />);
expect(container.querySelector('.pgn__form-autosuggest__dropdown-loading')).toBeTruthy();
});

expect(wrapper.find('input').instance().value).toEqual('Test Value');
expect(wrapper.props().value).toEqual('Test Value');
});
it('renders the auto-populated value if it exists', () => {
render(<FormAutosuggestWrapper value="Test Value" />);
expect(screen.getByDisplayValue('Test Value')).toBeInTheDocument();
});

it('renders component with options', () => {
container.find('input').simulate('click');
const optionsList = container.find('.pgn__form-autosuggest__dropdown').find('li');
it('renders component with options', () => {
const { getByTestId, container } = render(<FormAutosuggestTestComponent />);
const input = getByTestId('autosuggest_textbox_input');
fireEvent.click(input);
const list = container.querySelectorAll('li');
expect(list.length).toBe(3);
});

expect(optionsList.length).toEqual(3);
it('renders with error msg', () => {
const { getByText, getByTestId } = render(<FormAutosuggestTestComponent />);
const input = getByTestId('autosuggest_textbox_input');

// if you click into the input and hit escape, you should see the error message
fireEvent.click(input);
fireEvent.keyDown(input, {
key: 'Escape',
code: 'Escape',
keyCode: 27,
charCode: 27,
});

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');
const formControlFeedback = getByText('Example error message');

expect(formControlFeedback.text()).toEqual('Example error message');
});
expect(formControlFeedback).toBeInTheDocument();
});
});

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

expect(container.find('input').instance().value).toEqual('Option 1');
expect(onSelected).toHaveBeenCalledWith('Option 1');
expect(onSelected).toHaveBeenCalledTimes(1);
});
fireEvent.click(input);
const menuItem = getByText('Option 1');
fireEvent.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(input.value).toEqual('Option 1');
});

expect(onClick).toHaveBeenCalledTimes(1);
});
it('calls onSelected based on clicked option', () => {
const onSelected = jest.fn();
const { getByText, getByTestId } = render(<FormAutosuggestTestComponent onSelected={onSelected} />);
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');
fireEvent.click(input);
const menuItem = getByText('Option 1');
fireEvent.click(menuItem);

expect(onClick).toHaveBeenCalledTimes(0);
});
expect(onSelected).toHaveBeenCalledWith('Option 1');
expect(onSelected).toHaveBeenCalledTimes(1);
});

it('options list depends on empty field value', () => {
container.find('input').simulate('change', { target: { value: '' } });
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');

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

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

expect(container.find('.pgn__form-autosuggest__dropdown').find('li').length).toEqual(1);
expect(onSelected).toHaveBeenCalledTimes(0);
});
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');

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

expect(container.find(dropdownContainer).find('li').length).toEqual(1);
expect(onClick).toHaveBeenCalledTimes(0);
});

container.find('button.pgn__form-autosuggest__icon-button').simulate('click');
expect(container.find(dropdownContainer).find('li').length).toEqual(0);
it('filters dropdown based on typed field value with one match', () => {
const { getByTestId, container } = render(<FormAutosuggestTestComponent />);
const input = getByTestId('autosuggest_textbox_input');

container.find('button.pgn__form-autosuggest__icon-button').simulate('click');
expect(container.find(dropdownContainer).find('li').length).toEqual(1);
});
fireEvent.click(input);
fireEvent.change(input, { target: { value: 'Option 1' } });

it('shows options list depends on field value', () => {
container.find('input').simulate('change', { target: { value: '1' } });
const list = container.querySelectorAll('li');
expect(list.length).toBe(1);
});

expect(container.find('.pgn__form-autosuggest__dropdown').find('li').length).toEqual(2);
});
it('toggles options list', () => {
const { container } = render(<FormAutosuggestTestComponent />);
const dropdownBtn = container.querySelector('button.pgn__form-autosuggest__icon-button');

it('closes options list on click outside', () => {
const fireEvent = createDocumentListenersMock();
const dropdownContainer = '.pgn__form-autosuggest__dropdown';
fireEvent.click(dropdownBtn);
const list = container.querySelectorAll('li');
expect(list.length).toBe(3);

container.find('input').simulate('click');
expect(container.find(dropdownContainer).find('li').length).toEqual(2);
fireEvent.click(dropdownBtn);
const updatedList = container.querySelectorAll('li');
expect(updatedList.length).toBe(0);

act(() => { fireEvent.click(document.body); });
container.update();
fireEvent.click(dropdownBtn);
const reopenedList = container.querySelectorAll('li');
expect(reopenedList.length).toBe(3);
});

expect(container.find(dropdownContainer).find('li').length).toEqual(0);
});
it('filters dropdown based on typed field value with multiple matches', () => {
const { getByTestId, container } = render(<FormAutosuggestTestComponent />);
const input = getByTestId('autosuggest_textbox_input');

fireEvent.click(input);
fireEvent.change(input, { target: { value: '1' } });

const list = container.querySelectorAll('li');
expect(list.length).toBe(2);
});

it('closes options list on click outside', () => {
const { getByTestId, container } = render(<FormAutosuggestTestComponent />);
const input = getByTestId('autosuggest_textbox_input');

fireEvent.click(input);
const list = container.querySelectorAll('li');
expect(list.length).toBe(3);

fireEvent.click(document.body);
const updatedList = container.querySelectorAll('li');
expect(updatedList.length).toBe(0);
});
});

0 comments on commit 47739c5

Please sign in to comment.