diff --git a/src/visits/charts/LineChartCard.tsx b/src/visits/charts/LineChartCard.tsx index 039afce5..a6e4b4ba 100644 --- a/src/visits/charts/LineChartCard.tsx +++ b/src/visits/charts/LineChartCard.tsx @@ -235,7 +235,7 @@ export const LineChartCard = ( return ( - + {title}
diff --git a/test/__mocks__/setUpCanvas.ts b/test/__mocks__/setUpCanvas.ts index 9308a25d..66c32b3b 100644 --- a/test/__mocks__/setUpCanvas.ts +++ b/test/__mocks__/setUpCanvas.ts @@ -4,7 +4,7 @@ import { render } from '@testing-library/react'; export const setUpCanvas = (element: ReactElement) => { const result = render(element); 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 }; }; diff --git a/test/visits/charts/LineChartCard.test.tsx b/test/visits/charts/LineChartCard.test.tsx index e77511d9..474f51fc 100644 --- a/test/visits/charts/LineChartCard.test.tsx +++ b/test/visits/charts/LineChartCard.test.tsx @@ -1,103 +1,68 @@ -import { shallow, ShallowWrapper } from 'enzyme'; -import { CardHeader, DropdownItem } from 'reactstrap'; -import { Line } from 'react-chartjs-2'; +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { formatISO, subDays, subMonths, subYears } from 'date-fns'; import { Mock } from 'ts-mockery'; import { LineChartCard } from '../../../src/visits/charts/LineChartCard'; -import { ToggleSwitch } from '../../../src/utils/ToggleSwitch'; import { NormalizedVisit } from '../../../src/visits/types'; -import { prettify } from '../../../src/utils/helpers/numbers'; -import { pointerOnHover, renderChartLabel } from '../../../src/utils/helpers/charts'; +import { setUpCanvas } from '../../__mocks__/setUpCanvas'; describe('', () => { - let wrapper: ShallowWrapper; - const createWrapper = (visits: NormalizedVisit[] = [], highlightedVisits: NormalizedVisit[] = []) => { - wrapper = shallow(); - - return wrapper; - }; - - afterEach(() => wrapper?.unmount()); + const setUp = (visits: NormalizedVisit[] = [], highlightedVisits: NormalizedVisit[] = []) => ({ + user: userEvent.setup(), + ...setUpCanvas(), + }); it('renders provided title', () => { - const wrapper = createWrapper(); - const header = wrapper.find(CardHeader); - - expect(header.html()).toContain('Cool title'); + setUp(); + expect(screen.getByRole('heading')).toHaveTextContent('Cool title'); }); it.each([ - [[], 'monthly'], - [[{ date: formatISO(subDays(new Date(), 1)) }], 'hourly'], - [[{ date: formatISO(subDays(new Date(), 3)) }], 'daily'], - [[{ date: formatISO(subMonths(new Date(), 2)) }], 'weekly'], - [[{ date: formatISO(subMonths(new Date(), 6)) }], 'weekly'], - [[{ date: formatISO(subMonths(new Date(), 7)) }], 'monthly'], - [[{ date: formatISO(subYears(new Date(), 1)) }], 'monthly'], - ])('renders group menu and selects proper grouping item based on visits dates', (visits, expectedActiveItem) => { - const wrapper = createWrapper(visits.map((visit) => Mock.of(visit))); - const items = wrapper.find(DropdownItem); + [[], 0], + [[{ date: formatISO(subDays(new Date(), 1)) }], 3], + [[{ date: formatISO(subDays(new Date(), 3)) }], 2], + [[{ date: formatISO(subMonths(new Date(), 2)) }], 1], + [[{ date: formatISO(subMonths(new Date(), 6)) }], 1], + [[{ date: formatISO(subMonths(new Date(), 7)) }], 0], + [[{ date: formatISO(subYears(new Date(), 1)) }], 0], + ])('renders group menu and selects proper grouping item based on visits dates', async ( + visits, + expectedActiveIndex, + ) => { + const { user } = setUp(visits.map((visit) => Mock.of(visit))); + + await user.click(screen.getByRole('button', { name: /Group by/ })); + + const items = screen.getAllByRole('menuitem'); expect(items).toHaveLength(4); - expect(items.at(0).prop('children')).toEqual('Month'); - expect(items.at(0).prop('active')).toEqual(expectedActiveItem === 'monthly'); - expect(items.at(1).prop('children')).toEqual('Week'); - expect(items.at(1).prop('active')).toEqual(expectedActiveItem === 'weekly'); - expect(items.at(2).prop('children')).toEqual('Day'); - 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, - })); + expect(items[0]).toHaveTextContent('Month'); + expect(items[1]).toHaveTextContent('Week'); + expect(items[2]).toHaveTextContent('Day'); + expect(items[3]).toHaveTextContent('Hour'); + expect(items[expectedActiveIndex]).toHaveAttribute('class', expect.stringContaining('active')); }); it.each([ - [[Mock.of({ date: '2016-04-01' })], [], 1], - [[Mock.of({ date: '2016-04-01' })], [Mock.of({ date: '2016-04-01' })], 2], - ])('renders chart with expected data', (visits, highlightedVisits, expectedLines) => { - const wrapper = createWrapper(visits, highlightedVisits); - const chart = wrapper.find(Line); - const { datasets } = chart.prop('data') as any; + [undefined, undefined], + [[], []], + [[Mock.of({ date: '2016-04-01' })], []], + [[Mock.of({ date: '2016-04-01' })], [Mock.of({ date: '2016-04-01' })]], + ])('renders chart with expected data', (visits, highlightedVisits) => { + 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', () => { - const wrapper = createWrapper([ + it('includes stats for visits with no dates if selected', async () => { + const { getEvents, user } = setUp([ Mock.of({ date: '2016-04-01' }), Mock.of({ date: '2016-01-01' }), ]); - expect((wrapper.find(Line).prop('data') as any).labels).toHaveLength(2); - wrapper.find(ToggleSwitch).simulate('change'); - expect((wrapper.find(Line).prop('data') as any).labels).toHaveLength(4); + const eventsBefore = getEvents(); + await user.click(screen.getByLabelText('Skip dates with no visits')); + expect(eventsBefore).not.toEqual(getEvents()); }); }); diff --git a/test/visits/charts/__snapshots__/LineChartCard.test.tsx.snap b/test/visits/charts/__snapshots__/LineChartCard.test.tsx.snap new file mode 100644 index 00000000..105b15cf --- /dev/null +++ b/test/visits/charts/__snapshots__/LineChartCard.test.tsx.snap @@ -0,0 +1,461 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 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[` 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[` 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[` 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", + }, +] +`;