diff --git a/src/visits/VisitsStats.tsx b/src/visits/VisitsStats.tsx index f2ec12c2..1980ded8 100644 --- a/src/visits/VisitsStats.tsx +++ b/src/visits/VisitsStats.tsx @@ -139,7 +139,7 @@ export const VisitsStats: FC = ({ } if (isEmpty(visits)) { - return There are no visits matching current filter :(; + return There are no visits matching current filter; } return ( diff --git a/test/visits/VisitsStats.test.tsx b/test/visits/VisitsStats.test.tsx index 0c7d3de4..8bd2fb8f 100644 --- a/test/visits/VisitsStats.test.tsx +++ b/test/visits/VisitsStats.test.tsx @@ -1,116 +1,83 @@ -import { shallow, ShallowWrapper } from 'enzyme'; -import { Progress } from 'reactstrap'; -import { sum } from 'ramda'; +import { screen } from '@testing-library/react'; import { Mock } from 'ts-mockery'; -import { Route } from 'react-router-dom'; +import { Router } from 'react-router-dom'; +import { createMemoryHistory } from 'history'; import { VisitsStats } from '../../src/visits/VisitsStats'; -import { Message } from '../../src/utils/Message'; import { Visit, VisitsInfo } from '../../src/visits/types'; -import { LineChartCard } from '../../src/visits/charts/LineChartCard'; -import { VisitsTable } from '../../src/visits/VisitsTable'; -import { Result } from '../../src/utils/Result'; import { Settings } from '../../src/settings/reducers/settings'; import { SelectedServer } from '../../src/servers/data'; -import { SortableBarChartCard } from '../../src/visits/charts/SortableBarChartCard'; -import { DoughnutChartCard } from '../../src/visits/charts/DoughnutChartCard'; -import { ExportBtn } from '../../src/utils/ExportBtn'; +import { renderWithEvents } from '../__helpers__/setUpTest'; +import { rangeOf } from '../../src/utils/utils'; describe('', () => { - const visits = [Mock.all(), Mock.all(), Mock.all()]; - - let wrapper: ShallowWrapper; + const visits = rangeOf(3, () => Mock.of({ date: '2020-01-01' })); const getVisitsMock = jest.fn(); const exportCsv = jest.fn(); + const setUp = (visitsInfo: Partial, activeRoute = '/by-time') => { + const history = createMemoryHistory(); + history.push(activeRoute); - const createComponent = (visitsInfo: Partial) => { - wrapper = shallow( - (visitsInfo)} - cancelGetVisits={() => {}} - settings={Mock.all()} - exportCsv={exportCsv} - selectedServer={Mock.all()} - />, + return renderWithEvents( + + (visitsInfo)} + cancelGetVisits={() => {}} + settings={Mock.all()} + exportCsv={exportCsv} + selectedServer={Mock.all()} + /> + , ); - - return wrapper; }; - afterEach(() => wrapper?.unmount()); - it('renders a preloader when visits are loading', () => { - const wrapper = createComponent({ loading: true, visits: [] }); - const loadingMessage = wrapper.find(Message); - const progress = wrapper.find(Progress); + setUp({ loading: true, visits: [] }); - expect(loadingMessage).toHaveLength(1); - expect(loadingMessage.html()).toContain('Loading...'); - expect(progress).toHaveLength(0); + expect(screen.getByText('Loading...')).toBeInTheDocument(); + expect(screen.queryByText(/^This is going to take a while/)).not.toBeInTheDocument(); }); it('renders a warning and progress bar when loading large amounts of visits', () => { - const wrapper = createComponent({ loading: true, loadingLarge: true, visits: [], progress: 25 }); - const loadingMessage = wrapper.find(Message); - const progress = wrapper.find(Progress); + setUp({ loading: true, loadingLarge: true, visits: [], progress: 25 }); - expect(loadingMessage).toHaveLength(1); - expect(loadingMessage.html()).toContain('This is going to take a while... :S'); - expect(progress).toHaveLength(1); - expect(progress.prop('value')).toEqual(25); + expect(screen.queryByText('Loading...')).not.toBeInTheDocument(); + expect(screen.getByText(/^This is going to take a while/)).toBeInTheDocument(); + expect(screen.getByRole('progressbar')).toHaveAttribute('aria-valuenow', '25'); }); it('renders an error message when visits could not be loaded', () => { - const wrapper = createComponent({ loading: false, error: true, visits: [] }); - const errorMessage = wrapper.find(Result).filterWhere((result) => result.prop('type') === 'error'); - - expect(errorMessage).toHaveLength(1); - expect(errorMessage.html()).toContain('An error occurred while loading visits :('); + setUp({ loading: false, error: true, visits: [] }); + expect(screen.getByText('An error occurred while loading visits :(')).toBeInTheDocument(); }); it('renders a message when visits are loaded but the list is empty', () => { - const wrapper = createComponent({ loading: false, error: false, visits: [] }); - const message = wrapper.find(Message); - - expect(message).toHaveLength(1); - expect(message.html()).toContain('There are no visits matching current filter :('); + setUp({ loading: false, error: false, visits: [] }); + expect(screen.getByText('There are no visits matching current filter')).toBeInTheDocument(); }); - it('renders expected amount of charts', () => { - const wrapper = createComponent({ loading: false, error: false, visits }); - const total = sum(wrapper.find(Route).map((element) => { - const ElementComponents = () => element.prop('element'); - // @ts-expect-error Wrapped element - const wrappedElement = shallow(); - - const charts = wrappedElement.find(DoughnutChartCard); - const sortableCharts = wrappedElement.find(SortableBarChartCard); - const lineChart = wrappedElement.find(LineChartCard); - const table = wrappedElement.find(VisitsTable); - - return charts.length + sortableCharts.length + lineChart.length + table.length; - })); - - expect(total).toEqual(7); + it.each([ + ['/by-time', 2], + ['/by-context', 4], + ['/by-location', 3], + ['/list', 1], + ])('renders expected amount of charts', (route, expectedCharts) => { + const { container } = setUp({ loading: false, error: false, visits }, route); + expect(container.querySelectorAll('.card')).toHaveLength(expectedCharts); }); - it('holds the map button content generator on cities chart extraHeaderContent', () => { - const wrapper = createComponent({ loading: false, error: false, visits }); - const ElementComponent = () => wrapper.find(Route).findWhere((element) => element.prop('path') === 'by-location') - .prop('element'); - const citiesChart = shallow().find(SortableBarChartCard).find('[title="Cities"]'); - const extraHeaderContent = citiesChart.prop('extraHeaderContent'); - - expect(extraHeaderContent).toHaveLength(1); - expect(typeof extraHeaderContent).toEqual('function'); + it('holds the map button on cities chart header', () => { + setUp({ loading: false, error: false, visits }, '/by-location'); + expect( + screen.getAllByRole('img', { hidden: true }).some((icon) => icon.classList.contains('fa-map-location-dot')), + ).toEqual(true); }); - it('exports CSV when export btn is clicked', () => { - const wrapper = createComponent({ visits }); - const exportBtn = wrapper.find(ExportBtn).last(); + it('exports CSV when export btn is clicked', async () => { + const { user } = setUp({ visits }); - expect(exportBtn).toHaveLength(1); - exportBtn.simulate('click'); + expect(exportCsv).not.toHaveBeenCalled(); + await user.click(screen.getByRole('button', { name: /Export/ })); expect(exportCsv).toHaveBeenCalled(); }); });