Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

pa11y

Package Overview
Dependencies
Maintainers
9
Versions
103
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pa11y - npm Package Compare versions

Comparing version 6.2.3 to 7.0.0

2

bin/pa11y.js

@@ -231,3 +231,3 @@ #!/usr/bin/env node

* @param {String} reporterName - Name of the reporter
* @param {String} reporterSupportString - List of supported versions, e.g. '^5.0.0'
* @param {String} reporterSupportString - List of supported versions, e.g. '^7.0.0'
* @param {String} pa11yVersion - This version of pa11y

@@ -234,0 +234,0 @@ * @returns {void}

@@ -83,6 +83,7 @@ 'use strict';

/**
* Sanitize a URL, ensuring it has a scheme. If the URL begins with a slash or a period
* or it is a valid path relative to the current directory, it will be resolved as a
* path against the current working directory. If the URL does begin with a scheme, it
* will be prepended with "http://".
* Sanitize a URL, ensuring it has a scheme. If the URL begins with a period or it
* is a valid path relative to the current directory, it is assumed to be a file path
* and is resolved relative to the current working directory. If it is an absolute
* file path, that file path is used. If the URL does begin with a scheme, it will
* be prepended with "http://".
* @private

@@ -94,3 +95,6 @@ * @param {String} url - The URL to sanitize.

let sanitizedUrl = url;
if (/^[./]/i.test(url) || fs.existsSync(url)) {
if (/^[.]/i.test(url) || path.isAbsolute(url) || fs.existsSync(url)) {
// This works for absolute paths since path.resolve starts at the right and
// works left, stopping once it has an absolute path. So, if the URL is an
// absolute path it is returned.
sanitizedUrl = `file://${path.resolve(process.cwd(), url)}`;

@@ -97,0 +101,0 @@ } else if (!/^(https?|file):\/\//i.test(url)) {

@@ -6,2 +6,3 @@ 'use strict';

const fs = require('fs');
const path = require('path');
const pkg = require('../package.json');

@@ -127,3 +128,3 @@ const promiseTimeout = require('p-timeout');

'Using a pre-configured Headless Chrome instance, ' +
'the `chromeLaunchConfig` option will be ignored'
'the `chromeLaunchConfig` option will be ignored'
);

@@ -288,3 +289,3 @@ state.browser = options.browser;

if (!runnersJavascript.pa11y) {
runnersJavascript.pa11y = fs.readFileSync(`${__dirname}/runner.js`, 'utf-8');
runnersJavascript.pa11y = fs.readFileSync(path.join(__dirname, 'runner.js'), 'utf-8');
}

@@ -383,6 +384,6 @@

* @param {String} pa11yVersion - The version of Pa11y to test support for.
* @throws {Error} Throws an error if the reporter does not support the given version of Pa11y
* @throws {Error} Throws an error if the runner does not support the given version of Pa11y
* @returns {void}
*/
function assertReporterCompatibility(runnerName, runnerSupportString, pa11yVersion) {
function assertRunnerCompatibility(runnerName, runnerSupportString, pa11yVersion) {
if (!runnerSupportString || !semver.satisfies(pa11yVersion, runnerSupportString)) {

@@ -392,3 +393,3 @@ throw new Error([

'Please update your version of Pa11y or the runner',
`Reporter Support: ${runnerSupportString}`,
`Runner Support: ${runnerSupportString}`,
`Pa11y Version: ${pa11yVersion}`

@@ -402,3 +403,3 @@ ].join('\n'));

* @param {String} runner - The name of the runner.
* @throws {Error} Throws an error if the reporter does not support the given version of Pa11y
* @throws {Error} Throws an error if the runner does not support the given version of Pa11y
* @returns {String} Javascript source of the runner

@@ -410,3 +411,3 @@ */

assertReporterCompatibility(runner, runnerModule.supports, pkg.version);
assertRunnerCompatibility(runner, runnerModule.supports, pkg.version);

@@ -413,0 +414,0 @@ for (const runnerScript of runnerModule.scripts) {

@@ -8,3 +8,3 @@ 'use strict';

// Pa11y version support
report.supports = '^6.0.0 || ^6.0.0-alpha || ^6.0.0-beta';
report.supports = '^7.0.0 || ^7.0.0-alpha || ^7.0.0-beta';

@@ -11,0 +11,0 @@ // Helper strings for use in reporter methods

@@ -6,3 +6,3 @@ 'use strict';

// Pa11y version support
report.supports = '^6.0.0 || ^6.0.0-alpha || ^6.0.0-beta';
report.supports = '^7.0.0 || ^7.0.0-alpha || ^7.0.0-beta';

@@ -9,0 +9,0 @@ // Output formatted results

@@ -12,3 +12,3 @@ 'use strict';

// Pa11y version support
report.supports = '^6.0.0 || ^6.0.0-alpha || ^6.0.0-beta';
report.supports = '^7.0.0 || ^7.0.0-alpha || ^7.0.0-beta';

@@ -15,0 +15,0 @@ // Compile template and output formatted results

@@ -8,3 +8,3 @@ 'use strict';

// Pa11y version support
report.supports = '^6.0.0 || ^6.0.0-alpha || ^6.0.0-beta';
report.supports = '^7.0.0 || ^7.0.0-alpha || ^7.0.0-beta';

@@ -11,0 +11,0 @@ // Output formatted results

@@ -6,3 +6,3 @@ 'use strict';

// Pa11y version support
report.supports = '^6.0.0 || ^6.0.0-alpha || ^6.0.0-beta';
report.supports = '^7.0.0 || ^7.0.0-alpha || ^7.0.0-beta';

@@ -9,0 +9,0 @@ // Output formatted results

@@ -13,3 +13,3 @@ 'use strict';

*/
runner.supports = '^6.0.0 || ^6.0.0-alpha || ^6.0.0-beta';
runner.supports = '^7.0.0 || ^7.0.0-alpha || ^7.0.0-beta';

@@ -16,0 +16,0 @@ /**

@@ -10,3 +10,3 @@ 'use strict';

*/
runner.supports = '^6.0.0 || ^6.0.0-alpha || ^6.0.0-beta';
runner.supports = '^7.0.0 || ^7.0.0-alpha || ^7.0.0-beta';

@@ -13,0 +13,0 @@ /**

{
"name": "pa11y",
"version": "6.2.3",
"version": "7.0.0",
"description": "Pa11y is your automated accessibility testing pal",

@@ -32,22 +32,22 @@ "keywords": [

"engines": {
"node": ">=12"
"node": ">=18"
},
"dependencies": {
"axe-core": "~4.2.1",
"bfj": "~7.0.2",
"commander": "~8.0.0",
"envinfo": "~7.8.1",
"axe-core": "~4.8.2",
"bfj": "~8.0.0",
"commander": "~11.1.0",
"envinfo": "~7.11.0",
"html_codesniffer": "~2.5.1",
"kleur": "~4.1.5",
"mustache": "~4.2.0",
"html_codesniffer": "~2.5.1",
"kleur": "~4.1.4",
"node.extend": "~2.0.2",
"node.extend": "~2.0.3",
"p-timeout": "~4.1.0",
"puppeteer": "~9.1.1",
"semver": "~7.3.5"
"puppeteer": "^20.9.0",
"semver": "~7.5.4"
},
"devDependencies": {
"eslint": "^7.27.0",
"eslint-plugin-jest": "^25.3.4",
"jest": "^27.4.7",
"pa11y-lint-config": "^2.0.0"
"eslint": "^8.52.0",
"eslint-plugin-jest": "^27.6.0",
"jest": "^29.7.0",
"pa11y-lint-config": "^3.0.0"
},

@@ -62,4 +62,4 @@ "main": "./lib/pa11y.js",

"test-coverage": "jest test/unit --coverage",
"test-integration": "MOCK_SERVER_PORT=8081 jest test/integration",
"test": "MOCK_SERVER_PORT=8081 jest --coverage"
"test-integration": "jest test/integration",
"test": "jest --coverage"
},

@@ -66,0 +66,0 @@ "files": [

@@ -13,3 +13,3 @@ # Pa11y

```sh
pa11y https://example.com/
pa11y https://example.com
```

@@ -22,91 +22,23 @@

pa11y('https://example.com/').then((results) => {
// Do something with the results
pa11y('https://example.com').then((results) => {
// Use the results
});
```
## Table of contents
* [Table of contents](#table-of-contents)
* [Requirements](#requirements)
* [Linux and macOS](#linux-and-macos)
* [Windows](#windows)
* [Command-Line Interface](#command-line-interface)
* [Running Tests](#running-tests)
* [Exit Codes](#exit-codes)
* [Command-Line Configuration](#command-line-configuration)
* [Ignoring](#ignoring)
* [Reporters](#reporters)
* [JavaScript Interface](#javascript-interface)
* [Transforming the Results](#transforming-the-results)
* [Async/Await](#asyncawait)
* [Callback interface](#callback-interface)
* [Validating actions](#validating-actions)
* [Configuration](#configuration)
* [`actions` (array)](#actions-array)
* [`browser` (Browser) and `page` (Page)](#browser-browser-and-page-page)
* [`chromeLaunchConfig` (object)](#chromelaunchconfig-object)
* [`headers` (object)](#headers-object)
* [`hideElements` (string)](#hideelements-string)
* [`ignore` (array)](#ignore-array)
* [`ignoreUrl` (boolean)](#ignoreurl-boolean)
* [`includeNotices` (boolean)](#includenotices-boolean)
* [`includeWarnings` (boolean)](#includewarnings-boolean)
* [`level` (string)](#level-string)
* [`log` (object)](#log-object)
* [`method` (string)](#method-string)
* [`postData` (string)](#postdata-string)
* [`reporter` (string)](#reporter-string)
* [`rootElement` (element)](#rootelement-element)
* [`runners` (array)](#runners-array)
* [`rules` (array)](#rules-array)
* [`screenCapture` (string)](#screencapture-string)
* [`standard` (string)](#standard-string)
* [`threshold` (number)](#threshold-number)
* [`timeout` (number)](#timeout-number)
* [`userAgent` (string)](#useragent-string)
* [`viewport` (object)](#viewport-object)
* [`wait` (number)](#wait-number)
* [Actions](#actions)
* [Click Element](#click-element)
* [Set Field Value](#set-field-value)
* [Clear Field Value](#clear-field-value)
* [Check/Uncheck Field](#checkuncheck-field)
* [Screen Capture](#screen-capture)
* [Wait For Fragment/Path/URL](#wait-for-fragmentpathurl)
* [Wait For Element State](#wait-for-element-state)
* [Wait For Element Event](#wait-for-element-event)
* [Navigate To URL](#navigate-to-url)
* [Runners](#runners)
* [Examples](#examples)
* [Basic Example](#basic-example)
* [Multiple Example](#multiple-example)
* [Actions Example](#actions-example)
* [Puppeteer Example](#puppeteer-example)
* [Common Questions and Troubleshooting](#common-questions-and-troubleshooting)
* [Tutorials and articles](#tutorials-and-articles)
* [Contributing](#contributing)
* [Support and Migration](#support-and-migration)
* [License](#license)
## Requirements
Pa11y requires [Node.js][node] 12+ to run. If you need support for older versions of Node.js, then please use [Pa11y 5.x][5.x].
Pa11y 7 requires [Node.js][node] 18 or 20 to run. An older version of Node.js can be used with a [previous major version](#support-and-migration) of Pa11y.
### Linux and macOS
To install [Node.js][node] you can use [nvm][nvm]:
To install [Node.js][node] you can use [nvm][nvm]. For example, to install with `nvm` with [Homebrew][brew], and then install the latest version of Node:
```sh
brew install nvm
nvm install node
nvm install-latest-npm
```
You can also install Node.js using a package manager like for example [Homebrew][brew]:
Alternatively, you can also download pre-built packages from the [Node.js][node] website for your operating system.
```sh
brew install node
```
Alternatively, you can also download pre-built packages from the [Node.js][node] website for your particular Operating System.
### Windows

@@ -116,3 +48,3 @@

## Command-Line Interface
## Command-line interface

@@ -153,5 +85,5 @@ Install Pa11y globally with [npm][npm]:

### Running Tests
### Testing with `pa11y`
Run an accessibility test against a URL:
Find accessibility issues at a URL:

@@ -162,42 +94,42 @@ ```sh

Run an accessibility test against a file (absolute paths only, not relative):
The default [test runner](#runners) is [HTML_CodeSniffer][htmlcs], but [axe] is also supported. To use `axe`:
```sh
pa11y ./path/to/your/file.html
pa11y https://example.com --runner axe
```
Run a test with CSV reporting and save to a file:
Use both axe and HTML_CodeSniffer in the same run:
```sh
pa11y --reporter csv https://example.com > report.csv
pa11y https://example.com --runner axe --runner htmlcs
```
Run Pa11y using [aXe] as a [test runner](#runners):
Generate results in CSV format, and output to a file, `report.csv`:
```sh
pa11y --runner axe https://example.com
pa11y https://example.com > report.csv --reporter csv
```
Run Pa11y using [aXe] _and_ [HTML CodeSniffer][htmlcs] as [test runners](#runners):
Find accessibility issues in a local HTML file (absolute paths only, not relative):
```sh
pa11y --runner axe --runner htmlcs https://example.com
pa11y ./path/to/your/file.html
```
### Exit Codes
### Exit codes
The command-line tool uses the following exit codes:
* `0`: Pa11y ran successfully, and there are no errors
* `1`: Pa11y failed run due to a technical fault
* `2`: Pa11y ran successfully but there are errors in the page
- `0`: Pa11y ran successfully, and there are no errors
- `1`: Pa11y failed run due to a technical fault
- `2`: Pa11y ran successfully but there are errors in the page
By default, only accessibility issues with a type of `error` will exit with a code of `2`. This is configurable with the `--level` flag which can be set to one of the following:
* `error`: exit with a code of `2` on errors only, exit with a code of `0` on warnings and notices
* `warning`: exit with a code of `2` on errors and warnings, exit with a code of `0` on notices
* `notice`: exit with a code of `2` on errors, warnings, and notices
* `none`: always exit with a code of `0`
- `error`: exit with a code of `2` on errors only, exit with a code of `0` on warnings and notices
- `warning`: exit with a code of `2` on errors and warnings, exit with a code of `0` on notices
- `notice`: exit with a code of `2` on errors, warnings, and notices
- `none`: always exit with a code of `0`
### Command-Line Configuration
### Command-line configuration

@@ -207,3 +139,3 @@ The command-line tool can be configured with a JSON file as well as arguments. By default it will look for a `pa11y.json` file in the current directory, but you can change this with the `--config` flag:

```sh
pa11y --config ./path/to/config.json https://example.com
pa11y https://example.com --config ./path/to/config.json
```

@@ -220,3 +152,3 @@

```sh
pa11y --ignore "issue-code-1;issue-code-2" https://example.com
pa11y https://example.com --ignore "issue-code-1;issue-code-2"
```

@@ -227,3 +159,3 @@

```sh
pa11y --ignore issue-code-1 --ignore issue-code-2 https://example.com
pa11y https://example.com --ignore issue-code-1 --ignore issue-code-2
```

@@ -234,3 +166,3 @@

```sh
pa11y --threshold 10 https://example.com
pa11y https://example.com --threshold 10
```

@@ -240,9 +172,9 @@

The command-line tool can report test results in a few different ways using the `--reporter` flag. The built-in reporters are:
The command-line tool can provide test results in a few different ways using the `--reporter` flag. The built-in reporters are:
* `cli`: output test results in a human-readable format
* `csv`: output test results as comma-separated values
* `html`: output test results as an HTML page
* `json`: output test results as a JSON array
* `tsv`: output test results as tab-separated values
- `cli`: output test results in a human-readable format
- `csv`: output test results as comma-separated values
- `html`: output test results as an HTML page
- `json`: output test results as a JSON array
- `tsv`: output test results as tab-separated values

@@ -252,3 +184,3 @@ You can also write and publish your own reporters. Pa11y looks for reporters in your `node_modules` folder (with a naming pattern), and the current working directory. The first reporter found will be loaded. So with this command:

```sh
pa11y --reporter rainbows https://example.com
pa11y https://example.com --reporter rainbows
```

@@ -263,9 +195,9 @@

A Pa11y reporter _must_ export a property named `supports`. This is a [semver range] (as a string) which indicates which versions of Pa11y the reporter supports:
A Pa11y reporter _must_ export a string property named `supports`. This is a [semver range] which indicates which versions of Pa11y the reporter supports:
```js
exports.supports = '^5.0.0';
exports.supports = '^7.0.0';
```
A reporter should export the following methods, which should all return strings. If your reporter needs to perform asynchronous operations, then it may return a promise which resolves to a string:
A reporter should export the following methods, each returning one string. If your reporter needs to perform asynchronous operations, then it may return a promise which resolves to a string:

@@ -277,11 +209,11 @@ ```js

info(message); // Called when an information message is reported
results(results); // Called with the results of a test run
results(results); // Called with a test run's results
```
## JavaScript Interface
## JavaScript interface
Install Pa11y with [npm][npm] or add to your `package.json`:
Add Pa11y to your project with [npm][npm], most commonly as a development dependency:
```sh
npm install pa11y
npm install pa11y --save-dev
```

@@ -298,23 +230,22 @@

```js
pa11y('https://example.com/').then((results) => {
// Do something with the results
pa11y(url).then((results) => {
// Use the results
});
```
Pa11y can also be run with [some options](#configuration):
Pa11y can also be run with [options](#configuration):
```js
pa11y('https://example.com/', {
// Options go here
}).then((results) => {
// Do something with the results
const options = { /* ... */ };
pa11y(url, options)).then((results) => {
// Use the results
});
```
Pa11y resolves with a `results` object, containing details about the page and accessibility issues from HTML CodeSniffer. It looks like this:
Pa11y resolves with a `results` object, containing details about the page, and an array of accessibility issues found by the test runner:
```js
{
documentTitle: 'The title of the page that was tested',
pageUrl: 'The URL that Pa11y was run against',
pageUrl: 'The tested URL',
documentTitle: 'Title of the page under test',
issues: [

@@ -329,3 +260,2 @@ {

}
// more issues appear here
]

@@ -335,5 +265,5 @@ }

### Transforming the Results
### Transforming the results
If you wish to transform these results with the command-line reporters, then you can do so in your code by requiring them in. The `csv`, `tsv`, `html`, `json`, and `markdown` reporters all expose a `process` method:
If you wish to transform these results with the command-line reporters, then you can do so in your code by requiring them in. The `csv`, `tsv`, `html`, `json`, and `markdown` reporters each expose a method `process`:

@@ -343,9 +273,9 @@ ```js

// are available in a `results` variable:
const htmlReporter = require('pa11y/reporter/html');
const htmlReporter = require('pa11y/lib/reporters/html');
const html = await htmlReporter.results(results);
```
### Async/Await
### `async`/`await`
Because Pa11y is promise based, you can use `async` functions and the `await` keyword:
Pa11y uses promises, so you can use `async` functions and the `await` keyword:

@@ -355,7 +285,8 @@ ```js

try {
const results = await pa11y('https://example.com/');
// Do something with the results
} catch (error) {
// Handle the error
const results = await pa11y(url);
// Use the results
}
catch (error) {
// Handle error
}
}

@@ -368,7 +299,7 @@

If you would rather use callbacks than promises or `async`/`await`, then Pa11y supports this. This interface should be considered legacy, however, and may not appear in the next major version of Pa11y:
For those who prefer callbacks to promises:
```js
pa11y('https://example.com/', (error, results) => {
// Do something with the results or handle the error
pa11y(url, (error, results) => {
// Use results, handle error
});

@@ -399,3 +330,3 @@ ```

```js
pa11y('https://example.com/', {
pa11y(url, {
actions: [

@@ -430,3 +361,3 @@ 'set field #username to exampleUser',

pa11y('https://example.com/', {
pa11y(url, {
browser: browser

@@ -447,3 +378,3 @@ });

```js
pa11y('https://example.com/', {
pa11y(url, {
chromeLaunchConfig: {

@@ -469,3 +400,3 @@ executablePath: '/path/to/Chrome',

```js
pa11y('https://example.com/', {
pa11y(url, {
headers: {

@@ -484,3 +415,3 @@ Cookie: 'foo=bar'

```js
pa11y('https://example.com/', {
pa11y(url, {
hideElements: '.advert, #modal, div[aria-role=presentation]'

@@ -495,3 +426,3 @@ });

```js
pa11y('https://example.com/', {
pa11y(url, {
ignore: [

@@ -513,3 +444,3 @@ 'WCAG2AA.Principle3.Guideline3_1.3_1_1.H57.2'

pa11y('https://example.com/', {
pa11y(url, {
ignoreUrl: true,

@@ -528,3 +459,3 @@ page: page,

```js
pa11y('https://example.com/', {
pa11y(url, {
includeNotices: true

@@ -541,3 +472,3 @@ });

```js
pa11y('https://example.com/', {
pa11y(url, {
includeWarnings: true

@@ -566,3 +497,3 @@ });

```js
pa11y('https://example.com/', {
pa11y(url, {
log: {

@@ -583,3 +514,3 @@ debug: console.log,

```js
pa11y('https://example.com/', {
pa11y(url, {
method: 'POST'

@@ -596,3 +527,3 @@ });

```js
pa11y('https://example.com/', {
pa11y(url, {
headers: {

@@ -609,3 +540,3 @@ 'Content-Type': 'application/x-www-form-urlencoded'

```js
pa11y('https://example.com/', {
pa11y(url, {
headers: {

@@ -638,3 +569,3 @@ 'Content-Type': 'application/json'

```js
pa11y('https://example.com/', {
pa11y(url, {
rootElement: '#main'

@@ -651,3 +582,3 @@ });

```js
pa11y('https://example.com/', {
pa11y(url, {
runners: [

@@ -673,3 +604,3 @@ 'axe',

```js
pa11y('https://example.com/', {
pa11y(url, {
rules: [

@@ -686,3 +617,3 @@ 'Principle1.Guideline1_3.1_3_1_AAA'

```js
pa11y('https://example.com/', {
pa11y(url, {
screenCapture: `${__dirname}/my-screen-capture.png`

@@ -699,3 +630,3 @@ });

```js
pa11y('https://example.com/', {
pa11y(url, {
standard: 'WCAG2A'

@@ -726,3 +657,3 @@ });

```js
pa11y('https://example.com/', {
pa11y(url, {
timeout: 500

@@ -739,3 +670,3 @@ });

```js
pa11y('https://example.com/', {
pa11y(url, {
userAgent: 'A11Y TESTS'

@@ -752,3 +683,3 @@ });

```js
pa11y('https://example.com/', {
pa11y(url, {
viewport: {

@@ -774,6 +705,6 @@ width: 320,

The time in milliseconds to wait before running HTML CodeSniffer on the page.
The time in milliseconds to wait before running HTML_CodeSniffer on the page.
```js
pa11y('https://example.com/', {
pa11y(url, {
wait: 500

@@ -790,3 +721,3 @@ });

```js
pa11y('https://example.com/', {
pa11y(url, {
actions: [

@@ -811,8 +742,8 @@ 'click element #tab-1',

### Click Element
### `click element <selector>`
This allows you to click an element by passing in a CSS selector. This action takes the form `click element <selector>`. E.g.
Clicks an element:
```js
pa11y('https://example.com/', {
pa11y(url, {
actions: [

@@ -826,8 +757,8 @@ 'click element #tab-1'

### Set Field Value
### `set field <selector> to <value>`
This allows you to set the value of a text-based input or select box by passing in a CSS selector and value. This action takes the form `set field <selector> to <value>`. E.g.
Sets the value of a text-based `input` or `select`:
```js
pa11y('https://example.com/', {
pa11y(url, {
actions: [

@@ -839,8 +770,8 @@ 'set field #fullname to John Doe'

### Clear Field Value
### `clear field <selector>`
This allows you to clear the value of a text-based input or select box by passing in a CSS selector and value. This action takes the form `clear field <selector>`. E.g.
Clears the value of a text-based `input` or `select`:
```js
pa11y('https://example.com/', {
pa11y(url, {
actions: [

@@ -852,8 +783,8 @@ 'clear field #middlename'

### Check/Uncheck Field
### `check field <selector>`, `uncheck field <selector>`
This allows you to check or uncheck checkbox and radio inputs by passing in a CSS selector. This action takes the form `check field <selector>` or `uncheck field <selector>`. E.g.
Checks/unchecks an `input` of type `radio` or `checkbox`:
```js
pa11y('https://example.com/', {
pa11y(url, {
actions: [

@@ -866,8 +797,8 @@ 'check field #terms-and-conditions',

### Screen Capture
### `screen capture <to-file-path.png>`
This allows you to capture the screen between other actions, useful to verify that the page looks as you expect before the Pa11y test runs. This action takes the form `screen capture <file-path>`. E.g.
Captures the screen, saving the image to a file, which can be useful between actions for debugging, or just for visual reassurance:
```js
pa11y('https://example.com/', {
pa11y(url, {
actions: [

@@ -879,12 +810,14 @@ 'screen capture example.png'

### Wait For Fragment/Path/URL
### `wait for`
#### `wait for <fragment|path|url>`
This allows you to pause the test until a condition is met, and the page has either a given fragment, path, or URL. This will wait until Pa11y times out so it should be used after another action that would trigger the change in state. You can also wait until the page does **not** have a given fragment, path, or URL using the `to not be` syntax. This action takes one of the forms:
* `wait for fragment to be <fragment>` (including the preceding `#`)
* `wait for fragment to not be <fragment>` (including the preceding `#`)
* `wait for path to be <path>` (including the preceding `/`)
* `wait for path to not be <path>` (including the preceding `/`)
* `wait for url to be <url>`
* `wait for url to not be <url>`
- `wait for fragment to be <fragment>` (including the preceding `#`)
- `wait for fragment to not be <fragment>` (including the preceding `#`)
- `wait for path to be <path>` (including the preceding `/`)
- `wait for path to not be <path>` (including the preceding `/`)
- `wait for url to be <url>`
- `wait for url to not be <url>`

@@ -894,3 +827,3 @@ E.g.

```js
pa11y('https://example.com/', {
pa11y(url, {
actions: [

@@ -903,10 +836,10 @@ 'click element #login-link',

### Wait For Element State
#### `wait for element`'s state
This allows you to pause the test until an element on the page (matching a CSS selector) is either added, removed, visible, or hidden. This will wait until Pa11y times out so it should be used after another action that would trigger the change in state. This action takes one of the forms:
* `wait for element <selector> to be added`
* `wait for element <selector> to be removed`
* `wait for element <selector> to be visible`
* `wait for element <selector> to be hidden`
- `wait for element <selector> to be added`
- `wait for element <selector> to be removed`
- `wait for element <selector> to be visible`
- `wait for element <selector> to be hidden`

@@ -916,3 +849,3 @@ E.g.

```js
pa11y('https://example.com/', {
pa11y(url, {
actions: [

@@ -925,3 +858,3 @@ 'click element #tab-2',

### Wait For Element Event
#### `wait for element`'s event

@@ -931,3 +864,3 @@ This allows you to pause the test until an element on the page (matching a CSS selector) emits an event. This will wait until Pa11y times out so it should be used after another action that would trigger the event. This action takes the form `wait for element <selector> to emit <event-type>`. E.g.

```js
pa11y('https://example.com/', {
pa11y(url, {
actions: [

@@ -940,3 +873,3 @@ 'click element #tab-2',

### Navigate To URL
### `navigate to <url>`

@@ -946,3 +879,3 @@ This action allows you to navigate to a new URL if, for example, the URL is inaccessible using other methods. This action takes the form `navigate to <url>`. E.g.

```js
pa11y('https://example.com/', {
pa11y(url, {
actions: [

@@ -956,6 +889,6 @@ 'navigate to https://another-example.com'

Pa11y supports multiple test runners which return different results. The built-in test runners are:
Pa11y supports multiple test runners which return different results. The built-in options are:
* `axe`: run tests using [aXe-core][axe].
* `htmlcs` (default): run tests using [HTML CodeSniffer][htmlcs]
- `axe`: run tests using [axe-core][axe].
- `htmlcs` (default): run tests using [HTML_CodeSniffer][htmlcs]

@@ -965,3 +898,3 @@ You can also write and publish your own runners. Pa11y looks for runners in your `node_modules` folder (with a naming pattern), and the current working directory. The first runner found will be loaded. So with this command:

```sh
pa11y --runner my-testing-tool https://example.com
pa11y https://example.com --runner custom-tool
```

@@ -972,11 +905,11 @@

```sh
<cwd>/node_modules/pa11y-runner-my-testing-tool
<cwd>/node_modules/my-testing-tool
<cwd>/my-testing-tool
<cwd>/node_modules/pa11y-runner-custom-tool
<cwd>/node_modules/custom-tool
<cwd>/custom-tool
```
A Pa11y runner _must_ export a property named `supports`. This is a [semver range] (as a string) which indicates which versions of Pa11y the runner supports:
A Pa11y runner _must_ export a string property named `supports`. This is a [semver range] which indicates which versions of Pa11y the runner supports:
```js
exports.supports = '^5.0.0';
exports.supports = '^7.0.0';
```

@@ -998,6 +931,6 @@

* `options`: Options specified in the test runner
* `pa11y`: The Pa11y test runner, which includes some helper methods:
* `pa11y.getElementContext(element)`: Get a short HTML context snippet for an element
* `pa11y.getElementSelector(element)`: Get a unique selector with which you can select this element in a page
- `options`: Options specified in the test runner
- `pa11y`: The Pa11y test runner, which includes some helper methods:
- `pa11y.getElementContext(element)`: Get a short HTML context snippet for an element
- `pa11y.getElementSelector(element)`: Get a unique selector with which you can select this element in a page

@@ -1008,7 +941,7 @@ The `run` method _must_ resolve with an array of Pa11y issues. These follow the format:

{
code: '123', // An ID or code which identifies this error
element: {}, // The HTML element this issue relates to, or null if no element is found
message: 'example', // A descriptive message outlining the issue
type: 'error', // A type of "error", "warning", or "notice"
runnerExtras: {} // Additional data that your runner can provide, but isn't used by Pa11y
code: '123', // An identifier for this error
element: {}, // The HTML element this issue relates to; `null` if no element is involved
message: 'example', // A description of the issue
type: 'error', // 'error', 'warning', or 'notice'
runnerExtras: {} // Additional data a runner is free to provide; unused by Pa11y itself
}

@@ -1019,19 +952,19 @@ ```

### Basic Example
### Basic example
Run Pa11y on a URL and output the results. [See the example](example/basic/index.js).
### Multiple Example
### Multiple URLs example
Run Pa11y on multiple URLs at once and output the results. [See the example](example/multiple/index.js).
### Actions Example
### Actions example
Step through some actions before Pa11y runs. This example logs into a fictional site then waits until the account page has loaded before running Pa11y. [See the example](example/actions/index.js).
### Puppeteer Example
### Puppeteer example
Pass in pre-created Puppeteer browser and page instances so that you can reuse them between tests. [See the example](example/puppeteer/index.js).
## Common Questions and Troubleshooting
## Common questions and troubleshooting

@@ -1046,5 +979,5 @@ See our [Troubleshooting guide](TROUBLESHOOTING.md) to get the answers to common questions about Pa11y, along with some ideas to help you troubleshoot any problems.

There are many ways to contribute to Pa11y, we cover these in the [contributing guide](CONTRIBUTING.md) for this repo.
There are many ways to contribute to Pa11y, some of which we describe in the [contributing guide](CONTRIBUTING.md) for this repo.
If you're ready to contribute some code, clone this repo locally and commit your code on a new branch.
If you're ready to contribute some code, clone this repo, commit your code to a new branch, then create a pull request to bring your changes into `main`. If you're an external contributor, [fork this repo][fork-pa11y] first, then follow the same process.

@@ -1054,46 +987,44 @@ Please write unit tests for your code, and check that everything works by running the following before opening a pull request:

```sh
npm run lint
npm test
npm run lint # Lint the code
npm test # Run every test, reporting coverage
```
You can also run verifications and tests individually:
You can also run test suites individually:
```sh
npm run lint # Verify all of the code (ESLint)
npm test # Run all tests
npm run test-unit # Run the unit tests
npm run coverage # Run the unit tests with coverage
npm run test-integration # Run the integration tests
npm run test-unit # Run the unit tests alone
npm run test-integration # Run the integration tests alone
npm run coverage # Run the unit tests alone, reporting coverage
```
To debug a test file you need to ensure that [setup.test.js](test/integration/setup.test.js) is ran before the test file. This adds a `before/each` to start and stop the integration test server.
## Support and migration
## Support and Migration
> [!TIP]
> We maintain a [migration guide](MIGRATION.md) to help you migrate between major versions.
Pa11y major versions are normally supported for 6 months after their last minor release. This means that patch-level changes will be added and bugs will be fixed. The table below outlines the end-of-support dates for major versions, and the last minor release for that version.
When we release a new major version we will continue to support the previous major version for 6 months. This support will be limited to fixes for critical bugs and security issues. If you're opening an issue related to this project, please mention the specific version that the issue affects.
We also maintain a [migration guide](MIGRATION.md) to help you migrate.
The following table lists the major versions available and, for each previous major version, its end-of-support date, and its final minor version released.
| :grey_question: | Major Version | Last Minor Release | Node.js Versions | Support End Date |
| :-------------- | :------------ | :----------------- | :--------------- | :--------------- |
| :heart: | 6 | N/A | 12+ | N/A |
| :skull: | 5 | 5.3 | 8+ | 2021-11-25 |
| :skull: | 4 | 4.13 | 4–8 | 2018-08-15 |
| :skull: | 3 | 3.8 | 0.12–6 | 2016-12-05 |
| :skull: | 2 | 2.4 | 0.10–0.12 | 2016-10-16 |
| :skull: | 1 | 1.7 | 0.10 | 2016-06-08 |
| Major version | Final minor version | Node.js support | Support end date |
| :------------ | :-------------------- | :--------------- | :--------------- |
| `7` | | `18`, `20` | ✅ Current major version |
| `6` | `6.2` | `12`, `14`, `16` | July 2024 |
| `5` | `5.3` | `8`, `10`, `12` | 2021-11-25 |
| `4` | `4.13` | `4`, `6`, `8` | 2018-08-15 |
| `3` | `3.8` | `0.12`, `4` | 2016-12-05 |
| `2` | `2.4` | `0.10`, `0.12` | 2016-10-16 |
| `1` | `1.7` | `0.10` | 2016-06-08 |
If you're opening issues related to these, please mention the version that the issue relates to.
## License
Pa11y is licensed under the [Lesser General Public License (LGPL-3.0-only)][info-license].
Copyright &copy; 2013–2021, Team Pa11y and contributors
Pa11y is licensed under the [Lesser General Public License (LGPL-3.0-only)][info-license].
Copyright &copy; 2013–2024, Team Pa11y and contributors
[5.x]: https://github.com/pa11y/pa11y/tree/5.x
[axe]: https://www.axe-core.org/
[brew]: https://mxcl.github.com/homebrew/
[fork-pa11y]: (https://github.com/pa11y/pa11y/fork)
[htmlcs-wcag2aaa-ruleset]: https://squizlabs.github.io/HTML_CodeSniffer/Standards/WCAG2/
[htmlcs]: https://squizlabs.github.io/HTML_CodeSniffer/
[info-build]: https://github.com/pa11y/pa11y/actions/workflows/build-and-test.yml
[info-build]: https://github.com/pa11y/pa11y/actions/workflows/tests.yml
[info-license]: LICENSE

@@ -1106,6 +1037,6 @@ [info-node]: package.json

[promise]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise
[puppeteer-browser]: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-browser
[puppeteer-launch]: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions
[puppeteer-page]: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-page
[puppeteer-viewport]: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagesetviewportviewport
[puppeteer-browser]: https://pptr.dev/next/api/puppeteer.browser
[puppeteer-launch]: https://pptr.dev/next/api/puppeteer.puppeteerlaunchoptions
[puppeteer-page]: https://pptr.dev/api/puppeteer.page
[puppeteer-viewport]: https://pptr.dev/api/puppeteer.page.setviewport
[semver range]: https://github.com/npm/node-semver#ranges

@@ -1112,0 +1043,0 @@ [shield-build]: https://github.com/pa11y/pa11y/actions/workflows/tests.yml/badge.svg

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc