Skip to content

Commit

Permalink
fix: dashboard crashes if an item is missing type [TECH-588] (#1812)
Browse files Browse the repository at this point in the history
One character fix in itemTypes.js

The rest is support for new cypress tests that mock a request with missing or unrecognized item types.

Look at view_errors.feature for a summary of what the new new cypress tests do. Some cypress changes are just moving functions to common so that all tests can access the function
  • Loading branch information
jenniferarnesen authored Jun 11, 2021
1 parent e732862 commit a200395
Show file tree
Hide file tree
Showing 13 changed files with 161 additions and 48 deletions.
8 changes: 7 additions & 1 deletion cypress/elements/dashboardItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ export const getDashboardItem = itemUid =>
cy.get(`[data-test="dashboarditem-${itemUid}"]`)

export const clickMenuButton = itemUid =>
getDashboardItem(itemUid).find(itemMenuButton).click()
getDashboardItem(itemUid).scrollIntoView().find(itemMenuButton).click()

export const clickItemDeleteButton = itemUid =>
getDashboardItem(itemUid)
.scrollIntoView()
.find('[data-test="delete-item-button"]')
.click()

//map

Expand Down
8 changes: 8 additions & 0 deletions cypress/integration/common/view/open_print_layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { When } from 'cypress-cucumber-preprocessor/steps'
import { clickViewActionButton } from '../../../elements/viewDashboard'

When('I click to preview the print layout', () => {
clickViewActionButton('More')
cy.get('[data-test="print-menu-item"]').click()
cy.get('[data-test="print-layout-menu-item"]').click()
})
12 changes: 12 additions & 0 deletions cypress/integration/common/view/print_layout_displays.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Then } from 'cypress-cucumber-preprocessor/steps'
import { dashboards } from '../../../assets/backends/sierraLeone_236'

Then('the print layout displays for {string} dashboard', title => {
//check the url
cy.location().should(loc => {
expect(loc.hash).to.equal(`${dashboards[title].route}/printlayout`)
})

//check for some elements
cy.get('[data-test="print-layout-page"]').should('be.visible')
})
16 changes: 0 additions & 16 deletions cypress/integration/view/view_dashboard/print.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,6 @@ import { When, Then } from 'cypress-cucumber-preprocessor/steps'
import { dashboards } from '../../../assets/backends/sierraLeone_236'
import { clickViewActionButton } from '../../../elements/viewDashboard'

When('I click to preview the print layout', () => {
clickViewActionButton('More')
cy.get('[data-test="print-menu-item"]').click()
cy.get('[data-test="print-layout-menu-item"]').click()
})

Then('the print layout displays for {string} dashboard', title => {
//check the url
cy.location().should(loc => {
expect(loc.hash).to.equal(`${dashboards[title].route}/printlayout`)
})

//check for some elements
cy.get('[data-test="print-layout-page"]').should('be.visible')
})

When('I click to exit print preview', () => {
cy.get('button').not('.small').contains('Exit print preview').click()
})
Expand Down
18 changes: 18 additions & 0 deletions cypress/integration/view/view_errors.feature
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,24 @@ Feature: Errors while in view mode
Then a warning message is displayed stating that starring dashboard failed
And the "Delivery" dashboard is not starred


Scenario: View dashboard containing item that is missing type
Given I open the Delivery dashboard with items missing a type
Then the "Delivery" dashboard displays in view mode
And the items missing type are displayed with a warning

Scenario: Edit dashboard containing item that is missing type
Given I open the Delivery dashboard with items missing a type
When I choose to edit dashboard
Then the items missing type are displayed with a warning
And I can delete the items

Scenario: Print dashboard containing item that is missing type
Given I open the Delivery dashboard with items missing a type
When I click to preview the print layout
Then the print layout displays for "Delivery" dashboard
And the items missing type are displayed with a warning

# TODO unflake this flaky test
# @nonmutating
# Scenario: Toggling show description fails
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Given, Then } from 'cypress-cucumber-preprocessor/steps'
import { EXTENDED_TIMEOUT } from '../../../support/utils'
import {
dashboardChipSel,
dashboardTitleSel,
} from '../../../elements/viewDashboard'
import {
getDashboardItem,
clickItemDeleteButton,
} from '../../../elements/dashboardItem'

const ITEM_1_UID = 'GaVhJpqABYX'
const ITEM_2_UID = 'qXsjttMYuoZ'
const ITEM_3_UID = 'Rwb3oXJ3bZ9'

const interceptDashboardRequest = () => {
cy.intercept(/dashboards\/iMnYyBfSxmM/, req => {
req.reply(res => {
// modify 3 items with different styles of "missing" type property
res.body.dashboardItems.find(
item => item.id === ITEM_1_UID
).type = null

const item = res.body.dashboardItems.find(
item => item.id === ITEM_2_UID
)

delete item.type

res.body.dashboardItems.find(item => item.id === ITEM_3_UID).type =
'Unrecognized'

res.send({ body: res.body })
})
})
}

Given('I open the Delivery dashboard with items missing a type', () => {
interceptDashboardRequest()
cy.get(dashboardChipSel, EXTENDED_TIMEOUT).contains('Delivery').click()
cy.get(dashboardTitleSel).should('be.visible').and('contain', 'Delivery')
})

