Skip to content

Commit

Permalink
Feature/a11y testing (#6398)
Browse files Browse the repository at this point in the history
* Configured Cypress A11y testing to run in the browser from the command

Co-Authored-By: Onyela Ogah <[email protected]>

* Configured Cypress A11y testing to iterate through multiple routes in one file

Co-Authored-By: Onyela Ogah <[email protected]>

* Removed ARIA failing test for DropdownMenuGroup button

Co-Authored-By: Onyela Ogah <[email protected]>

* Added the ability to iterate to the next level of urls

Co-Authored-By: Onyela Ogah <[email protected]>

* Added support for multiple url variable identifiers

Co-Authored-By: Onyela Ogah <[email protected]>

* Sanitised A11y test variable names to make sense

Co-Authored-By: Onyela Ogah <[email protected]>

* Additional renaming it variables in A11y testing

Co-Authored-By: Onyela Ogah <[email protected]>

* Amended array creation to remove data endpoints

Co-Authored-By: Onyela Ogah <[email protected]>

* Added url exclusion mechanism for tests that fail for pages that can't be found

Co-Authored-By: Onyela Ogah <[email protected]>

* Added all mount points to A11y tests

Co-Authored-By: Onyela Ogah <[email protected]>

* Reworded variables to be be more logical

Co-Authored-By: Onyela Ogah <[email protected]>

* Documented how to use the accessibility tests

Co-Authored-By: Onyela Ogah <[email protected]>

* refactoring and decoupling the A11y implementation to increase maintainability

Co-Authored-By: Onyela Ogah <[email protected]>

* Added interaction spec

Co-Authored-By: Onyela Ogah <[email protected]>

* Sanitising URL exclusions

Co-Authored-By: Onyela Ogah <[email protected]>

* Updated documentation

Co-Authored-By: Onyela Ogah <[email protected]>

* Added interactions to A11y testing spec

Co-Authored-By: Onyela Ogah <[email protected]>

* Configured Cypress A11y testing to run in the browser from the command

Co-Authored-By: Onyela Ogah <[email protected]>

* Configured Cypress A11y testing to iterate through multiple routes in one file

Co-Authored-By: Onyela Ogah <[email protected]>

* Removed ARIA failing test for DropdownMenuGroup button

Co-Authored-By: Onyela Ogah <[email protected]>

* Added the ability to iterate to the next level of urls

Co-Authored-By: Onyela Ogah <[email protected]>

* Added support for multiple url variable identifiers

Co-Authored-By: Onyela Ogah <[email protected]>

* Sanitised A11y test variable names to make sense

Co-Authored-By: Onyela Ogah <[email protected]>

* Additional renaming it variables in A11y testing

Co-Authored-By: Onyela Ogah <[email protected]>

* Amended array creation to remove data endpoints

Co-Authored-By: Onyela Ogah <[email protected]>

* Added url exclusion mechanism for tests that fail for pages that can't be found

Co-Authored-By: Onyela Ogah <[email protected]>

* Added all mount points to A11y tests

Co-Authored-By: Onyela Ogah <[email protected]>

* Reworded variables to be be more logical

Co-Authored-By: Onyela Ogah <[email protected]>

* Documented how to use the accessibility tests

Co-Authored-By: Onyela Ogah <[email protected]>

* refactoring and decoupling the A11y implementation to increase maintainability

Co-Authored-By: Onyela Ogah <[email protected]>

* Added interaction spec

Co-Authored-By: Onyela Ogah <[email protected]>

* Sanitising URL exclusions

Co-Authored-By: Onyela Ogah <[email protected]>

* Updated documentation

Co-Authored-By: Onyela Ogah <[email protected]>

* Added interactions to A11y testing spec

Co-Authored-By: Onyela Ogah <[email protected]>

---------

Co-authored-by: Onyela Ogah <[email protected]>
  • Loading branch information
PaulWheatcroft and onyela-o authored Jan 3, 2024
1 parent 727422d commit 4d818f0
Show file tree
Hide file tree
Showing 19 changed files with 444 additions and 11 deletions.
18 changes: 12 additions & 6 deletions docs/Running tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,14 +257,20 @@ Updating the baseline consists in 2 steps:
There is work to be done to allow update of a given baseline image rather than only have the option to update all of them at once.

## Accessibility tests

> “ a11y ” stands for “accessibility.” It is a numeronym, with 11 representing the count of letters between the letter a and the letter y.
The aim of this suite is to ensure our HTML pages are usable by as many people as possible.
## Running the Tests in the Browser

To run the tests first ensure any locally running instances of the application are stopped. Then start 4 terminal sessions to for the following instructions.

1. redis-server
2. cd test/sandbox && npm install && npx nodemon .
3. npm run develop
4. npm run test:a11y:watch

4 Tabs:

1. cd test/sandbox && npm install && npx nodemon .
2. redis-server
3. npm run develop
4. npm run test:a11y
This will open Cypress in the browser. When the browser opens, select **E2E Testing** and then start E2E testing in the browser of your choice.

## Component unit tests
The aim of this suite is to run tests directly against our React components without having to start the frontend.
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"test:unit": "NODE_ENV=test API_ROOT=http://test MOCHA_FILE=junit/test-results.xml npx mocha ./src/**/*.test.js --exit",
"test:functional": "CYPRESS_retries=3 nyc cypress run --browser chrome",
"test:a11y": "CYPRESS_coverage=false cypress run --config-file cypress.a11y.config.js --browser chrome",
"test:a11y:watch": "CYPRESS_coverage=false cypress open --config-file cypress.a11y.config.js --browser chrome",
"test:unit-client": "NODE_ENV=test WEBPACK_ENV=develop MOCHA_FILE=junit/test-results.xml npx mochapack --webpack-config webpack.node.config.js --opts ./test/unit-client/mocha.opts ./test/unit-client/assets/javascripts/**/*.test.{js,jsx}",
"test:functional:watch": "cypress open --e2e --browser chrome",
"test:e2e:lep": "CYPRESS_coverage=false cypress run --config '{\"specPattern\":[\"test/end-to-end/cypress/specs/LEP/**/*.js\"]}' --browser chrome",
Expand Down
5 changes: 1 addition & 4 deletions src/client/components/DropdownMenu/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,15 +170,12 @@ const DropdownMenu = ({
icon={<Icon src={trianglePng} active={open} alt="" />}
aria-haspopup={true}
aria-expanded={open}
aria-controls="dropDownOptionsMenu"
>
{(open ? closedLabel : label) || label}
</DropdownToggleButton>
</DropdownButtonContainer>
{open && (
<DropdownMenuGroup id="dropDownOptionsMenu" ref={childrenGroupRef}>
{children}
</DropdownMenuGroup>
<DropdownMenuGroup ref={childrenGroupRef}>{children}</DropdownMenuGroup>
)}
</DropdownMenuContainer>
)
Expand Down
2 changes: 1 addition & 1 deletion src/lib/urls.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ module.exports = {
export: url('/contacts', '/export'),
audit: url('/contacts', '/:contactId/audit'),
contact: url('/contacts', '/:contactId'),
create: url('/contacts/create?company=', ':companyId'),
create: url('/contacts/create?company=', '/:companyId'),
contactActivities: url('/contacts', '/:contactId/interactions'),
details: url('/contacts', '/:contactId/details'),
edit: url('/contacts', '/:contactId/edit'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import urls from '../../../../../src/lib/urls'
import { urlTestExclusions } from './config/urlTestExclusions'
import { cleanseArrayOfUrls, createArrayOfUrls } from './config/utils'

const mountPoint = urls.companies
const excludedUrls = urlTestExclusions.companies

const arrayOfUrls = createArrayOfUrls(mountPoint)

const filteredArrayOfUrls = cleanseArrayOfUrls(arrayOfUrls, excludedUrls)

filteredArrayOfUrls.map((path) => {
describe(`${path}`, () => {
before(() => {
cy.visit(path, { timeout: 20000 })
// Wait until page has loaded first
cy.initA11y()
})

it('Page should not have any a11y violations', () => {
cy.runA11y()
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import urls from '../../../../../src/lib/urls'
import { urlTestExclusions } from './config/urlTestExclusions'
import { cleanseArrayOfUrls, createArrayOfUrls } from './config/utils'

const mountPoint = urls.companyLists
const excludedUrls = urlTestExclusions.companyLists

const arrayOfUrls = createArrayOfUrls(mountPoint)

const filteredArrayOfUrls = cleanseArrayOfUrls(arrayOfUrls, excludedUrls)

filteredArrayOfUrls.map((path) => {
describe(`${path}`, () => {
before(() => {
cy.visit(path, { timeout: 20000 })
// Wait until page has loaded first
cy.initA11y()
})

it('Page should not have any a11y violations', () => {
cy.runA11y()
})
})
})
20 changes: 20 additions & 0 deletions test/a11y/cypress/specs/integration/config/testIdentityNumbers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export const testIdentityNumbers = {
':aventriEventId': '1111',
':companyId': '0fb3379c-341c-4da4-b825-bf8d47b26baa',
':contactId': '952232d2-1d25-4c3a-bcac-2f3a30a94da9',
':countryId': '3e6debb4-1596-40c5-aa25-f00da0e05af9',
':eventId': 'b93d4273-36fe-4008-ac40-fbc197910791',
':globalHqId': '3e6debb4-1596-40c5-aa25-f00da0e05af9',
':interactionId': 'd14abf23-7f07-4640-8908-cb6b40dc3ce3',
':investmentId': 'b30dee70-b2d6-48cf-9ce4-b9264854470c',
':listId': '75e14e32-292e-4d1b-a361-992d548251f7',
':opportunityId': 'a84f8405-c419-40a6-84c8-642b7c3209b2',
':orderId': '7ea3943c-6220-41c8-b704-ff0c4b33b346',
':projectId': '0e686ea4-b8a2-4337-aec4-114d92ad4588',
':referralId': 'cc5b9953-894c-44b4-a4ac-d0f6a6f6128f',
':subsidiaryCompanyId': 'cc7e2f19-7251-4a41-a27a-f98437720532',
// Missing ID numbers
':kind': 'do_not_have',
':pipelineItemId': 'do_not_have',
':theme': 'do_not_have',
}
57 changes: 57 additions & 0 deletions test/a11y/cypress/specs/integration/config/urlTestExclusions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
export const urlTestExclusions = {
companies: [
// 404 errors for the below
{ url: '/companies/:companyId/audit' },
{ url: '/companies/:companyId/archive' },
{ url: '/companies/:companyId/lists' },
{ url: '/companies/:companyId/manage-company-list' },
// don't have permission to view this page
{ url: '/companies/:companyId/dnb-hierarchy' },
// No history countryId for the sandbox companyId
{ url: '/companies/:companyId/exports/history/:countryId' },
{ url: '/companies/:companyId/referrals/:referralId/interactions' },
],
companyLists: [
{ url: '/company-lists/:listId/delete' },
{ url: '/company-lists/:listId/rename' },
],
contacts: [
// 404 errors for the below
{ url: '/contacts/:contactId/archive' },
{ url: '/contacts/:contactId/unarchive' },
],
events: [],
dashboard: [],
interactions: [
{ url: '/interactions/create' },
{ url: '/interactions/create/:theme/:kind' },
{ url: '/interactions/activeEvents' },
{ url: '/activeEvents/' },
],
investments: [
// don't have permission to view this page
{ url: '/investments/projects/:investmentId/propositions' },
{ url: '/investments/projects/:investmentId/propositions/:propositionId' },
// 404 error for the below
{ url: '/investments/opportunities/:opportunityId' },
// No sandbox data available for testing the below locations
{ url: '/investments/projects/create/investment-type/info/:anchor' },
// 404 error for the below
{ url: '/investments/:investmentId/edit-history' },
// No sandbox data available for testing the below locations
{ url: '/investments/:investmentId/interactions/:interactionsId' },
],
omis: [
// 404 error for the below
{ url: '/omis/edit/payment-reconciliation' },
],
pipelines: [
// No sandbox data available for testing the below locations
{ url: '/my-pipeline/:pipelineId/edit' },
{ url: '/my-pipeline/:pipelineId/archive' },
{ url: '/my-pipeline/:pipelineId/unarchive' },
{ url: '/my-pipeline/:pipelineId/delete' },
],
reminders: [],
search: [],
}
65 changes: 65 additions & 0 deletions test/a11y/cypress/specs/integration/config/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { differenceBy } from 'lodash'
import { testIdentityNumbers } from './testIdentityNumbers'

export const createArrayOfUrls = (mountPoint) => {
const arrayOfUrls = []

for (const levelOnePath in mountPoint) {
if (mountPoint[levelOnePath].route) {
arrayOfUrls.push({
url:
mountPoint[levelOnePath].mountPoint + mountPoint[levelOnePath].route,
})
} else {
const levelTwoPaths = Object.keys(mountPoint[levelOnePath])
levelTwoPaths.forEach((levelTwoPath) => {
if (mountPoint[levelOnePath][levelTwoPath].route) {
arrayOfUrls.push({
url:
mountPoint[levelOnePath][levelTwoPath].mountPoint +
mountPoint[levelOnePath][levelTwoPath].route,
})
} else {
const levelThreePaths = Object.keys(
mountPoint[levelOnePath][levelTwoPath]
)
levelThreePaths.forEach((levelThreePath) => {
if (mountPoint[levelOnePath][levelTwoPath][levelThreePath].route) {
arrayOfUrls.push({
url:
mountPoint[levelOnePath][levelTwoPath][levelThreePath]
.mountPoint +
mountPoint[levelOnePath][levelTwoPath][levelThreePath].route,
})
}
})
}
})
}
}
return arrayOfUrls
}

export const cleanseArrayOfUrls = (arrayOfUrls, excludedUrls) => {
let filteredArrayOfUrls = differenceBy(arrayOfUrls, excludedUrls, 'url')

filteredArrayOfUrls = filteredArrayOfUrls.filter(
(path) => path.url.split('/').pop() !== 'data'
)

filteredArrayOfUrls = filteredArrayOfUrls.filter(
(path) => path.url.split('/').pop() !== 'export'
)

filteredArrayOfUrls = filteredArrayOfUrls.map((path) => {
let pathUrl = path.url.split('/')
const currentPathUrl = pathUrl.map((pathSegment) => {
if (pathSegment.startsWith(':')) {
return (pathSegment = testIdentityNumbers[pathSegment])
}
return pathSegment
})
return currentPathUrl.join('/')
})
return filteredArrayOfUrls
}
24 changes: 24 additions & 0 deletions test/a11y/cypress/specs/integration/contacts-accessibility.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import urls from '../../../../../src/lib/urls'
import { urlTestExclusions } from './config/urlTestExclusions'
import { cleanseArrayOfUrls, createArrayOfUrls } from './config/utils'

const mountPoint = urls.contacts
const excludedUrls = urlTestExclusions.contacts

const arrayOfUrls = createArrayOfUrls(mountPoint)

const filteredArrayOfUrls = cleanseArrayOfUrls(arrayOfUrls, excludedUrls)

filteredArrayOfUrls.map((path) => {
describe(`${path}`, () => {
before(() => {
cy.visit(path, { timeout: 20000 })
// Wait until page has loaded first
cy.initA11y()
})

it('Page should not have any a11y violations', () => {
cy.runA11y()
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
describe('Dashboard', () => {
before(() => {
cy.visit('/')
// Wait until page has loaded first
cy.initA11y()
})

it('should not have any a11y violations', () => {
cy.runA11y()
})
})
24 changes: 24 additions & 0 deletions test/a11y/cypress/specs/integration/events-accessibility.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import urls from '../../../../../src/lib/urls'
import { urlTestExclusions } from './config/urlTestExclusions'
import { cleanseArrayOfUrls, createArrayOfUrls } from './config/utils'

const mountPoint = urls.events
const excludedUrls = urlTestExclusions.events

const arrayOfUrls = createArrayOfUrls(mountPoint)

const filteredArrayOfUrls = cleanseArrayOfUrls(arrayOfUrls, excludedUrls)

filteredArrayOfUrls.map((path) => {
describe(`${path}`, () => {
before(() => {
cy.visit(path, { timeout: 20000 })
// Wait until page has loaded first
cy.initA11y()
})

it('Page should not have any a11y violations', () => {
cy.runA11y()
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import urls from '../../../../../src/lib/urls'
import { urlTestExclusions } from './config/urlTestExclusions'
import { cleanseArrayOfUrls, createArrayOfUrls } from './config/utils'

const mountPoint = urls.interactions
const excludedUrls = urlTestExclusions.interactions

const arrayOfUrls = createArrayOfUrls(mountPoint)

const filteredArrayOfUrls = cleanseArrayOfUrls(arrayOfUrls, excludedUrls)

filteredArrayOfUrls.map((path) => {
describe(`${path}`, () => {
before(() => {
cy.visit(path, { timeout: 20000 })
// Wait until page has loaded first
cy.initA11y()
})

it('Page should not have any a11y violations', () => {
cy.runA11y()
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import urls from '../../../../../src/lib/urls'
import { urlTestExclusions } from './config/urlTestExclusions'
import { cleanseArrayOfUrls, createArrayOfUrls } from './config/utils'

const mountPoint = urls.investments
const excludedUrls = urlTestExclusions.investments

const arrayOfUrls = createArrayOfUrls(mountPoint)

const filteredArrayOfUrls = cleanseArrayOfUrls(arrayOfUrls, excludedUrls)

filteredArrayOfUrls.map((path) => {
describe(`${path}`, () => {
before(() => {
cy.visit(path, { timeout: 20000 })
// Wait until page has loaded first
cy.initA11y()
})

it('Page should not have any a11y violations', () => {
cy.runA11y()
})
})
})
24 changes: 24 additions & 0 deletions test/a11y/cypress/specs/integration/omis-accessibility.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import urls from '../../../../../src/lib/urls'
import { urlTestExclusions } from './config/urlTestExclusions'
import { cleanseArrayOfUrls, createArrayOfUrls } from './config/utils'

const mountPoint = urls.omis
const excludedUrls = urlTestExclusions.omis

const arrayOfUrls = createArrayOfUrls(mountPoint)

const filteredArrayOfUrls = cleanseArrayOfUrls(arrayOfUrls, excludedUrls)

filteredArrayOfUrls.map((path) => {
describe(`${path}`, () => {
before(() => {
cy.visit(path, { timeout: 20000 })
// Wait until page has loaded first
cy.initA11y()
})

it('Page should not have any a11y violations', () => {
cy.runA11y()
})
})
})
Loading

0 comments on commit 4d818f0

Please sign in to comment.