From 91ee4a32cd6c80fa20f9d7e2aaa7043f7f3b8750 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 8 Jul 2022 10:48:29 +0200 Subject: [PATCH] Migrated Tag test to react testing library --- src/tags/helpers/Tag.tsx | 2 +- test/tags/helpers/Tag.test.tsx | 68 +++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/src/tags/helpers/Tag.tsx b/src/tags/helpers/Tag.tsx index b61bc1b5..2e116a80 100644 --- a/src/tags/helpers/Tag.tsx +++ b/src/tags/helpers/Tag.tsx @@ -19,6 +19,6 @@ export const Tag: FC = ({ text, children, clearable, className = '', c onClick={onClick} > {children ?? text} - {clearable && ×} + {clearable && ×} ); diff --git a/test/tags/helpers/Tag.test.tsx b/test/tags/helpers/Tag.test.tsx index 11ecfc4e..ff17fdb7 100644 --- a/test/tags/helpers/Tag.test.tsx +++ b/test/tags/helpers/Tag.test.tsx @@ -1,29 +1,40 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { Mock } from 'ts-mockery'; -import { shallow, ShallowWrapper } from 'enzyme'; import { ReactNode } from 'react'; import { ColorGenerator } from '../../../src/utils/services/ColorGenerator'; import { MAIN_COLOR } from '../../../src/utils/theme'; import { Tag } from '../../../src/tags/helpers/Tag'; +const hexToRgb = (hex: string) => { + const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + if (!result) { + throw new Error((`Could not convert color ${hex} to RGB`)); + } + + return { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16), + }; +}; + describe('', () => { const onClick = jest.fn(); const onClose = jest.fn(); const isColorLightForKey = jest.fn(() => false); const getColorForKey = jest.fn(() => MAIN_COLOR); const colorGenerator = Mock.of({ getColorForKey, isColorLightForKey }); - let wrapper: ShallowWrapper; - const createWrapper = (text: string, clearable?: boolean, children?: ReactNode) => { - wrapper = shallow( + const setUp = (text: string, clearable?: boolean, children?: ReactNode) => ({ + user: userEvent.setup(), + ...render( {children} , - ); - - return wrapper; - }; + ), + }); afterEach(jest.clearAllMocks); - afterEach(() => wrapper?.unmount()); it.each([ [true], @@ -31,9 +42,13 @@ describe('', () => { ])('includes an extra class when the color is light', (isLight) => { isColorLightForKey.mockReturnValue(isLight); - const wrapper = createWrapper('foo'); + const { container } = setUp('foo'); - expect((wrapper.prop('className') as string).includes('tag--light-bg')).toEqual(isLight); + if (isLight) { + expect(container.firstChild).toHaveClass('tag--light-bg'); + } else { + expect(container.firstChild).not.toHaveClass('tag--light-bg'); + } }); it.each([ @@ -45,21 +60,25 @@ describe('', () => { ])('includes generated color as backgroundColor', (generatedColor) => { getColorForKey.mockReturnValue(generatedColor); - const wrapper = createWrapper('foo'); + const { container } = setUp('foo'); + const { r, g, b } = hexToRgb(generatedColor); - expect((wrapper.prop('style') as any).backgroundColor).toEqual(generatedColor); + expect(container.firstChild).toHaveAttribute( + 'style', + expect.stringContaining(`background-color: rgb(${r}, ${g}, ${b})`), + ); }); - it('invokes expected callbacks when appropriate events are triggered', () => { - const wrapper = createWrapper('foo', true); + it('invokes expected callbacks when appropriate events are triggered', async () => { + const { container, user } = setUp('foo', true); - expect(onClick).not.toBeCalled(); - expect(onClose).not.toBeCalled(); + expect(onClick).not.toHaveBeenCalled(); + expect(onClose).not.toHaveBeenCalled(); - wrapper.simulate('click'); + container.firstElementChild && await user.click(container.firstElementChild); expect(onClick).toHaveBeenCalledTimes(1); - wrapper.find('.tag__close-selected-tag').simulate('click'); + await user.click(screen.getByLabelText('Close')); expect(onClose).toHaveBeenCalledTimes(1); }); @@ -68,18 +87,17 @@ describe('', () => { [false, 0, 'pointer'], [undefined, 0, 'pointer'], ])('includes a close component when the tag is clearable', (clearable, expectedCloseBtnAmount, expectedCursor) => { - const wrapper = createWrapper('foo', clearable); + const { container } = setUp('foo', clearable); - expect(wrapper.find('.tag__close-selected-tag')).toHaveLength(expectedCloseBtnAmount); - expect((wrapper.prop('style') as any).cursor).toEqual(expectedCursor); + expect(screen.queryAllByLabelText('Close')).toHaveLength(expectedCloseBtnAmount); + expect(container.firstChild).toHaveAttribute('style', expect.stringContaining(`cursor: ${expectedCursor}`)); }); it.each([ [undefined, 'foo'], ['bar', 'bar'], ])('falls back to text as children when no children are provided', (children, expectedChildren) => { - const wrapper = createWrapper('foo', false, children); - - expect(wrapper.html()).toContain(`>${expectedChildren}`); + const { container } = setUp('foo', false, children); + expect(container.firstChild).toHaveTextContent(expectedChildren); }); });