Skip to content

Commit

Permalink
fix: ou item filter on App items was crashing Dashboards [DHIS2-9725] (
Browse files Browse the repository at this point in the history
…#1183)

The path is a property on the filter object. Added unit tests for the component
  • Loading branch information
jenniferarnesen committed Oct 19, 2020
1 parent 860104f commit 614a42f
Show file tree
Hide file tree
Showing 5 changed files with 443 additions and 9 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,16 @@
"devDependencies": {
"@dhis2/cli-app-scripts": "^5",
"@dhis2/cli-style": "^7.0.0",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"d2-manifest": "^1.0.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"enzyme-to-json": "^3.5.0",
"immutability-helper": "^3.1.1",
"patch-package": "^6.2.2",
"postinstall-postinstall": "^2.1.0"
"postinstall-postinstall": "^2.1.0",
"redux-mock-store": "^1.5.4"
},
"jest": {
"setupFilesAfterEnv": [
Expand Down
13 changes: 5 additions & 8 deletions src/components/Item/AppItem/Item.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,23 @@ import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import NotInterestedIcon from '@material-ui/icons/NotInterested'

import ItemHeader from '../ItemHeader/ItemHeader'
import Line from '../../../widgets/Line'

import { FILTER_ORG_UNIT } from '../../../actions/itemFilters'
import {
sGetItemFiltersRoot,
DEFAULT_STATE_ITEM_FILTERS,
} from '../../../reducers/itemFilters'
import ItemHeader from '../ItemHeader/ItemHeader'
import Line from '../../../widgets/Line'

import { isEditMode } from '../../Dashboard/dashboardModes'

const getIframeSrc = (appDetails, item, itemFilters) => {
let iframeSrc = `${appDetails.launchUrl}?dashboardItemId=${item.id}`

if (
itemFilters &&
itemFilters[FILTER_ORG_UNIT] &&
itemFilters[FILTER_ORG_UNIT].length
) {
if (itemFilters[FILTER_ORG_UNIT] && itemFilters[FILTER_ORG_UNIT].length) {
const ouIds = itemFilters[FILTER_ORG_UNIT].map(
ouPath => ouPath.split('/').slice(-1)[0]
ouFilter => ouFilter.path.split('/').slice(-1)[0]
)

iframeSrc += `&userOrgUnit=${ouIds.join(',')}`
Expand Down
117 changes: 117 additions & 0 deletions src/components/Item/AppItem/__tests__/Item.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import React from 'react'
import PropTypes from 'prop-types'
import { render } from '@testing-library/react'
import { Provider } from 'react-redux'
import configureMockStore from 'redux-mock-store'

import Item from '../Item'

const mockStore = configureMockStore()

const item = {
appKey: 'scorecard',
id: 'rainbowdash',
shortened: false,
}

test('renders a valid App item in view mode', () => {
const store = {
itemFilters: {},
}
const { container } = render(
<Provider store={mockStore(store)}>
<D2Provider>
<Item item={item} dashboardMode={'view'} />
</D2Provider>
</Provider>
)
expect(container).toMatchSnapshot()
})

test('renders a valid App item with filter in view mode', () => {
const store = {
itemFilters: {
ou: [{ path: '/rainbow' }],
},
}

const { container } = render(
<Provider store={mockStore(store)}>
<D2Provider>
<Item item={item} dashboardMode={'view'} />
</D2Provider>
</Provider>
)
expect(container).toMatchSnapshot()
})

test('renders a valid App item with filter in edit mode', () => {
const store = {
itemFilters: {
ou: [{ path: '/rainbow' }],
},
}

const { container } = render(
<Provider store={mockStore(store)}>
<D2Provider>
<Item item={item} dashboardMode={'edit'} />
</D2Provider>
</Provider>
)
expect(container).toMatchSnapshot()
})

test('renders an invalid App item', () => {
const store = {
itemFilters: {
ou: [{ path: '/rainbow' }],
},
}

const invalidItem = {
appKey: 'unknownApp',
id: 'unknown',
shortened: false,
}

const { container } = render(
<Provider store={mockStore(store)}>
<D2Provider>
<Item item={invalidItem} dashboardMode={'edit'} />
</D2Provider>
</Provider>
)
expect(container).toMatchSnapshot()
})

// Mock context provider
class D2Provider extends React.Component {
getChildContext() {
return {
d2: {
system: {
installedApps: [
{
key: 'scorecard',
name: 'Scorecard',
launchUrl: 'launchurl',
},
],
},
},
}
}

render() {
return this.props.children
}
}

D2Provider.childContextTypes = {
d2: PropTypes.object,
}

D2Provider.propTypes = {
children: PropTypes.node,
}
124 changes: 124 additions & 0 deletions src/components/Item/AppItem/__tests__/__snapshots__/Item.spec.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders a valid App item in view mode 1`] = `
<div>
<div
class="itemHeaderWrap"
>
<p
class="itemTitle"
>
Scorecard
</p>
</div>
<hr
style="background-color: rgb(243, 245, 247); height: 1px; margin: 0px 0px 5px 0px;"
/>
<iframe
class="dashboard-item-content"
src="launchurl?dashboardItemId=rainbowdash"
title="Scorecard"
/>
</div>
`;

exports[`renders a valid App item with filter in edit mode 1`] = `
<div>
<div
class="itemHeaderWrap"
>
<p
class="itemTitle"
>
Scorecard
</p>
<div
class="itemActionsWrap"
>
<button
class="deleteItemButton"
title="Delete item"
type="button"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-1"
focusable="false"
role="presentation"
style="fill: #d32f2f;"
viewBox="0 0 24 24"
>
<path
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"
/>
</svg>
</button>
</div>
</div>
<hr
style="background-color: rgb(243, 245, 247); height: 1px; margin: 0px 0px 5px 0px;"
/>
<iframe
class="dashboard-item-content"
src="launchurl?dashboardItemId=rainbowdash"
title="Scorecard"
/>
</div>
`;

exports[`renders a valid App item with filter in view mode 1`] = `
<div>
<div
class="itemHeaderWrap"
>
<p
class="itemTitle"
>
Scorecard
</p>
</div>
<hr
style="background-color: rgb(243, 245, 247); height: 1px; margin: 0px 0px 5px 0px;"
/>
<iframe
class="dashboard-item-content"
src="launchurl?dashboardItemId=rainbowdash&userOrgUnit=rainbow"
title="Scorecard"
/>
</div>
`;

exports[`renders an invalid App item 1`] = `
<div>
<div
class="itemHeaderWrap"
>
<p
class="itemTitle"
>
unknownApp app not found
</p>
</div>
<hr
style="background-color: rgb(243, 245, 247); height: 1px; margin: 0px 0px 5px 0px;"
/>
<div
class="dashboard-item-content"
style="display: flex; justify-content: center; align-items: center; height: 90%;"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-10 MuiSvgIcon-colorDisabled-15"
disabled=""
focusable="false"
role="presentation"
style="width: 100px; height: 100px;"
viewBox="0 0 24 24"
>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8 0-1.85.63-3.55 1.69-4.9L16.9 18.31C15.55 19.37 13.85 20 12 20zm6.31-3.1L7.1 5.69C8.45 4.63 10.15 4 12 4c4.42 0 8 3.58 8 8 0 1.85-.63 3.55-1.69 4.9z"
/>
</svg>
</div>
</div>
`;
Loading

0 comments on commit 614a42f

Please sign in to comment.