Socket
Socket
Sign inDemoInstall

axe-core

Package Overview
Dependencies
Maintainers
4
Versions
1362
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

axe-core - npm Package Compare versions

Comparing version 3.0.2 to 3.0.3

build/tasks/aria-supported.js

9

.github/PULL_REQUEST_TEMPLATE.md
## PR Checklist
Please check if your PR fulfills the following requirements:

@@ -11,12 +12,10 @@

## Description of the changes
- Github issue:
## Does this PR introduce a breaking change?
```
[ ] Yes
[ ] No
```
- [ ] Yes
- [ ] No
## Other information

@@ -7,12 +7,7 @@ {

"MD006": false,
"MD007": false,
"MD009": false,
"MD010": false,
"MD012": false,
"MD013": false,
"MD022": false,
"MD024": false,
"MD026": false,
"MD029": false,
"MD030": false,
"MD031": false,

@@ -23,4 +18,3 @@ "MD032": false,

"MD036": false,
"MD040": false,
"MD041": false
}

@@ -15,2 +15,4 @@ // Type definitions for axe-core 3.0.2

type resultGroups = "inapplicable" | "passes" | "incomplete" | "violations";
type RunOnlyObject = {

@@ -34,3 +36,4 @@ include?: string[] | string[][],

elementRef?: Boolean,
selectors?: Boolean
selectors?: Boolean,
resultTypes?: resultGroups[],
}

