diff --git a/src/visits/VisitsStats.tsx b/src/visits/VisitsStats.tsx index 41e37d0a..f2ec12c2 100644 --- a/src/visits/VisitsStats.tsx +++ b/src/visits/VisitsStats.tsx @@ -235,7 +235,7 @@ export const VisitsStats: FC = ({ stats={cities} highlightedStats={highlightedVisitsToStats(highlightedVisits, 'city')} highlightedLabel={highlightedLabel} - extraHeaderContent={(activeCities: string[]) => mapLocations.length > 0 && ( + extraHeaderContent={(activeCities) => mapLocations.length > 0 && ( )} sortingItems={{ diff --git a/src/visits/charts/SortableBarChartCard.tsx b/src/visits/charts/SortableBarChartCard.tsx index 83219b73..8d43bdb3 100644 --- a/src/visits/charts/SortableBarChartCard.tsx +++ b/src/visits/charts/SortableBarChartCard.tsx @@ -1,4 +1,4 @@ -import { FC, useState } from 'react'; +import { FC, ReactNode, useState } from 'react'; import { fromPairs, pipe, reverse, sortBy, splitEvery, toLower, toPairs, type, zipObj } from 'ramda'; import { rangeOf } from '../../utils/utils'; import { Order } from '../../utils/helpers/ordering'; @@ -14,7 +14,7 @@ interface SortableBarChartCardProps extends Omit title: Function | string; sortingItems: Record; withPagination?: boolean; - extraHeaderContent?: Function; + extraHeaderContent?: (activeCities?: string[]) => ReactNode; } const toLowerIfString = (value: any) => (type(value) === 'String' ? toLower(value) : value); diff --git a/src/visits/helpers/MapModal.tsx b/src/visits/helpers/MapModal.tsx index 94dfa823..27296ff9 100644 --- a/src/visits/helpers/MapModal.tsx +++ b/src/visits/helpers/MapModal.tsx @@ -40,7 +40,7 @@ export const MapModal = ({ toggle, isOpen, title, locations = [] }: MapModalProp

{title} -

diff --git a/src/visits/helpers/OpenMapModalBtn.tsx b/src/visits/helpers/OpenMapModalBtn.tsx index c6b367e1..9d3032e7 100644 --- a/src/visits/helpers/OpenMapModalBtn.tsx +++ b/src/visits/helpers/OpenMapModalBtn.tsx @@ -9,7 +9,7 @@ import './OpenMapModalBtn.scss'; interface OpenMapModalBtnProps { modalTitle: string; - activeCities: string[]; + activeCities?: string[]; locations?: CityStats[]; } @@ -19,7 +19,9 @@ export const OpenMapModalBtn = ({ modalTitle, activeCities, locations = [] }: Op const [locationsToShow, setLocationsToShow] = useState([]); const id = useDomId(); - const filterLocations = (cities: CityStats[]) => cities.filter(({ cityName }) => activeCities.includes(cityName)); + const filterLocations = (cities: CityStats[]) => ( + !activeCities ? cities : cities.filter(({ cityName }) => activeCities?.includes(cityName)) + ); const onClick = () => { if (!activeCities) { setLocationsToShow(locations); diff --git a/test/common/SimplePaginator.test.tsx b/test/common/SimplePaginator.test.tsx index 128221d9..7b2c060a 100644 --- a/test/common/SimplePaginator.test.tsx +++ b/test/common/SimplePaginator.test.tsx @@ -9,7 +9,7 @@ describe('', () => { it.each([-3, -2, 0, 1])('renders empty when the amount of pages is smaller than 2', (pagesCount) => { const { container } = setUp(pagesCount); - expect(container.firstChild).toEqual(null); + expect(container.firstChild).toBeNull(); }); describe('ELLIPSIS are rendered where expected', () => { diff --git a/test/servers/reducers/selectedServer.test.ts b/test/servers/reducers/selectedServer.test.ts index f50a12ac..2074bcd3 100644 --- a/test/servers/reducers/selectedServer.test.ts +++ b/test/servers/reducers/selectedServer.test.ts @@ -14,7 +14,7 @@ import { NonReachableServer, NotFoundServer, RegularServer } from '../../../src/ describe('selectedServerReducer', () => { describe('reducer', () => { it('returns default when action is RESET_SELECTED_SERVER', () => - expect(reducer(null, { type: RESET_SELECTED_SERVER, selectedServer: null })).toEqual(null)); + expect(reducer(null, { type: RESET_SELECTED_SERVER, selectedServer: null })).toBeNull()); it('returns selected server when action is SELECT_SERVER', () => { const selectedServer = Mock.of({ id: 'abc123' }); diff --git a/test/utils/table/TableOrderIcon.test.tsx b/test/utils/table/TableOrderIcon.test.tsx index 8a4f72c9..03bc25e5 100644 --- a/test/utils/table/TableOrderIcon.test.tsx +++ b/test/utils/table/TableOrderIcon.test.tsx @@ -1,38 +1,29 @@ -import { shallow, ShallowWrapper } from 'enzyme'; -import { faCaretDown as caretDownIcon, faCaretUp as caretUpIcon } from '@fortawesome/free-solid-svg-icons'; +import { render } from '@testing-library/react'; import { TableOrderIcon } from '../../../src/utils/table/TableOrderIcon'; import { OrderDir } from '../../../src/utils/helpers/ordering'; describe('', () => { - let wrapper: ShallowWrapper; - const createWrapper = (field: string, currentDir?: OrderDir, className?: string) => { - wrapper = shallow( - , - ); - - return wrapper; - }; - - afterEach(() => wrapper?.unmount()); + const setUp = (field: string, currentDir?: OrderDir, className?: string) => render( + , + ); it.each([ ['foo', undefined], ['bar', 'DESC' as OrderDir], ['bar', 'ASC' as OrderDir], ])('renders empty when not all conditions are met', (field, dir) => { - const wrapper = createWrapper(field, dir); - - expect(wrapper.html()).toEqual(null); + const { container } = setUp(field, dir); + expect(container.firstChild).toBeNull(); }); it.each([ - ['DESC' as OrderDir, caretDownIcon], - ['ASC' as OrderDir, caretUpIcon], - ])('renders an icon when all conditions are met', (dir, expectedIcon) => { - const wrapper = createWrapper('foo', dir); + ['DESC' as OrderDir], + ['ASC' as OrderDir], + ])('renders an icon when all conditions are met', (dir) => { + const { container } = setUp('foo', dir); - expect(wrapper.html()).not.toEqual(null); - expect(wrapper.prop('icon')).toEqual(expectedIcon); + expect(container.firstChild).not.toBeNull(); + expect(container.firstChild).toMatchSnapshot(); }); it.each([ @@ -40,8 +31,7 @@ describe('', () => { ['foo', 'foo'], ['bar', 'bar'], ])('renders expected classname', (className, expectedClassName) => { - const wrapper = createWrapper('foo', 'ASC', className); - - expect(wrapper.prop('className')).toEqual(expectedClassName); + const { container } = setUp('foo', 'ASC', className); + expect(container.firstChild).toHaveClass(expectedClassName); }); }); diff --git a/test/utils/table/__snapshots__/TableOrderIcon.test.tsx.snap b/test/utils/table/__snapshots__/TableOrderIcon.test.tsx.snap new file mode 100644 index 00000000..ba31f4f9 --- /dev/null +++ b/test/utils/table/__snapshots__/TableOrderIcon.test.tsx.snap @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders an icon when all conditions are met 1`] = ` + +`; + +exports[` renders an icon when all conditions are met 2`] = ` + +`; diff --git a/test/visits/helpers/MapModal.test.tsx b/test/visits/helpers/MapModal.test.tsx index f582a582..2b053896 100644 --- a/test/visits/helpers/MapModal.test.tsx +++ b/test/visits/helpers/MapModal.test.tsx @@ -1,14 +1,9 @@ -import { shallow, ShallowWrapper } from 'enzyme'; -import { Marker, Popup } from 'react-leaflet'; -import { Modal } from 'reactstrap'; +import { render, screen } from '@testing-library/react'; import { MapModal } from '../../../src/visits/helpers/MapModal'; import { CityStats } from '../../../src/visits/types'; describe('', () => { - let wrapper: ShallowWrapper; - const toggle = () => ''; - const isOpen = true; - const title = 'Foobar'; + const toggle = jest.fn(); const zaragozaLat = 41.6563497; const zaragozaLong = -0.876566; const newYorkLat = 40.730610; @@ -26,36 +21,8 @@ describe('', () => { }, ]; - beforeEach(() => { - wrapper = shallow(); - }); - - afterEach(() => wrapper.unmount()); - - it('renders modal with provided props', () => { - const modal = wrapper.find(Modal); - const header = wrapper.find('.map-modal__modal-title'); - - expect(modal.prop('toggle')).toEqual(toggle); - expect(modal.prop('isOpen')).toEqual(isOpen); - expect(header.find('.btn-close').prop('onClick')).toEqual(toggle); - expect(header.text()).toContain(title); - }); - - it('renders open street map tile', () => { - expect(wrapper.find('OpenStreetMapTile')).toHaveLength(1); - }); - - it('renders proper amount of markers', () => { - const markers = wrapper.find(Marker); - - expect(markers).toHaveLength(locations.length); - locations.forEach(({ latLong, count, cityName }, index) => { - const marker = markers.at(index); - const popup = marker.find(Popup); - - expect(marker.prop('position')).toEqual(latLong); - expect(popup.text()).toEqual(`${count} visits from ${cityName}`); - }); + it('renders expected map', () => { + render(); + expect(screen.getByRole('dialog')).toMatchSnapshot(); }); }); diff --git a/test/visits/helpers/OpenMapModalBtn.test.tsx b/test/visits/helpers/OpenMapModalBtn.test.tsx index 89eea4fc..f33e67a8 100644 --- a/test/visits/helpers/OpenMapModalBtn.test.tsx +++ b/test/visits/helpers/OpenMapModalBtn.test.tsx @@ -1,61 +1,54 @@ -import { shallow, ShallowWrapper } from 'enzyme'; -import { Dropdown, DropdownItem, UncontrolledTooltip } from 'reactstrap'; +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { Mock } from 'ts-mockery'; import { OpenMapModalBtn } from '../../../src/visits/helpers/OpenMapModalBtn'; -import { MapModal } from '../../../src/visits/helpers/MapModal'; import { CityStats } from '../../../src/visits/types'; describe('', () => { - let wrapper: ShallowWrapper; const title = 'Foo'; const locations = [ - Mock.of({ cityName: 'foo', count: 30 }), - Mock.of({ cityName: 'bar', count: 45 }), + Mock.of({ cityName: 'foo', count: 30, latLong: [5, 5] }), + Mock.of({ cityName: 'bar', count: 45, latLong: [88, 88] }), ]; - const createWrapper = (activeCities: string[] = []) => { - wrapper = shallow(); - - return wrapper; - }; - - afterEach(() => wrapper?.unmount()); - - it('renders expected content', () => { - const wrapper = createWrapper(); - const button = wrapper.find('.open-map-modal-btn__btn'); - const tooltip = wrapper.find(UncontrolledTooltip); - const dropdown = wrapper.find(Dropdown); - const modal = wrapper.find(MapModal); - - expect(button).toHaveLength(1); - expect(tooltip).toHaveLength(1); - expect(dropdown).toHaveLength(1); - expect(modal).toHaveLength(1); + const setUp = (activeCities?: string[]) => ({ + user: userEvent.setup(), + ...render(), }); - it('opens dropdown instead of modal when a list of active cities has been provided', () => { - const wrapper = createWrapper(['bar']); + it('renders tooltip on button hover and opens modal on click', async () => { + const { user } = setUp(); - wrapper.find('.open-map-modal-btn__btn').simulate('click'); + expect(screen.queryByRole('tooltip')).not.toBeInTheDocument(); + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + expect(screen.queryByRole('menu')).not.toBeInTheDocument(); - expect(wrapper.find(Dropdown).prop('isOpen')).toEqual(true); - expect(wrapper.find(MapModal).prop('isOpen')).toEqual(false); + await user.click(screen.getByRole('button')); + await waitFor(() => expect(screen.getByRole('tooltip')).toBeInTheDocument()); + await waitFor(() => expect(screen.getByRole('dialog')).toBeInTheDocument()); + expect(screen.queryByRole('menu')).not.toBeInTheDocument(); }); - it('filters out non-active cities from list of locations', () => { - const wrapper = createWrapper(['bar']); + it('opens dropdown instead of modal when a list of active cities has been provided', async () => { + const { user } = setUp(['bar']); - wrapper.find('.open-map-modal-btn__btn').simulate('click'); - wrapper.find(Dropdown).find(DropdownItem).at(1).simulate('click'); + expect(screen.queryByRole('menu')).not.toBeInTheDocument(); + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); - const modal = wrapper.find(MapModal); + await user.click(screen.getByRole('button')); - expect(modal.prop('title')).toEqual(title); - expect(modal.prop('locations')).toEqual([ - { - cityName: 'bar', - count: 45, - }, - ]); + await waitFor(() => expect(screen.getByRole('menu')).toBeInTheDocument()); + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + }); + + it.each([ + ['Show all locations'], + ['Show locations in current page'], + ])('filters out non-active cities from list of locations', async (name) => { + const { user } = setUp(['bar']); + + await user.click(screen.getByRole('button')); + await user.click(screen.getByRole('menuitem', { name })); + + expect(await screen.findByRole('dialog')).toMatchSnapshot(); }); }); diff --git a/test/visits/helpers/__snapshots__/MapModal.test.tsx.snap b/test/visits/helpers/__snapshots__/MapModal.test.tsx.snap new file mode 100644 index 00000000..73591165 --- /dev/null +++ b/test/visits/helpers/__snapshots__/MapModal.test.tsx.snap @@ -0,0 +1,184 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders expected map 1`] = ` +