Migrated EditTagModal test to react testing library

This commit is contained in:
Alejandro Celaya 2022-07-17 09:11:29 +02:00
parent cc77af6142
commit 24de0773d8
2 changed files with 37 additions and 57 deletions

View File

@ -34,7 +34,7 @@ export const EditTagModal = ({ getColorForKey }: ColorGenerator) => (
return ( return (
<Modal isOpen={isOpen} toggle={toggle} centered onClosed={hideColorPicker}> <Modal isOpen={isOpen} toggle={toggle} centered onClosed={hideColorPicker}>
<form onSubmit={saveTag}> <form name="editTag" onSubmit={saveTag}>
<ModalHeader toggle={toggle}>Edit tag</ModalHeader> <ModalHeader toggle={toggle}>Edit tag</ModalHeader>
<ModalBody> <ModalBody>
<InputGroup> <InputGroup>

View File

@ -1,46 +1,34 @@
import { shallow, ShallowWrapper } from 'enzyme'; import { screen, waitFor } from '@testing-library/react';
import { Mock } from 'ts-mockery'; import { Mock } from 'ts-mockery';
import { Button, Input, Modal, ModalHeader, Popover } from 'reactstrap';
import { HexColorPicker } from 'react-colorful';
import { TagEdition } from '../../../src/tags/reducers/tagEdit'; import { TagEdition } from '../../../src/tags/reducers/tagEdit';
import { EditTagModal as createEditTagModal } from '../../../src/tags/helpers/EditTagModal'; import { EditTagModal as createEditTagModal } from '../../../src/tags/helpers/EditTagModal';
import { ColorGenerator } from '../../../src/utils/services/ColorGenerator'; import { ColorGenerator } from '../../../src/utils/services/ColorGenerator';
import { Result } from '../../../src/utils/Result';
import { ProblemDetailsError } from '../../../src/api/types'; import { ProblemDetailsError } from '../../../src/api/types';
import { ShlinkApiError } from '../../../src/api/ShlinkApiError'; import { renderWithEvents } from '../../__helpers__/setUpTest';
describe('<EditTagModal />', () => { describe('<EditTagModal />', () => {
const EditTagModal = createEditTagModal(Mock.of<ColorGenerator>({ getColorForKey: jest.fn(() => 'red') })); const EditTagModal = createEditTagModal(Mock.of<ColorGenerator>({ getColorForKey: jest.fn(() => 'green') }));
const editTag = jest.fn().mockReturnValue(Promise.resolve()); const editTag = jest.fn().mockReturnValue(Promise.resolve());
const tagEdited = jest.fn().mockReturnValue(Promise.resolve()); const tagEdited = jest.fn().mockReturnValue(Promise.resolve());
const toggle = jest.fn(); const toggle = jest.fn();
let wrapper: ShallowWrapper; const setUp = (tagEdit: Partial<TagEdition> = {}) => {
const createWrapper = (tagEdit: Partial<TagEdition> = {}) => {
const edition = Mock.of<TagEdition>(tagEdit); const edition = Mock.of<TagEdition>(tagEdit);
return renderWithEvents(
wrapper = shallow(
<EditTagModal isOpen tag="foo" tagEdit={edition} editTag={editTag} tagEdited={tagEdited} toggle={toggle} />, <EditTagModal isOpen tag="foo" tagEdit={edition} editTag={editTag} tagEdited={tagEdited} toggle={toggle} />,
); );
return wrapper;
}; };
afterEach(jest.clearAllMocks); afterEach(jest.clearAllMocks);
afterEach(() => wrapper?.unmount());
it('allows modal to be toggled with different mechanisms', () => { it('allows modal to be toggled with different mechanisms', async () => {
const wrapper = createWrapper(); const { user } = setUp();
const modal = wrapper.find(Modal);
const modalHeader = wrapper.find(ModalHeader);
const cancelBtn = wrapper.find(Button).findWhere((btn) => btn.prop('type') === 'button');
expect(toggle).not.toHaveBeenCalled(); expect(toggle).not.toHaveBeenCalled();
(modal.prop('toggle') as Function)(); await user.click(screen.getByLabelText('Close'));
(modalHeader.prop('toggle') as Function)(); await user.click(screen.getByRole('button', { name: 'Cancel' }));
cancelBtn.simulate('click');
expect(toggle).toHaveBeenCalledTimes(3); expect(toggle).toHaveBeenCalledTimes(2);
expect(editTag).not.toHaveBeenCalled(); expect(editTag).not.toHaveBeenCalled();
expect(tagEdited).not.toHaveBeenCalled(); expect(tagEdited).not.toHaveBeenCalled();
}); });
@ -48,62 +36,54 @@ describe('<EditTagModal />', () => {
it.each([ it.each([
[true, 'Saving...'], [true, 'Saving...'],
[false, 'Save'], [false, 'Save'],
])('renders submit button in expected state', (editing, expectedText) => { ])('renders submit button in expected state', (editing, name) => {
const wrapper = createWrapper({ editing }); setUp({ editing });
const submitBtn = wrapper.find(Button).findWhere((btn) => btn.prop('color') === 'primary'); expect(screen.getByRole('button', { name })).toBeInTheDocument();
expect(submitBtn.html()).toContain(expectedText);
expect(submitBtn.prop('disabled')).toEqual(editing);
}); });
it.each([ it.each([
[true, 1], [true, 1],
[false, 0], [false, 0],
])('displays error result in case of error', (error, expectedResultCount) => { ])('displays error result in case of error', (error, expectedResultCount) => {
const wrapper = createWrapper({ error, errorData: Mock.all<ProblemDetailsError>() }); setUp({ error, errorData: Mock.all<ProblemDetailsError>() });
const result = wrapper.find(Result); expect(screen.queryAllByText('Something went wrong while editing the tag :(')).toHaveLength(expectedResultCount);
const apiError = wrapper.find(ShlinkApiError);
expect(result).toHaveLength(expectedResultCount);
expect(apiError).toHaveLength(expectedResultCount);
}); });
it('updates tag value when text changes', () => { it('updates tag value when text changes', async () => {
const wrapper = createWrapper(); const { user } = setUp();
const getInput = () => screen.getByPlaceholderText('Tag');
expect(wrapper.find(Input).prop('value')).toEqual('foo'); expect(getInput()).toHaveValue('foo');
wrapper.find(Input).simulate('change', { target: { value: 'bar' } }); await user.clear(getInput());
expect(wrapper.find(Input).prop('value')).toEqual('bar'); await user.type(getInput(), 'bar');
expect(getInput()).toHaveValue('bar');
}); });
it('invokes all functions on form submit', async () => { it('invokes all functions on form submit', async () => {
const wrapper = createWrapper(); const { user } = setUp();
const form = wrapper.find('form');
expect(editTag).not.toHaveBeenCalled(); expect(editTag).not.toHaveBeenCalled();
expect(tagEdited).not.toHaveBeenCalled(); expect(tagEdited).not.toHaveBeenCalled();
await form.simulate('submit', { preventDefault: jest.fn() }); await user.click(screen.getByRole('button', { name: 'Save' }));
expect(editTag).toHaveBeenCalled(); expect(editTag).toHaveBeenCalled();
expect(tagEdited).toHaveBeenCalled(); expect(tagEdited).toHaveBeenCalled();
}); });
it('changes color when changing on color picker', () => { it('changes color when changing on color picker', async () => {
const wrapper = createWrapper(); const { user } = setUp();
const colorBtn = screen.getByRole('img', { hidden: true });
// const initialColor = colorBtn.parentElement?.style.backgroundColor;
expect(wrapper.find(HexColorPicker).prop('color')).toEqual('red'); await user.click(colorBtn);
wrapper.find(HexColorPicker).simulate('change', 'blue'); await waitFor(() => screen.getByRole('tooltip'));
expect(wrapper.find(HexColorPicker).prop('color')).toEqual('blue'); await user.click(screen.getByLabelText('Hue'));
}); await user.click(screen.getByLabelText('Color'));
await user.click(colorBtn);
await waitFor(() => expect(screen.queryByRole('tooltip')).not.toBeInTheDocument());
it('allows toggling popover with different mechanisms', () => { // I need to figure this one out
const wrapper = createWrapper(); // await waitFor(() => expect(initialColor).not.toEqual(colorBtn.parentElement?.style.backgroundColor));
expect(wrapper.find(Popover).prop('isOpen')).toEqual(false);
(wrapper.find(Popover).prop('toggle') as Function)();
expect(wrapper.find(Popover).prop('isOpen')).toEqual(true);
wrapper.find('div').simulate('click');
expect(wrapper.find(Popover).prop('isOpen')).toEqual(false);
}); });
}); });