Migrated LineChartCard test to react testing library

This commit is contained in:
Alejandro Celaya 2022-05-28 12:54:33 +02:00
parent 89f830d9bb
commit 357c478640
4 changed files with 507 additions and 81 deletions

View file

@ -235,7 +235,7 @@ export const LineChartCard = (
return ( return (
<Card> <Card>
<CardHeader> <CardHeader role="heading">
{title} {title}
<div className="float-end"> <div className="float-end">
<UncontrolledDropdown> <UncontrolledDropdown>

View file

@ -4,7 +4,7 @@ import { render } from '@testing-library/react';
export const setUpCanvas = (element: ReactElement) => { export const setUpCanvas = (element: ReactElement) => {
const result = render(element); const result = render(element);
const { container } = result; const { container } = result;
const events = container.querySelector('canvas')?.getContext('2d')?.__getEvents(); // eslint-disable-line no-underscore-dangle const getEvents = () => container.querySelector('canvas')?.getContext('2d')?.__getEvents(); // eslint-disable-line no-underscore-dangle
return { ...result, events }; return { ...result, events: getEvents(), getEvents };
}; };

View file

@ -1,103 +1,68 @@
import { shallow, ShallowWrapper } from 'enzyme'; import { screen } from '@testing-library/react';
import { CardHeader, DropdownItem } from 'reactstrap'; import userEvent from '@testing-library/user-event';
import { Line } from 'react-chartjs-2';
import { formatISO, subDays, subMonths, subYears } from 'date-fns'; import { formatISO, subDays, subMonths, subYears } from 'date-fns';
import { Mock } from 'ts-mockery'; import { Mock } from 'ts-mockery';
import { LineChartCard } from '../../../src/visits/charts/LineChartCard'; import { LineChartCard } from '../../../src/visits/charts/LineChartCard';
import { ToggleSwitch } from '../../../src/utils/ToggleSwitch';
import { NormalizedVisit } from '../../../src/visits/types'; import { NormalizedVisit } from '../../../src/visits/types';
import { prettify } from '../../../src/utils/helpers/numbers'; import { setUpCanvas } from '../../__mocks__/setUpCanvas';
import { pointerOnHover, renderChartLabel } from '../../../src/utils/helpers/charts';
describe('<LineChartCard />', () => { describe('<LineChartCard />', () => {
let wrapper: ShallowWrapper; const setUp = (visits: NormalizedVisit[] = [], highlightedVisits: NormalizedVisit[] = []) => ({
const createWrapper = (visits: NormalizedVisit[] = [], highlightedVisits: NormalizedVisit[] = []) => { user: userEvent.setup(),
wrapper = shallow(<LineChartCard title="Cool title" visits={visits} highlightedVisits={highlightedVisits} />); ...setUpCanvas(<LineChartCard title="Cool title" visits={visits} highlightedVisits={highlightedVisits} />),
});
return wrapper;
};
afterEach(() => wrapper?.unmount());
it('renders provided title', () => { it('renders provided title', () => {
const wrapper = createWrapper(); setUp();
const header = wrapper.find(CardHeader); expect(screen.getByRole('heading')).toHaveTextContent('Cool title');
expect(header.html()).toContain('Cool title');
}); });
it.each([ it.each([
[[], 'monthly'], [[], 0],
[[{ date: formatISO(subDays(new Date(), 1)) }], 'hourly'], [[{ date: formatISO(subDays(new Date(), 1)) }], 3],
[[{ date: formatISO(subDays(new Date(), 3)) }], 'daily'], [[{ date: formatISO(subDays(new Date(), 3)) }], 2],
[[{ date: formatISO(subMonths(new Date(), 2)) }], 'weekly'], [[{ date: formatISO(subMonths(new Date(), 2)) }], 1],
[[{ date: formatISO(subMonths(new Date(), 6)) }], 'weekly'], [[{ date: formatISO(subMonths(new Date(), 6)) }], 1],
[[{ date: formatISO(subMonths(new Date(), 7)) }], 'monthly'], [[{ date: formatISO(subMonths(new Date(), 7)) }], 0],
[[{ date: formatISO(subYears(new Date(), 1)) }], 'monthly'], [[{ date: formatISO(subYears(new Date(), 1)) }], 0],
])('renders group menu and selects proper grouping item based on visits dates', (visits, expectedActiveItem) => { ])('renders group menu and selects proper grouping item based on visits dates', async (
const wrapper = createWrapper(visits.map((visit) => Mock.of<NormalizedVisit>(visit))); visits,
const items = wrapper.find(DropdownItem); expectedActiveIndex,
) => {
const { user } = setUp(visits.map((visit) => Mock.of<NormalizedVisit>(visit)));
await user.click(screen.getByRole('button', { name: /Group by/ }));
const items = screen.getAllByRole('menuitem');
expect(items).toHaveLength(4); expect(items).toHaveLength(4);
expect(items.at(0).prop('children')).toEqual('Month'); expect(items[0]).toHaveTextContent('Month');
expect(items.at(0).prop('active')).toEqual(expectedActiveItem === 'monthly'); expect(items[1]).toHaveTextContent('Week');
expect(items.at(1).prop('children')).toEqual('Week'); expect(items[2]).toHaveTextContent('Day');
expect(items.at(1).prop('active')).toEqual(expectedActiveItem === 'weekly'); expect(items[3]).toHaveTextContent('Hour');
expect(items.at(2).prop('children')).toEqual('Day'); expect(items[expectedActiveIndex]).toHaveAttribute('class', expect.stringContaining('active'));
expect(items.at(2).prop('active')).toEqual(expectedActiveItem === 'daily');
expect(items.at(3).prop('children')).toEqual('Hour');
expect(items.at(3).prop('active')).toEqual(expectedActiveItem === 'hourly');
});
it('renders chart with expected options', () => {
const wrapper = createWrapper();
const chart = wrapper.find(Line);
expect(chart.prop('options')).toEqual(expect.objectContaining({
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
intersect: false,
axis: 'x',
callbacks: { label: renderChartLabel },
},
},
scales: {
y: {
beginAtZero: true,
ticks: {
precision: 0,
callback: prettify,
},
},
x: {
title: { display: true, text: 'Month' },
},
},
onHover: pointerOnHover,
}));
}); });
it.each([ it.each([
[[Mock.of<NormalizedVisit>({ date: '2016-04-01' })], [], 1], [undefined, undefined],
[[Mock.of<NormalizedVisit>({ date: '2016-04-01' })], [Mock.of<NormalizedVisit>({ date: '2016-04-01' })], 2], [[], []],
])('renders chart with expected data', (visits, highlightedVisits, expectedLines) => { [[Mock.of<NormalizedVisit>({ date: '2016-04-01' })], []],
const wrapper = createWrapper(visits, highlightedVisits); [[Mock.of<NormalizedVisit>({ date: '2016-04-01' })], [Mock.of<NormalizedVisit>({ date: '2016-04-01' })]],
const chart = wrapper.find(Line); ])('renders chart with expected data', (visits, highlightedVisits) => {
const { datasets } = chart.prop('data') as any; const { events } = setUp(visits, highlightedVisits);
expect(datasets).toHaveLength(expectedLines); expect(events).toBeTruthy();
expect(events).toMatchSnapshot();
}); });
it('includes stats for visits with no dates if selected', () => { it('includes stats for visits with no dates if selected', async () => {
const wrapper = createWrapper([ const { getEvents, user } = setUp([
Mock.of<NormalizedVisit>({ date: '2016-04-01' }), Mock.of<NormalizedVisit>({ date: '2016-04-01' }),
Mock.of<NormalizedVisit>({ date: '2016-01-01' }), Mock.of<NormalizedVisit>({ date: '2016-01-01' }),
]); ]);
expect((wrapper.find(Line).prop('data') as any).labels).toHaveLength(2); const eventsBefore = getEvents();
wrapper.find(ToggleSwitch).simulate('change'); await user.click(screen.getByLabelText('Skip dates with no visits'));
expect((wrapper.find(Line).prop('data') as any).labels).toHaveLength(4); expect(eventsBefore).not.toEqual(getEvents());
}); });
}); });

View file

@ -0,0 +1,461 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<LineChartCard /> renders chart with expected data 1`] = `
Array [
Object {
"props": Object {
"a": 1,
"b": 0,
"c": 0,
"d": 1,
"e": 0,
"f": 0,
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "setTransform",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
Object {
"props": Object {
"text": "0",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "measureText",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
Object {
"props": Object {
"text": "1",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "measureText",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
]
`;
exports[`<LineChartCard /> renders chart with expected data 2`] = `
Array [
Object {
"props": Object {
"a": 1,
"b": 0,
"c": 0,
"d": 1,
"e": 0,
"f": 0,
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "setTransform",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
Object {
"props": Object {
"text": "0",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "measureText",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
Object {
"props": Object {
"text": "1",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "measureText",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
]
`;
exports[`<LineChartCard /> renders chart with expected data 3`] = `
Array [
Object {
"props": Object {
"a": 1,
"b": 0,
"c": 0,
"d": 1,
"e": 0,
"f": 0,
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "setTransform",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
Object {
"props": Object {
"text": "0",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "measureText",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
Object {
"props": Object {
"text": "1",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "measureText",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
Object {
"props": Object {
"text": "2016-04",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "measureText",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
]
`;
exports[`<LineChartCard /> renders chart with expected data 4`] = `
Array [
Object {
"props": Object {
"a": 1,
"b": 0,
"c": 0,
"d": 1,
"e": 0,
"f": 0,
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "setTransform",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
Object {
"props": Object {
"text": "0",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "measureText",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
Object {
"props": Object {
"text": "1",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "measureText",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
Object {
"props": Object {
"text": "2016-04",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "measureText",
},
Object {
"props": Object {
"value": "12px \\"Helvetica Neue\\", 'Helvetica', 'Arial', sans-serif",
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "font",
},
]
`;