You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -8,30 +8,67 @@ Test accessibility with [axe-core](https://github.com/dequelabs/axe-core) in [Cy
8
8
>
9
9
> **Reasons**: to upgrade dependencies (i.e. `Cypress ^7` & `axe-core ^4`) and try out some of the suggesions in [RFC 75](https://github.com/component-driven/cypress-axe/issues/75) 👀
10
10
11
-
## Installation
12
11
13
-
1.**Install `cypress-axe-core` from npm:**
12
+
1.[Installation and Setup](#Installation-and-Setup)
As its name implies, this package has two peer dependencies: [cypress](https://github.com/cypress-io) and [axe-core](https://github.com/dequelabs/axe-core)
21
30
```sh
22
31
npm install --save-dev cypress axe-core
23
32
```
24
33
25
-
3.**Include the commands.** Update `cypress/support/index.js` file to include the cypress-axe commands by adding:
34
+
2.**Include the commands.** Update `cypress/support/index.js` file to include the cypress-axe commands by adding:
26
35
27
36
```js
28
37
import'cypress-axe-core'
29
38
```
30
39
31
-
4.**Add a task to log the messages to the terminal** when Cypress executes the spec files. [Example - configuring log task](https://docs.cypress.io/api/commands/task.html#Usage).
40
+
3.**Enable logging results to terminal** by defining _logging_ tasks in cypress `plugins/index.js`.
41
+
```js
42
+
// cypress/plugins/index.js
43
+
module.exports= (on, config) => {
44
+
on('task', {
45
+
log(message) {
46
+
console.log(message);
47
+
returnnull;
48
+
},
49
+
50
+
table(message) {
51
+
console.table(message);
52
+
returnnull;
53
+
},
54
+
});
55
+
};
56
+
```
57
+
> **NOTE**: You can control how results are displayed via [the `violationsCallback` config option](##cy.configureCypressAxe)
58
+
59
+
After following the steps above (_and defining cy.tasks_), violations will be displayed as follows:
If you’re using TypeScript, add cypress-axe-core types to your Cypress’ `tsconfig.json` file:
36
73
37
74
```json
@@ -46,24 +83,29 @@ If you’re using TypeScript, add cypress-axe-core types to your Cypress’ `tsc
46
83
}
47
84
```
48
85
49
-
## Usage
86
+
#Examples
50
87
51
-
###Simple check
88
+
## Simple
52
89
53
90
```js
54
91
it('passes axe', () => {
55
92
cy.visit('/')
56
93
cy.injectAxe()
57
94
// ...
58
-
cy.get('button').checkA11y() //check certain elements only
95
+
cy.get('.my-button').checkA11y() //target certain elements
59
96
// OR
60
97
cy.checkA11y() // check the whole document
61
98
})
62
99
```
63
100
64
-
### Customized check
101
+
## Customised
102
+
103
+
Leveraging ([Cypress commands](https://docs.cypress.io/api/cypress-api/custom-commands)) You can either:
104
+
105
+
- Overwrite `cy.checkA11y`_or_
106
+
- Wrap it in your own custom command
65
107
66
-
You can provide `shouldFail` function to decide which rules should fail. For example, only assert against _serious_ & _critical_ violations but ignore _color-contrast_ rule
108
+
then pass it a `shouldFailFn` function to decide which rules should fail. For example, only assert against _serious_ & _critical_ violations but ignore _color-contrast_ rule.
This will inject the `axe-core` runtime into the page under test. You must run this **after** a call to `cy.visit()` and before you run the `checkA11y` command.
103
145
@@ -110,9 +152,40 @@ beforeEach(() => {
110
152
})
111
153
```
112
154
113
-
###cy.configureAxe
155
+
## cy.checkA11y
114
156
115
-
#### Purpose
157
+
When not chained to another element, it will run against the whole document. You can have it at the end of your test (after other interaction assertions) so it checks against all possible violations. It accepts the same (optional) config object that [`cy.configureCypressAxe`](##cy.configureCypressAxe) accepts
158
+
159
+
**Note**: if you have a toggle-able element i.e. a side menu, make sure it's on (shown) by the time `cy.checkA11y` is called, otherwise you might end up with some false-positive cases. Or, you can target those elements directly to make sure they're tested
160
+
```js
161
+
cy.get('#menu-button').click();
162
+
cy.get('#side-menu-container').checkA11y()
163
+
```
164
+
165
+
## cy.configureCypressAxe
166
+
167
+
Instead of wrapping or overwriting `cy.checkA11y`, you can configure it. It accepts the following:
168
+
-`axeOptions` passed to axe-core.
169
+
-`shouldFailFn` function that returns array of violations to check for.
170
+
-`skipFailures` if true, it will log the violations but not assert against them.
171
+
-`violationsCallback` reporter function that receives the result.
172
+
173
+
**The default**`violationsCallback` function assumes that `cy.task('log')` and `cy.task('table')` have been defined already during the [Installation & setup](##Installation-and-Setup). If you don't want to define those tasks, you can pass a function here to control how results are outputted.
174
+
175
+
```js
176
+
cy.configureCypressAxe({
177
+
axeOptions: [], // axe.RunOptions[]
178
+
shouldFailFn:violations=> violations,
179
+
skipFailures:false,
180
+
violationsCallback: ({
181
+
filename:'test.spec.ts', // spec filename
182
+
results: [], // violations axe.Result[]
183
+
label:'my custom component', // if passed to checkA11y
184
+
}) =>void,
185
+
})
186
+
```
187
+
188
+
## cy.configureAxe
116
189
117
190
To configure the format of the data used by aXe. This can be used to add new rules, which must be registered with the library to execute.
118
191
@@ -139,149 +212,6 @@ it('Has no detectable a11y violations on load (custom configuration)', () => {
139
212
})
140
213
```
141
214
142
-
### cy.checkA11y
143
-
144
-
This will run axe against the document at the point in which it is called. This means you can call this after interacting with your page and uncover accessibility issues introduced as a result of rendering in response to user actions.
145
-
146
-
#### Parameters on cy.checkA11y (axe.run)
147
-
148
-
##### context (optional)
149
-
150
-
Defines the scope of the analysis - the part of the DOM that you would like to analyze. This will typically be the document or a specific selector such as class name, ID, selector, etc.
151
-
152
-
##### options (optional)
153
-
154
-
Set of options passed into rules or checks, temporarily modifying them. This contrasts with axe.configure, which is more permanent.
155
-
156
-
The keys consist of [those accepted by `axe.run`'s options argument](https://www.deque.com/axe/documentation/api-documentation/#parameters-axerun) as well as a custom `includedImpacts` key.
157
-
158
-
The `includedImpacts` key is an array of strings that map to `impact` levels in violations. Specifying this array will only include violations where the impact matches one of the included values. Possible impact values are "minor", "moderate", "serious", or "critical".
159
-
160
-
Filtering based on impact in combination with the `skipFailures` argument allows you to introduce `cypress-axe` into tests for a legacy application without failing in CI before you have an opportunity to address accessibility issues. Ideally, you would steadily move towards stricter testing as you address issues.
161
-
162
-
##### violationsCallback (optional)
163
-
164
-
Allows you to define a callback that receives the violations for custom side-effects, such as adding custom output to the terminal.
165
-
166
-
**NOTE:**_This respects the `includedImpacts` filter and will only execute with violations that are included._
167
-
168
-
##### skipFailures (optional, defaults to false)
169
-
170
-
Disables assertions based on violations and only logs violations to the console output. This enabled you to see violations while allowing your tests to pass. This should be used as a temporary measure while you address accessibility violations.
The violation callback parameter accepts a function and allows you to add custom behavior when violations are found.
219
-
220
-
This example adds custom logging to the terminal running Cypress, using `cy.task` and the `violationCallback` argument for `cy.checkA11y`
221
-
222
-
##### In Cypress plugins file
223
-
224
-
This registers a `log` task as seen in the [Cypress docs for cy.task](https://docs.cypress.io/api/commands/task.html#Usage) as well as a `table` task for sending tabular data to the terminal.
225
-
226
-
```js
227
-
module.exports= (on, config) => {
228
-
on('task', {
229
-
log(message) {
230
-
console.log(message)
231
-
232
-
returnnull
233
-
},
234
-
table(message) {
235
-
console.table(message)
236
-
237
-
returnnull
238
-
}
239
-
})
240
-
}
241
-
```
242
-
243
-
#### In your spec file
244
-
245
-
Then we create a function that uses our tasks and pass it as the `validationCallback` argument to `cy.checkA11y`
246
-
247
-
```js
248
-
// Define at the top of the spec file or just import it
249
-
functionterminalLog(violations) {
250
-
cy.task(
251
-
'log',
252
-
`${violations.length} accessibility violation${
253
-
violations.length===1?'':'s'
254
-
}${violations.length===1?'was':'were'} detected`
255
-
)
256
-
// pluck specific keys to keep the table readable
257
-
constviolationData=violations.map(
258
-
({ id, impact, description, nodes }) => ({
259
-
id,
260
-
impact,
261
-
description,
262
-
nodes:nodes.length
263
-
})
264
-
)
265
-
266
-
cy.task('table', violationData)
267
-
}
268
-
269
-
// Then in your test...
270
-
it('Logs violations to the terminal', () => {
271
-
cy.checkA11y(null, null, terminalLog)
272
-
})
273
-
```
274
-
275
-
This custom logging behavior results in terminal output like this:
276
-
277
-

278
-
279
-
## Standard Output
280
-
281
-
When accessibility violations are detected, your test will fail and an entry titled "A11Y ERROR!" will be added to the command log for each type of violation found (they will be above the failed assertion). Clicking on those will reveal more specifics about the error in the DevTools console.
282
-
283
-

284
-
285
215
## Authors
286
216
287
217
The project was created by [Andy Van Slaars](https://vanslaars.io/), and maintained by [Artem Sapegin](https://sapegin.me).
0 commit comments