Skip to content

Commit d92a0d4

Browse files
authored
Merge pull request #102 from ministryofjustice/CBA-197-add-automated-accessibility-tests
Add automated accessibility tests
2 parents d91b348 + f84838b commit d92a0d4

File tree

7 files changed

+76
-4
lines changed

7 files changed

+76
-4
lines changed

cypress.config.ts

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { resetStubs } from './integration_tests/mockApis/wiremock'
33
import auth from './integration_tests/mockApis/auth'
44
import tokenVerification from './integration_tests/mockApis/tokenVerification'
55
import applications from './integration_tests/mockApis/applications'
6+
import accessibilityViolations from './integration_tests/tasks/accessibilityViolations'
67

78
export default defineConfig({
89
chromeWebSecurity: false,
@@ -21,6 +22,7 @@ export default defineConfig({
2122
...auth,
2223
...tokenVerification,
2324
...applications,
25+
...accessibilityViolations,
2426
})
2527
},
2628
baseUrl: 'http://localhost:3007',

integration_tests/mockApis/auth.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ const redirect = () =>
6969
'Content-Type': 'text/html',
7070
Location: 'http://localhost:3007/sign-in/callback?code=codexxxx&state=stateyyyy',
7171
},
72-
body: '<html><body>Sign in page<h1>Sign in</h1></body></html>',
72+
body: '<html lang="en"><head><title>Sign in</title></head><body><main>Sign in page<h1>Sign in</h1></main></body></html>',
7373
},
7474
})
7575

@@ -84,7 +84,7 @@ const signOut = () =>
8484
headers: {
8585
'Content-Type': 'text/html',
8686
},
87-
body: '<html><body>Sign in page<h1>Sign in</h1></body></html>',
87+
body: '<html lang="en"><head><title>Sign in</title></head><body><main>Sign in page<h1>Sign in</h1></main></body></html>',
8888
},
8989
})
9090

@@ -99,7 +99,7 @@ const manageDetails = () =>
9999
headers: {
100100
'Content-Type': 'text/html',
101101
},
102-
body: '<html><body><h1>Your account details</h1></body></html>',
102+
body: '<html lang="en"><head><title>Sign in</title></head><body><main><h1>Your account details</h1></main></body></html>',
103103
},
104104
})
105105

integration_tests/pages/page.ts

+26
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'cypress-axe'
2+
import { Result } from 'axe-core'
13
import errorLookups from '../../server/i18n/en/errors.json'
24

35
export type PageElement = Cypress.Chainable<JQuery>
@@ -17,6 +19,16 @@ export default abstract class Page {
1719

1820
checkOnPage(): void {
1921
cy.get('h1').contains(this.title)
22+
cy.injectAxe()
23+
cy.configureAxe({
24+
rules: [
25+
// Temporary rule whilst this issue is resolved https://github.com/w3c/aria/issues/1404
26+
{ id: 'aria-allowed-attr', reviewOnFail: true },
27+
// Ignore the "All page content should be contained by landmarks", which conflicts with GOV.UK guidance (https://design-system.service.gov.uk/components/back-link/#how-it-works)
28+
{ id: 'region', reviewOnFail: true, selector: '.govuk-back-link' },
29+
],
30+
})
31+
cy.checkA11y(undefined, undefined, this.logAccessibilityViolations)
2032
}
2133

2234
checkNameIsNotInDocumentTitle(): void {
@@ -55,4 +67,18 @@ export default abstract class Page {
5567
signOut = (): PageElement => cy.get('[data-qa=signOut]')
5668

5769
manageDetails = (): PageElement => cy.get('[data-qa=manageDetails]')
70+
71+
logAccessibilityViolations(violations: Result[]): void {
72+
cy.task('logAccessibilityViolationsSummary', `Accessibility violations detected: ${violations.length}`)
73+
74+
const violationData = violations.map(({ id, impact, description, nodes }) => ({
75+
id,
76+
impact,
77+
description,
78+
nodes: nodes.length,
79+
nodeTargets: nodes.map(node => node.target).join(' - '),
80+
}))
81+
82+
cy.task('logAccessibilityViolationsTable', violationData)
83+
}
5884
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Result } from 'axe-core'
2+
3+
export default {
4+
logAccessibilityViolationsSummary: (message: string): null => {
5+
// eslint-disable-next-line no-console
6+
console.log(message)
7+
8+
return null
9+
},
10+
logAccessibilityViolationsTable: (violations: Result[]): null => {
11+
// eslint-disable-next-line no-console
12+
console.table(violations)
13+
14+
return null
15+
},
16+
}

integration_tests/tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"target": "es5",
44
"noEmit": true,
55
"lib": ["es5", "dom", "es2015.promise"],
6-
"types": ["cypress", "express", "express-session"],
6+
"types": ["cypress", "cypress-axe", "express", "express-session"],
77
"esModuleInterop": true,
88
"skipLibCheck": true,
99
"paths": {

package-lock.json

+26
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,11 @@
154154
"@typescript-eslint/parser": "^8.23.0",
155155
"audit-ci": "^7.1.0",
156156
"aws-sdk-client-mock": "^4.1.0",
157+
"axe-core": "^4.10.2",
157158
"chokidar": "^3.6.0",
158159
"concurrently": "^9.1.2",
159160
"cypress": "^14.0.2",
161+
"cypress-axe": "^1.6.0",
160162
"cypress-multi-reporters": "^2.0.5",
161163
"esbuild": "^0.23.1",
162164
"esbuild-plugin-clean": "^1.0.1",

0 commit comments

Comments
 (0)