From 56a3dbd07fd270f20fa6c668245b148b941ff0ba Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Mon, 20 Sep 2021 20:32:54 +0200 Subject: [PATCH] Created EditTagModal test --- src/tags/helpers/EditTagModal.tsx | 22 ++--- test/tags/helpers/EditTagModal.test.tsx | 109 ++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 11 deletions(-) create mode 100644 test/tags/helpers/EditTagModal.test.tsx diff --git a/src/tags/helpers/EditTagModal.tsx b/src/tags/helpers/EditTagModal.tsx index 7cbd5169..e70875f1 100644 --- a/src/tags/helpers/EditTagModal.tsx +++ b/src/tags/helpers/EditTagModal.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { Modal, ModalBody, ModalFooter, ModalHeader, Popover } from 'reactstrap'; +import { Button, Input, Modal, ModalBody, ModalFooter, ModalHeader, Popover } from 'reactstrap'; import { ChromePicker } from 'react-color'; import { faPalette as colorIcon } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -25,10 +25,12 @@ const EditTagModal = ({ getColorForKey }: ColorGenerator) => ( const [ color, setColor ] = useState(getColorForKey(tag)); const [ showColorPicker, toggleColorPicker, , hideColorPicker ] = useToggle(); const { editing, error, errorData } = tagEdit; - const saveTag = handleEventPreventingDefault(async () => editTag(tag, newTagName, color) - .then(() => tagEdited(tag, newTagName, color)) - .then(toggle) - .catch(() => {})); + const saveTag = handleEventPreventingDefault( + async () => editTag(tag, newTagName, color) + .then(() => tagEdited(tag, newTagName, color)) + .then(toggle) + .catch(() => {}), + ); return ( @@ -47,13 +49,11 @@ const EditTagModal = ({ getColorForKey }: ColorGenerator) => ( setColor(hex)} /> - setNewTagName(e.target.value)} + onChange={({ target }) => setNewTagName(target.value)} /> @@ -64,8 +64,8 @@ const EditTagModal = ({ getColorForKey }: ColorGenerator) => ( )} - - + + diff --git a/test/tags/helpers/EditTagModal.test.tsx b/test/tags/helpers/EditTagModal.test.tsx new file mode 100644 index 00000000..d486fb53 --- /dev/null +++ b/test/tags/helpers/EditTagModal.test.tsx @@ -0,0 +1,109 @@ +import { shallow, ShallowWrapper } from 'enzyme'; +import { Mock } from 'ts-mockery'; +import { Button, Input, Modal, ModalHeader, Popover } from 'reactstrap'; +import { TagEdition } from '../../../src/tags/reducers/tagEdit'; +import createEditTagModal from '../../../src/tags/helpers/EditTagModal'; +import ColorGenerator from '../../../src/utils/services/ColorGenerator'; +import { Result } from '../../../src/utils/Result'; +import { ProblemDetailsError } from '../../../src/api/types'; +import { ShlinkApiError } from '../../../src/api/ShlinkApiError'; +import { ChromePicker } from 'react-color'; + +describe('', () => { + const EditTagModal = createEditTagModal(Mock.of({ getColorForKey: jest.fn(() => 'red') })); + const editTag = jest.fn().mockReturnValue(Promise.resolve()); + const tagEdited = jest.fn().mockReturnValue(Promise.resolve()); + const toggle = jest.fn(); + let wrapper: ShallowWrapper; + const createWrapper = (tagEdit: Partial = {}) => { + const edition = Mock.of(tagEdit); + + wrapper = shallow( + , + ); + + return wrapper; + }; + + afterEach(jest.clearAllMocks); + afterEach(() => wrapper?.unmount()); + + test('modal can be toggled with different mechanisms', () => { + const wrapper = createWrapper(); + 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(); + + (modal.prop('toggle') as Function)(); + (modalHeader.prop('toggle') as Function)(); + cancelBtn.simulate('click'); + + expect(toggle).toHaveBeenCalledTimes(3); + expect(editTag).not.toHaveBeenCalled(); + expect(tagEdited).not.toHaveBeenCalled(); + }); + + test.each([ + [ true, 'Saving...' ], + [ false, 'Save' ], + ])('submit button is rendered in expected state', (editing, expectedText) => { + const wrapper = createWrapper({ editing }); + const submitBtn = wrapper.find(Button).findWhere((btn) => btn.prop('color') === 'primary'); + + expect(submitBtn.html()).toContain(expectedText); + expect(submitBtn.prop('disabled')).toEqual(editing); + }); + + test.each([ + [ true, 1 ], + [ false, 0 ], + ])('error result is displayed in case of error', (error, expectedResultCount) => { + const wrapper = createWrapper({ error, errorData: Mock.all() }); + const result = wrapper.find(Result); + const apiError = wrapper.find(ShlinkApiError); + + expect(result).toHaveLength(expectedResultCount); + expect(apiError).toHaveLength(expectedResultCount); + }); + + test('tag value is updated when text changes', () => { + const wrapper = createWrapper(); + + expect(wrapper.find(Input).prop('value')).toEqual('foo'); + wrapper.find(Input).simulate('change', { target: { value: 'bar' } }); + expect(wrapper.find(Input).prop('value')).toEqual('bar'); + }); + + test('all functions are invoked on form submit', async () => { + const wrapper = createWrapper(); + const form = wrapper.find('form'); + + expect(editTag).not.toHaveBeenCalled(); + expect(tagEdited).not.toHaveBeenCalled(); + + await form.simulate('submit', { preventDefault: jest.fn() }); // eslint-disable-line @typescript-eslint/await-thenable + + expect(editTag).toHaveBeenCalled(); + expect(tagEdited).toHaveBeenCalled(); + }); + + test('color is changed when changing on color picker', () => { + const wrapper = createWrapper(); + + expect(wrapper.find(ChromePicker).prop('color')).toEqual('red'); + wrapper.find(ChromePicker).simulate('change', { hex: 'blue' }); + expect(wrapper.find(ChromePicker).prop('color')).toEqual('blue'); + }); + + test('popover can be toggled with different mechanisms', () => { + const wrapper = createWrapper(); + + 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('.input-group-prepend').simulate('click'); + expect(wrapper.find(Popover).prop('isOpen')).toEqual(false); + }); +});