Skip to content

Commit

Permalink
Merge pull request #1074 from GSA/980-cypress-axe
Browse files Browse the repository at this point in the history
980 cypress axe
  • Loading branch information
scottqueen-bixal authored Mar 15, 2024
2 parents d81df1c + 0b8ca21 commit 65fbcd7
Show file tree
Hide file tree
Showing 13 changed files with 740 additions and 1,480 deletions.
4 changes: 1 addition & 3 deletions benefit-finder/.storybook/preview-body.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,4 @@
style="display: none; visibility: hidden"
></iframe
></noscript>
<a href="#skip-to-h1" class="usa-skipnav usa-sr-only focusable">
Skip to main content
</a>
<a href="#skip-to-h1" class="usa-skipnav usa-sr-only"> Skip to main content </a>
8 changes: 5 additions & 3 deletions benefit-finder/.storybook/preview.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import '../build/assets/benefit-finder.min.css'
export default {
decorators: [
Story => (
<div id="benefit-finder">
<Story />
</div>
<main>
<div id="benefit-finder">
<Story />
</div>
</main>
),
],
parameters: {
Expand Down
15 changes: 15 additions & 0 deletions benefit-finder/cypress.config.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
/* eslint-disable no-console */
const { defineConfig } = require('cypress')

module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:6006',
excludeSpecPattern: 'cypress/e2e/usagov-public-site/*.cy.js',
setupNodeEvents(on, config) {
on('task', {
log(message) {
console.log(message)

return null
},
table(message) {
console.table(message)

return null
},
})
},
},
component: {
devServer: {
Expand Down
138 changes: 138 additions & 0 deletions benefit-finder/cypress/e2e/storybook/axe-a11y.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/// <reference types="cypress" />

import * as utils from '../../support/utils.js'
import * as EN_LOCALE_DATA from '../../../../benefit-finder/src/shared/locales/en/en.json'
import * as EN_DOLO_MOCK_DATA from '../../../../benefit-finder/src/shared/api/mock-data/current.json'
import { pageObjects } from '../../support/pageObjects'

function terminalLog(violations) {
cy.task(
'log',
`${violations.length} accessibility violation${
violations.length === 1 ? '' : 's'
} ${violations.length === 1 ? 'was' : 'were'} detected`
)
// pluck specific keys to keep the table readable
const violationData = violations.map(
({ id, impact, description, nodes }) => ({
id,
impact,
description,
nodes: nodes.length,
})
)

cy.task('table', violationData)
}

const dob = utils.getDateByOffset(-(18 * 365.2425 - 1))
const dod = utils.getDateByOffset(-(18 * 365.2425 - 1))
const relation =
EN_DOLO_MOCK_DATA.data.lifeEventForm.sectionsEligibilityCriteria[0].section
.fieldsets[1].fieldset.inputs[0].inputCriteria.values[1].value
const status =
EN_DOLO_MOCK_DATA.data.lifeEventForm.sectionsEligibilityCriteria[0].section
.fieldsets[2].fieldset.inputs[0].inputCriteria.values[1].value

describe(`Validate code passes axe scanning`, () => {
const runA11y = (skipFailOnError = null) => {
cy.checkA11y(
null,
{
retries: 3,
interval: 100,
},
terminalLog,
skipFailOnError
)
}

beforeEach(() => {
cy.visit(utils.storybookUri)
cy.injectAxe()
})

it('Has no detectable a11y violations on load', () => {
// Test the page at initial load
pageObjects.button().contains(EN_LOCALE_DATA.intro.button) // wait for button to load
runA11y()
})

// go to first step
it('Has no detectable a11y violations on step 1', () => {
pageObjects.button().contains(EN_LOCALE_DATA.intro.button).click()
runA11y()
})

// create an error
it('Has no detectable a11y violations on error state', () => {
pageObjects.button().contains(EN_LOCALE_DATA.intro.button).click()
pageObjects.button().contains(EN_LOCALE_DATA.buttonGroup[1].value).click()
runA11y({ skipFailOnError: true }) // remove skip after https://github.com/GSA/px-benefit-finder/issues/1072 is resolved
})

it('Has no detectable a11y violations on error state resolved', () => {
pageObjects.button().contains(EN_LOCALE_DATA.intro.button).click()
utils.dataInputs({ dob, relation, status })
runA11y()
})

it('Has no detectable a11y violations on step 2', () => {
pageObjects.button().contains(EN_LOCALE_DATA.intro.button).click()
utils.dataInputs({ dob, relation, status })
pageObjects.button().contains(EN_LOCALE_DATA.buttonGroup[1].value).click()
runA11y()
})

it('Has no detectable a11y violations on modal launch', () => {
pageObjects.button().contains(EN_LOCALE_DATA.intro.button).click()
utils.dataInputs({ dob, relation, status })
pageObjects.button().contains(EN_LOCALE_DATA.buttonGroup[1].value).click()
utils.dataInputs({ dod })
pageObjects.button().contains(EN_LOCALE_DATA.buttonGroup[1].value).click()
runA11y()
})

it('Has no detectable a11y violations on modal close review selections', () => {
pageObjects.button().contains(EN_LOCALE_DATA.intro.button).click()
utils.dataInputs({ dob, relation, status })
pageObjects.button().contains(EN_LOCALE_DATA.buttonGroup[1].value).click()
utils.dataInputs({ dod })
pageObjects.button().contains(EN_LOCALE_DATA.buttonGroup[1].value).click()
pageObjects
.button()
.contains(EN_LOCALE_DATA.reviewSelectionModal.buttonGroup[0].value)
.click()
runA11y()
})

it('Has no detectable a11y violations on see benefits', () => {
pageObjects.button().contains(EN_LOCALE_DATA.intro.button).click()
utils.dataInputs({ dob, relation, status })
pageObjects.button().contains(EN_LOCALE_DATA.buttonGroup[1].value).click()
utils.dataInputs({ dod })
pageObjects.button().contains(EN_LOCALE_DATA.buttonGroup[1].value).click()
pageObjects
.button()
.contains(EN_LOCALE_DATA.reviewSelectionModal.buttonGroup[1].value)
.click()
runA11y()
})

it('Has no detectable a11y violations on see benefits you did not qualify for', () => {
pageObjects.button().contains(EN_LOCALE_DATA.intro.button).click()
utils.dataInputs({ dob, relation, status })
pageObjects.button().contains(EN_LOCALE_DATA.buttonGroup[1].value).click()
utils.dataInputs({ dod })
pageObjects.button().contains(EN_LOCALE_DATA.buttonGroup[1].value).click()
pageObjects
.button()
.contains(EN_LOCALE_DATA.reviewSelectionModal.buttonGroup[1].value)
.click()
pageObjects
.button()
.contains(EN_LOCALE_DATA.resultsView.notEligibleResults.cta)
.click()
runA11y({ skipFailOnError: true }) // remove skip after https://github.com/GSA/px-benefit-finder/issues/1073 is resolved
})
})
40 changes: 12 additions & 28 deletions benefit-finder/cypress/e2e/storybook/error-message-display.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,13 @@ import * as EN_DOLO_MOCK_DATA from '../../../../benefit-finder/src/shared/api/mo
import * as EN_LOCALE_DATA from '../../../../benefit-finder/src/shared/locales/en/en.json'
import 'cypress-plugin-tab'

const dateOfBirth = utils.getDateByOffset(-(18 * 365.2425 - 1))

const dataInputs = ({ dob, relation, status }) => {
// input date of birth
dob &&
cy.enterDateOfBirth(dateOfBirth.month, dateOfBirth.day, dateOfBirth.year)
// input relation to deceaseed
relation &&
pageObjects
.applicantRelationshipToDeceased()
.select(
EN_DOLO_MOCK_DATA.data.lifeEventForm.sectionsEligibilityCriteria[0]
.section.fieldsets[1].fieldset.inputs[0].inputCriteria.values[1].value
)
// input relation to deceaseed
status &&
pageObjects
.applicantMaritalStatus()
.select(
EN_DOLO_MOCK_DATA.data.lifeEventForm.sectionsEligibilityCriteria[0]
.section.fieldsets[2].fieldset.inputs[0].inputCriteria.values[1].value
)
}
const dob = utils.getDateByOffset(-(18 * 365.2425 - 1))
const relation =
EN_DOLO_MOCK_DATA.data.lifeEventForm.sectionsEligibilityCriteria[0].section
.fieldsets[1].fieldset.inputs[0].inputCriteria.values[1].value
const status =
EN_DOLO_MOCK_DATA.data.lifeEventForm.sectionsEligibilityCriteria[0].section
.fieldsets[2].fieldset.inputs[0].inputCriteria.values[1].value

const alertHiddenState = {
'aria-hidden': 'true', // expects a hidden error notice to have "aria-hidden=true"
Expand Down Expand Up @@ -92,14 +76,14 @@ describe('Validate correct error messages display for negative scenarios', () =>
cy.focused().should('have.class', 'bf-usa-date-alert')

// expect when a user has resolved all errors the top level error notices is not visible or accessible
dataInputs({ dob: true, relation: true, status: true })
utils.dataInputs({ dob, relation, status })

// expect the error notice to be hidden if errors are present
pageObjects.benefitSectionAlert().should('have.class', 'display-none')
pageObjects.dateAlert().should('not.exist')
})

it.only('Should not allow moving forward by clicking continue when error banner is present', () => {
it('Should not allow moving forward by clicking continue when error banner is present', () => {
// expect when a user tabs from the focus error they can tab any other error notices in the form
pageObjects.button().contains(EN_LOCALE_DATA.buttonGroup[1].value).click()
cy.focused().should('have.class', 'usa-alert--error').tab()
Expand All @@ -113,7 +97,7 @@ describe('Validate correct error messages display for negative scenarios', () =>
}

// expect when a user has resolved all errors the top level error notices is not visible or accessible
dataInputs({ relation: true })
utils.dataInputs({ relation })

// expect the error notice to be visible if errors are present
pageObjects.benefitSectionAlert().should('not.have.class', 'display-none')
Expand All @@ -128,14 +112,14 @@ describe('Validate correct error messages display for negative scenarios', () =>
}
})

it.only('Should not allow moving forward by clicking step nav when error banner is present', () => {
it('Should not allow moving forward by clicking step nav when error banner is present', () => {
// expect when a user tabs from the focus error they can tab any other error notices in the form
pageObjects.button().contains(EN_LOCALE_DATA.buttonGroup[1].value).click()
cy.focused().should('have.class', 'usa-alert--error').tab()
cy.focused().should('have.class', 'bf-usa-date-alert')

// expect when a user has resolved all errors the top level error notices is not visible or accessible
dataInputs({ dob: true, relation: true })
utils.dataInputs({ dob, relation })

// expect the error notice to be visible and focused if errors are present
pageObjects.benefitSectionAlert().should('not.have.class', 'display-none')
Expand Down
1 change: 1 addition & 0 deletions benefit-finder/cypress/support/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// https://on.cypress.io/configuration
// ***********************************************************
import './commands'
import 'cypress-axe'

import * as sbPreview from '../../.storybook/preview'
import { setProjectAnnotations } from '@storybook/react'
Expand Down
4 changes: 1 addition & 3 deletions benefit-finder/cypress/support/e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,4 @@

// Import commands.js using ES2015 syntax:
import './commands'

// Alternatively you can use CommonJS syntax:
// require('./commands')
import 'cypress-axe'
13 changes: 13 additions & 0 deletions benefit-finder/cypress/support/utils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { pageObjects } from '../support/pageObjects'

export function getDateByOffset(offset) {
const date = new Date(Date.now())
const n = Number(offset)
Expand Down Expand Up @@ -27,3 +29,14 @@ export const encodeURIFromObject = obj => {

// can be used by all the test that are visiting in storymode
export const storybookUri = `/iframe.html?args=&id=app--primary&viewMode=story&`

export const dataInputs = ({ dob, relation, status, dod }) => {
// input date of birth
dob && cy.enterDateOfBirth(dob.month, dob.day, dob.year)
// input relation to deceaseed
relation && pageObjects.applicantRelationshipToDeceased().select(relation)
// input relation to deceaseed
status && pageObjects.applicantMaritalStatus().select(status)
// input date of death
dod && cy.enterDateOfDeath(dod.month, dod.day, dod.year)
}
Loading

0 comments on commit 65fbcd7

Please sign in to comment.