Then('the items missing type are displayed with a warning', () => {
getDashboardItem(ITEM_1_UID)
.scrollIntoView()
.contains('The item type is missing')
.should('be.visible')

getDashboardItem(ITEM_2_UID)
.scrollIntoView()
.contains('The item type is missing')
.should('be.visible')

getDashboardItem(ITEM_3_UID)
.scrollIntoView()
.contains('Item type "Unrecognized" is not supported')
.should('be.visible')
})

Then('I can delete the items', () => {
clickItemDeleteButton(ITEM_1_UID)
clickItemDeleteButton(ITEM_2_UID)
clickItemDeleteButton(ITEM_3_UID)

getDashboardItem(ITEM_1_UID).should('not.exist')
getDashboardItem(ITEM_2_UID).should('not.exist')
getDashboardItem(ITEM_3_UID).should('not.exist')
})
11 changes: 7 additions & 4 deletions i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"POT-Creation-Date: 2021-05-12T08:56:39.093Z\n"
"PO-Revision-Date: 2021-05-12T08:56:39.093Z\n"
"POT-Creation-Date: 2021-06-10T10:08:47.318Z\n"
"PO-Revision-Date: 2021-06-10T10:08:47.318Z\n"

msgid "Untitled dashboard"
msgstr "Untitled dashboard"
Expand All @@ -23,8 +23,11 @@ msgstr "Messages"
msgid "See all messages"
msgstr "See all messages"

msgid "Item type \"{{type}}\" not supported"
msgstr "Item type \"{{type}}\" not supported"
msgid "Item type \"{{type}}\" is not supported"
msgstr "Item type \"{{type}}\" is not supported"

msgid "Item type is missing"
msgstr "Item type is missing"

msgid "Filters applied"
msgstr "Filters applied"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ exports[`renders a valid App item with filter in edit mode 1`] = `
>
<button
class="jsx-2371629422 secondary small icon-only"
data-test="dhis2-uicore-button"
data-test="delete-item-button"
type="button"
>
<span
Expand Down Expand Up @@ -119,7 +119,7 @@ exports[`renders a valid App item with title in edit mode irrespective of app se
>
<button
class="jsx-2371629422 secondary small icon-only"
data-test="dhis2-uicore-button"
data-test="delete-item-button"
type="button"
>
<span
Expand Down
1 change: 1 addition & 0 deletions src/components/Item/ItemHeader/DeleteItemButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const DeleteItemButton = ({ onClick }) => (
small
onClick={onClick}
icon={<IconDelete24 color={colors.red600} />}
dataTest="delete-item-button"
/>
</Tooltip>
)
Expand Down
51 changes: 29 additions & 22 deletions src/components/Item/NotSupportedItem/Item.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,35 @@ import i18n from '@dhis2/d2-i18n'
import { colors, IconQuestion24 } from '@dhis2/ui'
import ItemHeader from '../ItemHeader/ItemHeader'

const NotSupportedItem = props => (
<>
<ItemHeader
title={i18n.t('Item type "{{type}}" not supported', {
type: props.item.type,
})}
itemId={props.item.id}
dashboardMode={props.dashboardMode}
isShortened={props.item.shortened}
/>
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '90%',
}}
>
<IconQuestion24 color={colors.grey500} />
</div>
</>
)
const NotSupportedItem = ({ item, dashboardMode }) => {
const message = item.type
? i18n.t('Item type "{{type}}" is not supported', {
type: item.type,
})
: i18n.t('The item type is missing')

return (
<>
<ItemHeader
itemId={item.id}
dashboardMode={dashboardMode}
isShortened={item.shortened}
/>
<div
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: '90%',
}}
>
<p>{message}</p>
<IconQuestion24 color={colors.grey500} />
</div>
</>
)
}

NotSupportedItem.propTypes = {
dashboardMode: PropTypes.string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ exports[`Visualization/Item renders edit mode 1`] = `
>
<button
class="jsx-2371629422 secondary small icon-only"
data-test="dhis2-uicore-button"
data-test="delete-item-button"
type="button"
>
<span
Expand Down
3 changes: 2 additions & 1 deletion src/modules/itemTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const DOMAIN_TYPE_TRACKER = 'TRACKER'

// Dashboard helpers
export const isVisualizationType = item =>
!!itemTypeMap[item.type].isVisualizationType
!!itemTypeMap[item.type]?.isVisualizationType
export const hasMapView = itemType =>
itemTypeMap[itemType].domainType === DOMAIN_TYPE_AGGREGATE
export const isTrackerDomainType = itemType =>
Expand All @@ -51,6 +51,7 @@ export const itemTypeMap = {
endPointName: 'visualizations',
propName: 'visualization',
pluralTitle: i18n.t('Visualizations'),
isVisualizationType: true,
appUrl: id => `dhis-web-data-visualizer/#/${id}`,
appName: 'Data Visualizer',
defaultItemCount: 10,
Expand Down
6 changes: 5 additions & 1 deletion src/pages/print/PrintLayoutItemGrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ class PrintLayoutItemGrid extends Component {
})

return (
<div key={item.i} className={itemClassNames}>
<div
key={item.i}
className={itemClassNames}
data-test={`dashboarditem-${item.id}`}
>
<Item item={item} dashboardMode={PRINT_LAYOUT} />
</div>
)
Expand Down

0 comments on commit a200395

Please sign in to comment.