Comparing version 5.3.0 to 6.0.0-alpha
@@ -6,2 +6,3 @@ #!/usr/bin/env node | ||
const extend = require('node.extend'); | ||
const envinfo = require('envinfo'); | ||
const path = require('path'); | ||
@@ -14,3 +15,7 @@ const pkg = require('../package.json'); | ||
configureProgram(); | ||
runProgram(); | ||
if (program.environment) { | ||
outputEnvironmentInfo(); | ||
} else { | ||
runProgram(); | ||
} | ||
@@ -30,3 +35,4 @@ /** | ||
'-s, --standard <name>', | ||
'the accessibility standard to use: Section508, WCAG2A, WCAG2AA (default), WCAG2AAA – only used by htmlcs runner' | ||
'the accessibility standard to use: Section508, WCAG2A, WCAG2AA (default), ' + | ||
'WCAG2AAA – only used by htmlcs runner' | ||
) | ||
@@ -97,3 +103,4 @@ .option( | ||
'-A, --add-rule <rule>', | ||
'WCAG 2.0 rules to include, a repeatable value or separated by semi-colons – only used by htmlcs runner', | ||
'WCAG 2.0 rules to include, a repeatable value or separated by semi-colons ' + | ||
'– only used by htmlcs runner', | ||
collectOptions, | ||
@@ -107,13 +114,17 @@ [] | ||
/** | ||
* Test the page and generate the results | ||
* Handle help | ||
* @returns {void} | ||
*/ | ||
async function runProgram() { | ||
if (program.environment) { | ||
outputEnvironmentInfo(); | ||
process.exit(0); | ||
} | ||
function handleHelp() { | ||
if (!program.url || program.args[1]) { | ||
program.help(); | ||
} | ||
} | ||
/** | ||
* Test the page and generate the results | ||
* @returns {void} | ||
*/ | ||
async function runProgram() { | ||
handleHelp(); | ||
const options = processOptions(); | ||
@@ -123,3 +134,3 @@ const report = loadReporter(options.reporter); | ||
if (!program.debug) { | ||
options.log.debug = () => {}; | ||
options.log.debug = () => { /* NoOp */ }; | ||
} | ||
@@ -199,3 +210,6 @@ await report.begin(program.url); | ||
} catch (error) { | ||
console.error(`An error occurred when loading the "${name}" reporter. This is not an error`); | ||
console.error( | ||
`An error occurred when loading the "${name}" reporter. ` + | ||
'This is not an error' | ||
); | ||
console.error('with Pa11y itself, please contact the creator of this reporter\n'); | ||
@@ -223,3 +237,6 @@ console.error(error.stack); | ||
if (!reporterSupportString || !semver.satisfies(pa11yVersion, reporterSupportString)) { | ||
console.error(`Error: The installed "${reporterName}" reporter does not support Pa11y ${pa11yVersion}`); | ||
console.error( | ||
`Error: The installed "${reporterName}" reporter does not support ` + | ||
`Pa11y ${pa11yVersion}` | ||
); | ||
console.error('Please update your version of Pa11y or the reporter'); | ||
@@ -293,20 +310,14 @@ console.error(`Reporter Support: ${reporterSupportString}`); | ||
* Output environment info for debugging purposes | ||
* @param {Object} pkg - The package.json object | ||
* @returns {void} | ||
* @returns {Promise} - resolves a string with environment information from envinfo | ||
*/ | ||
function outputEnvironmentInfo() { | ||
const versions = { | ||
pa11y: pkg.version, | ||
node: process.version.replace('v', ''), | ||
npm: '[unavailable]', | ||
os: require('os').release() | ||
}; | ||
try { | ||
versions.npm = require('child_process').execSync('npm -v').toString().trim(); | ||
} catch (error) {} | ||
async function outputEnvironmentInfo() { | ||
const envData = await envinfo.run({ | ||
System: ['OS', 'CPU', 'Memory', 'Shell'], | ||
Binaries: ['Node', 'Yarn', 'npm'], | ||
npmPackages: ['pa11y'] | ||
}); | ||
console.log(`Pa11y: ${versions.pa11y}`); | ||
console.log(`Node.js: ${versions.node}`); | ||
console.log(`npm: ${versions.npm}`); | ||
console.log(`OS: ${versions.os} (${process.platform})`); | ||
console.log(envData); | ||
process.exit(0); | ||
} | ||
422
CHANGELOG.md
@@ -1,481 +0,485 @@ | ||
# Changelog | ||
## 6.0.0-alpha (2020-04-28) | ||
* Update HTML_CodeSniffer to 2.5.1, which includes support for WCAG 2.1 | ||
* Drop support for Node.js versions older than 10. | ||
## 5.3.0 (2019-09-30) | ||
* Adds support for [aXe](https://www.deque.com/axe/) test runner (thanks @rowanmanning) | ||
* Adds support for multiple test runners (thanks @rowanmanning) | ||
* Adds support for sites using `AMD` (thanks @joeyciechanowicz) | ||
* Removes dependency on `fs-extra` (thanks @timnovis) | ||
* Improves JSDoc typings (thanks @josebolos) | ||
* Inverts the order of `setViewport` and `goto` to prevent accidental page reloads (thanks @josebolos) | ||
* Minor documentation updates (thanks @sjparkinson, @josebolos) | ||
* Adds support for [aXe](https://www.deque.com/axe/) test runner (thanks @rowanmanning) | ||
* Adds support for multiple test runners (thanks @rowanmanning) | ||
* Adds support for sites using `AMD` (thanks @joeyciechanowicz) | ||
* Removes dependency on `fs-extra` (thanks @timnovis) | ||
* Improves JSDoc typings (thanks @josebolos) | ||
* Inverts the order of `setViewport` and `goto` to prevent accidental page reloads (thanks @josebolos) | ||
* Minor documentation updates (thanks @sjparkinson, @josebolos) | ||
## 5.2.0 (2019-07-04) | ||
* Allow pa11y to use an existing puppeteer page instance (thanks @kevinatown) | ||
* Fixed a bug where `set field` may fail if the text contains the string " to " (thanks @kkoskelin) | ||
* Use npm version of HTML_CodeSniffer instead of a static one (thanks @paazmaya) and update to version 2.4.0 | ||
* Add a `package-lock.json` file to the package | ||
* Several dependency and tooling updates (thanks @leeroyrose and others) | ||
* Other bugfixes (thanks @joeyciechanowicz) | ||
* Minor documentation updates | ||
* Allow pa11y to use an existing puppeteer page instance (thanks @kevinatown) | ||
* Fixed a bug where `set field` may fail if the text contains the string " to " (thanks @kkoskelin) | ||
* Use npm version of HTML_CodeSniffer instead of a static one (thanks @paazmaya) and update to version 2.4.0 | ||
* Add a `package-lock.json` file to the package | ||
* Several dependency and tooling updates (thanks @leeroyrose and others) | ||
* Other bugfixes (thanks @joeyciechanowicz) | ||
* Minor documentation updates | ||
## 5.1.0 (2018-10-18) | ||
* Intercept first page requests only when necessary, to [work around a Puppeteer bug](https://github.com/pa11y/pa11y/issues/421). | ||
* Add an .nvmrc file to specify the minimum Node version already [listed in the requirements](https://github.com/pa11y/pa11y#requirements) | ||
* Update dependencies | ||
* commander: ^2.14.1 to ^2.19.0 | ||
* eslint: ^4.17.0 to ^4.19.1 | ||
* mocha: ^5.0.1 to ^5.2.0 | ||
* nyc: ^11.4.1 to ^11.9.0 | ||
* puppeteer: ^1.4.0 to ^1.9.0 | ||
* semver: ^5.5.0 to ^5.6.0 | ||
* sinon: ^4.3.0 to ^4.5.0 | ||
* HTML CodeSniffer: 2.1.1 to 2.2.0 | ||
* Intercept first page requests only when necessary, to [work around a Puppeteer bug](https://github.com/pa11y/pa11y/issues/421). | ||
* Add an .nvmrc file to specify the minimum Node version already [listed in the requirements](https://github.com/pa11y/pa11y#requirements) | ||
* Update dependencies | ||
* commander: ^2.14.1 to ^2.19.0 | ||
* eslint: ^4.17.0 to ^4.19.1 | ||
* mocha: ^5.0.1 to ^5.2.0 | ||
* nyc: ^11.4.1 to ^11.9.0 | ||
* puppeteer: ^1.4.0 to ^1.9.0 | ||
* semver: ^5.5.0 to ^5.6.0 | ||
* sinon: ^4.3.0 to ^4.5.0 | ||
* HTML CodeSniffer: 2.1.1 to 2.2.0 | ||
## 5.0.4 (2018-05-21) | ||
* Update dependencies | ||
* puppeteer: 1.0.0 to ^1.4.0 | ||
* Correct and clarify some of the documentation | ||
* Update dependencies | ||
* puppeteer: 1.0.0 to ^1.4.0 | ||
* Correct and clarify some of the documentation | ||
## 5.0.3 (2018-03-09) | ||
* Fix an issue caused by a site having a global `module.exports` property | ||
* Fix an issue caused by a site having a global `module.exports` property | ||
## 5.0.2 (2018-03-08) | ||
* Pin puppeteer at 1.0.0 to fix file URL issues | ||
* Pin puppeteer at 1.0.0 to fix file URL issues | ||
## 5.0.1 (2018-02-16) | ||
* Update dependencies | ||
* commander: ^2.9.0 to ^2.14.1 | ||
* p-timeout: ^1.2.0 to ^2.0.1 | ||
* semver: ^5.4.1 to ^5.5.0 | ||
* eslint: ^3.1.8 to ^4.17.0 | ||
* mocha: ^3.2.0 to ^5.0.1 | ||
* nyc: ^10.1.2 to ^11.4.1 | ||
* proclaim: ^3.4.4 to ^3.5.1 | ||
* sinon: ^3.2.0 to ^4.3.0 | ||
* Update dependencies | ||
* commander: ^2.9.0 to ^2.14.1 | ||
* p-timeout: ^1.2.0 to ^2.0.1 | ||
* semver: ^5.4.1 to ^5.5.0 | ||
* eslint: ^3.1.8 to ^4.17.0 | ||
* mocha: ^3.2.0 to ^5.0.1 | ||
* nyc: ^10.1.2 to ^11.4.1 | ||
* proclaim: ^3.4.4 to ^3.5.1 | ||
* sinon: ^3.2.0 to ^4.3.0 | ||
## 5.0.0 (2018-02-15) | ||
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-40-to-50) for details | ||
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-40-to-50) for details | ||
## 5.0.0-beta.10 pre-release (2018-02-14) | ||
* Allow passing in a Chrome page instance to a test | ||
* Allow passing in a Chrome page instance to a test | ||
## 5.0.0-beta.9 pre-release (2018-01-30) | ||
* Update dependencies | ||
* pa11y-reporter-cli: ^1.0.0 to ^1.0.1 | ||
* Update dependencies | ||
* pa11y-reporter-cli: ^1.0.0 to ^1.0.1 | ||
## 5.0.0-beta.8 pre-release (2018-01-22) | ||
* Allow sharing a Chrome browser instance between test runs | ||
* Fix Content-Security-Policy issues | ||
* Allow sharing a Chrome browser instance between test runs | ||
* Fix Content-Security-Policy issues | ||
## 5.0.0-beta.7 pre-release (2018-01-17) | ||
* Fix browser logging | ||
* Fix browser logging | ||
## 5.0.0-beta.6 pre-release (2018-01-16) | ||
* Add the `navigate-url` action | ||
* Correct documentation on `isValidAction` | ||
* Update dependencies | ||
* puppeteer: ^0.13.0 to ^1.0.0 | ||
* Add the `navigate-url` action | ||
* Correct documentation on `isValidAction` | ||
* Update dependencies | ||
* puppeteer: ^0.13.0 to ^1.0.0 | ||
## 5.0.0-beta.5 pre-release (2017-12-11) | ||
* Update dependencies | ||
* puppeteer: ^0.11.0 to ^0.13.0 | ||
* Update dependencies | ||
* puppeteer: ^0.11.0 to ^0.13.0 | ||
## 5.0.0-beta.4 pre-release (2017-12-06) | ||
* Add reporter, threshold and level as configuration options | ||
* Clarify some documentation | ||
* Add reporter, threshold and level as configuration options | ||
* Clarify some documentation | ||
## 5.0.0-beta.3 pre-release (2017-11-26) | ||
* Fix a timeout issue | ||
* Fix an issue with the built in copy of HTML CodeSniffer | ||
* Fix a timeout issue | ||
* Fix an issue with the built in copy of HTML CodeSniffer | ||
## 5.0.0-beta.2 pre-release (2017-10-04) | ||
* Output browser console messages to the debug log | ||
* Add the `screen-capture` action | ||
* Add the `wait-for-element-event` action | ||
* Update dependencies | ||
* puppeteer: ^0.10.2 to ^0.11.0 | ||
* pa11y-lint-config: ^1.2.0 to ^1.2.1 | ||
* Output browser console messages to the debug log | ||
* Add the `screen-capture` action | ||
* Add the `wait-for-element-event` action | ||
* Update dependencies | ||
* puppeteer: ^0.10.2 to ^0.11.0 | ||
* pa11y-lint-config: ^1.2.0 to ^1.2.1 | ||
## 5.0.0-beta.1 pre-release (2017-09-11) | ||
* See the [migration guide](https://github.com/pa11y/pa11y/blob/5.x/MIGRATION.md#migrating-from-40-to-50) for details | ||
* See the [migration guide](https://github.com/pa11y/pa11y/blob/5.x/MIGRATION.md#migrating-from-40-to-50) for details | ||
## 4.13.2 (2017-11-26) | ||
* Fix an issue with the built in copy of HTML CodeSniffer | ||
* Fix an issue with the built in copy of HTML CodeSniffer | ||
## 4.13.1 (2017-10-16) | ||
* Trigger correct change/input events for check-field and set-field-value actions | ||
* Trigger correct change/input events for check-field and set-field-value actions | ||
## 4.13.0 (2017-09-15) | ||
* Update dependencies | ||
* HTML CodeSniffer: 2.0.7 to 2.1.1 | ||
* Update dependencies | ||
* HTML CodeSniffer: 2.0.7 to 2.1.1 | ||
## 4.12.2 (2017-09-11) | ||
* Exit with an error when using an incompatible command-line reporter | ||
* Exit with an error when using an incompatible command-line reporter | ||
## 4.12.1 (2017-08-23) | ||
* Roll back dependencies | ||
* HTML CodeSniffer: 2.1.0 to 2.0.7 | ||
* Roll back dependencies | ||
* HTML CodeSniffer: 2.1.0 to 2.0.7 | ||
## 4.12.0 (2017-08-23) | ||
* Add the `wait-for-element-state` action | ||
* Update the `wait-for-url` action to support waiting for hostname | ||
* Update dependencies | ||
* HTML CodeSniffer: 2.0.7 to 2.1.0 | ||
* Lots of updates to the README and trouble-shooting guide | ||
* Support Node.js 8.x | ||
* Add the `wait-for-element-state` action | ||
* Update the `wait-for-url` action to support waiting for hostname | ||
* Update dependencies | ||
* HTML CodeSniffer: 2.0.7 to 2.1.0 | ||
* Lots of updates to the README and trouble-shooting guide | ||
* Support Node.js 8.x | ||
## 4.11.0 (2017-06-02) | ||
* Add the ability to make Pa11y perform POST requests | ||
* Documentation improvements | ||
* Update dependencies | ||
* truffler: ^3.0.1 to ^3.1.0 | ||
* Add the ability to make Pa11y perform POST requests | ||
* Documentation improvements | ||
* Update dependencies | ||
* truffler: ^3.0.1 to ^3.1.0 | ||
## 4.10.0 (2017-04-18) | ||
* Update example URLs across the project for clarity | ||
* Add a TSV reporter | ||
* Update example URLs across the project for clarity | ||
* Add a TSV reporter | ||
## 4.9.0 (2017-03-29) | ||
* Add the ability to add additional WCAG rules to the selected standard | ||
* Update dependencies | ||
* async: ~1.4 to ^2.2.0 | ||
* bfj: ~1.2 to ^2.1.2 | ||
* chalk: ~1.1 to ^1.1.3 | ||
* commander: ~2.8 to ^2.9.0 | ||
* lower-case: ~1.1 to ^1.1.4 | ||
* node.extend: ~1.1 to ^1.1.6 | ||
* once: ~1.3 to ^1.4.0 | ||
* truffler: ~3.0 to ^3.0.1 | ||
* mocha: ^3 to ^3.2.0 | ||
* mockery: ~1.4 to ^2.0.0 | ||
* proclaim: ^3 to ^3.4.4 | ||
* sinon: ^1 to ^2.1.0 | ||
* Use the standard Pa11y lint config | ||
* Update the tooling for consistency with other projects | ||
* Add the ability to add additional WCAG rules to the selected standard | ||
* Update dependencies | ||
* async: ~1.4 to ^2.2.0 | ||
* bfj: ~1.2 to ^2.1.2 | ||
* chalk: ~1.1 to ^1.1.3 | ||
* commander: ~2.8 to ^2.9.0 | ||
* lower-case: ~1.1 to ^1.1.4 | ||
* node.extend: ~1.1 to ^1.1.6 | ||
* once: ~1.3 to ^1.4.0 | ||
* truffler: ~3.0 to ^3.0.1 | ||
* mocha: ^3 to ^3.2.0 | ||
* mockery: ~1.4 to ^2.0.0 | ||
* proclaim: ^3 to ^3.4.4 | ||
* sinon: ^1 to ^2.1.0 | ||
* Use the standard Pa11y lint config | ||
* Update the tooling for consistency with other projects | ||
## 4.8.0 (2017-03-17) | ||
* Add the `--environment` flag for easier debugging | ||
* Update the Windows requirements to include Windows 10 | ||
* Update the trouble-shooting guide and common questions | ||
* Add the `--environment` flag for easier debugging | ||
* Update the Windows requirements to include Windows 10 | ||
* Update the trouble-shooting guide and common questions | ||
## 4.7.0 (2017-03-08) | ||
* Add the ability to screen capture the tested page | ||
* Move the main bin to a .js file | ||
* Clean up coveralls | ||
* Add the ability to screen capture the tested page | ||
* Move the main bin to a .js file | ||
* Clean up coveralls | ||
## 4.6.0 (2017-01-30) | ||
* Add negation to the "wait for..." actions | ||
* Add negation to the "wait for..." actions | ||
## 4.5.0 (2017-01-25) | ||
* Expose action validation for use in dependent projects | ||
* Expose action validation for use in dependent projects | ||
## 4.4.0 (2017-01-19) | ||
* Add support for actions | ||
* Add support for actions | ||
## 4.3.0 (2016-12-15) | ||
* Add a `verifyPage` option, and a `--verify-page` flag | ||
* Switch from JSHint/JSCS to ESLint | ||
* Add a contributing guide | ||
* Update dependencies | ||
* istanbul: ~0.3 to ~0.4 | ||
* Add a `verifyPage` option, and a `--verify-page` flag | ||
* Switch from JSHint/JSCS to ESLint | ||
* Add a contributing guide | ||
* Update dependencies | ||
* istanbul: ~0.3 to ~0.4 | ||
## 4.2.0 (2016-11-25) | ||
* Display the page title in the logs to help with debugging | ||
* Display the page title in the logs to help with debugging | ||
## 4.1.1 (2016-11-24) | ||
* Update dependencies | ||
* truffler: ~2.3 to ~3.0 | ||
* Update dependencies | ||
* truffler: ~2.3 to ~3.0 | ||
## 4.1.0 (2016-11-21) | ||
* Install PhantomJS as a dependency if the latest version isn't present | ||
* Remove the SSL protocol from the default PhantomJS config | ||
* Install PhantomJS as a dependency if the latest version isn't present | ||
* Remove the SSL protocol from the default PhantomJS config | ||
## 4.0.3 (2016-11-20) | ||
* Add protocols to URLs, make path instructions explicit | ||
* Add protocols to URLs, make path instructions explicit | ||
## 4.0.2 (2016-11-10) | ||
* Update dependencies | ||
* truffler: ~2.2 to ~2.3 | ||
* Fix typos and mistakes across the documentation | ||
* Update dependencies | ||
* truffler: ~2.2 to ~2.3 | ||
* Fix typos and mistakes across the documentation | ||
## 4.0.1 (2016-08-18) | ||
* Upgrade mocha to version 3. This fixes a security vuln with versions of minimatch older than | ||
* Upgrade mocha to version 3. This fixes a security vuln with versions of minimatch older than | ||
3.0.2. Minimatch is one of mocha's dependencies. This only affects `devDependencies`. | ||
* Documentation updates. | ||
* Documentation updates. | ||
## 4.0.0 (2016-06-05) | ||
* Drop Node.js 0.12 support | ||
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-30-to-40) for details | ||
* Drop Node.js 0.12 support | ||
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-30-to-40) for details | ||
## 3.8.1 (2016-06-03) | ||
* Fixes the `hideElements` option | ||
* Fixes the `hideElements` option | ||
## 3.8.0 (2016-05-25) | ||
* Make the built-in reporters usable in JavaScript | ||
* Tidy up the examples | ||
* Make the built-in reporters usable in JavaScript | ||
* Tidy up the examples | ||
## 3.7.1 (2016-05-03) | ||
* Support Node.js 6.x | ||
* Support Node.js 6.x | ||
## 3.7.0 (2016-04-27) | ||
* Update dependencies | ||
* truffler: ~2.1 to ~2.2 | ||
* HTML CodeSniffer: 2.0.1 to 2.0.7 | ||
* Update dependencies | ||
* truffler: ~2.1 to ~2.2 | ||
* HTML CodeSniffer: 2.0.1 to 2.0.7 | ||
## 3.6.0 (2016-03-01) | ||
* Adding the `rootElement` option so a subset of the document can be tested | ||
* Adding the `hideElements` option so elements can be hidden from testing | ||
* Adding the `rootElement` option so a subset of the document can be tested | ||
* Adding the `hideElements` option so elements can be hidden from testing | ||
## 3.5.1 (2016-02-09) | ||
* Update repository references to springernature | ||
* Update the license | ||
* Update repository references to springernature | ||
* Update the license | ||
## 3.5.0 (2016-02-09) | ||
* Adding the `beforeScript` option so JavaScript can be run on the page before testing | ||
* Re-license under the LGPL 3.0 | ||
* Adding the `beforeScript` option so JavaScript can be run on the page before testing | ||
* Re-license under the LGPL 3.0 | ||
## 3.4.0 (2016-02-01) | ||
* Document running Pa11y against local files | ||
* Add a trouble-shooting guide for Windows | ||
* Make allowed standards configurable | ||
* Document running Pa11y against local files | ||
* Add a trouble-shooting guide for Windows | ||
* Make allowed standards configurable | ||
## 3.3.0 (2016-01-11) | ||
* Add the ability to use the `--ignore` command line more than once | ||
* Add the ability to use the `--ignore` command line more than once | ||
## 3.2.1 (2016-01-05) | ||
* Fix an issue where JSON output was truncated | ||
* Fix an issue where JSON output was truncated | ||
## 3.2.0 (2015-12-17) | ||
* Add a threshold CLI parameter to allow a certain number of errors before failing | ||
* Add a threshold CLI parameter to allow a certain number of errors before failing | ||
## 3.1.0 (2015-12-14) | ||
* Add the ability to specify the path to the PhantomJS binary | ||
* Add the ability to specify the path to the PhantomJS binary | ||
## 3.0.1 (2015-11-09) | ||
* Support Node.js 5.x | ||
* Support Node.js 5.x | ||
## 3.0.0 (2015-10-16) | ||
* Initial 3.0 release | ||
* Overhaul the API (now uses Truffler 2.0) | ||
* Drop Node.js 0.10 support | ||
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-20-to-30) for details | ||
* Initial 3.0 release | ||
* Overhaul the API (now uses Truffler 2.0) | ||
* Drop Node.js 0.10 support | ||
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-20-to-30) for details | ||
## 2.4.5 (2016-01-05) | ||
* Fix an issue where JSON output was truncated | ||
* Fix an issue where JSON output was truncated | ||
## 2.4.4 (2015-08-20) | ||
* Handle PhantomJS exits better when a timeout occurs | ||
* Handle PhantomJS exits better when a timeout occurs | ||
## 2.4.3 (2015-08-18) | ||
* Add code coverage reporting and increase coverage | ||
* Add code coverage reporting and increase coverage | ||
## 2.4.2 (2015-08-09) | ||
* Update dependencies | ||
* Increase linter coverage | ||
* Update dependencies | ||
* Increase linter coverage | ||
## 2.4.1 (2015-07-13) | ||
* Add a question about proxying to the README | ||
* Add a question about proxying to the README | ||
## 2.4.0 (2015-07-13) | ||
* Add a Markdown reporter | ||
* Update dependencies | ||
* Add a Markdown reporter | ||
* Update dependencies | ||
## 2.3.0 (2015-06-23) | ||
* Add a `wait` option for pages which take time to fully render | ||
* Relax development dependencies | ||
* Add a `wait` option for pages which take time to fully render | ||
* Relax development dependencies | ||
## 2.2.1 (2015-06-19) | ||
* Update the migration guide | ||
* Update the migration guide | ||
## 2.2.0 (2015-06-18) | ||
* Add the ability to specify a HTML CodeSniffer URL/path | ||
* Make sure that the HTML reporter passes WCAG2AA | ||
* Add the ability to specify a HTML CodeSniffer URL/path | ||
* Make sure that the HTML reporter passes WCAG2AA | ||
## 2.1.0 (2015-06-09) | ||
* Add CSS selectors to the results, making it easier to find elements in the page | ||
* Add CSS selectors to the results, making it easier to find elements in the page | ||
## 2.0.2 (2015-06-09) | ||
* Fix a bug caused by PhantomJS stdout | ||
* Fix a bug caused by PhantomJS stdout | ||
## 2.0.1 (2015-06-08) | ||
* Update dependencies | ||
* Update dependencies | ||
## 2.0.0 (2015-06-08) | ||
* Initial 2.0 release | ||
* Full rewrite | ||
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-10-to-20) for details | ||
* Initial 2.0 release | ||
* Full rewrite | ||
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-10-to-20) for details | ||
## 1.7.0 (2015-05-08) | ||
* Add HTML snippets to results for additional context | ||
* Add HTML snippets to results for additional context | ||
## 1.6.3 (2015-01-17) | ||
* Fix memory issues by reducing data sent between node and phantom | ||
* Fix memory issues by reducing data sent between node and phantom | ||
## 1.6.2 (2014-10-07) | ||
* Documentation updates | ||
* Documentation updates | ||
## 1.6.1 (2014-06-27) | ||
* Document the viewport option | ||
* Expose the viewport option to the CLI | ||
* Document the viewport option | ||
* Expose the viewport option to the CLI | ||
## 1.6.0 (2014-06-27) | ||
* Output debug messages to `stderr` | ||
* Output debug messages in the JSON/CSV reporters | ||
* Allow configuring viewport width/height | ||
* Output debug messages to `stderr` | ||
* Output debug messages in the JSON/CSV reporters | ||
* Allow configuring viewport width/height | ||
## 1.5.4 (2014-04-30) | ||
* Increase the timeout for functional tests | ||
* Increase the timeout for functional tests | ||
## 1.5.3 (2014-02-10) | ||
* Add the GPL preamble to all files | ||
* Add the GPL preamble to all files | ||
## 1.5.2 (2014-01-13) | ||
* Fix a formatting issue which caused files generated by the CSV reporter to display incorrectly in Excel | ||
* Fix a formatting issue which caused files generated by the CSV reporter to display incorrectly in Excel | ||
## 1.5.1 (2013-11-26) | ||
* Set default exit status to -1 to not conflict with error count status codes | ||
* Throw a more helpful error when PhantomJS cannot be found | ||
* Set default exit status to -1 to not conflict with error count status codes | ||
* Throw a more helpful error when PhantomJS cannot be found | ||
## 1.5.0 (2013-10-31) | ||
* Allow cookies to be set in-browser, for testing pages which require authentication | ||
* Add "strict mode", where warnings are treated as errors | ||
* Move from Make to Grunt for easier development on Windows | ||
* Full rewrite of the functional tests | ||
* Allow cookies to be set in-browser, for testing pages which require authentication | ||
* Add "strict mode", where warnings are treated as errors | ||
* Move from Make to Grunt for easier development on Windows | ||
* Full rewrite of the functional tests | ||
## 1.4.3 (2013-10-03) | ||
* Remove instances of `process.exit` from the library | ||
* Remove instances of `process.exit` from the library | ||
## 1.4.2 (2013-09-10) | ||
* Fix an issue where a premature exit caused the timer to kill the parent process | ||
* Fix an issue where a premature exit caused the timer to kill the parent process | ||
## 1.4.1 (2013-09-09) | ||
* Fix an issue where HTML CodeSniffer errors can derail Pa11y | ||
* Fix an issue where HTML CodeSniffer errors can derail Pa11y | ||
## 1.4.0 (2013-08-30) | ||
* Allow users to specify a port to run PhantomJS on. This means you can run multiple Pa11y commands in parallel | ||
* Allow users to specify a port to run PhantomJS on. This means you can run multiple Pa11y commands in parallel | ||
## 1.3.0 (2013-08-23) | ||
* Finalise and document the JavaScript API (for non-command-line use) | ||
* Use a custom UserAgent string (pa11y/<version>) | ||
* Allow users to specify their own UserAgent string | ||
* Finalise and document the JavaScript API (for non-command-line use) | ||
* Use a custom UserAgent string (pa11y/<version>) | ||
* Allow users to specify their own UserAgent string | ||
## 1.2.1 (2013-08-16) | ||
* Sanitize local HTMLCS URLs for API consistency | ||
* Sanitize local HTMLCS URLs for API consistency | ||
## 1.2.0 (2013-07-18) | ||
* Add the ability to ignore certain rules through a JSON config file | ||
* Exit with a non-zero code if any "Error" level messages are present in the results | ||
* Simplify the output of the default console reporter | ||
* Large code overhaul and more complete test suite | ||
* Add the ability to ignore certain rules through a JSON config file | ||
* Exit with a non-zero code if any "Error" level messages are present in the results | ||
* Simplify the output of the default console reporter | ||
* Large code overhaul and more complete test suite | ||
## 1.1.0 (2013-07-10) | ||
* Add a CLI option for self-hosted HTML_CodeSniffer | ||
* Fix broken tests on some ISPs | ||
* Add a CLI option for self-hosted HTML_CodeSniffer | ||
* Fix broken tests on some ISPs | ||
## 1.0.1 (2013-06-26) | ||
* Bug fixes | ||
* Bug fixes | ||
## 1.0.0 (2013-06-25) | ||
* Test Windows support | ||
* Final config tweaks for stable release | ||
* Test Windows support | ||
* Final config tweaks for stable release | ||
## 1.0.0-beta.3 pre-release (2013-06-24) | ||
* Documentation updates | ||
* Large-scale refactoring and testing | ||
* Documentation updates | ||
* Large-scale refactoring and testing | ||
## 1.0.0-beta.2 pre-release (2013-06-11) | ||
* Add a `debug` command line option | ||
* Node 0.10.x support | ||
* Add a `debug` command line option | ||
* Node 0.10.x support | ||
## 1.0.0-beta.1 pre-release (2013-06-04) | ||
* Initial release | ||
* Initial release |
@@ -90,5 +90,4 @@ 'use strict'; | ||
try { | ||
/* eslint-disable no-shadow */ | ||
await page.evaluate((selector, value) => { | ||
const target = document.querySelector(selector); | ||
await page.evaluate((targetSelector, desiredValue) => { | ||
const target = document.querySelector(targetSelector); | ||
if (!target) { | ||
@@ -101,5 +100,5 @@ return Promise.reject(new Error('No element found')); | ||
if (prototypeValueSetter) { | ||
prototypeValueSetter.call(target, value); | ||
prototypeValueSetter.call(target, desiredValue); | ||
} else { | ||
target.value = value; | ||
target.value = desiredValue; | ||
} | ||
@@ -111,3 +110,2 @@ target.dispatchEvent(new Event('input', { | ||
}, selector, value); | ||
/* eslint-enable no-shadow */ | ||
} catch (error) { | ||
@@ -129,9 +127,8 @@ throw new Error(`Failed action: no element matching selector "${selector}"`); | ||
try { | ||
/* eslint-disable no-shadow */ | ||
await page.evaluate((selector, checked) => { | ||
const target = document.querySelector(selector); | ||
await page.evaluate((targetSelector, isChecked) => { | ||
const target = document.querySelector(targetSelector); | ||
if (!target) { | ||
return Promise.reject(new Error('No element found')); | ||
} | ||
target.checked = checked; | ||
target.checked = isChecked; | ||
target.dispatchEvent(new Event('change', { | ||
@@ -142,3 +139,2 @@ bubbles: true | ||
}, selector, checked); | ||
/* eslint-enable no-shadow */ | ||
} catch (error) { | ||
@@ -193,10 +189,16 @@ throw new Error(`Failed action: no element matching selector "${selector}"`); | ||
/* eslint-disable no-shadow */ | ||
await page.waitForFunction((property, expectedValue, negated) => { | ||
if (negated) { | ||
return window.location[property] !== expectedValue; | ||
} | ||
return window.location[property] === expectedValue; | ||
}, {}, property, expectedValue, negated); | ||
/* eslint-enable no-shadow */ | ||
function locationHasProperty(locationProperty, value, isNegated) { | ||
return isNegated ? | ||
window.location[locationProperty] !== value : | ||
window.location[locationProperty] === value; | ||
} | ||
await page.waitForFunction( | ||
locationHasProperty, | ||
{}, | ||
property, | ||
expectedValue, | ||
negated | ||
); | ||
} | ||
@@ -215,38 +217,40 @@ }, | ||
/* eslint-disable no-shadow */ | ||
await page.waitForFunction((selector, state) => { | ||
const targetElement = document.querySelector(selector); | ||
await page.waitForFunction((targetSelector, desiredState) => { | ||
const targetElement = document.querySelector(targetSelector); | ||
const statusChecks = { | ||
isAddedOrRemoved: el => | ||
Boolean( | ||
(desiredState === 'added' && el) || | ||
(desiredState === 'removed' && !el) | ||
), | ||
isHiddenOrVisible: isVisible => | ||
Boolean( | ||
(desiredState === 'visible' && isVisible) || | ||
(desiredState === 'hidden' && !isVisible) | ||
), | ||
isTargetVisible: el => | ||
Boolean( | ||
el && | ||
(el.offsetWidth || | ||
el.offsetHeight || | ||
el.getClientRects().length) | ||
) | ||
}; | ||
// Check for added/removed states | ||
if (state === 'added' && targetElement) { | ||
if (statusChecks.isAddedOrRemoved(targetElement)) { | ||
return true; | ||
} | ||
if (state === 'removed' && !targetElement) { | ||
return true; | ||
} | ||
// Check element visibility | ||
let targetElementVisible = false; | ||
if (targetElement) { | ||
targetElementVisible = Boolean( | ||
targetElement.offsetWidth || | ||
targetElement.offsetHeight || | ||
targetElement.getClientRects().length | ||
); | ||
} | ||
const isTargetVisible = statusChecks.isTargetVisible(targetElement); | ||
// Check for visible/hidden states | ||
if (state === 'visible' && targetElementVisible) { | ||
return true; | ||
} | ||
if (state === 'hidden' && !targetElementVisible) { | ||
return true; | ||
} | ||
const isInDesiredVisibilityState = statusChecks.isHiddenOrVisible(isTargetVisible); | ||
// Default to false | ||
return false; | ||
return isInDesiredVisibilityState; | ||
}, { | ||
polling: 200 | ||
}, selector, state); | ||
/* eslint-enable no-shadow */ | ||
} | ||
@@ -265,14 +269,20 @@ }, | ||
try { | ||
/* eslint-disable no-shadow, no-underscore-dangle */ | ||
await page.evaluate((selector, eventType) => { | ||
const target = document.querySelector(selector); | ||
if (!target) { | ||
return Promise.reject(new Error('No element found')); | ||
} | ||
target.addEventListener(eventType, () => { | ||
window._pa11yWaitForElementEventFired = true; | ||
}, { | ||
once: true | ||
}); | ||
}, selector, eventType); | ||
/* eslint-disable no-underscore-dangle */ | ||
await page.evaluate( | ||
(targetSelector, desiredEvent) => { | ||
const target = document.querySelector(targetSelector); | ||
if (!target) { | ||
return Promise.reject( | ||
new Error('No element found') | ||
); | ||
} | ||
target.addEventListener(desiredEvent, () => { | ||
window._pa11yWaitForElementEventFired = true; | ||
}, { | ||
once: true | ||
}); | ||
}, | ||
selector, | ||
eventType | ||
); | ||
await page.waitForFunction(() => { | ||
@@ -287,3 +297,3 @@ if (window._pa11yWaitForElementEventFired) { | ||
}); | ||
/* eslint-enable no-shadow, no-underscore-dangle */ | ||
/* eslint-enable no-underscore-dangle */ | ||
} catch (error) { | ||
@@ -290,0 +300,0 @@ throw new Error(`Failed action: no element matching selector "${selector}"`); |
413
lib/pa11y.js
@@ -22,3 +22,3 @@ 'use strict'; | ||
* @public | ||
* @param {String} [url] - The URL to run tests against. | ||
* @param {String} url - The URL to run tests against. | ||
* @param {Object} [options={}] - Options to change the way tests run. | ||
@@ -30,23 +30,7 @@ * @param {Function} [callback] - An optional callback to use instead of promises. | ||
const state = {}; | ||
let pa11yError; | ||
let pa11yResults; | ||
[url, options, callback] = parseArguments(url, options, callback); | ||
/* eslint-disable prefer-rest-params */ | ||
// Check for presence of a callback function | ||
if (typeof arguments[arguments.length - 1] === 'function') { | ||
callback = arguments[arguments.length - 1]; | ||
} else { | ||
callback = undefined; | ||
} | ||
/* eslint-enable prefer-rest-params */ | ||
try { | ||
// Switch parameters if only an options object is provided, | ||
// and default the options | ||
if (typeof url !== 'string') { | ||
options = url; | ||
url = options.url; | ||
} | ||
url = sanitizeUrl(url); | ||
options = defaultOptions(options); | ||
// Verify that the given options are valid | ||
@@ -57,3 +41,3 @@ verifyOptions(options); | ||
// a timeout if it takes too long | ||
const results = await promiseTimeout( | ||
pa11yResults = await promiseTimeout( | ||
runPa11yTest(url, options, state), | ||
@@ -63,22 +47,57 @@ options.timeout, | ||
); | ||
// Run callback if present, and resolve with results | ||
} catch (error) { | ||
// Capture error if a callback is provided, otherwise reject with error | ||
if (callback) { | ||
return callback(null, results); | ||
pa11yError = error; | ||
} else { | ||
throw error; | ||
} | ||
return results; | ||
} finally { | ||
await stateCleanup(state); | ||
} | ||
// Run callback if present, and resolve with pa11yResults | ||
return callback ? callback(pa11yError, pa11yResults) : pa11yResults; | ||
} | ||
} catch (error) { | ||
if (state.browser && state.autoClose) { | ||
state.browser.close(); | ||
} else if (state.page && state.autoClosePage) { | ||
state.page.close(); | ||
} | ||
/** | ||
* Parse arguments from the command-line to properly identify the url, options, and callback | ||
* @private | ||
* @param {String} url - The URL to run tests against. | ||
* @param {Object} [options={}] - Options to change the way tests run. | ||
* @param {Function} [callback] - An optional callback to use instead of promises. | ||
* @returns {Array} the new values of url, options, and callback | ||
*/ | ||
function parseArguments(url, options, callback) { | ||
if (!callback && typeof options === 'function') { | ||
callback = options; | ||
options = {}; | ||
} | ||
if (typeof url !== 'string') { | ||
options = url; | ||
url = options.url; | ||
} | ||
url = sanitizeUrl(url); | ||
options = defaultOptions(options); | ||
// Run callback if present, and reject with error | ||
if (callback) { | ||
return callback(error); | ||
} | ||
throw error; | ||
return [url, | ||
options, | ||
callback]; | ||
} | ||
/** | ||
* Default the passed in options using Pa11y's defaults. | ||
* @private | ||
* @param {Object} [options] - The options to apply defaults to. | ||
* @returns {Object} Returns the defaulted options. | ||
*/ | ||
function defaultOptions(options) { | ||
options = extend({}, pa11y.defaults, options); | ||
options.ignore = options.ignore.map(ignored => ignored.toLowerCase()); | ||
if (!options.includeNotices) { | ||
options.ignore.push('notice'); | ||
} | ||
if (!options.includeWarnings) { | ||
options.ignore.push('warning'); | ||
} | ||
return options; | ||
} | ||
@@ -89,5 +108,6 @@ | ||
* @private | ||
* @param {String} [url] - The URL to run tests against. | ||
* @param {Object} [options] - Options to change the way tests run. | ||
* @param {Object} [state] - An object state information will be added to. | ||
* @param {String} url - The URL to run tests against. | ||
* @param {Object} options - Options to change the way tests run. | ||
* @param {Object} state - The current pa11y internal state, fields will be mutated by | ||
* this function. | ||
* @returns {Promise} Returns a promise which resolves with a results object. | ||
@@ -99,8 +119,64 @@ */ | ||
// Check whether we have a browser already | ||
let browser; | ||
let page; | ||
await setBrowser(options, state); | ||
await setPage(options, state); | ||
await interceptRequests(options, state); | ||
await gotoUrl(url, options, state); | ||
await runActionsList(options, state); | ||
await injectRunners(options, state); | ||
// Launch the test runner! | ||
options.log.debug('Running Pa11y on the page'); | ||
/* istanbul ignore next */ | ||
if (options.wait > 0) { | ||
options.log.debug(`Waiting for ${options.wait}ms`); | ||
} | ||
const results = await runPa11yWithOptions(options, state); | ||
options.log.debug(`Document title: "${results.documentTitle}"`); | ||
await saveScreenCapture(options, state); | ||
return results; | ||
} | ||
/** | ||
* Ensures that puppeteer resources are freed and listeners removed. | ||
* @private | ||
* @param {Object} state - The last-known state of the test-run. | ||
* @returns {Promise} A promise which resolves when resources are released | ||
*/ | ||
async function stateCleanup(state) { | ||
if (state.browser && state.autoClose) { | ||
await state.browser.close(); | ||
} else if (state.page) { | ||
state.page.removeListener('request', state.requestInterceptCallback); | ||
state.page.removeListener('console', state.consoleCallback); | ||
if (state.autoClosePage) { | ||
await state.page.close(); | ||
} | ||
} | ||
} | ||
/** | ||
* Sets or initialises the browser. | ||
* @private | ||
* @param {Object} options - Options to change the way tests run. | ||
* @param {Object} state - The current pa11y internal state, fields will be mutated by | ||
* this function. | ||
* @returns {Promise} A promise which resolves when resources are released | ||
*/ | ||
async function setBrowser(options, state) { | ||
if (options.browser) { | ||
options.log.debug('Using a pre-configured Headless Chrome instance, the `chromeLaunchConfig` option will be ignored'); | ||
browser = state.browser = options.browser; | ||
options.log.debug( | ||
'Using a pre-configured Headless Chrome instance, ' + | ||
'the `chromeLaunchConfig` option will be ignored' | ||
); | ||
state.browser = options.browser; | ||
state.autoClose = false; | ||
@@ -112,14 +188,48 @@ } else { | ||
options.log.debug('Launching Headless Chrome'); | ||
browser = state.browser = await puppeteer.launch(options.chromeLaunchConfig); | ||
state.browser = await puppeteer.launch( | ||
options.chromeLaunchConfig | ||
); | ||
state.autoClose = true; | ||
} | ||
} | ||
/** | ||
* Configures the browser page to be used for the test. | ||
* @private | ||
* @param {Object} [options] - Options to change the way tests run. | ||
* @param {Object} state - The current pa11y internal state, fields will be mutated by | ||
* this function. | ||
* @returns {Promise} A promise which resolves when the page has been configured. | ||
*/ | ||
async function setPage(options, state) { | ||
if (options.browser && options.page) { | ||
page = state.page = options.page; | ||
state.page = options.page; | ||
state.autoClosePage = false; | ||
} else { | ||
page = state.page = await browser.newPage(); | ||
state.page = await state.browser.newPage(); | ||
state.autoClosePage = true; | ||
} | ||
// Listen for console logs on the page so that we can | ||
// output them for debugging purposes | ||
state.consoleCallback = message => { | ||
options.log.debug(`Browser Console: ${message.text()}`); | ||
}; | ||
state.page.on('console', state.consoleCallback); | ||
options.log.debug('Opening URL in Headless Chrome'); | ||
if (options.userAgent) { | ||
await state.page.setUserAgent(options.userAgent); | ||
} | ||
await state.page.setViewport(options.viewport); | ||
} | ||
/** | ||
* Configures the browser page to intercept requests if necessary | ||
* @private | ||
* @param {Object} [options] - Options to change the way tests run. | ||
* @param {Object} state - The current pa11y internal state, fields will be mutated by | ||
* this function. | ||
* @returns {Promise} A promise which resolves immediately if no listeners are necessary | ||
* or after listener functions have been attached. | ||
*/ | ||
async function interceptRequests(options, state) { | ||
// Avoid to use `page.setRequestInterception` when not necessary | ||
@@ -129,76 +239,92 @@ // because it occasionally stops page load: | ||
// https://github.com/GoogleChrome/puppeteer/issues/3121 | ||
if ((options.headers && Object.keys(options.headers).length) || | ||
const shouldInterceptRequests = | ||
(options.headers && Object.keys(options.headers).length) || | ||
(options.method && options.method.toLowerCase() !== 'get') || | ||
options.postData) { | ||
options.postData; | ||
// Intercept page requests, we need to do this in order | ||
// to set the HTTP method or post data | ||
await page.setRequestInterception(true); | ||
if (!shouldInterceptRequests) { | ||
return; | ||
} | ||
// Intercept page requests, we need to do this in order | ||
// to set the HTTP method or post data | ||
await state.page.setRequestInterception(true); | ||
// Intercept requests so we can set the HTTP method | ||
// and post data. We only want to make changes to the | ||
// first request that's handled, which is the request | ||
// for the page we're testing | ||
let interceptionHandled = false; | ||
page.on('request', interceptedRequest => { | ||
const overrides = {}; | ||
if (!interceptionHandled) { | ||
// Intercept requests so we can set the HTTP method | ||
// and post data. We only want to make changes to the | ||
// first request that's handled, which is the request | ||
// for the page we're testing | ||
let interceptionHandled = false; | ||
state.requestInterceptCallback = interceptedRequest => { | ||
const overrides = {}; | ||
if (!interceptionHandled) { | ||
// Override the request method | ||
options.log.debug('Setting request method'); | ||
overrides.method = options.method; | ||
// Override the request method | ||
options.log.debug('Setting request method'); | ||
overrides.method = options.method; | ||
// Override the request headers (and include the user-agent) | ||
options.log.debug('Setting request headers'); | ||
overrides.headers = {}; | ||
for (const [key, value] of Object.entries(options.headers)) { | ||
overrides.headers[key.toLowerCase()] = value; | ||
} | ||
// Override the request headers (and include the user-agent) | ||
options.log.debug('Setting request headers'); | ||
overrides.headers = {}; | ||
for (const [key, value] of Object.entries(options.headers)) { | ||
overrides.headers[key.toLowerCase()] = value; | ||
} | ||
// Override the request POST data if present | ||
if (options.postData) { | ||
options.log.debug('Setting request POST data'); | ||
overrides.postData = options.postData; | ||
} | ||
interceptionHandled = true; | ||
// Override the request POST data if present | ||
if (options.postData) { | ||
options.log.debug('Setting request POST data'); | ||
overrides.postData = options.postData; | ||
} | ||
interceptedRequest.continue(overrides); | ||
}); | ||
} | ||
// Listen for console logs on the page so that we can | ||
// output them for debugging purposes | ||
page.on('console', message => { | ||
options.log.debug(`Browser Console: ${message.text()}`); | ||
}); | ||
interceptionHandled = true; | ||
} | ||
interceptedRequest.continue(overrides); | ||
}; | ||
state.page.on('request', state.requestInterceptCallback); | ||
} | ||
options.log.debug('Opening URL in Headless Chrome'); | ||
const gotoConfig = {waitUntil: 'networkidle2'}; | ||
gotoConfig.timeout = options.timeout; | ||
if (options.userAgent) { | ||
// Set the user agent | ||
await page.setUserAgent(options.userAgent); | ||
} | ||
// Resize the viewport | ||
await page.setViewport(options.viewport); | ||
/** | ||
* Instructs the page to go to the provided url unless options.ignoreUrl is true | ||
* @private | ||
* @param {String} [url] - The URL of the page to be tested. | ||
* @param {Object} [options] - Options to change the way tests run. | ||
* @param {Object} state - The current pa11y internal state, fields will be mutated by | ||
* this function. | ||
* @returns {Promise} A promise which resolves when the page URL has been set | ||
*/ | ||
async function gotoUrl(url, options, state) { | ||
// Navigate to the URL we're going to test | ||
if (!options.ignoreUrl) { | ||
await page.goto(url, gotoConfig); | ||
await state.page.goto(url, { | ||
waitUntil: 'networkidle2', | ||
timeout: options.timeout | ||
}); | ||
} | ||
} | ||
// Run actions | ||
/** | ||
* Carries out a synchronous list of actions in the page | ||
* @private | ||
* @param {Object} options - Options to change the way tests run. | ||
* @param {Object} state - The current pa11y internal state, fields will be mutated by | ||
* this function. | ||
* @returns {Promise} A promise which resolves when all actions have completed | ||
*/ | ||
async function runActionsList(options, state) { | ||
if (options.actions.length) { | ||
options.log.info('Running actions'); | ||
for (const action of options.actions) { | ||
await runAction(browser, page, options, action); | ||
await runAction(state.browser, state.page, options, action); | ||
} | ||
options.log.info('Finished running actions'); | ||
} | ||
} | ||
// Load the test runners and Pa11y client-side scripts if required | ||
/** | ||
* Loads the test runners and Pa11y client-side scripts if required | ||
* @private | ||
* @param {Object} options - Options to change the way tests run. | ||
* @param {Object} state - The current pa11y internal state, fields will be mutated by | ||
* this function. | ||
* @returns {Promise} A promise which resolves when all runners have been injected and evaluated | ||
*/ | ||
async function injectRunners(options, state) { | ||
// We only load these files once on the first run of Pa11y as they don't | ||
@@ -218,18 +344,23 @@ // change between runs | ||
options.log.debug('Injecting Pa11y'); | ||
await page.evaluate(await runnerJavascriptPromises.pa11y); | ||
await state.page.evaluate(await runnerJavascriptPromises.pa11y); | ||
for (const runner of options.runners) { | ||
options.log.debug(`Injecting runner: ${runner}`); | ||
const script = await runnerJavascriptPromises[runner]; | ||
await page.evaluate(script); | ||
await state.page.evaluate(script); | ||
} | ||
} | ||
// Launch the test runner! | ||
options.log.debug('Running Pa11y on the page'); | ||
/* istanbul ignore next */ | ||
if (options.wait > 0) { | ||
options.log.debug(`Waiting for ${options.wait}ms`); | ||
} | ||
/* eslint-disable no-shadow, no-underscore-dangle */ | ||
const results = await page.evaluate(options => { | ||
return window.__pa11y.run(options); | ||
/** | ||
* Sends a request to the page to instruct the injected pa11y script to run with the | ||
* provided options | ||
* @private | ||
* @param {Object} options - Options to change the way tests run. | ||
* @param {Object} state - The current pa11y internal state, fields will be mutated by | ||
* this function. | ||
* @returns {Promise} A promise which resolves with the results of the pa11y evaluation | ||
*/ | ||
function runPa11yWithOptions(options, state) { | ||
/* eslint-disable no-underscore-dangle */ | ||
return state.page.evaluate(runOptions => { | ||
return window.__pa11y.run(runOptions); | ||
}, { | ||
@@ -245,11 +376,21 @@ hideElements: options.hideElements, | ||
}); | ||
/* eslint-enable no-shadow, no-underscore-dangle */ | ||
/* eslint-enable no-underscore-dangle */ | ||
} | ||
options.log.debug(`Document title: "${results.documentTitle}"`); | ||
/** | ||
* Generates a screen capture if required by the provided options | ||
* @private | ||
* @param {Object} options - Options to change the way tests run. | ||
* @param {Object} state - The current pa11y internal state, fields will be mutated by | ||
* this function. | ||
* @returns {Promise} A promise which resolves when the screenshot is complete | ||
*/ | ||
async function saveScreenCapture(options, state) { | ||
// Generate a screen capture | ||
if (options.screenCapture) { | ||
options.log.info(`Capturing screen, saving to "${options.screenCapture}"`); | ||
options.log.info( | ||
`Capturing screen, saving to "${options.screenCapture}"` | ||
); | ||
try { | ||
await page.screenshot({ | ||
await state.page.screenshot({ | ||
path: options.screenCapture, | ||
@@ -262,34 +403,8 @@ fullPage: true | ||
} | ||
// Close the browser and return the Pa11y results | ||
if (state.autoClose) { | ||
await browser.close(); | ||
} else if (state.autoClosePage) { | ||
await page.close(); | ||
} | ||
return results; | ||
} | ||
/** | ||
* Default the passed in options using Pa11y's defaults. | ||
* @private | ||
* @param {Object} [options={}] - The options to apply defaults to. | ||
* @returns {Object} Returns the defaulted options. | ||
*/ | ||
function defaultOptions(options) { | ||
options = extend({}, pa11y.defaults, options); | ||
options.ignore = options.ignore.map(ignored => ignored.toLowerCase()); | ||
if (!options.includeNotices) { | ||
options.ignore.push('notice'); | ||
} | ||
if (!options.includeWarnings) { | ||
options.ignore.push('warning'); | ||
} | ||
return options; | ||
} | ||
/** | ||
* Verify that passed in options are valid. | ||
* @private | ||
* @param {Object} [options={}] - The options to verify. | ||
* @param {Object} options - The options to verify. | ||
* @returns {Undefined} Returns nothing. | ||
@@ -365,3 +480,3 @@ * @throws {Error} Throws if options are not valid. | ||
* Loads a runner script | ||
* @param runner | ||
* @param {String} runner - The name of the runner. | ||
* @throws {Error} Throws an error if the reporter does not support the given version of Pa11y | ||
@@ -388,5 +503,3 @@ * @returns {Promise<String>} Promise | ||
/* istanbul ignore next */ | ||
/* eslint-disable no-empty-function */ | ||
const noop = () => {}; | ||
/* eslint-enable no-empty-function */ | ||
const noop = () => { /* No-op */ }; | ||
@@ -423,3 +536,3 @@ /** | ||
screenCapture: null, | ||
standard: 'WCAG2AA', // DONE | ||
standard: 'WCAG2AA', | ||
timeout: 30000, | ||
@@ -426,0 +539,0 @@ userAgent: `pa11y/${pkg.version}`, |
@@ -34,3 +34,3 @@ 'use strict'; | ||
if (typeof method !== 'function') { | ||
method = () => {}; | ||
method = () => { /* NoOp */ }; | ||
} | ||
@@ -37,0 +37,0 @@ return async input => { |
{ | ||
"name": "pa11y", | ||
"version": "5.3.0", | ||
"version": "6.0.0-alpha", | ||
"description": "Pa11y is your automated accessibility testing pal", | ||
@@ -36,21 +36,22 @@ "keywords": [ | ||
"commander": "^3.0.2", | ||
"envinfo": "^7.5.0", | ||
"node.extend": "^2.0.2", | ||
"p-timeout": "^2.0.1", | ||
"pa11y-reporter-cli": "^1.0.1", | ||
"pa11y-reporter-csv": "^1.0.0", | ||
"pa11y-reporter-json": "^1.0.0", | ||
"pa11y-runner-axe": "^1.0.1", | ||
"pa11y-runner-htmlcs": "^1.2.0", | ||
"puppeteer": "^1.13.0", | ||
"semver": "^5.6.0" | ||
"pa11y-reporter-cli": "^2.0.0", | ||
"pa11y-reporter-csv": "^2.0.0", | ||
"pa11y-reporter-json": "^2.0.0", | ||
"pa11y-runner-axe": "^2.0.0", | ||
"pa11y-runner-htmlcs": "^2.0.0", | ||
"puppeteer": "^2.1.1", | ||
"semver": "^5.7.1" | ||
}, | ||
"devDependencies": { | ||
"@rowanmanning/make": "^1.0.1", | ||
"eslint": "^6.0.1", | ||
"mocha": "^6.1.4", | ||
"mockery": "^2.0.0", | ||
"nyc": "~13.2.0", | ||
"@rowanmanning/make": "^2.1.0", | ||
"eslint": "^6.8.0", | ||
"mocha": "^7.1.1", | ||
"mockery": "^2.1.0", | ||
"nyc": "^15.0.1", | ||
"pa11y-lint-config": "^1.2.1", | ||
"proclaim": "^3.5.1", | ||
"sinon": "^7.0.0" | ||
"proclaim": "^3.6.0", | ||
"sinon": "^9.0.2" | ||
}, | ||
@@ -57,0 +58,0 @@ "main": "./lib/pa11y.js", |
@@ -12,8 +12,2 @@ | ||
--- | ||
:sparkles: ☑️ 👩🎨 **Hi! We’re working on improving the design and usability of the Pa11y website. You can help us enormously by [filling in our survey](https://forms.gle/ZJzFwbC7DCVT2CNh7). Thanks!** | ||
--- | ||
On the command line: | ||
@@ -61,4 +55,9 @@ | ||
On a Mac, you can install the required dependency with [Homebrew][brew]: | ||
To install [Node.js][node] you can use [nvm][nvm]: | ||
```sh | ||
$ nvm install node | ||
``` | ||
Alternatively on a Mac, you can install the required dependency with [Homebrew][brew]: | ||
```sh | ||
@@ -68,3 +67,3 @@ $ brew install node | ||
Alternatively download pre-built packages from the [Node.js][node] website. | ||
You can also download pre-built packages from the [Node.js][node] website. | ||
@@ -1023,2 +1022,3 @@ ### Linux | ||
[npm]: https://www.npmjs.com/ | ||
[nvm]: https://github.com/nvm-sh/nvm | ||
[promise]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise | ||
@@ -1025,0 +1025,0 @@ [puppeteer-browser]: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-browser |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
96914
1324
0
11
1
+ Addedenvinfo@^7.5.0
+ Added@types/mime-types@2.1.4(transitive)
+ Addedagent-base@5.1.1(transitive)
+ Addedaxe-core@4.10.2(transitive)
+ Addedbfj@7.1.0(transitive)
+ Addedbluebird@3.7.2(transitive)
+ Addedcheck-types@11.2.3(transitive)
+ Addeddeep-is@0.1.4(transitive)
+ Addedenvinfo@7.14.0(transitive)
+ Addedescodegen@1.14.3(transitive)
+ Addedesprima@1.2.24.0.1(transitive)
+ Addedestraverse@4.3.0(transitive)
+ Addedesutils@2.0.3(transitive)
+ Addedfast-levenshtein@2.0.6(transitive)
+ Addedhtml_codesniffer@2.5.1(transitive)
+ Addedhttps-proxy-agent@4.0.0(transitive)
+ Addedjsonpath@1.1.1(transitive)
+ Addedkleur@4.1.5(transitive)
+ Addedlevn@0.3.0(transitive)
+ Addedmime-db@1.52.0(transitive)
+ Addedmime-types@2.1.35(transitive)
+ Addedoptionator@0.8.3(transitive)
+ Addedpa11y-reporter-cli@2.0.1(transitive)
+ Addedpa11y-reporter-csv@2.0.1(transitive)
+ Addedpa11y-reporter-json@2.0.1(transitive)
+ Addedpa11y-runner-axe@2.0.1(transitive)
+ Addedpa11y-runner-htmlcs@2.0.1(transitive)
+ Addedprelude-ls@1.1.2(transitive)
+ Addedpuppeteer@2.1.1(transitive)
+ Addedsource-map@0.6.1(transitive)
+ Addedstatic-eval@2.0.2(transitive)
+ Addedtype-check@0.3.2(transitive)
+ Addedunderscore@1.12.1(transitive)
+ Addedword-wrap@1.2.5(transitive)
- Removedagent-base@4.3.0(transitive)
- Removedansi-styles@3.2.1(transitive)
- Removedaxe-core@3.5.6(transitive)
- Removedbfj@4.2.4(transitive)
- Removedchalk@2.4.2(transitive)
- Removedcheck-types@7.4.0(transitive)
- Removedcolor-convert@1.9.3(transitive)
- Removedcolor-name@1.1.3(transitive)
- Removeddebug@3.2.7(transitive)
- Removedes6-promise@4.2.8(transitive)
- Removedes6-promisify@5.0.0(transitive)
- Removedescape-string-regexp@1.0.5(transitive)
- Removedhas-flag@3.0.0(transitive)
- Removedhtml_codesniffer@2.4.1(transitive)
- Removedhttps-proxy-agent@2.2.4(transitive)
- Removedpa11y-reporter-cli@1.0.1(transitive)
- Removedpa11y-reporter-csv@1.0.0(transitive)
- Removedpa11y-reporter-json@1.0.0(transitive)
- Removedpa11y-runner-axe@1.0.2(transitive)
- Removedpa11y-runner-htmlcs@1.2.1(transitive)
- Removedpuppeteer@1.20.0(transitive)
- Removedsupports-color@5.5.0(transitive)
Updatedpa11y-reporter-cli@^2.0.0
Updatedpa11y-reporter-csv@^2.0.0
Updatedpa11y-reporter-json@^2.0.0
Updatedpa11y-runner-axe@^2.0.0
Updatedpa11y-runner-htmlcs@^2.0.0
Updatedpuppeteer@^2.1.1
Updatedsemver@^5.7.1