Migrated Tag test to react testing library

This commit is contained in:
Alejandro Celaya 2022-07-08 10:48:29 +02:00
parent 498668929f
commit 91ee4a32cd
2 changed files with 44 additions and 26 deletions

View file

@ -19,6 +19,6 @@ export const Tag: FC<TagProps> = ({ text, children, clearable, className = '', c
onClick={onClick} onClick={onClick}
> >
{children ?? text} {children ?? text}
{clearable && <span className="close tag__close-selected-tag" onClick={onClose}>&times;</span>} {clearable && <span aria-label="Close" className="close tag__close-selected-tag" onClick={onClose}>&times;</span>}
</span> </span>
); );

View file

@ -1,29 +1,40 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Mock } from 'ts-mockery'; import { Mock } from 'ts-mockery';
import { shallow, ShallowWrapper } from 'enzyme';
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { ColorGenerator } from '../../../src/utils/services/ColorGenerator'; import { ColorGenerator } from '../../../src/utils/services/ColorGenerator';
import { MAIN_COLOR } from '../../../src/utils/theme'; import { MAIN_COLOR } from '../../../src/utils/theme';
import { Tag } from '../../../src/tags/helpers/Tag'; 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('<Tag />', () => { describe('<Tag />', () => {
const onClick = jest.fn(); const onClick = jest.fn();
const onClose = jest.fn(); const onClose = jest.fn();
const isColorLightForKey = jest.fn(() => false); const isColorLightForKey = jest.fn(() => false);
const getColorForKey = jest.fn(() => MAIN_COLOR); const getColorForKey = jest.fn(() => MAIN_COLOR);
const colorGenerator = Mock.of<ColorGenerator>({ getColorForKey, isColorLightForKey }); const colorGenerator = Mock.of<ColorGenerator>({ getColorForKey, isColorLightForKey });
let wrapper: ShallowWrapper; const setUp = (text: string, clearable?: boolean, children?: ReactNode) => ({
const createWrapper = (text: string, clearable?: boolean, children?: ReactNode) => { user: userEvent.setup(),
wrapper = shallow( ...render(
<Tag text={text} clearable={clearable} colorGenerator={colorGenerator} onClick={onClick} onClose={onClose}> <Tag text={text} clearable={clearable} colorGenerator={colorGenerator} onClick={onClick} onClose={onClose}>
{children} {children}
</Tag>, </Tag>,
); ),
});
return wrapper;
};
afterEach(jest.clearAllMocks); afterEach(jest.clearAllMocks);
afterEach(() => wrapper?.unmount());
it.each([ it.each([
[true], [true],
@ -31,9 +42,13 @@ describe('<Tag />', () => {
])('includes an extra class when the color is light', (isLight) => { ])('includes an extra class when the color is light', (isLight) => {
isColorLightForKey.mockReturnValue(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([ it.each([
@ -45,21 +60,25 @@ describe('<Tag />', () => {
])('includes generated color as backgroundColor', (generatedColor) => { ])('includes generated color as backgroundColor', (generatedColor) => {
getColorForKey.mockReturnValue(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', () => { it('invokes expected callbacks when appropriate events are triggered', async () => {
const wrapper = createWrapper('foo', true); const { container, user } = setUp('foo', true);
expect(onClick).not.toBeCalled(); expect(onClick).not.toHaveBeenCalled();
expect(onClose).not.toBeCalled(); expect(onClose).not.toHaveBeenCalled();
wrapper.simulate('click'); container.firstElementChild && await user.click(container.firstElementChild);
expect(onClick).toHaveBeenCalledTimes(1); expect(onClick).toHaveBeenCalledTimes(1);
wrapper.find('.tag__close-selected-tag').simulate('click'); await user.click(screen.getByLabelText('Close'));
expect(onClose).toHaveBeenCalledTimes(1); expect(onClose).toHaveBeenCalledTimes(1);
}); });
@ -68,18 +87,17 @@ describe('<Tag />', () => {
[false, 0, 'pointer'], [false, 0, 'pointer'],
[undefined, 0, 'pointer'], [undefined, 0, 'pointer'],
])('includes a close component when the tag is clearable', (clearable, expectedCloseBtnAmount, expectedCursor) => { ])('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(screen.queryAllByLabelText('Close')).toHaveLength(expectedCloseBtnAmount);
expect((wrapper.prop('style') as any).cursor).toEqual(expectedCursor); expect(container.firstChild).toHaveAttribute('style', expect.stringContaining(`cursor: ${expectedCursor}`));
}); });
it.each([ it.each([
[undefined, 'foo'], [undefined, 'foo'],
['bar', 'bar'], ['bar', 'bar'],
])('falls back to text as children when no children are provided', (children, expectedChildren) => { ])('falls back to text as children when no children are provided', (children, expectedChildren) => {
const wrapper = createWrapper('foo', false, children); const { container } = setUp('foo', false, children);
expect(container.firstChild).toHaveTextContent(expectedChildren);
expect(wrapper.html()).toContain(`>${expectedChildren}</span>`);
}); });
}); });