@@ -37,0 +40,0 @@ interface AxeResults {

{
"name": "axe-core",
"version": "3.0.2",
"version": "3.0.3",
"contributors": [

@@ -46,2 +46,2 @@ {

"devDependencies": {}
}
}

@@ -9,5 +9,5 @@ /*eslint-env node */

var buildManual = require('./build-manual');
var entities = new (require('html-entities').AllHtmlEntities)();
var entities = new (require('html-entities').AllHtmlEntities)();
var descriptionHeaders = '| Rule ID | Description | Tags | Enabled by default |\n| :------- | :------- | :------- | :------- |\n';
var descriptionHeaders = '| Rule ID | Description | Impact | Tags | Enabled by default |\n| :------- | :------- | :------- | :------- | :------- |\n';

@@ -28,2 +28,3 @@ dot.templateSettings.strip = false;

function buildRules(grunt, options, commons, callback) {
var axeImpact = Object.freeze(['minor', 'moderate', 'serious', 'critical']); // TODO: require('../axe') does not work if grunt configure is moved after uglify, npm test breaks with undefined. Complicated grunt concurrency issue.
var locale = getLocale(grunt, options);

@@ -33,2 +34,20 @@ options.getFiles = false;

var metadata = {
rules: {},
checks: {}
};
var descriptions = [];
var tags = options.tags ? options.tags.split(/\s*,\s*/) : [];
var rules = result.rules;
var checks = result.checks;
// Translate checks
if (locale && locale.checks) {
checks.forEach(function (check) {
if (locale.checks[check.id] && check.metadata) {
check.metadata.messages = locale.checks[check.id];
}
})
}
function parseMetaData(source, propType) {

@@ -70,3 +89,3 @@ var data = source.metadata

var result = {};
summaries.forEach(function(summary) {
summaries.forEach(function (summary) {
if (summary.incompleteFallbackMessage) {

@@ -79,3 +98,2 @@ result = dot.template(summary.incompleteFallbackMessage).toString();

function replaceFunctions(string) {

@@ -89,3 +107,2 @@ return string.replace(/"(evaluate|after|gather|matches|source|commons)":\s*("[^"]+?")/g, function (m, p1, p2) {

});
}

@@ -116,23 +133,2 @@

var metadata = {
rules: {},
checks: {}
};
var descriptions = [];
var tags = options.tags ? options.tags.split(/\s*,\s*/) : [];
var rules = result.rules;
var checks = result.checks;
// Translate checks
if (locale && locale.checks) {
checks.forEach(function (check) {
if (locale.checks[check.id] && check.metadata) {
check.metadata.messages = locale.checks[check.id]
}
})
}
function parseChecks(collection) {

@@ -155,15 +151,73 @@ return collection.map(function (check) {

});
}
function parseImpactForRule(rule) {
function capitalize(s) {
return s.charAt(0).toUpperCase() + s.slice(1);
}
function getUniqueArr(arr) {
return arr.filter(function (value, index, self) {
return self.indexOf(value) === index;
})
}
function getImpactScores(checkCollection) {
return checkCollection.reduce(function (out, check) {
var id = typeof check === 'string' ? check : check.id;
var definition = clone(findCheck(checks, id));
if (!definition) {
grunt.log.error('check ' + id + ' not found');
}
if (definition && definition.metadata && definition.metadata.impact) {
var impactScore = axeImpact.indexOf(definition.metadata.impact);
out.push(impactScore);
}
return out;
}, []);
}
function getScore(checkCollection, onlyHighestScore) {
var scores = getImpactScores(checkCollection);
if (scores && scores.length) {
return onlyHighestScore
? [Math.max.apply(null, scores)]
: getUniqueArr(scores);
} else {
return [];
}
}
var highestImpactForRuleTypeAny = getScore(rule.any, true);
var allUniqueImpactsForRuleTypeAll = getScore(rule.all, false);
var allUniqueImpactsForRuleTypeNone = getScore(rule.none, false);
var cumulativeImpacts = highestImpactForRuleTypeAny.concat(allUniqueImpactsForRuleTypeAll).concat(allUniqueImpactsForRuleTypeNone);
var cumulativeScores = getUniqueArr(cumulativeImpacts).sort(); //order lowest to highest
return cumulativeScores.reduce(function (out, cV) {
return out.length
? out + ', ' + capitalize(axeImpact[cV])
: capitalize(axeImpact[cV]);
}, '');
}
rules.map(function (rule) {
var impact = parseImpactForRule(rule);
rule.any = parseChecks(rule.any);
rule.all = parseChecks(rule.all);
rule.none = parseChecks(rule.none);
if (rule.metadata && !metadata.rules[rule.id]) {
// Translate rules
metadata.rules[rule.id] = parseMetaData(rule, 'rules');
metadata.rules[rule.id] = parseMetaData(rule, 'rules'); // Translate rules
}
descriptions.push([rule.id, entities.encode(rule.metadata.description), rule.tags.join(', '), rule.enabled === false ? false : true]);
descriptions.push([
rule.id,
entities.encode(rule.metadata.description),
impact,
rule.tags.join(', '),
rule.enabled === false ? false : true
]);
if (tags.length) {

@@ -170,0 +224,0 @@ rule.enabled = !!rule.tags.filter(function (t) {

/*global window */
/*eslint-env node */
/*eslint
max-statements: ["error", 20],
*/
'use strict';

@@ -15,2 +17,3 @@

function collectTestResults(driver) {
// inject a script that waits half a second

@@ -29,3 +32,3 @@ return driver.executeAsyncScript(function () {

// if there are, return them
// if there are, return them
} else {

@@ -40,3 +43,3 @@ return Promise.resolve(result);

*/
function runTestUrls(driver, urls, errors) {
function runTestUrls(driver, isMobile, urls, errors) {
var url = urls.shift();

@@ -46,3 +49,3 @@ errors = errors || [];

// Give each page enough time
driver.manage().timeouts().setScriptTimeout(60000);
driver.manage().timeouts().setScriptTimeout(!isMobile ? 60000 * 5 : (60000 * 10));

@@ -53,5 +56,5 @@ return driver.get(url)

return collectTestResults(driver);
})
// And process them
}).then(function (result) {
.then(function (result) {
grunt.log.writeln(url);

@@ -67,6 +70,6 @@

// Log the result of the page tests
grunt.log[ (result.failures ? 'error' : 'ok') ](
grunt.log[(result.failures ? 'error' : 'ok')](
'passes: ' + result.passes + ', ' +
'failures: ' + result.failures + ', ' +
'duration: ' + (result.duration / 1000) +'s'
'duration: ' + (result.duration / 1000) + 's'
);

@@ -78,3 +81,3 @@ grunt.log.writeln();

if (urls.length > 0) {
return runTestUrls(driver, urls, errors);
return runTestUrls(driver, isMobile, urls, errors);
} else {

@@ -91,3 +94,4 @@ driver.quit();

function buildWebDriver(browser) {
var webdriver, capabilities;
var webdriver,
capabilities;
var mobileBrowser = browser.split('-mobile');

@@ -97,3 +101,3 @@ if (mobileBrowser.length > 1) {

capabilities = {
browserName: mobileBrowser[0],
browserName: mobileBrowser[0],
chromeOptions: {

@@ -110,4 +114,5 @@ mobileEmulation: {

}
if (process.env.REMOTE_SELENIUM_URL) {
webdriver = new WebDriver.Builder()
webdriver = new WebDriver.Builder()
.forBrowser(browser)

@@ -124,3 +129,6 @@ .withCapabilities(capabilities)

return webdriver;
return {
driver: webdriver,
isMobile: (mobileBrowser.length > 1)
};
}

@@ -135,2 +143,3 @@

var driver;
var isMobile = false;
var done = this.async();

@@ -145,5 +154,5 @@ var options = this.options({

if ((process.platform === 'win32' && options.browser === 'safari') ||
(process.platform === 'darwin' && ['ie', 'MicrosoftEdge'].indexOf(options.browser) !== -1) ||
((process.platform === 'linux' || process.env.REMOTE_SELENIUM_URL) &&
['ie', 'MicrosoftEdge', 'safari'].indexOf(options.browser) !== -1)
(process.platform === 'darwin' && ['ie', 'MicrosoftEdge'].indexOf(options.browser) !== -1) ||
((process.platform === 'linux' || process.env.REMOTE_SELENIUM_URL) &&
['ie', 'MicrosoftEdge', 'safari'].indexOf(options.browser) !== -1)
) {

@@ -157,5 +166,6 @@ grunt.log.writeln();

try {
driver = buildWebDriver(options.browser);
// If load fails, warn user and move to the next task
var webDriver = buildWebDriver(options.browser);
driver = webDriver.driver;
isMobile = webDriver.isMobile;
// If load fails, warn user and move to the next task
} catch (err) {

@@ -169,6 +179,6 @@ grunt.log.writeln();

// Test all pages
runTestUrls(driver, options.urls)
runTestUrls(driver, isMobile, options.urls)
.then(function (testErrors) {
// log each error and abort
testErrors.forEach(function(err) {
testErrors.forEach(function (err) {
grunt.log.writeln();

@@ -185,3 +195,3 @@ grunt.log.error('URL: ' + err.url);

// catch any potential problems
// catch any potential problems
}).catch(function (err) {

@@ -188,0 +198,0 @@ grunt.log.error(err);

@@ -28,2 +28,3 @@ exports = module.exports = function (grunt, options) {

run: true,
growlOnSuccess: false,
mocha: {

@@ -40,2 +41,3 @@ grep: grunt.option('grep')

run: true,
growlOnSuccess: false,
mocha: {

@@ -42,0 +44,0 @@ grep: grunt.option('grep')

@@ -5,3 +5,30 @@ # Change Log

<a name="3.0.3"></a>
## [3.0.3](https://github.com/dequelabs/axe-core/compare/v3.0.2...v3.0.3) (2018-06-04)
### Bug Fixes
* Resolve markdown lint errors. ([efdad94](https://github.com/dequelabs/axe-core/commit/efdad94)) ([aa90155](https://github.com/dequelabs/axe-core/commit/aa90155))
* Don't require all ARIA IDREFS to exist ([#921](https://github.com/dequelabs/axe-core/issues/921)) ([130efed](https://github.com/dequelabs/axe-core/commit/130efed))
* generate unsupported aria roles and attributes. ([7315662](https://github.com/dequelabs/axe-core/commit/7315662))
* Make empty role=lisbox elements as incomplete ([#927](https://github.com/dequelabs/axe-core/issues/927)) ([87e979f](https://github.com/dequelabs/axe-core/commit/87e979f))
* Prevent axe-core crashing on “-“ as a class name ([#884](https://github.com/dequelabs/axe-core/issues/884)) ([9c4d84e](https://github.com/dequelabs/axe-core/commit/9c4d84e))
* Right trim URLs before outputting them in getSelector ([#924](https://github.com/dequelabs/axe-core/issues/924)) ([4775a23](https://github.com/dequelabs/axe-core/commit/4775a23)), closes [#788](https://github.com/dequelabs/axe-core/issues/788)
* td-has-heading to ignore td with its role changed ([#928](https://github.com/dequelabs/axe-core/issues/928)) ([d68af4c](https://github.com/dequelabs/axe-core/commit/d68af4c))
* Update tags for frame-title rule ([#935](https://github.com/dequelabs/axe-core/issues/935)) ([6436bbf](https://github.com/dequelabs/axe-core/commit/6436bbf))
* **core:** Define 'axe-core' as an AMD module ([#859](https://github.com/dequelabs/axe-core/issues/859)) ([7b46f63](https://github.com/dequelabs/axe-core/commit/7b46f63)), closes [#849](https://github.com/dequelabs/axe-core/issues/849) [#856](https://github.com/dequelabs/axe-core/issues/856) [#861](https://github.com/dequelabs/axe-core/issues/861) [#847](https://github.com/dequelabs/axe-core/issues/847) [#844](https://github.com/dequelabs/axe-core/issues/844) [#871](https://github.com/dequelabs/axe-core/issues/871) [#849](https://github.com/dequelabs/axe-core/issues/849) [#849](https://github.com/dequelabs/axe-core/issues/849)
* Update tags to accesskey & link-name rules ([#922](https://github.com/dequelabs/axe-core/issues/922)) ([a8e801c](https://github.com/dequelabs/axe-core/commit/a8e801c))
* **rule:** Layout-table does not match presentation / none roles ([#828](https://github.com/dequelabs/axe-core/issues/828)) ([5651ecc](https://github.com/dequelabs/axe-core/commit/5651ecc))
* **rule:** restore labelledBy on unlabeled select ([b7bdf66](https://github.com/dequelabs/axe-core/commit/b7bdf66))
* **rules:** Allow focusable role=application elements ([b5de450](https://github.com/dequelabs/axe-core/commit/b5de450))
* **typescript:** Update ElementContext type ([#822](https://github.com/dequelabs/axe-core/issues/822)) ([eb09248](https://github.com/dequelabs/axe-core/commit/eb09248))
### Features
* generate ARIA supported documentation for roles and attributes. ([6f095dd](https://github.com/dequelabs/axe-core/commit/6f095dd))
* generated impacts as a part of rule descriptions ([#898](https://github.com/dequelabs/axe-core/issues/898)) ([6265608](https://github.com/dequelabs/axe-core/commit/6265608))
<a name="3.0.2"></a>

@@ -8,0 +35,0 @@ ## [3.0.2](https://github.com/dequelabs/axe-core/compare/v3.0.0-beta.2...v3.0.2) (2018-04-24)

@@ -34,2 +34,1 @@ # How we make decisions on rules

We recognize that this topic is somewhat controvertial and the rules we have represent Deque's opinion on what constitutes a best practice.

@@ -6,22 +6,22 @@ # aXe Javascript Accessibility API

1. [Section 1: Introduction](#section-1-introduction)
1. [Get Started](#getting-started)
1. [Get Started](#getting-started)
1. [Section 2: API Reference](#section-2-api-reference)
1. [Overview](#overview)
1. [API Notes](#api-notes)
1. [API Name: axe.getRules](#api-name-axegetrules)
1. [API Name: axe.configure](#api-name-axeconfigure)
1. [API Name: axe.reset](#api-name-axereset)
1. [API Name: axe.run](#api-name-axerun)
1. [Parameters axe.run](#parameters-axerun)
1. [Context Parameter](#context-parameter)
2. [Options Parameter](#options-parameter)
3. [Callback Parameter](#callback-parameter)
1. [Return Promise](#return-promise)
1. [Error result](#error-result)
1. [Results Object](#results-object)
1. [API Name: axe.registerPlugin](#api-name-axeregisterplugin)
1. [API Name: axe.cleanup](#api-name-axecleanup)
1. [Virtual DOM Utilities](#virtual-dom-utilities)
1. [API Name: axe.utils.querySelectorAll](#api-name-axeutilsqueryselectorall)
1. [Common Functions](#common-functions)
1. [Overview](#overview)
1. [API Notes](#api-notes)
1. [API Name: axe.getRules](#api-name-axegetrules)
1. [API Name: axe.configure](#api-name-axeconfigure)
1. [API Name: axe.reset](#api-name-axereset)
1. [API Name: axe.run](#api-name-axerun)
1. [Parameters axe.run](#parameters-axerun)
1. [Context Parameter](#context-parameter)
2. [Options Parameter](#options-parameter)
3. [Callback Parameter](#callback-parameter)
1. [Return Promise](#return-promise)
1. [Error result](#error-result)
1. [Results Object](#results-object)
1. [API Name: axe.registerPlugin](#api-name-axeregisterplugin)
1. [API Name: axe.cleanup](#api-name-axecleanup)
1. [Virtual DOM Utilities](#virtual-dom-utilities)
1. [API Name: axe.utils.querySelectorAll](#api-name-axeutilsqueryselectorall)
1. [Common Functions](#common-functions)
1. [Section 3: Example Reference](#section-3-example-reference)

@@ -42,2 +42,3 @@ 1. [Section 4: Performance](#section-4-performance)

### Getting Started
This section gives a quick description of how to use the aXe APIs to analyze web page content and return a JSON object that lists any accessibility violations found.

@@ -53,3 +54,2 @@

## Section 2: API Reference

@@ -114,3 +114,2 @@

#### Example 1

@@ -126,6 +125,6 @@

[
{ ruleId: "area-alt", description: "Checks the <area> elements of image…" },
{ ruleId: "aria-allowed-attr", description: "Checks all attributes that start…" },
{ ruleId: "aria-required-attr", description: "Checks all elements that contain…" },
{ ruleId: "area-alt", description: "Checks the <area> elements of image…" },
{ ruleId: "aria-allowed-attr", description: "Checks all attributes that start…" },
{ ruleId: "aria-required-attr", description: "Checks all elements that contain…" },
]

@@ -148,9 +147,9 @@ ```

axe.configure({
branding: {
brand: String,
application: String
},
reporter: "option",
checks: [Object],
rules: [Object]});
branding: {
brand: String,
application: String
},
reporter: "option",
checks: [Object],
rules: [Object]});
```

@@ -161,30 +160,30 @@

* `configurationOptions` - Options object; where the valid name, value pairs are:
* `branding` - mixed(optional) Used to set the branding of the helpUrls
* `brand` - string(optional) sets the brand string - default "axe"
* `application` - string(optional) sets the application string - default "axeAPI"
* `reporter` - Used to set the output format that the axe.run function will pass to the callback function
* `v1` to use the previous version's format: `axe.configure({ reporter: "v1" });`
* `v2` to use the current version's format: `axe.configure({ reporter: "v2" });`
* `checks` - Used to add checks to the list of checks used by rules, or to override the properties of existing checks
* The checks attribute is an array of check objects
* Each check object can contain the following attributes
* `id` - string(required). This uniquely identifies the check. If the check already exists, this will result in any supplied check properties being overridden. The properties below that are marked required if new are optional when the check is being overridden.
* `evaluate` - function(required for new). This is the function that implements the check's functionality.
* `after` - function(optional). This is the function that gets called for checks that operate on a page-level basis, to process the results from the iframes.
* `options` - mixed(optional). This is the options structure that is passed to the evaluate function and is intended to be used to configure checks. It is the most common property that is intended to be overridden for existing checks.
* `enabled` - boolean(optional, default `true`). This is used to indicate whether the check is on or off by default. Checks that are off are not evaluated, even when included in a rule. Overriding this is a common way to disable a particular check across multiple rules.
* `rules` - Used to add rules to the existing set of rules, or to override the properties of existing rules
* The rules attribute is an Array of rule objects
* each rule object can contain the following attributes
* `id` - string(required). This uniquely identifies the rule. If the rule already exists, it will be overridden with any of the attributes supplied. The attributes below that are marked required, are only required for new rules.
* `selector` - string(optional, default `*`). A CSS selector used to identify the elements that are passed into the rule for evaluation.
* `excludeHidden` - boolean(optional, default `true`). This indicates whether elements that are hidden from all users are to be passed into the rule for evaluation.
* `enabled` - boolean(optional, default `true`). Whether the rule is turned on. This is a common attribute for overriding.
* `pageLevel` - boolean(optional, default `false`). When set to true, this rule is only applied when the entire page is tested. Results from nodes on different frames are combined into a single result. See [page level rules](#page-level-rules).
* `any` - array(optional, default `[]`). This is the list of checks that must all "pass" or else there is a violation.
* `all` - array(optional, default `[]`). This is the list of checks that, if any "fails", will generate a violation.
* `none` - array(optional, default `[]`). This is a list of the checks that, if none "pass", will generate a violation.
* `tags` - array(optional, default `[]`). A list if the tags that "classify" the rule. In practice, you must supply some valid tags or the default evaluation will not invoke the rule. The convention is to include the standard (WCAG 2 and/or section 508), the WCAG 2 level, Section 508 paragraph, and the WCAG 2 success criteria. Tags are constructed by converting all letters to lower case, removing spaces and periods and concatinating the result. E.g. WCAG 2 A success criteria 1.1.1 would become ["wcag2a", "wcag111"]
* `matches` - string(optional, default `*`). A filtering CSS selector that will exclude elements that do not match the CSS selector.
* `disableOtherRules` - Disables all rules not included in the `rules` property.
* `branding` - mixed(optional) Used to set the branding of the helpUrls
* `brand` - string(optional) sets the brand string - default "axe"
* `application` - string(optional) sets the application string - default "axeAPI"
* `reporter` - Used to set the output format that the axe.run function will pass to the callback function
* `v1` to use the previous version's format: `axe.configure({ reporter: "v1" });`
* `v2` to use the current version's format: `axe.configure({ reporter: "v2" });`
* `checks` - Used to add checks to the list of checks used by rules, or to override the properties of existing checks
* The checks attribute is an array of check objects
* Each check object can contain the following attributes
* `id` - string(required). This uniquely identifies the check. If the check already exists, this will result in any supplied check properties being overridden. The properties below that are marked required if new are optional when the check is being overridden.
* `evaluate` - function(required for new). This is the function that implements the check's functionality.
* `after` - function(optional). This is the function that gets called for checks that operate on a page-level basis, to process the results from the iframes.
* `options` - mixed(optional). This is the options structure that is passed to the evaluate function and is intended to be used to configure checks. It is the most common property that is intended to be overridden for existing checks.
* `enabled` - boolean(optional, default `true`). This is used to indicate whether the check is on or off by default. Checks that are off are not evaluated, even when included in a rule. Overriding this is a common way to disable a particular check across multiple rules.
* `rules` - Used to add rules to the existing set of rules, or to override the properties of existing rules
* The rules attribute is an Array of rule objects
* each rule object can contain the following attributes
* `id` - string(required). This uniquely identifies the rule. If the rule already exists, it will be overridden with any of the attributes supplied. The attributes below that are marked required, are only required for new rules.
* `selector` - string(optional, default `*`). A CSS selector used to identify the elements that are passed into the rule for evaluation.
* `excludeHidden` - boolean(optional, default `true`). This indicates whether elements that are hidden from all users are to be passed into the rule for evaluation.
* `enabled` - boolean(optional, default `true`). Whether the rule is turned on. This is a common attribute for overriding.
* `pageLevel` - boolean(optional, default `false`). When set to true, this rule is only applied when the entire page is tested. Results from nodes on different frames are combined into a single result. See [page level rules](#page-level-rules).
* `any` - array(optional, default `[]`). This is the list of checks that must all "pass" or else there is a violation.
* `all` - array(optional, default `[]`). This is the list of checks that, if any "fails", will generate a violation.
* `none` - array(optional, default `[]`). This is a list of the checks that, if none "pass", will generate a violation.
* `tags` - array(optional, default `[]`). A list if the tags that "classify" the rule. In practice, you must supply some valid tags or the default evaluation will not invoke the rule. The convention is to include the standard (WCAG 2 and/or section 508), the WCAG 2 level, Section 508 paragraph, and the WCAG 2 success criteria. Tags are constructed by converting all letters to lower case, removing spaces and periods and concatinating the result. E.g. WCAG 2 A success criteria 1.1.1 would become ["wcag2a", "wcag111"]
* `matches` - string(optional, default `*`). A filtering CSS selector that will exclude elements that do not match the CSS selector.
* `disableOtherRules` - Disables all rules not included in the `rules` property.

@@ -222,3 +221,2 @@ **Returns:** Nothing

### API Name: axe.run

@@ -248,14 +246,13 @@

By default, axe.run will test the entire document. The context object is an optional parameter that can be used to specify which element should and which should not be tested. It can be passed one of the following:
By default, `axe.run` will test the entire document. The context object is an optional parameter that can be used to specify which element should and which should not be tested. It can be passed one of the following:
1. An element reference that represents the portion of the document that must be analyzed
* Example: To limit analysis to the `<div id="content">` element: `document.getElementById("content")`
* Example: To limit analysis to the `<div id="content">` element: `document.getElementById("content")`
2. A NodeList such as returned by `document.querySelectorAll`.
3. A CSS selector that selects the portion(s) of the document that must be analyzed. This includes:
* A CSS selector as a class name (e.g. `.classname`)
* A CSS selector as a node name (e.g. `div`)
* A CSS selector of an element id (e.g. `#tag`)
* A CSS selector as a class name (e.g. `.classname`)
* A CSS selector as a node name (e.g. `div`)
* A CSS selector of an element id (e.g. `#tag`)
4. An include-exclude object (see below)
###### Include-Exclude Object

@@ -267,6 +264,6 @@

* An array of arrays of CSS selectors
* If the nested array contains a single string, that string is the CSS selector
* If the nested array contains multiple strings
* The last string is the final CSS selector
* All other's are the nested structure of iframes inside the document
* If the nested array contains a single string, that string is the CSS selector
* If the nested array contains multiple strings
* The last string is the final CSS selector
* All other's are the nested structure of iframes inside the document

@@ -279,53 +276,52 @@ In most cases, the component arrays will contain only one CSS selector. Multiple CSS selectors are only required if you want to include or exclude regions of a page that are inside iframes (or iframes within iframes within iframes). In this case, the first n-1 selectors are selectors that select the iframe(s) and the nth selector, selects the region(s) within the iframe.

```javascript
{
include: $fixture[0],
exclude: $fixture[0].firstChild
}
```
```javascript
{
include: $fixture[0],
exclude: $fixture[0].firstChild
}
```
2. Include the element with the ID of `fix` but exclude any `div`s within it
```javascript
{
include: [['#fix']],
exclude: [['#fix div']]
}
```
```javascript
{
include: [['#fix']],
exclude: [['#fix div']]
}
```
3. Include the whole document except any structures whose parent contains the class `exclude1` or `exclude2`
```javascript
{
exclude: [['.exclude1'], ['.exclude2']]
}
```
```javascript
{
exclude: [['.exclude1'], ['.exclude2']]
}
```
4. Include the element with the ID of `fix`, within the iframe with id `frame`
```javascript
{
include: [['#frame', '#fix']]
}
```
```javascript
{
include: [['#frame', '#fix']]
}
```
5. Include the element with the ID of `fix`, within the iframe with id `frame2`, within the iframe with id `frame1`
```javascript
{
include: [['#frame1', '#frame2', '#fix']]
}
```
```javascript
{
include: [['#frame1', '#frame2', '#fix']]
}
```
6. Include the following:
* The element with the ID of `fix`, within the iframe with id `frame2`, within the iframe with id `frame1`
* The element with id `header`
* All links
* The element with the ID of `fix`, within the iframe with id `frame2`, within the iframe with id `frame1`
* The element with id `header`
* All links
```javascript
{
include: [
['#header'],
['a'],
['#frame1', '#frame2', '#fix']
]
}
```
```javascript
{
include: [
['#header'],
['a'],
['#frame1', '#frame2', '#fix']
]
}
```
##### Options Parameter

@@ -354,3 +350,2 @@

###### Options Parameter Examples

@@ -360,117 +355,117 @@

There are certain standards defined that can be used to select a set of rules. The defined standards and tag string are defined as follows:
There are certain standards defined that can be used to select a set of rules. The defined standards and tag string are defined as follows:
| Tag Name | Accessibility Standard |
|--------------------|:-------------------------------------:|
| `wcag2a` | WCAG 2.0 Level A |
| `wcag2aa` | WCAG 2.0 Level AA |
| `section508` | Section 508 |
| `best-practice` | Best practices endorsed by Deque |
| Tag Name | Accessibility Standard |
|--------------------|:-------------------------------------:|
| `wcag2a` | WCAG 2.0 Level A |
| `wcag2aa` | WCAG 2.0 Level AA |
| `section508` | Section 508 |
| `best-practice` | Best practices endorsed by Deque |
To run only WCAG 2.0 Level A rules, specify `options` as:
To run only WCAG 2.0 Level A rules, specify `options` as:
```javascript
{
runOnly: {
type: "tag",
values: ["wcag2a"]
}
}
```
```javascript
{
runOnly: {
type: "tag",
values: ["wcag2a"]
}
}
```
To run both WCAG 2.0 Level A and Level AA rules, you must specify both `wcag2a` and `wcag2aa`:
To run both WCAG 2.0 Level A and Level AA rules, you must specify both `wcag2a` and `wcag2aa`:
```javascript
{
runOnly: {
type: "tag",
values: ["wcag2a", "wcag2aa"]
}
}
```
```javascript
{
runOnly: {
type: "tag",
values: ["wcag2a", "wcag2aa"]
}
}
```
Alternatively, runOnly can be passed an array of tags:
Alternatively, runOnly can be passed an array of tags:
```javascript
{
runOnly: ["wcag2a", "wcag2aa"]
}
```
```javascript
{
runOnly: ["wcag2a", "wcag2aa"]
}
```
2. Run only a specified list of Rules
If you only want to run certain rules, specify options as:
If you only want to run certain rules, specify options as:
```javascript
{
runOnly: {
type: "rule",
values: [ "ruleId1", "ruleId2", "ruleId3" ]
}
}
```
```javascript
{
runOnly: {
type: "rule",
values: [ "ruleId1", "ruleId2", "ruleId3" ]
}
}
```
This example will only run the rules with the id of `ruleId1`, `ruleId2`, and `ruleId3`. No other rule will run.
This example will only run the rules with the id of `ruleId1`, `ruleId2`, and `ruleId3`. No other rule will run.
3. Run all enabled Rules except for a list of rules
The default operation for axe.run is to run all WCAG 2.0 Level A and Level AA rules. If certain rules should be disabled from being run, specify `options` as:
```javascript
{
"rules": {
"color-contrast": { enabled: false },
"valid-lang": { enabled: false }
}
}
```
The default operation for axe.run is to run all rules except for rules with the "experimental" tag. If certain rules should be disabled from being run, specify `options` as:
```javascript
{
"rules": {
"color-contrast": { enabled: false },
"valid-lang": { enabled: false }
}
}
```
This example will disable the rules with the id of `color-contrast` and `valid-lang`. All other rules will run. The list of valid rule IDs is specified in the section below.
This example will disable the rules with the id of `color-contrast` and `valid-lang`. All other rules will run. The list of valid rule IDs is specified in the section below.
4. Run a modified set or rules using tags and rule enable
By combining runOnly with type: tags and the rules option, a modified set can be defined. This lets you include rules with unspecified tags, and exclude rules that do have the specified tag(s).
```javascript
{
runOnly: {
type: "tag",
values: ["wcag2a"]
},
"rules": {
"color-contrast": { enabled: true },
"valid-lang": { enabled: false }
}
}
```
By combining runOnly with type: tags and the rules option, a modified set can be defined. This lets you include rules with unspecified tags, and exclude rules that do have the specified tag(s).
```javascript
{
runOnly: {
type: "tag",
values: ["wcag2a"]
},
"rules": {
"color-contrast": { enabled: true },
"valid-lang": { enabled: false }
}
}
```
This example includes all level A rules except for valid-lang, and in addition will include the level AA color-contrast rule.
This example includes all level A rules except for valid-lang, and in addition will include the level AA color-contrast rule.
5. Run only some tags, but exclude others
Similar to scope, the runOnly option can accept an object with an 'include' and 'exclude' property. Only those checks that match an included tag will run, except those that share a tag from the exclude list.
```javascript
{
runOnly: {
type: 'tags',
values: {
include: ['wcag2a', 'wcag2aa'],
exclude: ['experimental']
}
}
}
```
Similar to scope, the runOnly option can accept an object with an 'include' and 'exclude' property. Only those checks that match an included tag will run, except those that share a tag from the exclude list.
```javascript
{
runOnly: {
type: 'tags',
values: {
include: ['wcag2a', 'wcag2aa'],
exclude: ['experimental']
}
}
}
```
This example first includes all `wcag2a` and `wcag2aa` rules. All rules that are tagged as `experimental` are than removed from the list of rules to run.
This example first includes all `wcag2a` and `wcag2aa` rules. All rules that are tagged as `experimental` are than removed from the list of rules to run.
6. Only process certain types of results
The `resultTypes` option can be used to limit the result types that aXe will process, aggregate, and send to the reporter. This can be useful for improving performance on very large or complicated pages when you are only interested in certain types of results.
The `resultTypes` option can be used to limit the result types that aXe will process, aggregate, and send to the reporter. This can be useful for improving performance on very large or complicated pages when you are only interested in certain types of results.
Types listed in this option are processed normally and report all of their results. Types *not* listed process a maximum of one result. The caller can use this information to inform the user of the existence of that type of result if appropriate.
Types listed in this option are processed normally and report all of their results. Types *not* listed process a maximum of one result. The caller can use this information to inform the user of the existence of that type of result if appropriate.
```javascript
{
resultTypes: ['violations', 'incomplete', 'inapplicable']
}
```
This example will process all of the "violations", "incomplete", and "inapplicable" result types. Since "passes" was not specified, it will only process the first pass for each rule, if one exists. As a result, the results object's `passes` array will have a length of either `0` or `1`. On a series of extremely large pages, this would improve performance considerably.
```javascript
{
resultTypes: ['violations', 'incomplete', 'inapplicable']
}
```
This example will process all of the "violations", "incomplete", and "inapplicable" result types. Since "passes" was not specified, it will only process the first pass for each rule, if one exists. As a result, the results object's `passes` array will have a length of either `0` or `1`. On a series of extremely large pages, this would improve performance considerably.

@@ -481,3 +476,2 @@ ##### Callback Parameter

#### Return Promise

@@ -491,3 +485,2 @@

#### Results Object

@@ -530,15 +523,15 @@

* `nodes` - Array of all elements the Rule tested
* `html` - Snippet of HTML of the Element
* `impact` - How serious the violation is. Can be one of "minor", "moderate", "serious", or "critical" if the test failed or `null` if the check passed
* `target` - Array of either strings or Arrays of strings. If the item in the array is a string, then it is a CSS selector. If there are multiple items in the array each item corresponds to one level of iframe or frame. If there is one iframe or frame, there should be two entries in `target`. If there are three iframe levels, there should be four entries in `target`. If the item in the Array is an Array of strings, then it points to an element in a shadow DOM and each item (except the n-1th) in this array is a selector to a DOM element with a shadow DOM. The last element in the array points to the final shadow DOM node.
* `any` - Array of checks that were made where at least one must have passed. Each entry in the array contains:
* `id` - Unique identifier for this check. Check ids may be the same as Rule ids
* `impact` - How serious this particular check is. Can be one of "minor", "moderate", "serious", or "critical". Each check that is part of a rule can have different impacts. The highest impact of all the checks that fail is reported for the rule
* `message` - Description of why this check passed or failed
* `data` - Additional information that is specific to the type of Check which is optional. For example, a color contrast check would include the foreground color, background color, contrast ratio, etc.
* `relatedNodes` - Optional array of information about other nodes that are related to this check. For example, a duplicate id check violation would list the other selectors that had this same duplicate id. Each entry in the array contains the following information:
* `target` - Array of selectors for the related node
* `html` - HTML source of the related node
* `all` - Array of checks that were made where all must have passed. Each entry in the array contains the same information as the 'any' array
* `none` - Array of checks that were made where all must have not passed. Each entry in the array contains the same information as the 'any' array
* `html` - Snippet of HTML of the Element
* `impact` - How serious the violation is. Can be one of "minor", "moderate", "serious", or "critical" if the test failed or `null` if the check passed
* `target` - Array of either strings or Arrays of strings. If the item in the array is a string, then it is a CSS selector. If there are multiple items in the array each item corresponds to one level of iframe or frame. If there is one iframe or frame, there should be two entries in `target`. If there are three iframe levels, there should be four entries in `target`. If the item in the Array is an Array of strings, then it points to an element in a shadow DOM and each item (except the n-1th) in this array is a selector to a DOM element with a shadow DOM. The last element in the array points to the final shadow DOM node.
* `any` - Array of checks that were made where at least one must have passed. Each entry in the array contains:
* `id` - Unique identifier for this check. Check ids may be the same as Rule ids
* `impact` - How serious this particular check is. Can be one of "minor", "moderate", "serious", or "critical". Each check that is part of a rule can have different impacts. The highest impact of all the checks that fail is reported for the rule
* `message` - Description of why this check passed or failed
* `data` - Additional information that is specific to the type of Check which is optional. For example, a color contrast check would include the foreground color, background color, contrast ratio, etc.
* `relatedNodes` - Optional array of information about other nodes that are related to this check. For example, a duplicate id check violation would list the other selectors that had this same duplicate id. Each entry in the array contains the following information:
* `target` - Array of selectors for the related node
* `html` - HTML source of the related node
* `all` - Array of checks that were made where all must have passed. Each entry in the array contains the same information as the 'any' array
* `none` - Array of checks that were made where all must have not passed. Each entry in the array contains the same information as the 'any' array

@@ -551,4 +544,4 @@ #### Example 2

axe.run(document, function(err, results) {
if (err) throw err;
console.log(results);
if (err) throw err;
console.log(results);
});

@@ -560,11 +553,11 @@ ```

* `passes[0]`
...
* `help` - `"Elements must have sufficient color contrast"`
* `helpUrl` - `"https://dequeuniversity.com/courses/html-css/visual-layout/color-contrast"`
* `id` - `"color-contrast"`
* `nodes`
* `target[0]` - `"#js_off-canvas-wrap > .inner-wrap >.kinja-title.proxima.js_kinja-title-desktop"`
...
* `help` - `"Elements must have sufficient color contrast"`
* `helpUrl` - `"https://dequeuniversity.com/courses/html-css/visual-layout/color-contrast"`
* `id` - `"color-contrast"`
* `nodes`
* `target[0]` - `"#js_off-canvas-wrap > .inner-wrap >.kinja-title.proxima.js_kinja-title-desktop"`
* `passes[1]`
...
...

@@ -574,12 +567,11 @@ ###### `violations`

* `violations[0]`
* `help` - `"<button> elements must have alternate text"`
* `helpUrl` - `"https://dequeuniversity.com/courses/html-css/forms/form-labels#id84_example_button"`
* `id` - `"button-name"`
* `nodes`
* `target[0]` - `"post_5919997 > .row.content-wrapper > .column > span > iframe"`
* `target[1]` - `"#u_0_1 > .pluginConnectButton > .pluginButtonImage > button"`
* `help` - `"<button> elements must have alternate text"`
* `helpUrl` - `"https://dequeuniversity.com/courses/html-css/forms/form-labels#id84_example_button"`
* `id` - `"button-name"`
* `nodes`
* `target[0]` - `"post_5919997 > .row.content-wrapper > .column > span > iframe"`
* `target[1]` - `"#u_0_1 > .pluginConnectButton > .pluginButtonImage > button"`
* `violations[1]` ...
##### `passes` Results Array

@@ -603,16 +595,15 @@

#### Example 3
In this example, we pass the selector for the entire document, enable two additional best practice rules, and have a simple callback function that logs the entire results object to the console log:
In this example, we pass the selector for the entire document, enable two additional experimental rules, and have a simple callback function that logs the entire results object to the console log:
```javascript
axe.run(document, {
rules: {
"heading-order": { enabled: true },
"label-title-only": { enabled: true }
}
rules: {
"link-in-text-block": { enabled: true },
"p-as-heading": { enabled: true }
}
}, function(err, results) {
if (err) throw err;
console.log(results);
if (err) throw err;
console.log(results);
});

@@ -626,13 +617,14 @@ ```

##### `violations[0]`
```
```json
{
help : "Elements must have sufficient color contrast",
helpUrl: "https://dequeuniversity.com/rules/axe/2.1/color-contrast?application=axeAPI",
id: "color-contrast",
nodes: [{
target: [[
"header > aria-menu",
"li.expanded"
]]
}]
help : "Elements must have sufficient color contrast",
helpUrl: "https://dequeuniversity.com/rules/axe/2.1/color-contrast?application=axeAPI",
id: "color-contrast",
nodes: [{
target: [[
"header > aria-menu",
"li.expanded"
]]
}]
}

@@ -653,5 +645,5 @@ ```

```javascript
axe.cleanup(resolve, reject)
```
axe.cleanup(resolve, reject)
```

@@ -662,3 +654,2 @@ `resolve` and `reject` are functions that will be invoked on success or failure respectively.

### Virtual DOM Utilities

@@ -693,3 +684,2 @@

### Common Functions

@@ -708,2 +698,3 @@

##### Parameters
* `element` – HTMLElement. The element for which you want to find a parent

@@ -715,3 +706,2 @@

#### axe.commons.dom.getRootNode

@@ -728,2 +718,3 @@

##### Parameters
* `element` – HTMLElement. The element for which you want to find the root node

@@ -735,3 +726,2 @@

#### axe.commons.dom.findUp

@@ -748,2 +738,3 @@

##### Parameters
* `element` – HTMLElement. The starting element

@@ -756,3 +747,2 @@ * `selector` – String. The target selector for the HTMLElement

## Section 3: Example Reference

@@ -776,5 +766,5 @@

```
```json
{
resultTypes: ['violations']
resultTypes: ['violations']
}

@@ -781,0 +771,0 @@ ```

@@ -25,3 +25,3 @@ # Code Submission Guidelines

```
```html
<type>(<scope>): <subject>

@@ -39,3 +39,3 @@ <BLANK LINE>

Use async process to compare elements without UI lockup
Use async process to compare elements without UI lockup

@@ -75,3 +75,2 @@ Closes #1

#### Subject

@@ -130,3 +129,3 @@

```
```console
curl -L https://github.com/dequelabs/axe-core/pull/205.patch | git am -3

@@ -144,3 +143,3 @@ ```

You can use git's interactive rebase to manipulate, merge, and rename commits in your local
history. If these steps are followed, a force push shouldn't be necessary.
history. If these steps are followed, a force push shouldn't be necessary.

@@ -169,3 +168,3 @@ **Do not force push to develop or master under any circulstances.**

You can then push the latest code to develop (note that force push isn't needed if these steps are followed):
```
```console
git push origin develop

@@ -172,0 +171,0 @@ ```

@@ -9,15 +9,15 @@ # aXe Developer Guide

1. [Architecture Overview](#architecture-overview)
1. [Rules](#rules)
1. [Checks](#checks)
1. [Common Functions](#common-functions)
1. [Virtual Nodes](#virtual-nodes)
1. [Core Utilities](#core-utilities)
1. [Rules](#rules)
1. [Checks](#checks)
1. [Common Functions](#common-functions)
1. [Virtual Nodes](#virtual-nodes)
1. [Core Utilities](#core-utilities)
1. [Virtual DOM APIs](#virtual-dom-apis)
1. [API Name: axe.utils.getFlattenedTree](#api-name-axeutilsgetflattenedtree)
1. [API Name: axe.utils.getNodeFromTree](#api-name-axeutilsgetnodefromtree)
1. [API Name: axe.utils.getFlattenedTree](#api-name-axeutilsgetflattenedtree)
1. [API Name: axe.utils.getNodeFromTree](#api-name-axeutilsgetnodefromtree)
1. [Test Utilities](#test-utilities)
1. [Test Util Name: axe.testUtils.MockCheckContext](#test-util-name-axetestutilsmockcheckcontext)
1. [Test Util Name: axe.testUtils.shadowSupport](#test-util-name-axetestutilsshadowsupport)
1. [Test Util Name: axe.testUtils.fixtureSetup](#test-util-name-axetestutilsfixturesetup)
1. [Test Util Name: axe.testUtils.checkSetup](#test-util-name-axetestutilschecksetup)
1. [Test Util Name: axe.testUtils.MockCheckContext](#test-util-name-axetestutilsmockcheckcontext)
1. [Test Util Name: axe.testUtils.shadowSupport](#test-util-name-axetestutilsshadowsupport)
1. [Test Util Name: axe.testUtils.fixtureSetup](#test-util-name-axetestutilsfixturesetup)
1. [Test Util Name: axe.testUtils.checkSetup](#test-util-name-axetestutilschecksetup)

@@ -28,5 +28,5 @@ ## Getting Started

1. You must have NodeJS installed.
2. Grunt must be installed globally. `npm install -g grunt-cli` (You may need to do this as `sudo npm install -g grunt-cli`)
3. Install npm development dependencies. In the root folder of your axe-core repository, run `npm install`
1. You must have NodeJS installed.
2. Grunt must be installed globally. `npm install -g grunt-cli` (You may need to do this as `sudo npm install -g grunt-cli`)
3. Install npm development dependencies. In the root folder of your axe-core repository, run `npm install`

@@ -43,9 +43,8 @@ ### Building axe.js

1. [Core Tests](../test/core/)
2. [Commons Tests](../test/commons/)
3. [Check Tests](../test/checks/)
4. [Integration Tests](../test/integration/rules/)
5. There are additional tests located in [test/integration/full/](../test/integration/full/) for tests that need to be run against their own document.
1. [Core Tests](../test/core/)
2. [Commons Tests](../test/commons/)
3. [Check Tests](../test/checks/)
4. [Integration Tests](../test/integration/rules/)
5. There are additional tests located in [test/integration/full/](../test/integration/full/) for tests that need to be run against their own document.
## Architecture Overview

@@ -59,3 +58,2 @@

### Rules

@@ -73,5 +71,5 @@

* `metadata` - `Object` Consisting of:
* `description` - `String` Text string that describes what the rule does.
* `helpUrl` - `String` **optional** URL that provides more information about the specifics of the violation. Links to a page on the Deque University site.
* `help` - `String` Help text that describes the test that was performed.
* `description` - `String` Text string that describes what the rule does.
* `helpUrl` - `String` **optional** URL that provides more information about the specifics of the violation. Links to a page on the Deque University site.
* `help` - `String` Help text that describes the test that was performed.
* `any` - `Array` Checks that make up this Rule; one of these checks must return `true` for a Rule to pass.

@@ -105,7 +103,7 @@ * `all` - `Array` Checks that make up this Rule; all these checks must return `true` for a Rule to pass.

* `metadata` - `Object` Consisting of:
* `impact` - `String` (one of `minor`, `moderate`, `serious`, or `critical`)
* `messages` - `Object` These messages are displayed when the Check passes or fails
* `pass` - `String` [doT.js](http://olado.github.io/doT/) template string displayed when the Check passes
* `fail` - `String` [doT.js](http://olado.github.io/doT/) template string displayed when the Check fails
* `incomplete` – `String|Object` – [doT.js](http://olado.github.io/doT/) template string displayed when the Check is incomplete OR an object with `missingData` on why it returned incomplete. Refer to [rules.md](./rules.md).
* `impact` - `String` (one of `minor`, `moderate`, `serious`, or `critical`)
* `messages` - `Object` These messages are displayed when the Check passes or fails
* `pass` - `String` [doT.js](http://olado.github.io/doT/) template string displayed when the Check passes
* `fail` - `String` [doT.js](http://olado.github.io/doT/) template string displayed when the Check fails
* `incomplete` – `String|Object` – [doT.js](http://olado.github.io/doT/) template string displayed when the Check is incomplete OR an object with `missingData` on why it returned incomplete. Refer to [rules.md](./rules.md).

@@ -141,7 +139,7 @@ #### Check `evaluate`

return results.filter(function (r) {
if (uniqueIds.indexOf(r.data) === -1) {
uniqueIds.push(r.data);
return true;
}
return false;
if (uniqueIds.indexOf(r.data) === -1) {
uniqueIds.push(r.data);
return true;
}
return false;
});

@@ -255,8 +253,7 @@ ```

#### DqElement Class
The DqElement is a "serialized" `HTMLElement`. It will calculate the CSS selector, grab the source outerHTML and offer an array for storing frame paths. The DqElement class takes the following parameters:
* `Element` - `HTMLElement` The element to serialize
* `Spec` - `Object` Properties to use in place of the element when instantiated on Elements from other frames
* `Element` - `HTMLElement` The element to serialize
* `Spec` - `Object` Properties to use in place of the element when instantiated on Elements from other frames

@@ -274,3 +271,2 @@ ```javascript

## Virtual DOM APIs

@@ -298,5 +294,6 @@

#### Parameters
- `node` – HTMLElement. The current HTML node for which you want a flattened DOM tree.
- `shadowId` – string(optional). ID of the shadow DOM that is the closest shadow ancestor of the node
- `node` – HTMLElement. The current HTML node for which you want a flattened DOM tree.
- `shadowId` – string(optional). ID of the shadow DOM that is the closest shadow ancestor of the node
#### Returns

@@ -303,0 +300,0 @@

@@ -9,24 +9,24 @@ # Turning violation nodes into readable HTML

```
```javascript
function helperItemIterator(items, template) {
var out = '';
if (items) {
for (var i = 0; i < items.length; i++) {
out += template(items[i]);
}
}
return out;
var out = '';
if (items) {
for (var i = 0; i < items.length; i++) {
out += template(items[i]);
}
}
return out;
}
Handlebars.registerHelper('violations', function(items) {
return helperItemIterator(items, compiledRowTemplate);
return helperItemIterator(items, compiledRowTemplate);
});
Handlebars.registerHelper('related', function(items) {
return helperItemIterator(items, compiledRelatedNodeTemplate);
return helperItemIterator(items, compiledRelatedNodeTemplate);
});
Handlebars.registerHelper('reasons', function(items) {
return helperItemIterator(items, compiledFailureTemplate);
return helperItemIterator(items, compiledFailureTemplate);
});
// Setup handlebars templates
compiledRowTemplate = Handlebars.compile(rowTemplate.innerHTML);

@@ -38,42 +38,42 @@ compiledTableTemplate = Handlebars.compile(tableTemplate.innerHTML);

compiledReasonsTemplate = Handlebars.compile(reasonsTemplate.innerHTML);
function messageFromRelatedNodes(relatedNodes) {
var retVal = '';
if (relatedNodes.length) {
var list = relatedNodes.map(function (node) {
return {
targetArrayString: JSON.stringify(node.target),
targetString: node.target.join(' ')
};
});
retVal += compiledRelatedListTemplate({relatedNodeList: list});
}
return retVal;
var retVal = '';
if (relatedNodes.length) {
var list = relatedNodes.map(function (node) {
return {
targetArrayString: JSON.stringify(node.target),
targetString: node.target.join(' ')
};
});
retVal += compiledRelatedListTemplate({relatedNodeList: list});
}
return retVal;
}
function messagesFromArray(nodes) {
var list = nodes.map(function (failure) {
return {
message: failure.message.replace(/</gi, '&lt;').replace(/>/gi, '&gt;'),
relatedNodesMessage: messageFromRelatedNodes(failure.relatedNodes)
}
});
return compiledReasonsTemplate({reasonsList: list});
var list = nodes.map(function (failure) {
return {
message: failure.message.replace(/</gi, '&lt;').replace(/>/gi, '&gt;'),
relatedNodesMessage: messageFromRelatedNodes(failure.relatedNodes)
}
});
return compiledReasonsTemplate({reasonsList: list});
}
function summary(node) {
var retVal = '';
if (node.any.length) {
retVal += '<h3 class="error-title">Fix any of the following</h3>';
retVal += messagesFromArray(node.any);
}
var all = node.all.concat(node.none);
if (all.length) {
retVal += '<h3 class="error-title">Fix all of the following</h3>';
retVal += messagesFromArray(all);
}
return retVal;
var retVal = '';
if (node.any.length) {
retVal += '<h3 class="error-title">Fix any of the following</h3>';
retVal += messagesFromArray(node.any);
}
var all = node.all.concat(node.none);
if (all.length) {
retVal += '<h3 class="error-title">Fix all of the following</h3>';
retVal += messagesFromArray(all);
}
return retVal;
}
/*

@@ -86,22 +86,22 @@ * This code will generate a table of the rules that failed including counts and links to the Deque University help

*/
if (results.violations.length) {
var violations = results.violations.map(function (rule, i) {
return {
impact: rule.impact,
help: rule.help.replace(/</gi, '&lt;').replace(/>/gi, '&gt;'),
bestpractice: (rule.tags.indexOf('best-practice') !== -1),
helpUrl: rule.helpUrl,
count: rule.nodes.length,
index: i
};
});
html = compiledTableTemplate({violationList: violations});
var violations = results.violations.map(function (rule, i) {
return {
impact: rule.impact,
help: rule.help.replace(/</gi, '&lt;').replace(/>/gi, '&gt;'),
bestpractice: (rule.tags.indexOf('best-practice') !== -1),
helpUrl: rule.helpUrl,
count: rule.nodes.length,
index: i
};
});
html = compiledTableTemplate({violationList: violations});
}
/*
* To generate the human readable summary, call the `summary` function with the node. This will return HTML for that node.
*/
reasonHtml = summary(node);

@@ -112,19 +112,19 @@ ```

```
```handlebars
<script id="rowTemplate" type="text/x-handlebars-template">
<tr>
<th scope="row" class="help">
<a href="javascript:;" class="rule" data-index="{{index}}">
{{{help}}}
</a>
</th>
<td scope="row">
<a target="_blank" href="{{helpUrl}}">?</a>
</td>
<td class="count">
{{count}}
</td>
<td class="impact">
{{impact}}
</td>
<th scope="row" class="help">
<a href="javascript:;" class="rule" data-index="{{index}}">
{{{help}}}
</a>
</th>
<td scope="row">
<a target="_blank" href="{{helpUrl}}">?</a>
</td>
<td class="count">
{{count}}
</td>
<td class="impact">
{{impact}}
</td>
</tr>

@@ -134,9 +134,9 @@ </script>

<table>
<tr>
<th scope="col">Description</th>
<th scope="col">Info</th>
<th scope="col">Count</th>
<th scope="col">Impact</th>
</tr>
{{#violations violationList}}{{/violations}}
<tr>
<th scope="col">Description</th>
<th scope="col">Info</th>
<th scope="col">Count</th>
<th scope="col">Impact</th>
</tr>
{{#violations violationList}}{{/violations}}
</table>

@@ -146,3 +146,3 @@ </script>

<ul>Related Nodes:
{{#related relatedNodeList}}{{/related}}
{{#related relatedNodeList}}{{/related}}
</ul>

@@ -152,5 +152,5 @@ </script>

<li>
<a href="javascript:;" class="related-node" data-element="{{targetArrayString}}">
{{targetString}}
</a>
<a href="javascript:;" class="related-node" data-element="{{targetArrayString}}">
{{targetString}}
</a>
</li>

@@ -160,5 +160,5 @@ </script>

<p class="summary">
<ul class="failure-message">
{{#reasons reasonsList}}{{/reasons}}
</ul>
<ul class="failure-message">
{{#reasons reasonsList}}{{/reasons}}
</ul>
</p>

@@ -168,6 +168,6 @@ </script>

<li>
{{message}}
{{{relatedNodesMessage}}}
{{message}}
{{{relatedNodesMessage}}}
</li>
</script>
```

@@ -16,6 +16,6 @@ {

"devDependencies": {
"axe-core": "^2.6.1",
"axe-core": "^3.0.1",
"grunt": "~1.0.2",
"grunt-contrib-jasmine": "~1.1.0"
"grunt-contrib-jasmine": "~2.0.0"
}
}

@@ -16,7 +16,7 @@ {

"devDependencies": {
"axe-core": "^2.6.1",
"axe-core": "^3.0.1",
"chai": "~4.1.2",
"grunt": "~1.0.2",
"grunt-mocha": "1.0.0"
"grunt-mocha": "1.0.4"
}
}

@@ -16,5 +16,5 @@ {

"devDependencies": {
"axe-core": "^2.6.1",
"axe-core": "^3.0.1",
"phantomjs": "^2.1.7"
}
}

@@ -16,3 +16,3 @@ {

"devDependencies": {
"axe-core": "^2.6.1",
"axe-core": "^3.0.1",
"grunt": "~1.0.2",

@@ -19,0 +19,0 @@ "grunt-contrib-qunit": "~2.0.0",

@@ -25,35 +25,35 @@ # Plugins

axe.registerPlugin({
id: 'doStuff',
run: function (id, action, options, callback) {
var frames;
var q = axe.utils.queue();
var that = this;
frames = axe.utils.toArray(document.querySelectorAll('iframe, frame'));
id: 'doStuff',
run: function (id, action, options, callback) {
var frames;
var q = axe.utils.queue();
var that = this;
frames = axe.utils.toArray(document.querySelectorAll('iframe, frame'));
frames.forEach(function (frame) {
q.defer(function (done) {
axe.utils.sendCommandToFrame(frame, {
options: options,
command: 'run-doStuff',
parameter: id,
action: action
}, function () {
done();
});
});
});
frames.forEach(function (frame) {
q.defer(function (done) {
axe.utils.sendCommandToFrame(frame, {
options: options,
command: 'run-doStuff',
parameter: id,
action: action
}, function () {
done();
});
});
});
if (!options.context.length) {
q.defer(function (done) {
that._registry[id][action].call(that._registry[id], document, options, done);
});
}
q.then(callback);
},
commands: [{
id: 'run-doStuff',
callback: function (data, callback) {
return axe.plugins.doStuff.run(data.parameter, data.action, data.options, callback);
}
}]
if (!options.context.length) {
q.defer(function (done) {
that._registry[id][action].call(that._registry[id], document, options, done);
});
}
q.then(callback);
},
commands: [{
id: 'run-doStuff',
callback: function (data, callback) {
return axe.plugins.doStuff.run(data.parameter, data.action, data.options, callback);
}
}]
});

@@ -60,0 +60,0 @@ ```

@@ -1,69 +0,69 @@

| Rule ID | Description | Tags | Enabled by default |
| :------- | :------- | :------- | :------- |
| accesskeys | Ensures every accesskey attribute value is unique | wcag2a, wcag211, cat.keyboard | true |
| area-alt | Ensures &lt;area&gt; elements of image maps have alternate text | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a | true |
| aria-allowed-attr | Ensures ARIA attributes are allowed for an element&apos;s role | cat.aria, wcag2a, wcag411, wcag412 | true |
| aria-dpub-role-fallback | Ensures unsupported DPUB roles are only used on elements with implicit fallback roles | cat.aria, wcag2a, wcag131 | true |
| aria-hidden-body | Ensures aria-hidden=&apos;true&apos; is not present on the document body. | cat.aria, wcag2a, wcag412 | true |
| aria-required-attr | Ensures elements with ARIA roles have all required ARIA attributes | cat.aria, wcag2a, wcag411, wcag412 | true |
| aria-required-children | Ensures elements with an ARIA role that require child roles contain them | cat.aria, wcag2a, wcag131 | true |
| aria-required-parent | Ensures elements with an ARIA role that require parent roles are contained by them | cat.aria, wcag2a, wcag131 | true |
| aria-roles | Ensures all elements with a role attribute use a valid value | cat.aria, wcag2a, wcag131, wcag411, wcag412 | true |
| aria-valid-attr-value | Ensures all ARIA attributes have valid values | cat.aria, wcag2a, wcag131, wcag411, wcag412 | true |
| aria-valid-attr | Ensures attributes that begin with aria- are valid ARIA attributes | cat.aria, wcag2a, wcag411 | true |
| audio-caption | Ensures &lt;audio&gt; elements have captions | cat.time-and-media, wcag2a, wcag121, section508, section508.22.a | true |
| blink | Ensures &lt;blink&gt; elements are not used | cat.time-and-media, wcag2a, wcag222, section508, section508.22.j | true |
| button-name | Ensures buttons have discernible text | cat.name-role-value, wcag2a, wcag412, section508, section508.22.a | true |
| bypass | Ensures each page has at least one mechanism for a user to bypass navigation and jump straight to the content | cat.keyboard, wcag2a, wcag241, section508, section508.22.o | true |
| checkboxgroup | Ensures related &lt;input type=&quot;checkbox&quot;&gt; elements have a group and that the group designation is consistent | cat.forms, best-practice | true |
| color-contrast | Ensures the contrast between foreground and background colors meets WCAG 2 AA contrast ratio thresholds | cat.color, wcag2aa, wcag143 | true |
| definition-list | Ensures &lt;dl&gt; elements are structured correctly | cat.structure, wcag2a, wcag131 | true |
| dlitem | Ensures &lt;dt&gt; and &lt;dd&gt; elements are contained by a &lt;dl&gt; | cat.structure, wcag2a, wcag131 | true |
| document-title | Ensures each HTML document contains a non-empty &lt;title&gt; element | cat.text-alternatives, wcag2a, wcag242 | true |
| duplicate-id | Ensures every id attribute value is unique | cat.parsing, wcag2a, wcag411 | true |
| empty-heading | Ensures headings have discernible text | cat.name-role-value, best-practice | true |
| focus-order-semantics | Ensures elements in the focus order have an appropriate role | cat.keyboard, best-practice, experimental | true |
| frame-tested | Ensures &lt;iframe&gt; and &lt;frame&gt; elements contain the axe-core script | cat.structure, review-item | true |
| frame-title-unique | Ensures &lt;iframe&gt; and &lt;frame&gt; elements contain a unique title attribute | cat.text-alternatives, best-practice | true |
| frame-title | Ensures &lt;iframe&gt; and &lt;frame&gt; elements contain a non-empty title attribute | cat.text-alternatives, wcag2a, wcag241, section508, section508.22.i | true |
| heading-order | Ensures the order of headings is semantically correct | cat.semantics, best-practice | true |
| hidden-content | Informs users about hidden content. | cat.structure, experimental, review-item | true |
| html-has-lang | Ensures every HTML document has a lang attribute | cat.language, wcag2a, wcag311 | true |
| html-lang-valid | Ensures the lang attribute of the &lt;html&gt; element has a valid value | cat.language, wcag2a, wcag311 | true |
| image-alt | Ensures &lt;img&gt; elements have alternate text or a role of none or presentation | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a | true |
| image-redundant-alt | Ensure button and link text is not repeated as image alternative | cat.text-alternatives, best-practice | true |
| input-image-alt | Ensures &lt;input type=&quot;image&quot;&gt; elements have alternate text | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a | true |
| label-title-only | Ensures that every form element is not solely labeled using the title or aria-describedby attributes | cat.forms, best-practice | true |
| label | Ensures every form element has a label | cat.forms, wcag2a, wcag332, wcag131, section508, section508.22.n | true |
| landmark-banner-is-top-level | The banner landmark should not be contained in another landmark | cat.semantics, best-practice | true |
| landmark-contentinfo-is-top-level | The contentinfo landmark should not be contained in another landmark | cat.semantics, best-practice | true |
| landmark-main-is-top-level | The main landmark should not be contained in another landmark | cat.semantics, best-practice | true |
| landmark-no-duplicate-banner | Ensures the document has no more than one banner landmark | cat.semantics, best-practice | true |
| landmark-no-duplicate-contentinfo | Ensures the document has no more than one contentinfo landmark | cat.semantics, best-practice | true |
| landmark-one-main | Ensures a navigation point to the primary content of the page. If the page contains iframes, each iframe should contain either no main landmarks or just one | cat.semantics, best-practice | true |
| layout-table | Ensures presentational &lt;table&gt; elements do not use &lt;th&gt;, &lt;caption&gt; elements or the summary attribute | cat.semantics, wcag2a, wcag131 | true |
| link-in-text-block | Links can be distinguished without relying on color | cat.color, experimental, wcag2a, wcag141 | true |
| link-name | Ensures links have discernible text | cat.name-role-value, wcag2a, wcag111, wcag412, wcag244, section508, section508.22.a | true |
| list | Ensures that lists are structured correctly | cat.structure, wcag2a, wcag131 | true |
| listitem | Ensures &lt;li&gt; elements are used semantically | cat.structure, wcag2a, wcag131 | true |
| marquee | Ensures &lt;marquee&gt; elements are not used | cat.parsing, wcag2a, wcag222 | true |
| meta-refresh | Ensures &lt;meta http-equiv=&quot;refresh&quot;&gt; is not used | cat.time, wcag2a, wcag2aaa, wcag221, wcag224, wcag325 | true |
| meta-viewport-large | Ensures &lt;meta name=&quot;viewport&quot;&gt; can scale a significant amount | cat.sensory-and-visual-cues, best-practice | true |
| meta-viewport | Ensures &lt;meta name=&quot;viewport&quot;&gt; does not disable text scaling and zooming | cat.sensory-and-visual-cues, wcag2aa, wcag144 | true |
| object-alt | Ensures &lt;object&gt; elements have alternate text | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a | true |
| p-as-heading | Ensure p elements are not used to style headings | cat.semantics, wcag2a, wcag131, experimental | true |
| page-has-heading-one | Ensure that the page, or at least one of its frames contains a level-one heading | cat.semantics, best-practice | true |
| radiogroup | Ensures related &lt;input type=&quot;radio&quot;&gt; elements have a group and that the group designation is consistent | cat.forms, best-practice | true |
| region | Ensures all content is contained within a landmark region | cat.keyboard, best-practice | true |
| scope-attr-valid | Ensures the scope attribute is used correctly on tables | cat.tables, best-practice | true |
| server-side-image-map | Ensures that server-side image maps are not used | cat.text-alternatives, wcag2a, wcag211, section508, section508.22.f | true |
| skip-link | Ensure all skip links have a focusable target | cat.keyboard, best-practice | true |
| tabindex | Ensures tabindex attribute values are not greater than 0 | cat.keyboard, best-practice | true |
| table-duplicate-name | Ensure that tables do not have the same summary and caption | cat.tables, best-practice | true |
| table-fake-caption | Ensure that tables with a caption use the &lt;caption&gt; element. | cat.tables, experimental, wcag2a, wcag131, section508, section508.22.g | true |
| td-has-header | Ensure that each non-empty data cell in a large table has one or more table headers | cat.tables, experimental, wcag2a, wcag131, section508, section508.22.g | true |
| td-headers-attr | Ensure that each cell in a table using the headers refers to another cell in that table | cat.tables, wcag2a, wcag131, section508, section508.22.g | true |
| th-has-data-cells | Ensure that each table header in a data table refers to data cells | cat.tables, wcag2a, wcag131, section508, section508.22.g | true |
| valid-lang | Ensures lang attributes have valid values | cat.language, wcag2aa, wcag312 | true |
| video-caption | Ensures &lt;video&gt; elements have captions | cat.text-alternatives, wcag2a, wcag122, section508, section508.22.a | true |
| video-description | Ensures &lt;video&gt; elements have audio descriptions | cat.text-alternatives, wcag2aa, wcag125, section508, section508.22.b | true |
| Rule ID | Description | Impact | Tags | Enabled by default |
| :------- | :------- | :------- | :------- | :------- |
| accesskeys | Ensures every accesskey attribute value is unique | Serious | best-practice, cat.keyboard | true |
| area-alt | Ensures &lt;area&gt; elements of image maps have alternate text | Critical | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a | true |
| aria-allowed-attr | Ensures ARIA attributes are allowed for an element&apos;s role | Critical | cat.aria, wcag2a, wcag411, wcag412 | true |
| aria-dpub-role-fallback | Ensures unsupported DPUB roles are only used on elements with implicit fallback roles | Moderate | cat.aria, wcag2a, wcag131 | true |
| aria-hidden-body | Ensures aria-hidden=&apos;true&apos; is not present on the document body. | Critical | cat.aria, wcag2a, wcag412 | true |
| aria-required-attr | Ensures elements with ARIA roles have all required ARIA attributes | Critical | cat.aria, wcag2a, wcag411, wcag412 | true |
| aria-required-children | Ensures elements with an ARIA role that require child roles contain them | Critical | cat.aria, wcag2a, wcag131 | true |
| aria-required-parent | Ensures elements with an ARIA role that require parent roles are contained by them | Critical | cat.aria, wcag2a, wcag131 | true |
| aria-roles | Ensures all elements with a role attribute use a valid value | Serious, Critical | cat.aria, wcag2a, wcag131, wcag411, wcag412 | true |
| aria-valid-attr-value | Ensures all ARIA attributes have valid values | Critical | cat.aria, wcag2a, wcag131, wcag411, wcag412 | true |
| aria-valid-attr | Ensures attributes that begin with aria- are valid ARIA attributes | Critical | cat.aria, wcag2a, wcag411 | true |
| audio-caption | Ensures &lt;audio&gt; elements have captions | Critical | cat.time-and-media, wcag2a, wcag121, section508, section508.22.a | true |
| blink | Ensures &lt;blink&gt; elements are not used | Serious | cat.time-and-media, wcag2a, wcag222, section508, section508.22.j | true |
| button-name | Ensures buttons have discernible text | Serious, Critical | cat.name-role-value, wcag2a, wcag412, section508, section508.22.a | true |
| bypass | Ensures each page has at least one mechanism for a user to bypass navigation and jump straight to the content | Serious | cat.keyboard, wcag2a, wcag241, section508, section508.22.o | true |
| checkboxgroup | Ensures related &lt;input type=&quot;checkbox&quot;&gt; elements have a group and that the group designation is consistent | Critical | cat.forms, best-practice | true |
| color-contrast | Ensures the contrast between foreground and background colors meets WCAG 2 AA contrast ratio thresholds | Serious | cat.color, wcag2aa, wcag143 | true |
| definition-list | Ensures &lt;dl&gt; elements are structured correctly | Serious | cat.structure, wcag2a, wcag131 | true |
| dlitem | Ensures &lt;dt&gt; and &lt;dd&gt; elements are contained by a &lt;dl&gt; | Serious | cat.structure, wcag2a, wcag131 | true |
| document-title | Ensures each HTML document contains a non-empty &lt;title&gt; element | Serious | cat.text-alternatives, wcag2a, wcag242 | true |
| duplicate-id | Ensures every id attribute value is unique | Moderate | cat.parsing, wcag2a, wcag411 | true |
| empty-heading | Ensures headings have discernible text | Minor | cat.name-role-value, best-practice | true |
| focus-order-semantics | Ensures elements in the focus order have an appropriate role | Minor | cat.keyboard, best-practice, experimental | true |
| frame-tested | Ensures &lt;iframe&gt; and &lt;frame&gt; elements contain the axe-core script | Critical | cat.structure, review-item | true |
| frame-title-unique | Ensures &lt;iframe&gt; and &lt;frame&gt; elements contain a unique title attribute | Serious | cat.text-alternatives, best-practice | true |
| frame-title | Ensures &lt;iframe&gt; and &lt;frame&gt; elements contain a non-empty title attribute | Serious | cat.text-alternatives, wcag2a, wcag241, wcag412, section508, section508.22.i | true |
| heading-order | Ensures the order of headings is semantically correct | Moderate | cat.semantics, best-practice | true |
| hidden-content | Informs users about hidden content. | Minor | cat.structure, experimental, review-item | true |
| html-has-lang | Ensures every HTML document has a lang attribute | Serious | cat.language, wcag2a, wcag311 | true |
| html-lang-valid | Ensures the lang attribute of the &lt;html&gt; element has a valid value | Serious | cat.language, wcag2a, wcag311 | true |
| image-alt | Ensures &lt;img&gt; elements have alternate text or a role of none or presentation | Critical | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a | true |
| image-redundant-alt | Ensure button and link text is not repeated as image alternative | Minor | cat.text-alternatives, best-practice | true |
| input-image-alt | Ensures &lt;input type=&quot;image&quot;&gt; elements have alternate text | Critical | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a | true |
| label-title-only | Ensures that every form element is not solely labeled using the title or aria-describedby attributes | Serious | cat.forms, best-practice | true |
| label | Ensures every form element has a label | Minor, Serious, Critical | cat.forms, wcag2a, wcag332, wcag131, section508, section508.22.n | true |
| landmark-banner-is-top-level | The banner landmark should not be contained in another landmark | Moderate | cat.semantics, best-practice | true |
| landmark-contentinfo-is-top-level | The contentinfo landmark should not be contained in another landmark | Moderate | cat.semantics, best-practice | true |
| landmark-main-is-top-level | The main landmark should not be contained in another landmark | Moderate | cat.semantics, best-practice | true |
| landmark-no-duplicate-banner | Ensures the document has no more than one banner landmark | Moderate | cat.semantics, best-practice | true |
| landmark-no-duplicate-contentinfo | Ensures the document has no more than one contentinfo landmark | Moderate | cat.semantics, best-practice | true |
| landmark-one-main | Ensures a navigation point to the primary content of the page. If the page contains iframes, each iframe should contain either no main landmarks or just one | Moderate | cat.semantics, best-practice | true |
| layout-table | Ensures presentational &lt;table&gt; elements do not use &lt;th&gt;, &lt;caption&gt; elements or the summary attribute | Serious | cat.semantics, wcag2a, wcag131 | true |
| link-in-text-block | Links can be distinguished without relying on color | Serious | cat.color, experimental, wcag2a, wcag141 | true |
| link-name | Ensures links have discernible text | Serious | cat.name-role-value, wcag2a, wcag412, wcag244, section508, section508.22.a | true |
| list | Ensures that lists are structured correctly | Serious | cat.structure, wcag2a, wcag131 | true |
| listitem | Ensures &lt;li&gt; elements are used semantically | Serious | cat.structure, wcag2a, wcag131 | true |
| marquee | Ensures &lt;marquee&gt; elements are not used | Serious | cat.parsing, wcag2a, wcag222 | true |
| meta-refresh | Ensures &lt;meta http-equiv=&quot;refresh&quot;&gt; is not used | Critical | cat.time, wcag2a, wcag2aaa, wcag221, wcag224, wcag325 | true |
| meta-viewport-large | Ensures &lt;meta name=&quot;viewport&quot;&gt; can scale a significant amount | Minor | cat.sensory-and-visual-cues, best-practice | true |
| meta-viewport | Ensures &lt;meta name=&quot;viewport&quot;&gt; does not disable text scaling and zooming | Critical | cat.sensory-and-visual-cues, wcag2aa, wcag144 | true |
| object-alt | Ensures &lt;object&gt; elements have alternate text | Serious | cat.text-alternatives, wcag2a, wcag111, section508, section508.22.a | true |
| p-as-heading | Ensure p elements are not used to style headings | Serious | cat.semantics, wcag2a, wcag131, experimental | true |
| page-has-heading-one | Ensure that the page, or at least one of its frames contains a level-one heading | Moderate | cat.semantics, best-practice | true |
| radiogroup | Ensures related &lt;input type=&quot;radio&quot;&gt; elements have a group and that the group designation is consistent | Critical | cat.forms, best-practice | true |
| region | Ensures all content is contained within a landmark region | Moderate | cat.keyboard, best-practice | true |
| scope-attr-valid | Ensures the scope attribute is used correctly on tables | Moderate, Critical | cat.tables, best-practice | true |
| server-side-image-map | Ensures that server-side image maps are not used | Minor | cat.text-alternatives, wcag2a, wcag211, section508, section508.22.f | true |
| skip-link | Ensure all skip links have a focusable target | Moderate | cat.keyboard, best-practice | true |
| tabindex | Ensures tabindex attribute values are not greater than 0 | Serious | cat.keyboard, best-practice | true |
| table-duplicate-name | Ensure that tables do not have the same summary and caption | Minor | cat.tables, best-practice | true |
| table-fake-caption | Ensure that tables with a caption use the &lt;caption&gt; element. | Serious | cat.tables, experimental, wcag2a, wcag131, section508, section508.22.g | true |
| td-has-header | Ensure that each non-empty data cell in a large table has one or more table headers | Critical | cat.tables, experimental, wcag2a, wcag131, section508, section508.22.g | true |
| td-headers-attr | Ensure that each cell in a table using the headers refers to another cell in that table | Serious | cat.tables, wcag2a, wcag131, section508, section508.22.g | true |
| th-has-data-cells | Ensure that each table header in a data table refers to data cells | Serious | cat.tables, wcag2a, wcag131, section508, section508.22.g | true |
| valid-lang | Ensures lang attributes have valid values | Serious | cat.language, wcag2aa, wcag312 | true |
| video-caption | Ensures &lt;video&gt; elements have captions | Critical | cat.text-alternatives, wcag2a, wcag122, section508, section508.22.a | true |
| video-description | Ensures &lt;video&gt; elements have audio descriptions | Critical | cat.text-alternatives, wcag2aa, wcag125, section508, section508.22.b | true |

@@ -61,7 +61,7 @@ # Developing Axe-core Rules

As one example, the audio and video caption checks return an incomplete string:
```
```javascript
messages: {
pass: 'Why the check passed',
fail: 'Why the check failed',
incomplete: 'Why the check returned undefined'
pass: 'Why the check passed',
fail: 'Why the check failed',
incomplete: 'Why the check returned undefined'
}

@@ -75,10 +75,10 @@ ```

```
```javascript
messages: {
pass: 'Why the check passed',
fail: 'Why the check failed',
incomplete: {
bgImage: 'The background color could not be determined due to a background image',
default: 'fallback string'
}
pass: 'Why the check passed',
fail: 'Why the check failed',
incomplete: {
bgImage: 'The background color could not be determined due to a background image',
default: 'fallback string'
}
}

@@ -92,6 +92,6 @@ ```

```
```javascript
this.data({
missingData: 'bgImage'
missingData: 'bgImage'
});
```

@@ -1,3 +0,6 @@

/*eslint complexity: ["error",12], max-statements: ["error", 30],
camelcase: ["error", {"properties": "never"}]*/
/*eslint
complexity: ["error",12],
max-statements: ["error", 35],
camelcase: ["error", {"properties": "never"}]
*/
var testConfig = require('./build/test/config');

@@ -18,5 +21,5 @@

grunt.loadNpmTasks('grunt-mocha');
grunt.loadTasks('build/tasks');
grunt.loadNpmTasks('grunt-parallel');
grunt.loadNpmTasks('grunt-markdownlint');
grunt.loadTasks('build/tasks');

@@ -42,2 +45,6 @@ var langs;

var webDriverTestBrowsers = ['firefox', 'chrome', 'ie', 'chrome-mobile'];
process.env.NODE_NO_HTTP2 = 1; // to hide node warning - (node:18740) ExperimentalWarning: The http2 module is an experimental API.
grunt.initConfig({

@@ -48,15 +55,23 @@ pkg: grunt.file.readJSON('package.json'),

options: {
stream: true,
grunt: true
},
tasks: [
'test-webdriver:firefox',
'test-webdriver:chrome',
// Edge Webdriver isn't all too stable, manual testing required
// 'test-webdriver:edge',
// 'test-webdriver:safari',
'test-webdriver:ie',
'test-webdriver:chrome-mobile'
]
tasks: webDriverTestBrowsers.map(function (b) {
return 'test-webdriver:' + b;
})
}
},
'test-webdriver': (function () {
var tests = testConfig(grunt);
var options = Object.assign({}, tests.unit.options);
options.urls = options.urls.concat(tests.integration.options.urls);
var driverTests = {};
webDriverTestBrowsers.forEach(function (browser) {
driverTests[browser] = {
options: Object.assign({ browser: browser }, options)
};
});
return driverTests;
}()),
retire: {

@@ -135,2 +150,9 @@ options: {

},
'aria-supported': {
data: {
entry: 'lib/commons/aria/index.js',
destFile: 'doc/aria-supported.md',
listType: 'unsupported' // Possible values for listType: 'supported', 'unsupported', 'all'
}
},
configure: {

@@ -160,3 +182,3 @@ rules: {

},
langs : {
langs: {
generate: {

@@ -200,3 +222,3 @@ check: 'lib/commons/utils/valid-langs'

indent_level: 2,
bracketize: true,
braces: true,
quote_style: 1

@@ -215,8 +237,8 @@ },

options: {
preserveComments: function(node, comment) {
preserveComments: function (node, comment) {
// preserve comments that start with a bang
return /^!/.test( comment.value );
return /^!/.test(comment.value);
},
mangle: {
except: ['commons', 'utils', 'axe', 'window', 'document']
reserved: ['commons', 'utils', 'axe', 'window', 'document']
}

@@ -309,16 +331,3 @@ }

}),
'test-webdriver': (function () {
var tests = testConfig(grunt);
var options = Object.assign({}, tests.unit.options);
options.urls = options.urls.concat(tests.integration.options.urls);
var driverTests = {};
['firefox', 'chrome', 'ie', 'safari', 'edge', 'chrome-mobile']
.forEach(function (browser) {
driverTests[browser] = {
options: Object.assign({ browser: browser }, options)
};
});
return driverTests;
}()),
connect: {

@@ -341,4 +350,9 @@ test: {

src: [
'lib/**/*.js', 'test/**/*.js', 'build/**/*.js',
'doc/**/*.js', '!doc/examples/jest+react/*.js', 'Gruntfile.js',
'lib/**/*.js',
'test/**/*.js',
'build/**/*.js',
'doc/**/*.js',
'!doc/examples/jest_react/*.js',
'Gruntfile.js',
'!build/tasks/aria-supported.js',
'!**/node_modules/**/*.js'

@@ -352,3 +366,3 @@ ]

config: grunt.file.readJSON('.markdownlint.json')
},
},
src: [

@@ -363,22 +377,79 @@ 'README.md',

grunt.registerTask('default', ['build']);
grunt.registerTask('default', [
'build'
]);
grunt.registerTask('build', ['clean', 'eslint', 'validate', 'concat:commons', 'configure',
'babel', 'concat:engine', 'uglify']);
grunt.registerTask('build', [
'clean',
'eslint',
'validate',
'concat:commons',
'configure',
'babel',
'concat:engine',
'uglify',
'aria-supported'
]);
grunt.registerTask('test', ['build', 'retire', 'testconfig', 'fixture', 'connect',
'mocha', 'parallel', 'eslint', 'markdownlint']);
grunt.registerTask('test', [
'build',
'retire',
'testconfig',
'fixture',
'connect',
'mocha',
'parallel',
'eslint',
'markdownlint'
]);
grunt.registerTask('ci-build', ['build', 'retire', 'testconfig', 'fixture', 'connect',
'parallel', 'eslint']);
grunt.registerTask('ci-build', [
'build',
'retire',
'testconfig',
'fixture',
'connect',
'parallel',
'eslint'
]);
grunt.registerTask('test-fast', ['build', 'testconfig', 'fixture', 'connect',
'mocha', 'eslint']);
grunt.registerTask('test-fast', [
'build',
'testconfig',
'fixture',
'connect',
'mocha',
'eslint'
]);
grunt.registerTask('translate', ['clean', 'eslint', 'validate', 'concat:commons', 'add-locale']);
grunt.registerTask('translate', [
'clean',
'eslint',
'validate',
'concat:commons',
'add-locale'
]);
grunt.registerTask('dev', ['build', 'testconfig', 'fixture', 'connect', 'watch']);
grunt.registerTask('dev', [
'build',
'testconfig',
'fixture',
'connect',
'watch'
]);
grunt.registerTask('dev:no-lint', ['clean', 'validate', 'concat:commons', 'configure',
'babel', 'concat:engine', 'uglify', 'testconfig', 'fixture', 'connect', 'watch']);
grunt.registerTask('dev:no-lint', [
'clean',
'validate',
'concat:commons',
'configure',
'babel',
'concat:engine',
'uglify',
'testconfig',
'fixture',
'connect',
'watch'
]);
};

@@ -1,5 +0,6 @@

var requiredOwned = axe.commons.aria.requiredOwned,
implicitNodes = axe.commons.aria.implicitNodes,
matchesSelector = axe.commons.utils.matchesSelector,
idrefs = axe.commons.dom.idrefs;
const requiredOwned = axe.commons.aria.requiredOwned;
const implicitNodes = axe.commons.aria.implicitNodes;
const matchesSelector = axe.commons.utils.matchesSelector;
const idrefs = axe.commons.dom.idrefs;
const reviewEmpty = options && Array.isArray(options.reviewEmpty) ? options.reviewEmpty : [];

@@ -89,2 +90,7 @@ function owns(node, virtualTree, role, ariaOwned) {

this.data(missing);
return false;
if (reviewEmpty.includes(role)) {
return undefined;
} else {
return false;
}
{
"id": "aria-required-children",
"evaluate": "required-children.js",
"options": {
"reviewEmpty": ["listbox"]
},
"metadata": {

@@ -8,5 +11,6 @@ "impact": "critical",

"pass": "Required ARIA children are present",
"fail": "Required ARIA {{=it.data && it.data.length > 1 ? 'children' : 'child'}} role not present:{{~it.data:value}} {{=value}}{{~}}"
"fail": "Required ARIA {{=it.data && it.data.length > 1 ? 'children' : 'child'}} role not present:{{~it.data:value}} {{=value}}{{~}}",
"incomplete": "Expecting ARIA {{=it.data && it.data.length > 1 ? 'children' : 'child'}} role to be added:{{~it.data:value}} {{=value}}{{~}}"
}
}
}

@@ -17,2 +17,3 @@ /**

const VALID_ROLES_FOR_SCROLLABLE_REGIONS = {
application: true,
banner: false,

@@ -19,0 +20,0 @@ complementary: true,

@@ -12,6 +12,5 @@ var tableUtils = axe.commons.table;

// Check if it has any headers
var hasHeaders = tableUtils.getHeaders(cell);
hasHeaders = hasHeaders.reduce(function (hasHeaders, header) {
return (hasHeaders || header !== null && !!axe.commons.dom.hasContent(header));
}, false);
const hasHeaders = tableUtils.getHeaders(cell).some(header => {
return header !== null && !!axe.commons.dom.hasContent(header);
});

@@ -18,0 +17,0 @@ // If no headers, put it on the naughty list

@@ -92,7 +92,3 @@ /* global aria, axe, dom */

list = axe.utils.tokenList(value);
// Check if any value isn't in the list of values
return list.reduce(function (result, token) {
return !!(result && doc.getElementById(token));
// Initial state, fail if the list is empty
}, list.length !== 0);
return list.some((token) => doc.getElementById(token));

@@ -99,0 +95,0 @@ case 'string':

@@ -16,3 +16,8 @@ /* global table */

}
return cell.nodeName.toUpperCase() === 'TD';
const role = cell.getAttribute('role');
if (axe.commons.aria.isValidRole(role)) {
return ['cell', 'gridcell'].includes(role);
} else {
return cell.nodeName.toUpperCase() === 'TD';
}
};

@@ -49,3 +49,3 @@ /* global text, dom, aria, axe */

function shouldNeverCheckSubtree({ actualNode }) {
return ['TABLE', 'FIGURE'].includes(actualNode.nodeName.toUpperCase());
return ['TABLE', 'FIGURE', 'SELECT'].includes(actualNode.nodeName.toUpperCase());
}

@@ -59,3 +59,3 @@

*/
function formValueText({ actualNode }) {
function formValueText({ actualNode }, inLabelledByContext) {
const nodeName = actualNode.nodeName.toUpperCase();

@@ -70,3 +70,3 @@ if (nodeName === 'INPUT') {

if (nodeName === 'SELECT') {
if (nodeName === 'SELECT' && inLabelledByContext) {
var opts = actualNode.options;

@@ -317,3 +317,3 @@ if (opts && opts.length) {

if (inControlContext) {
returnText = formValueText(element);
returnText = formValueText(element, inLabelledByContext);
if (nonEmptyText(returnText)) {

@@ -325,3 +325,3 @@ return returnText;

//Step 2f
if (!shouldNeverCheckSubtree(element) &&
if ((inLabelledByContext || !shouldNeverCheckSubtree(element)) &&
(!role || aria.getRolesWithNameFromContents().indexOf(role) !== -1)) {

@@ -328,0 +328,0 @@

@@ -33,3 +33,2 @@ (function (axe) {

definitions.forEach(function (definition) {

@@ -36,0 +35,0 @@ var name = definition.name;

@@ -9,3 +9,4 @@ /*exported axe, commons */

if (typeof define === 'function' && define.amd) {
define([], function () {
// Explicitly naming the module to avoid mismatched anonymous define() modules when injected in a page
define('axe-core', [], function () {
'use strict';

@@ -12,0 +13,0 @@ return axe;

@@ -11,3 +11,3 @@ /**

/*eslint no-bitwise: 0, eqeqeq: 0, complexity: ["error",27],
max-statements:["error", 23], one-var: 0, -W041: 0 */
max-statements:["error", 25], one-var: 0, -W041: 0 */
var string = String(value);

@@ -24,13 +24,14 @@ var length = string.length;

// If the character is NULL (U+0000), then throw an
// `InvalidCharacterError` exception and terminate these steps.
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
// (U+FFFD).
if (codeUnit == 0x0000) {
throw new Error('INVALID_CHARACTER_ERR');
result += '\uFFFD';
continue;
}
if (
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or
// [\7F-\9F] (U+007F to U+009F), […]
(codeUnit >= 0x0001 && codeUnit <= 0x001F) ||
(codeUnit >= 0x007F && codeUnit <= 0x009F) ||
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
// U+007F, […]
(codeUnit >= 0x0001 && codeUnit <= 0x001F) ||
codeUnit == 0x007F ||
// If the character is the first character and is in the range [0-9]

@@ -43,3 +44,3 @@ // (U+0030 to U+0039), […]

) {
// http://dev.w3.org/csswg/cssom/#escape-a-character-as-code-point
// https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
result += '\\' + codeUnit.toString(16) + ' ';

@@ -49,6 +50,5 @@ continue;

// If the character is the second character and is `-` (U+002D) and the
// first character is `-` as well, […]
if (index == 1 && codeUnit == 0x002D && firstCodeUnit == 0x002D) {
// http://dev.w3.org/csswg/cssom/#escape-a-character
// If the character is the first character and is a `-` (U+002D), and
// there is no second character, […]
if (index == 0 && length == 1 && codeUnit == 0x002D) {
result += '\\' + string.charAt(index);

@@ -76,3 +76,3 @@ continue;

// Otherwise, the escaped character.
// http://dev.w3.org/csswg/cssom/#escape-a-character
// https://drafts.csswg.org/cssom/#escape-a-character
result += '\\' + string.charAt(index);

@@ -79,0 +79,0 @@

@@ -22,2 +22,6 @@ /* eslint max-statements:["error",18], complexity:["error",27], no-script-url:0 */

function trimRight (str) {
return str.replace(/\s+$/, '')
}
/**

@@ -94,5 +98,5 @@ * Take a relative or absolute URL and pull it into it's indivisual pieces

if (pathEnd && (pathEnd + hash).length <= maxLength) {
return pathEnd + hash;
return trimRight(pathEnd + hash);
} else if (pathEnd.length < 2 && hash.length > 2 && hash.length <= maxLength) {
return hash;
return trimRight(hash);
} else {

@@ -102,3 +106,3 @@ return;

} else if (domain && domain.length < maxLength && path.length <= 1) {// '' or '/'
return domain + path;
return trimRight(domain + path);
}

@@ -112,3 +116,3 @@

) {
return domain + path;
return trimRight(domain + path);
}

@@ -126,4 +130,4 @@

) {
return pathEnd;
return trimRight(pathEnd);
}
};

@@ -6,4 +6,3 @@ {

"tags": [
"wcag2a",
"wcag211",
"best-practice",
"cat.keyboard"

@@ -10,0 +9,0 @@ ],

@@ -8,2 +8,3 @@ {

"wcag241",
"wcag412",
"section508",

@@ -10,0 +11,0 @@ "section508.22.i"

@@ -8,3 +8,2 @@ {

"wcag2a",
"wcag111",
"wcag412",

@@ -11,0 +10,0 @@ "wcag244",

{
"name": "axe-core",
"description": "Accessibility engine for automated Web UI testing",
"version": "3.0.2",
"version": "3.0.3",
"license": "MPL-2.0",

@@ -52,2 +52,7 @@ "engines": {

"typings": "axe.d.ts",
"standard-version": {
"scripts": {
"postbump": "npm run sri-update"
}
},
"scripts": {

@@ -60,17 +65,20 @@ "build": "grunt",

"postinstall": "node build/utils/postinstall.js",
"release": "standard-version && node build/sri-update"
"release": "standard-version -a",
"sri-update": "grunt build && node build/sri-update && git add sri-history.json"
},
"devDependencies": {
"angular-precommit": "^1.0.3",
"aria-query": "^2.0.0",
"babel-core": "^6.26.0",
"babel-plugin-transform-object-rest-spread": "^6.6.5",
"babel-polyfill": "^6.7.4",
"babel-preset-es2015": "^6.6.0",
"babelify": "^7.2.0",
"babelify": "^8.0.0",
"blanket": "~1.2.3",
"chai": "~3.5.0",
"clone": "~1.0.2",
"dot": "~1.0.3",
"fs-extra": "^4.0.1",
"chai": "~4.1.2",
"clone": "~2.1.1",
"dot": "~1.1.2",
"fs-extra": "^6.0.0",
"grunt": "^1.0.2",
"grunt-babel": "^6.0.0",
"grunt-babel": "^7.0.0",
"grunt-contrib-clean": "^1.0.0",

@@ -80,7 +88,7 @@ "grunt-contrib-concat": "^1.0.1",

"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-uglify": "^2.1.0",
"grunt-contrib-watch": "^1.0.0",
"grunt-contrib-uglify": "^3.3.0",
"grunt-contrib-watch": "^1.1.0",
"grunt-eslint": "^20.1.0",
"grunt-markdownlint": "^1.1.2",
"grunt-mocha": "^1.0.4",
"grunt-markdownlint": "^1.1.5",
"grunt-mocha": "1.0.4",
"grunt-parallel": "^0.5.1",

@@ -90,6 +98,7 @@ "grunt-retire": "^1.0.7",

"jquery": "^3.0.0",
"mocha": "^3.2.0",
"promise": "~7.1.1",
"markdown-table": "^1.1.2",
"mocha": "^5.2.0",
"promise": "~8.0.1",
"revalidator": "~0.3.1",
"selenium-webdriver": "~3.4.0",
"selenium-webdriver": "~3.6.0",
"sri-toolbox": "^0.2.0",

@@ -99,2 +108,2 @@ "standard-version": "^4.2.0"

"dependencies": {}
}
}
# axe-core
[![Greenkeeper badge](https://badges.greenkeeper.io/dequelabs/axe-core.svg)](https://greenkeeper.io/)
[![License](https://img.shields.io/npm/l/axe-core.svg)](LICENSE)

@@ -44,3 +46,3 @@ [![Version](https://img.shields.io/npm/v/axe-core.svg)](https://www.npmjs.com/package/axe-core)

```
```console
npm install axe-core --save-dev

@@ -59,3 +61,3 @@ ```

axe.run(function (err, results) {
if (err) throw err;
if (err) throw err;
ok(results.violations.length === 0, 'Should be no accessibility issues');

@@ -66,2 +68,3 @@ // complete the async call

```
## Supported Browsers

@@ -104,2 +107,6 @@

## Supported ARIA Roles and Attributes.
Refer [aXe ARIA support](./doc/aria-supported.md) for a complete list of ARIA supported roles and attributes by axe.
## Contributing

@@ -106,0 +113,0 @@

@@ -109,3 +109,7 @@ {

"axe.min.js": "sha256-Hsc1oDUNhkVBP4gVUaC9jNm9t0qmLpTJzXW4uzx10bo="
},
"3.0.3": {
"axe.js": "sha256-QhYA1btt0EGa6HUDloEPZ5p6ZArWsL8J9C7PDoqi320=",
"axe.min.js": "sha256-Xlzi+kk/RJRo2x/+w04BppEgcrO/Cy9xTSbuIp6m/CU="
}
}

@@ -168,2 +168,30 @@ describe('aria-required-children', function () {

describe('options', function () {
it('should return undefined instead of false when the role is in options.reviewEmpty', function () {
var params = checkSetup('<div role="grid" id="target"></div>');
assert.isFalse(checks['aria-required-children'].evaluate.apply(checkContext, params));
// Options:
params[1] = {
reviewEmpty: ['grid']
}
assert.isUndefined(checks['aria-required-children'].evaluate.apply(checkContext, params));
});
it('should not throw when options is incorrect', function () {
var params = checkSetup('<div role="grid" id="target"></div>');
// Options: (incorrect)
params[1] = ['grid']
assert.isFalse(checks['aria-required-children'].evaluate.apply(checkContext, params));
// Options: (incorrect)
params[1] = null
assert.isFalse(checks['aria-required-children'].evaluate.apply(checkContext, params));
// Options: (incorrect)
params[1] = 'grid'
assert.isFalse(checks['aria-required-children'].evaluate.apply(checkContext, params));
});
});
});

@@ -41,3 +41,2 @@ describe('implicit-label', function () {

});
});

@@ -242,3 +242,2 @@ describe('aria.requiredAttr', function () {

it('should return false when a single referenced node is not found', function () {
node.setAttribute('cats', 'invalid');

@@ -249,8 +248,14 @@ // target2 not found

it('should return false when a referenced element is not found', function () {
it('should return false when at no referenced element is found', function () {
fixture.innerHTML = '<div id="target"></div>';
node.setAttribute('cats', 'target2 target3');
// target2 not found
assert.isFalse(axe.commons.aria.validateAttrValue(node, 'cats'));
});
it('should return true when at least one referenced element is found', function () {
fixture.innerHTML = '<div id="target"></div>';
node.setAttribute('cats', 'target target2');
// target2 not found
assert.isFalse(axe.commons.aria.validateAttrValue(node, 'cats'));
assert.isTrue(axe.commons.aria.validateAttrValue(node, 'cats'));
});

@@ -257,0 +262,0 @@

@@ -43,2 +43,40 @@ describe('table.isDataCell', function () {

it('should ignore TDs with a valid role other than (grid)cell', function () {
fixture.innerHTML = '<table>' +
'<tr><td id="target1" role="columnheader">heading</td></tr>' +
'<tr><td id="target2" role="rowheader">heading</td></tr>' +
'<tr><td id="target3" role="presentation">heading</td></tr>' +
'</table>';
var target1 = $id('target1');
var target2 = $id('target2');
var target3 = $id('target3');
assert.isFalse(axe.commons.table.isDataCell(target1));
assert.isFalse(axe.commons.table.isDataCell(target2));
assert.isFalse(axe.commons.table.isDataCell(target3));
});
it('should return true for elements with role="(grid)cell"', function () {
fixture.innerHTML = '<table>' +
'<tr><th id="target1" role="cell">heading</th></tr>' +
'<tr><th id="target2" role="gridcell">heading</th></tr>' +
'</table>';
var target1 = $id('target1');
var target2 = $id('target2');
assert.isTrue(axe.commons.table.isDataCell(target1));
assert.isTrue(axe.commons.table.isDataCell(target2));
});
it('should ignore invalid roles', function () {
fixture.innerHTML = '<table>' +
'<tr><td id="target1" role="foobar">heading</td></tr>' +
'<tr><th id="target2" role="foobar">heading</th></tr>' +
'</table>';
var target1 = $id('target1');
var target2 = $id('target2');
assert.isTrue(axe.commons.table.isDataCell(target1));
assert.isFalse(axe.commons.table.isDataCell(target2));
});
});

@@ -315,2 +315,58 @@ describe('text.accessibleTextVirtual', function() {

it('should come up empty if input is labeled only by select options', function () {
fixture.innerHTML = '<label for="target">' +
'<select id="select">' +
' <option selected="selected">Chosen</option>' +
' <option>Not Selected</option>' +
'</select>' +
'</label>' +
'<input id="target" type="text" />';
axe._tree = axe.utils.getFlattenedTree(fixture);
var target = axe.utils.querySelectorAll(axe._tree, '#target')[0];
assert.equal(axe.commons.text.accessibleTextVirtual(target), '');
});
it('should be empty if input is labeled by labeled select (ref\'d string labels have spotty support)', function () {
fixture.innerHTML = '<label for="select">My Select</label>' +
'<label for="target">' +
'<select id="select">' +
' <option selected="selected">Chosen</option>' +
' <option>Not Selected</option>' +
'</select>' +
'</label>' +
'<input id="target" type="text" />';
axe._tree = axe.utils.getFlattenedTree(fixture);
var target = axe.utils.querySelectorAll(axe._tree, '#target')[0];
assert.equal(axe.commons.text.accessibleTextVirtual(target), '');
});
it('should be empty for an empty label wrapping a select', function () {
fixture.innerHTML = '<label>' +
'<span class="label"></span>' +
'<select id="target">' +
'<option value="1" selected="selected">Please choose a region</option>' +
'<option value="2">Coastal</option>' +
'<option value="3">Forest</option>' +
'<option value="4">Grasslands</option>' +
'<option value="5">Mountains</option>' +
'</select>' +
'</label>';
axe._tree = axe.utils.getFlattenedTree(fixture);
var target = axe.utils.querySelectorAll(axe._tree, '#target')[0];
assert.equal(axe.commons.text.accessibleTextVirtual(target), '');
});
it('should return select options if input is aria-labelled by a select', function () {
fixture.innerHTML = '<label>' +
'<select id="select">' +
' <option selected="selected">Chosen</option>' +
' <option>Not Selected</option>' +
'</select>' +
'</label>' +
'<input aria-labelledby="select" type="text" id="target" />';
axe._tree = axe.utils.getFlattenedTree(fixture);
var target = axe.utils.querySelectorAll(axe._tree, '#target')[0];
assert.equal(axe.commons.text.accessibleTextVirtual(target), 'Chosen');
});
it('shoud properly fall back to title', function() {

@@ -317,0 +373,0 @@ fixture.innerHTML = '<a href="#" role="presentation" title="Hello"></a>';

@@ -6,8 +6,25 @@ /*eslint max-statements: 0 */

it('should serialize strings based on CSSOM spec', function () {
it('leaves characters that do not need to escape alone', function () {
assert.equal(escapeSelector('a0b'), 'a0b');
assert.equal(escapeSelector('a1b'), 'a1b');
assert.equal(escapeSelector('a2b'), 'a2b');
assert.equal(escapeSelector('a3b'), 'a3b');
assert.equal(escapeSelector('a4b'), 'a4b');
assert.equal(escapeSelector('a5b'), 'a5b');
assert.equal(escapeSelector('a6b'), 'a6b');
assert.equal(escapeSelector('a7b'), 'a7b');
assert.equal(escapeSelector('a8b'), 'a8b');
assert.equal(escapeSelector('a9b'), 'a9b');
assert.equal(escapeSelector('a0123456789b'), 'a0123456789b');
assert.equal(escapeSelector('abcdefghijklmnopqrstuvwxyz'), 'abcdefghijklmnopqrstuvwxyz');
assert.equal(escapeSelector('ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
});
assert.throws(function () { escapeSelector('\0'); }, Error);
assert.throws(function () { escapeSelector('a\0'); }, Error);
assert.throws(function () { escapeSelector('a\0b'); }, Error);
it('escapes null characters', function () {
assert.equal(escapeSelector('\0'), '\uFFFD');
assert.equal(escapeSelector('a\0'), 'a\uFFFD');
assert.equal(escapeSelector('a\0b'), 'a\uFFFDb');
});
it('stringifies non-string characters', function () {
assert.equal(escapeSelector(), 'undefined');

@@ -18,5 +35,5 @@ assert.equal(escapeSelector(true), 'true');

assert.equal(escapeSelector(''), '');
});
assert.equal(escapeSelector('\x01\x02\x1E\x1F'), '\\1 \\2 \\1e \\1f ');
it('escapes strings starting with a number', function () {
assert.equal(escapeSelector('0a'), '\\30 a');

@@ -32,14 +49,11 @@ assert.equal(escapeSelector('1a'), '\\31 a');

assert.equal(escapeSelector('9a'), '\\39 a');
});
assert.equal(escapeSelector('a0b'), 'a0b');
assert.equal(escapeSelector('a1b'), 'a1b');
assert.equal(escapeSelector('a2b'), 'a2b');
assert.equal(escapeSelector('a3b'), 'a3b');
assert.equal(escapeSelector('a4b'), 'a4b');
assert.equal(escapeSelector('a5b'), 'a5b');
assert.equal(escapeSelector('a6b'), 'a6b');
assert.equal(escapeSelector('a7b'), 'a7b');
assert.equal(escapeSelector('a8b'), 'a8b');
assert.equal(escapeSelector('a9b'), 'a9b');
it('only escapes "-" when before a number, or on its own', function () {
assert.equal(escapeSelector('-123'), '-\\31 23');
assert.equal(escapeSelector('-'), '\\-');
assert.equal(escapeSelector('--a'), '--a');
});
it('escapes characters staring with a negative number', function () {
assert.equal(escapeSelector('-0a'), '-\\30 a');

@@ -55,11 +69,9 @@ assert.equal(escapeSelector('-1a'), '-\\31 a');

assert.equal(escapeSelector('-9a'), '-\\39 a');
});
assert.equal(escapeSelector('--a'), '-\\-a');
assert.equal(escapeSelector('\x80\x2D\x5F\xA9'), '\\80 \x2D\x5F\xA9');
it('escapes hex character codes', function () {
assert.equal(escapeSelector('\x80\x2D\x5F\xA9'), '\x80\x2D\x5F\xA9');
assert.equal(escapeSelector('\xA0\xA1\xA2'), '\xA0\xA1\xA2');
assert.equal(escapeSelector('a0123456789b'), 'a0123456789b');
assert.equal(escapeSelector('abcdefghijklmnopqrstuvwxyz'), 'abcdefghijklmnopqrstuvwxyz');
assert.equal(escapeSelector('ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
assert.equal(escapeSelector('\x01\x02\x1E\x1F'), '\\1 \\2 \\1e \\1f ');
assert.equal(escapeSelector('\x20\x21\x78\x79'), '\\ \\!xy');

@@ -72,5 +84,4 @@

assert.equal(escapeSelector('\uD834'), '\uD834');
});
});

@@ -18,5 +18,12 @@ describe('axe.utils.getFriendlyUriEnd', function () {

it('trims whitespace', function () {
assert.equal(undefined, getFriendlyUriEnd(' '));
assert.equal('start page', getFriendlyUriEnd('start page\t'));
assert.equal('home#heading', getFriendlyUriEnd('home#heading '));
});
it('returns a hash URI', function () {
assert.equal('#footer', getFriendlyUriEnd('#footer'));
assert.equal('contact.html#footer', getFriendlyUriEnd('/contact.html#footer'));
assert.equal('home.html#main', getFriendlyUriEnd('/home.html#main '));
});

@@ -23,0 +30,0 @@

@@ -6,31 +6,34 @@

before(function (done) {
if (document.readyState !== 'complete') {
window.addEventListener('load', done.bind(this, null));
} else {
axe.testUtils.awaitNestedLoad(function () {
done();
}
});
});
describe('when set', function () {
var opts = {
frameWaitTime: 1
};
it('should modify the default frame timeout', function (done) {
var start = new Date();
// Run axe with an unreasonably short wait time,
// expecting the frame to time out
axe.run('main', opts, function (err, res) {
assert.isNotNull(err);
assert.isUndefined(res);
assert.equal(err.message, 'Axe in frame timed out: #frame');
// Ensure that axe waited less than the default wait time
assert.isBelow(new Date() - start, 60000);
done();
});
});
/**
* Commenting out test, due to issue addressed beloe.
* https://github.com/dequelabs/axe-core/issues/929
*/
// var opts = {
// frameWaitTime: 1
// };
it('should modify the default frame timeout'
// Issue -
// function (done) {
// var start = new Date();
// // Run axe with an unreasonably short wait time,
// // expecting the frame to time out
// axe.run('#frame', opts, function (err, res) {
// assert.isNotNull(err);
// assert.isUndefined(res);
// assert.equal(err.message, 'Axe in frame timed out: #frame');
// // Ensure that axe waited less than the default wait time
// assert.isBelow(new Date() - start, 60000);
// done();
// });
// }
);
});
describe('when not set', function () {
it('should use the default frame timeout', function (done) {

@@ -37,0 +40,0 @@ axe.run('main', function (err, res) {

@@ -9,6 +9,13 @@ /* global defineCalls */

var call = defineCalls[0];
assert.isFunction(call[1]);
assert.strictEqual(call[1](), axe);
assert.isFunction(call[2]);
assert.strictEqual(call[2](), axe);
});
it('defines module name as axe-core', function () {
assert.equal(defineCalls.length, 1);
var call = defineCalls[0];
assert.equal(call[0], 'axe-core');
});
});

@@ -18,3 +18,6 @@ {

["#pass8"]
],
"incomplete": [
["#incomplete1"]
]
}

@@ -11,3 +11,4 @@ {

["#pass6"],
["#pass7"]
["#pass7"],
["#pass8"]
],

@@ -14,0 +15,0 @@ "violations": [

@@ -14,4 +14,8 @@ {

["#fail9"],
["#fail10"],
["#fail22"],
["#fail23"]
["#fail23"],
["#fail24"],
["#fail25"],
["#fail26"]
],

@@ -33,4 +37,5 @@ "passes": [

["#pass14"],
["#pass15"]
["#pass15"],
["#pass16"]
]
}

@@ -5,3 +5,9 @@ {

"violations": [["#fail1"], ["#fail2"]],
"passes": [["#pass1"], ["#pass2"], ["#pass3"]]
"passes": [
["#pass1"],
["#pass2"],
["#pass3"],
["#pass4"],
["#pass5"]
]
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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