diff --git a/src/visits/ShortUrlVisits.js b/src/visits/ShortUrlVisits.js index 1de3c183..c5b4ef99 100644 --- a/src/visits/ShortUrlVisits.js +++ b/src/visits/ShortUrlVisits.js @@ -12,9 +12,11 @@ import VisitsHeader from './VisitsHeader'; import GraphCard from './GraphCard'; import { shortUrlDetailType } from './reducers/shortUrlDetail'; import './ShortUrlVisits.scss'; -import OpenMapModalBtn from './helpers/OpenMapModalBtn'; -const ShortUrlVisits = ({ processStatsFromVisits }) => class ShortUrlVisits extends React.PureComponent { +const ShortUrlVisits = ( + { processStatsFromVisits }, + OpenMapModalBtn +) => class ShortUrlVisits extends React.PureComponent { static propTypes = { match: PropTypes.shape({ params: PropTypes.object, diff --git a/src/visits/helpers/OpenMapModalBtn.js b/src/visits/helpers/OpenMapModalBtn.js index 2289ee06..5d3ec58b 100644 --- a/src/visits/helpers/OpenMapModalBtn.js +++ b/src/visits/helpers/OpenMapModalBtn.js @@ -3,7 +3,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faMapMarkedAlt as mapIcon } from '@fortawesome/free-solid-svg-icons'; import { Dropdown, DropdownItem, DropdownMenu, UncontrolledTooltip } from 'reactstrap'; import * as PropTypes from 'prop-types'; -import MapModal from './MapModal'; import './OpenMapModalBtn.scss'; const propTypes = { @@ -12,52 +11,50 @@ const propTypes = { activeCities: PropTypes.arrayOf(PropTypes.string), }; -const OpenMapModalBtn = ({ modalTitle, locations = [], activeCities }) => { - const [ mapIsOpened, setMapIsOpened ] = useState(false); - const [ dropdownIsOpened, setDropdownIsOpened ] = useState(false); - const [ locationsToShow, setLocationsToShow ] = useState([]); +const OpenMapModalBtn = (MapModal) => { + const OpenMapModalBtn = ({ modalTitle, locations = [], activeCities }) => { + const [ mapIsOpened, setMapIsOpened ] = useState(false); + const [ dropdownIsOpened, setDropdownIsOpened ] = useState(false); + const [ locationsToShow, setLocationsToShow ] = useState([]); - const buttonRef = React.createRef(); - const filterLocations = (locations) => locations.filter(({ cityName }) => activeCities.includes(cityName)); - const toggleMap = () => setMapIsOpened(!mapIsOpened); - const onClick = () => { - if (mapIsOpened) { - setMapIsOpened(false); + const buttonRef = React.createRef(); + const filterLocations = (locations) => locations.filter(({ cityName }) => activeCities.includes(cityName)); + const toggleMap = () => setMapIsOpened(!mapIsOpened); + const onClick = () => { + if (!activeCities) { + setLocationsToShow(locations); + setMapIsOpened(true); - return; - } + return; + } - if (!activeCities) { - setLocationsToShow(locations); + setDropdownIsOpened(true); + }; + const openMapWithLocations = (filtered) => () => { + setLocationsToShow(filtered ? filterLocations(locations) : locations); setMapIsOpened(true); + }; - return; - } - - setDropdownIsOpened(true); - }; - const openMapWithLocations = (filtered) => () => { - setLocationsToShow(filtered ? filterLocations(locations) : locations); - setMapIsOpened(true); + return ( + + + buttonRef.current}>Show in map + setDropdownIsOpened(!dropdownIsOpened)} inNavbar> + + Show all locations + Show locations in current page + + + + + ); }; - return ( - - - buttonRef.current}>Show in map - setDropdownIsOpened(!dropdownIsOpened)} inNavbar> - - Show all locations - Show locations in current page - - - - - ); + OpenMapModalBtn.propTypes = propTypes; + + return OpenMapModalBtn; }; -OpenMapModalBtn.propTypes = propTypes; - export default OpenMapModalBtn; diff --git a/src/visits/services/provideServices.js b/src/visits/services/provideServices.js index 8dcc498a..6258adda 100644 --- a/src/visits/services/provideServices.js +++ b/src/visits/services/provideServices.js @@ -1,11 +1,15 @@ import ShortUrlVisits from '../ShortUrlVisits'; import { cancelGetShortUrlVisits, getShortUrlVisits } from '../reducers/shortUrlVisits'; import { getShortUrlDetail } from '../reducers/shortUrlDetail'; +import OpenMapModalBtn from '../helpers/OpenMapModalBtn'; +import MapModal from '../helpers/MapModal'; import * as visitsParser from './VisitsParser'; const provideServices = (bottle, connect) => { // Components - bottle.serviceFactory('ShortUrlVisits', ShortUrlVisits, 'VisitsParser'); + bottle.serviceFactory('OpenMapModalBtn', OpenMapModalBtn, 'MapModal'); + bottle.serviceFactory('MapModal', () => MapModal); + bottle.serviceFactory('ShortUrlVisits', ShortUrlVisits, 'VisitsParser', 'OpenMapModalBtn'); bottle.decorator('ShortUrlVisits', connect( [ 'shortUrlVisits', 'shortUrlDetail' ], [ 'getShortUrlVisits', 'getShortUrlDetail', 'cancelGetShortUrlVisits' ] diff --git a/test/visits/ShortUrlVisits.test.js b/test/visits/ShortUrlVisits.test.js index d485a984..29e1e932 100644 --- a/test/visits/ShortUrlVisits.test.js +++ b/test/visits/ShortUrlVisits.test.js @@ -104,6 +104,6 @@ describe('', () => { const extraHeaderContent = citiesGraph.prop('extraHeaderContent'); expect(extraHeaderContent).toHaveLength(1); - expect(typeof extraHeaderContent[0]).toEqual('function'); + expect(typeof extraHeaderContent).toEqual('function'); }); }); diff --git a/test/visits/helpers/OpenMapModalBtn.test.js b/test/visits/helpers/OpenMapModalBtn.test.js index 3548992b..895d9310 100644 --- a/test/visits/helpers/OpenMapModalBtn.test.js +++ b/test/visits/helpers/OpenMapModalBtn.test.js @@ -1,42 +1,97 @@ import React from 'react'; -import { shallow } from 'enzyme'; -import { UncontrolledTooltip } from 'reactstrap'; -import OpenMapModalBtn from '../../../src/visits/helpers/OpenMapModalBtn'; -import MapModal from '../../../src/visits/helpers/MapModal'; +import { mount } from 'enzyme'; +import { Dropdown, DropdownItem, UncontrolledTooltip } from 'reactstrap'; +import createOpenMapModalBtn from '../../../src/visits/helpers/OpenMapModalBtn'; describe('', () => { let wrapper; const title = 'Foo'; - const locations = []; + const locations = [ + { + cityName: 'foo', + count: 30, + }, + { + cityName: 'bar', + count: 45, + }, + ]; + const MapModal = () => ''; + const OpenMapModalBtn = createOpenMapModalBtn(MapModal); + const createWrapper = (activeCities) => { + wrapper = mount(); - beforeEach(() => { - wrapper = shallow(); - }); + return wrapper; + }; - afterEach(() => wrapper.unmount()); + afterEach(() => wrapper && wrapper.unmount()); - it('Renders expected content', () => { + 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); }); - it('changes modal visibility when toggled', () => { - const modal = wrapper.find(MapModal); + it('sets provided props to the map', (done) => { + const wrapper = createWrapper(); + const button = wrapper.find('.open-map-modal-btn__btn'); - expect(wrapper.state('mapIsOpened')).toEqual(false); - modal.prop('toggle')(); - expect(wrapper.state('mapIsOpened')).toEqual(true); + button.simulate('click'); + setImmediate(() => { + const modal = wrapper.find(MapModal); + + expect(modal.prop('title')).toEqual(title); + expect(modal.prop('locations')).toEqual(locations); + expect(modal.prop('isOpen')).toEqual(true); + done(); + }); }); - it('sets provided props to the map', () => { - const modal = wrapper.find(MapModal); + it('opens dropdown instead of modal when a list of active cities has been provided', (done) => { + const wrapper = createWrapper([ 'bar' ]); + const button = wrapper.find('.open-map-modal-btn__btn'); - expect(modal.prop('title')).toEqual(title); - expect(modal.prop('locations')).toEqual(locations); + button.simulate('click'); + + setImmediate(() => { + const dropdown = wrapper.find(Dropdown); + const modal = wrapper.find(MapModal); + + expect(dropdown.prop('isOpen')).toEqual(true); + expect(modal.prop('isOpen')).toEqual(false); + done(); + }); + }); + + it('filters out non-active cities from list of locations', (done) => { + const wrapper = createWrapper([ 'bar' ]); + const button = wrapper.find('.open-map-modal-btn__btn'); + + button.simulate('click'); + setImmediate(() => { + const dropdown = wrapper.find(Dropdown); + const item = dropdown.find(DropdownItem).at(1); + + item.simulate('click'); + setImmediate(() => { + const modal = wrapper.find(MapModal); + + expect(modal.prop('title')).toEqual(title); + expect(modal.prop('locations')).toEqual([ + { + cityName: 'bar', + count: 45, + }, + ]); + done(); + }); + }); }); });