diff --git a/cypress/integration/interpretations.cy.js b/cypress/integration/interpretations.cy.js index 7662150da..4a1e54abe 100644 --- a/cypress/integration/interpretations.cy.js +++ b/cypress/integration/interpretations.cy.js @@ -67,4 +67,33 @@ context('Interpretations', () => { deleteMap() }) + + it('opens and closes the interpretation panel', () => { + cy.intercept({ method: 'POST', url: /dataStatistics/ }).as( + 'postDataStatistics' + ) + cy.visit( + '/?id=ZBjCfSaLSqD&interpretationId=yKqhXZdeJ6a', + EXTENDED_TIMEOUT + ) //ANC: LLITN coverage district and facility + + cy.wait('@postDataStatistics') + .its('response.statusCode') + .should('eq', 201) + + cy.getByDataTest('interpretation-modal') + .find('h1') + .contains( + 'Viewing interpretation: ANC: LLITN coverage district and facility' + ) + .should('be.visible') + + cy.getByDataTest('interpretation-modal') + .findByDataTest('dhis2-modal-close-button') + .click() + + cy.getByDataTest('interpretation-modal').should('not.exist') + + cy.getByDataTest('interpretations-list').should('be.visible') + }) }) diff --git a/cypress/integration/smoke.cy.js b/cypress/integration/smoke.cy.js index 5a7ad16e3..be0d0f82d 100644 --- a/cypress/integration/smoke.cy.js +++ b/cypress/integration/smoke.cy.js @@ -38,4 +38,46 @@ context('Smoke Test', () => { Layer.validateCardTitle('ANC 1 Coverage') cy.get('canvas.maplibregl-canvas').should('be.visible') }) + + it('loads with map id and interpretationid lowercase', () => { + cy.intercept({ method: 'POST', url: /dataStatistics/ }).as( + 'postDataStatistics' + ) + cy.visit( + '/?id=ZBjCfSaLSqD&interpretationid=yKqhXZdeJ6a', + EXTENDED_TIMEOUT + ) //ANC: LLITN coverage district and facility + + cy.wait('@postDataStatistics') + .its('response.statusCode') + .should('eq', 201) + + cy.getByDataTest('interpretation-modal') + .find('h1') + .contains( + 'Viewing interpretation: ANC: LLITN coverage district and facility' + ) + .should('be.visible') + }) + + it('loads with map id and interpretationId uppercase', () => { + cy.intercept({ method: 'POST', url: /dataStatistics/ }).as( + 'postDataStatistics' + ) + cy.visit( + '/?id=ZBjCfSaLSqD&interpretationId=yKqhXZdeJ6a', + EXTENDED_TIMEOUT + ) //ANC: LLITN coverage district and facility + + cy.wait('@postDataStatistics') + .its('response.statusCode') + .should('eq', 201) + + cy.getByDataTest('interpretation-modal') + .find('h1') + .contains( + 'Viewing interpretation: ANC: LLITN coverage district and facility' + ) + .should('be.visible') + }) }) diff --git a/src/components/app/App.js b/src/components/app/App.js index 762d13b8a..7e8f8ca55 100644 --- a/src/components/app/App.js +++ b/src/components/app/App.js @@ -7,6 +7,7 @@ import { useDispatch } from 'react-redux' import { tSetAnalyticalObject } from '../../actions/analyticalObject.js' import { removeBingBasemaps, setBingMapsApiKey } from '../../actions/basemap.js' import { tSetExternalLayers } from '../../actions/externalLayers.js' +import { setInterpretation } from '../../actions/interpretations.js' import { tOpenMap } from '../../actions/map.js' import { CURRENT_AO_KEY } from '../../util/analyticalObject.js' import { getUrlParameter } from '../../util/requests.js' @@ -33,6 +34,15 @@ const App = () => { } else if (getUrlParameter('currentAnalyticalObject') === 'true') { await dispatch(tSetAnalyticalObject(currentAO)) } + + // analytics interpretation component uses camelcase + const interpretationId = + getUrlParameter('interpretationid') || + getUrlParameter('interpretationId') + + if (interpretationId) { + dispatch(setInterpretation(interpretationId)) + } } if (!isEmpty(systemSettings)) { diff --git a/src/components/app/DetailsPanel.js b/src/components/app/DetailsPanel.js index ddb88d10e..a5dee646a 100644 --- a/src/components/app/DetailsPanel.js +++ b/src/components/app/DetailsPanel.js @@ -9,17 +9,14 @@ import styles from './styles/DetailsPanel.module.css' const DetailsPanel = ({ interpretationsRenderCount }) => { const detailsPanelOpen = useSelector((state) => state.ui.rightPanelOpen) const viewOrgUnitProfile = useSelector((state) => state.orgUnitProfile) + const interpretationId = useSelector((state) => state.interpretation?.id) const getContent = () => { - if (!detailsPanelOpen) { - return null + if (interpretationId || (detailsPanelOpen && !viewOrgUnitProfile)) { + return } - return viewOrgUnitProfile ? ( - - ) : ( - - ) + return detailsPanelOpen ? : null } return ( diff --git a/src/components/app/__tests__/Detailspanel.spec.js b/src/components/app/__tests__/Detailspanel.spec.js new file mode 100644 index 000000000..6d6110eef --- /dev/null +++ b/src/components/app/__tests__/Detailspanel.spec.js @@ -0,0 +1,142 @@ +import { render } from '@testing-library/react' +import React from 'react' +import { Provider } from 'react-redux' +import configureMockStore from 'redux-mock-store' +import DetailsPanel from '../DetailsPanel.js' + +const mockStore = configureMockStore() + +jest.mock( + '../../interpretations/Interpretations.js', + () => + function MockInterpretations() { + return
Interpretations
+ } +) + +jest.mock( + '../../orgunits/OrgUnitProfile.js', + () => + function MockOrgUnitProfile() { + return
Org Unit Profile
+ } +) + +describe('DetailsPanel', () => { + test('renders InterpretationsPanel when has interpretationId, has orgUnitProfile and panel is open', () => { + const store = { + interpretation: { id: 'abc123' }, + orgUnitProfile: 'xyzpdq', + ui: { rightPanelOpen: true }, + } + + const { container } = render( + + + + ) + expect(container).toMatchSnapshot() + }) + test('renders InterpretationsPanel when has interpretationId, has orgUnitProfile and panel is closed', () => { + const store = { + interpretation: { id: 'abc123' }, + orgUnitProfile: 'xyzpdq', + ui: { rightPanelOpen: false }, + } + + const { container } = render( + + + + ) + expect(container).toMatchSnapshot() + }) + test('renders InterpretationsPanel when has interpretationId, no orgUnitProfile and panel is open', () => { + const store = { + interpretation: { id: 'abc123' }, + orgUnitProfile: null, + ui: { rightPanelOpen: true }, + } + + const { container } = render( + + + + ) + expect(container).toMatchSnapshot() + }) + + test('renders InterpretationsPanel when has interpretationId, no orgUnitProfile and panel is closed', () => { + const store = { + interpretation: { id: 'abc123' }, + orgUnitProfile: null, + ui: { rightPanelOpen: false }, + } + + const { container } = render( + + + + ) + expect(container).toMatchSnapshot() + }) + + test('renders OrgUnitProfile when no interpretationId, has orgUnitProfile and panel is open', () => { + const store = { + interpretation: {}, + orgUnitProfile: 'xyzpdq', + ui: { rightPanelOpen: true }, + } + + const { container } = render( + + + + ) + expect(container).toMatchSnapshot() + }) + + test('renders null when no interpretationId, has orgUnitProfile, and panel closed', () => { + const store = { + interpretation: {}, + orgUnitProfile: 'xyzpdq', + ui: { rightPanelOpen: false }, + } + + const { container } = render( + + + + ) + expect(container).toMatchSnapshot() + }) + test('renders InterpretationsPanel when no interpretationId, no orgUnitProfile and panel open', () => { + const store = { + interpretation: {}, + orgUnitProfile: null, + ui: { rightPanelOpen: true }, + } + + const { container } = render( + + + + ) + expect(container).toMatchSnapshot() + }) + + test('renders null when no interpretationId, no orgUnitProfile, and panel closed', () => { + const store = { + interpretation: {}, + orgUnitProfile: null, + ui: { rightPanelOpen: false }, + } + + const { container } = render( + + + + ) + expect(container).toMatchSnapshot() + }) +}) diff --git a/src/components/app/__tests__/__snapshots__/Detailspanel.spec.js.snap b/src/components/app/__tests__/__snapshots__/Detailspanel.spec.js.snap new file mode 100644 index 000000000..b45d254ce --- /dev/null +++ b/src/components/app/__tests__/__snapshots__/Detailspanel.spec.js.snap @@ -0,0 +1,89 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`DetailsPanel renders InterpretationsPanel when has interpretationId, has orgUnitProfile and panel is closed 1`] = ` +
+ +
+`; + +exports[`DetailsPanel renders InterpretationsPanel when has interpretationId, has orgUnitProfile and panel is open 1`] = ` +
+
+
+ Interpretations +
+
+
+`; + +exports[`DetailsPanel renders InterpretationsPanel when has interpretationId, no orgUnitProfile and panel is closed 1`] = ` +
+ +
+`; + +exports[`DetailsPanel renders InterpretationsPanel when has interpretationId, no orgUnitProfile and panel is open 1`] = ` +
+
+
+ Interpretations +
+
+
+`; + +exports[`DetailsPanel renders InterpretationsPanel when no interpretationId, no orgUnitProfile and panel open 1`] = ` +
+
+
+ Interpretations +
+
+
+`; + +exports[`DetailsPanel renders OrgUnitProfile when no interpretationId, has orgUnitProfile and panel is open 1`] = ` +
+
+
+ Org Unit Profile +
+
+
+`; + +exports[`DetailsPanel renders null when no interpretationId, has orgUnitProfile, and panel closed 1`] = ` +
+ +`; + +exports[`DetailsPanel renders null when no interpretationId, no orgUnitProfile, and panel closed 1`] = ` +
+ +`; diff --git a/src/components/interpretations/Interpretations.js b/src/components/interpretations/Interpretations.js index c937e5ef9..f3cf14087 100644 --- a/src/components/interpretations/Interpretations.js +++ b/src/components/interpretations/Interpretations.js @@ -1,9 +1,7 @@ import PropTypes from 'prop-types' import React, { useEffect } from 'react' import { useSelector, useDispatch } from 'react-redux' -import { setInterpretation } from '../../actions/interpretations.js' import { openInterpretationsPanel } from '../../actions/ui.js' -import { getUrlParameter } from '../../util/requests.js' import InterpretationsPanel from './InterpretationsPanel.js' const Interpretations = ({ renderCount }) => { @@ -15,15 +13,7 @@ const Interpretations = ({ renderCount }) => { useEffect(() => { if (isMapLoaded) { - // analytics interpretation component uses camelcase - const urlInterpretationId = - getUrlParameter('interpretationid') || - getUrlParameter('interpretationId') - - if (urlInterpretationId) { - dispatch(setInterpretation(urlInterpretationId)) - dispatch(openInterpretationsPanel()) - } + dispatch(openInterpretationsPanel()) } }, [isMapLoaded, dispatch])