From 3fc384f56a2baf7c5073bd4bbd8d4137b8d5281d Mon Sep 17 00:00:00 2001 From: Marcy Sutton Date: Thu, 1 Mar 2018 16:26:48 -0800 Subject: [PATCH 1/5] chore: Remove unused less library --- build/build-manual.js | 36 ++++++------------------------------ build/configure.js | 3 +-- build/tasks/add-locale.js | 1 - build/tasks/configure.js | 1 - package.json | 3 +-- 5 files changed, 8 insertions(+), 36 deletions(-) diff --git a/build/build-manual.js b/build/build-manual.js index 2f72eb4717..c92d505d02 100644 --- a/build/build-manual.js +++ b/build/build-manual.js @@ -3,7 +3,6 @@ var path = require('path'); var templates = require('./templates'); -var less = require('less'); var Promise = require('promise'); module.exports = function build(grunt, options, commons, callback) { @@ -26,23 +25,6 @@ module.exports = function build(grunt, options, commons, callback) { }); } - function parseStyle(src, callback) { - Promise - .all(grunt.file.expand(src).map(function(file) { - return new Promise(function(resolve, reject) { - less.render(grunt.file.read(file), function(err, result) { - if (err) { - return reject(err); - } - resolve(result.css); - }); - }); - })) - .then(function(values) { - callback(values.join('\n')); - }); - } - function getSource(file, type) { return grunt.template.process(templates[type], { data: { @@ -51,17 +33,11 @@ module.exports = function build(grunt, options, commons, callback) { }); } - parseStyle(options.style, function(styles) { - - callback({ - rules: parseObject(options.rules), - checks: parseObject(options.checks), - tools: parseObject(options.tools), - misc: parseObject(options.misc), - commons: commons, - style: styles - }); - + callback({ + rules: parseObject(options.rules), + checks: parseObject(options.checks), + tools: parseObject(options.tools), + misc: parseObject(options.misc), + commons: commons }); - }; diff --git a/build/configure.js b/build/configure.js index e16851722a..365cc18189 100644 --- a/build/configure.js +++ b/build/configure.js @@ -181,8 +181,7 @@ function buildRules(grunt, options, commons, callback) { rules: rules, checks: checks, commons: result.commons, - tools: result.tools, - style: result.style + tools: result.tools }, blacklist)), descriptions: descriptionHeaders + descriptions.map(function (row) { return '| ' + row.join(' | ') + ' |'; diff --git a/build/tasks/add-locale.js b/build/tasks/add-locale.js index 227c28c0f7..6acb9df508 100644 --- a/build/tasks/add-locale.js +++ b/build/tasks/add-locale.js @@ -35,7 +35,6 @@ module.exports = function (grunt) { rules: ['lib/rules/**/*.json'], checks: ['lib/checks/**/*.json'], tools: ['lib/tools/**/*.json'], - style: ['lib/**/*.less'], misc: ['lib/misc/**/*.json'], blacklist: ['metadata'], tags: '', diff --git a/build/tasks/configure.js b/build/tasks/configure.js index 00b4b39b94..1ce63c4b44 100644 --- a/build/tasks/configure.js +++ b/build/tasks/configure.js @@ -10,7 +10,6 @@ module.exports = function (grunt) { rules: ['lib/rules/**/*.json'], checks: ['lib/checks/**/*.json'], tools: ['lib/tools/**/*.json'], - style: ['lib/**/*.less'], misc: ['lib/misc/**/*.json'], blacklist: ['metadata'], tags: '' diff --git a/package.json b/package.json index e36398cf44..7818dbb7f2 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,6 @@ "grunt-retire": "^1.0.7", "html-entities": "^1.2.0", "jquery": "^3.0.0", - "less": "~2.6.1", "mocha": "^3.2.0", "promise": "~7.1.1", "revalidator": "~0.3.1", @@ -92,4 +91,4 @@ "standard-version": "^4.2.0" }, "dependencies": {} -} \ No newline at end of file +} From f13ad3651d2ebee10625e4c8299791f020d9430a Mon Sep 17 00:00:00 2001 From: Marcy Sutton Date: Fri, 2 Mar 2018 14:39:22 -0800 Subject: [PATCH 2/5] chore: Switch to eslint from jshint Removes vulnerability in jshint, fixes lots of mixed spaces and tabs --- .eslintrc | 79 +++ Gruntfile.js | 37 +- build/build-manual.js | 2 +- build/configure.js | 3 +- build/tasks/add-locale.js | 137 ++--- build/tasks/configure.js | 49 +- build/tasks/fixture.js | 49 +- build/tasks/langs.js | 88 +-- build/tasks/test-webdriver.js | 175 +++--- build/tasks/testconfig.js | 39 +- build/tasks/update-help.js | 33 +- build/tasks/validate.js | 31 +- doc/examples/mocha/test/a11y.js | 2 +- lib/.eslintrc | 69 +++ lib/checks/.eslintrc | 80 +++ lib/checks/aria/allowed-attr.js | 4 +- lib/checks/aria/required-children.js | 16 +- lib/checks/aria/required-parent.js | 4 +- lib/checks/aria/valid-scrollable-semantics.js | 50 +- lib/checks/lists/has-listitem.js | 4 +- lib/checks/media/caption.js | 8 +- lib/checks/media/description.js | 10 +- lib/checks/navigation/p-as-heading.js | 7 +- lib/checks/navigation/skip-link.js | 2 +- lib/checks/shared/duplicate-id.js | 4 +- lib/checks/tables/td-headers-attr.js | 16 +- lib/checks/tables/th-has-data-cells.js | 24 +- lib/checks/visibility/hidden-content.js | 24 +- lib/commons/.eslintrc | 69 +++ lib/commons/aria/attributes.js | 2 +- lib/commons/color/element-is-distinct.js | 36 +- lib/commons/color/get-background-color.js | 34 +- lib/commons/dom/find-elms-in-context.js | 20 +- lib/commons/dom/find-up.js | 1 + lib/commons/dom/get-composed-parent.js | 30 +- lib/commons/dom/get-element-coordinates.js | 2 +- lib/commons/dom/get-scroll-offset.js | 2 +- lib/commons/dom/has-content-virtual.js | 48 +- lib/commons/dom/index.js | 2 +- lib/commons/dom/is-focusable.js | 3 +- lib/commons/dom/is-in-text-block.js | 2 +- lib/commons/dom/is-offscreen.js | 2 +- lib/commons/dom/is-visible.js | 4 +- lib/commons/dom/is-visual-content.js | 3 +- lib/commons/dom/shadow-elements-from-point.js | 30 +- lib/commons/dom/visually-contains.js | 6 +- lib/commons/dom/visually-overlaps.js | 2 +- lib/commons/index.js | 1 + lib/commons/table/get-headers.js | 8 +- lib/commons/table/get-scope.js | 6 +- lib/commons/table/index.js | 2 +- lib/commons/table/is-data-table.js | 2 +- lib/commons/table/traverse.js | 1 + lib/commons/text/accessible-text-virtual.js | 7 +- lib/commons/text/index.js | 2 +- lib/commons/utils/index.js | 2 +- lib/commons/utils/valid-langs.js | 2 +- lib/core/base/audit.js | 36 +- lib/core/base/check-result.js | 2 +- lib/core/base/check.js | 10 +- lib/core/base/context.js | 7 +- lib/core/base/rule-result.js | 2 +- lib/core/base/rule.js | 12 +- lib/core/constants.js | 106 ++-- lib/core/index.js | 7 +- lib/core/log.js | 2 +- lib/core/public/cleanup-plugins.js | 75 ++- lib/core/public/configure.js | 2 +- lib/core/public/load.js | 1 + lib/core/public/plugins.js | 1 + lib/core/public/run.js | 5 +- lib/core/reporters/helpers/failure-summary.js | 6 +- lib/core/reporters/helpers/index.js | 1 + .../reporters/helpers/process-aggregate.js | 36 +- lib/core/utils/aggregate.js | 5 +- lib/core/utils/aggregateNodeResults.js | 100 +-- lib/core/utils/aggregateResult.js | 12 +- lib/core/utils/clone.js | 2 +- lib/core/utils/contains.js | 2 +- lib/core/utils/css-parser.js | 2 +- lib/core/utils/dq-element.js | 10 +- lib/core/utils/element-matches.js | 8 +- lib/core/utils/escape-selector.js | 3 +- lib/core/utils/extend-meta-data.js | 16 +- lib/core/utils/flattened-tree.js | 3 +- lib/core/utils/get-check-option.js | 4 +- lib/core/utils/get-friendly-uri-end.js | 175 +++--- lib/core/utils/get-selector.js | 547 +++++++++-------- lib/core/utils/get-xpath.js | 2 +- lib/core/utils/index.js | 1 + lib/core/utils/is-shadow-root.js | 6 +- lib/core/utils/merge-results.js | 144 ++--- lib/core/utils/node-sorter.js | 4 +- lib/core/utils/pollyfills.js | 480 +++++++-------- lib/core/utils/qsa.js | 27 +- lib/core/utils/respondable.js | 5 +- lib/core/utils/rule-should-run.js | 4 +- lib/core/utils/scroll-state.js | 76 +-- lib/core/utils/select.js | 4 +- lib/core/utils/to-array.js | 12 +- lib/core/utils/uuid.js | 430 ++++++------- lib/rules/.eslintrc | 80 +++ lib/rules/heading-matches.js | 10 +- lib/rules/p-as-heading-matches.js | 10 +- package.json | 2 +- test/.eslintrc | 81 +++ test/checks/.eslintrc | 81 +++ test/checks/color/link-in-text-block.js | 24 +- test/checks/navigation/p-as-heading.js | 3 +- .../navigation/unique-frame-title-after.js | 1 + test/commons/color/element-is-distinct.js | 24 +- test/commons/color/get-background-color.js | 42 +- test/commons/dom/find-elms-in-context.js | 102 ++-- test/commons/dom/get-composed-parent.js | 114 ++-- test/commons/dom/get-scroll-offset.js | 20 +- test/commons/dom/has-content-virtual.js | 172 +++--- test/commons/table/traverse.js | 85 +-- test/core/base/audit.js | 1 + test/core/base/context.js | 3 +- test/core/public/cleanup-plugins.js | 175 +++--- test/core/public/configure.js | 4 +- test/core/public/plugins.js | 314 +++++----- test/core/public/run-rules.js | 120 ++-- test/core/public/run.js | 5 +- .../reporters/helpers/process-aggregate.js | 574 +++++++++--------- test/core/utils/aggregateNodeResults.js | 33 +- test/core/utils/aggregateResult.js | 220 +++---- test/core/utils/check-helper.js | 70 +-- .../core/utils/collect-results-from-frames.js | 38 +- test/core/utils/contains.js | 12 +- test/core/utils/dq-element.js | 2 + test/core/utils/escape-selector.js | 2 +- test/core/utils/find-by.js | 34 +- test/core/utils/get-all-checks.js | 72 +-- test/core/utils/get-check-option.js | 132 ++-- test/core/utils/get-friendly-uri-end.js | 98 +-- test/core/utils/get-selector.js | 24 +- test/core/utils/merge-results.js | 18 +- test/core/utils/qsa.js | 76 +-- test/core/utils/queue.js | 3 +- test/core/utils/respondable.js | 26 +- test/core/utils/scroll-state.js | 316 +++++----- test/core/utils/select.js | 4 +- test/core/utils/send-command-to-frame.js | 208 +++---- test/integration/full/async/async.js | 179 +++--- .../full/frame-wait-time/frame-wait-time.js | 70 +-- test/integration/full/umd/mock-define.js | 2 +- .../full/umd/mock-module-exports.js | 2 +- test/integration/rules/runner.js | 52 +- test/rule-matches/heading-matches.js | 108 ++-- test/rule-matches/label-matches.js | 118 ++-- test/testutils.js | 129 ++-- 152 files changed, 4230 insertions(+), 3637 deletions(-) create mode 100644 .eslintrc create mode 100644 lib/.eslintrc create mode 100644 lib/checks/.eslintrc create mode 100644 lib/commons/.eslintrc create mode 100644 lib/rules/.eslintrc create mode 100644 test/.eslintrc create mode 100644 test/checks/.eslintrc diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000000..3255bd7ca0 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,79 @@ +{ + "env": { + "node": true + }, + "globals": { + "axe": true + }, + "rules": { + "no-bitwise": 2, + "camelcase": 2, + "curly": 2, + "eqeqeq": 2, + "guard-for-in": 2, + "wrap-iife": [ + 2, + "any" + ], + "indent": ["error", "tab", {"SwitchCase": 0}], + "no-use-before-define": [ + 2, + { + "functions": false + } + ], + "new-cap": 2, + "no-caller": 2, + "no-empty": 2, + "no-new": 2, + "no-plusplus": 0, + "quotes": [ + 2, + "single" + ], + "no-undef": 2, + "no-unused-vars": 2, + "strict": 0, + "max-params": [ + 2, + 5 + ], + "max-depth": [ + 2, + 5 + ], + "max-statements": [ + 2, + 15 + ], + "complexity": [ + 1, + 12 + ], + "max-len": [ + 2, + { + "code": 120, + "ignoreComments": true + } + ], + "semi": 0, + "no-cond-assign": 0, + "no-debugger": 0, + "no-eq-null": 0, + "no-eval": 0, + "no-unused-expressions": 0, + "block-scoped-var": 0, + "no-iterator": 0, + "linebreak-style": 0, + "comma-style": ["error", "last"], + "no-loop-func": 0, + "no-multi-str": 0, + "no-proto": 0, + "no-script-url": 0, + "no-shadow": 0, + "dot-notation": 2, + "no-new-func": 0, + "no-new-wrappers": 0 + } +} diff --git a/Gruntfile.js b/Gruntfile.js index 2f28d89f3b..5c6500caba 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,4 +1,5 @@ -//jshint maxcomplexity: 12, maxstatements: false, camelcase: false +/*eslint complexity: ["error",12], max-statements: ["error", 30], + camelcase: ["error", {"properties": "never"}]*/ var testConfig = require('./build/test/config'); module.exports = function (grunt) { @@ -9,7 +10,7 @@ module.exports = function (grunt) { grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-copy'); - grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-eslint'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-retire'); @@ -20,10 +21,10 @@ module.exports = function (grunt) { var langs; if (grunt.option('lang')) { langs = (grunt.option('lang') || '') - .split(/[,;]/g).map(function (lang) { - lang = lang.trim(); - return (lang !== 'en' ? '.' + lang : ''); - }); + .split(/[,;]/g).map(function (lang) { + lang = lang.trim(); + return (lang !== 'en' ? '.' + lang : ''); + }); } else if (grunt.option('all-lang')) { var localeFiles = require('fs').readdirSync('./locales'); @@ -304,11 +305,11 @@ module.exports = function (grunt) { var driverTests = {}; ['firefox', 'chrome', 'ie', 'safari', 'edge', 'chrome-mobile'] - .forEach(function (browser) { - driverTests[browser] = { - options: Object.assign({ browser: browser }, options) - }; - }); + .forEach(function (browser) { + driverTests[browser] = { + options: Object.assign({ browser: browser }, options) + }; + }); return driverTests; }()), connect: { @@ -320,10 +321,10 @@ module.exports = function (grunt) { } } }, - jshint: { + eslint: { axe: { options: { - jshintrc: true, + eslintrc: true, reporter: grunt.option('report') ? 'checkstyle' : undefined, reporterOutput: grunt.option('report') ? 'tmp/lint.xml' : undefined }, @@ -338,19 +339,19 @@ module.exports = function (grunt) { grunt.registerTask('default', ['build']); - grunt.registerTask('build', ['clean', 'jshint', 'validate', 'concat:commons', 'configure', + grunt.registerTask('build', ['clean', 'eslint', 'validate', 'concat:commons', 'configure', 'babel', 'concat:engine', 'uglify']); grunt.registerTask('test', ['build', 'retire', 'testconfig', 'fixture', 'connect', - 'mocha', 'parallel', 'jshint']); + 'mocha', 'parallel', 'eslint']); grunt.registerTask('ci-build', ['build', 'retire', 'testconfig', 'fixture', 'connect', - 'parallel', 'jshint']); + 'parallel', 'eslint']); grunt.registerTask('test-fast', ['build', 'testconfig', 'fixture', 'connect', - 'mocha', 'jshint']); + 'mocha', 'eslint']); - grunt.registerTask('translate', ['clean', 'jshint', 'validate', 'concat:commons', 'add-locale']); + grunt.registerTask('translate', ['clean', 'eslint', 'validate', 'concat:commons', 'add-locale']); grunt.registerTask('dev', ['build', 'testconfig', 'fixture', 'connect', 'watch']); diff --git a/build/build-manual.js b/build/build-manual.js index c92d505d02..335095dfec 100644 --- a/build/build-manual.js +++ b/build/build-manual.js @@ -1,4 +1,4 @@ -/*jshint node: true */ +/*eslint-env node */ 'use strict'; var path = require('path'); diff --git a/build/configure.js b/build/configure.js index 365cc18189..f35b8a3096 100644 --- a/build/configure.js +++ b/build/configure.js @@ -1,4 +1,5 @@ -/*jshint node: true, maxstatements: 20 */ +/*eslint-env node */ +/*eslint max-statements: ["error", 20] */ 'use strict'; var clone = require('clone'); diff --git a/build/tasks/add-locale.js b/build/tasks/add-locale.js index 6acb9df508..913672eb8c 100644 --- a/build/tasks/add-locale.js +++ b/build/tasks/add-locale.js @@ -1,84 +1,85 @@ -/*jshint node: true */ +/*eslint-env node */ 'use strict'; var clone = require('clone'); var buildManual = require('../build-manual'); module.exports = function (grunt) { - function mergeMessages (newMessages, oldMessages) { - Object.keys(newMessages).forEach(function (key) { - if (!oldMessages.hasOwnProperty(key)) { - return; - } + function mergeMessages (newMessages, oldMessages) { + Object.keys(newMessages).forEach(function (key) { + if (!oldMessages.hasOwnProperty(key)) { + return; + } - var newValue = newMessages[key]; - var oldValue = oldMessages[key]; + var newValue = newMessages[key]; + var oldValue = oldMessages[key]; - if (typeof newValue === 'object') { - // the message format might be changed, ignore old message - if (typeof oldValue !== 'object') { - return; - } + if (typeof newValue === 'object') { + // the message format might be changed, ignore old message + if (typeof oldValue !== 'object') { + return; + } - newMessages[key] = mergeMessages(clone(newValue), oldValue); - } else { - newMessages[key] = clone(oldValue); - } - }); + newMessages[key] = mergeMessages(clone(newValue), oldValue); + } else { + newMessages[key] = clone(oldValue); + } + }); - return newMessages; - } + return newMessages; + } - grunt.registerMultiTask('add-locale', - 'Task for localizing messages in rules and checks', - function () { - var options = this.options({ - rules: ['lib/rules/**/*.json'], - checks: ['lib/checks/**/*.json'], - tools: ['lib/tools/**/*.json'], - misc: ['lib/misc/**/*.json'], - blacklist: ['metadata'], - tags: '', - lang: 'xxx' - }); + grunt.registerMultiTask('add-locale', + 'Task for localizing messages in rules and checks', + function () { + var options = this.options({ + rules: ['lib/rules/**/*.json'], + checks: ['lib/checks/**/*.json'], + tools: ['lib/tools/**/*.json'], + misc: ['lib/misc/**/*.json'], + blacklist: ['metadata'], + tags: '', + lang: 'xxx' + }); - this.files.forEach(function (file) { - var commons = file.src[0]; + this.files.forEach(function (file) { + var commons = file.src[0]; - buildManual(grunt, options, commons, function (result) { - var out = { - lang: options.lang, - rules: result.rules.reduce(function (out, rule) { - out[rule.id] = rule.metadata; - return out; - }, {}), - checks: result.checks.reduce(function (out, check) { - if (check.metadata) { - out[check.id] = check.metadata.messages; - } - return out; - }, {}), - failureSummaries: result.misc.reduce(function (out, misc) { - out[misc.type] = misc.metadata; - return out; - }, {}), - incompleteFallbackMessage: result.misc.reduce(function (out, misc) { - out[misc.incompleteFallbackMessage] = misc.metadata; - return out; - }, {}) - }; + buildManual(grunt, options, commons, function (result) { + var out = { + lang: options.lang, + rules: result.rules.reduce(function (out, rule) { + out[rule.id] = rule.metadata; + return out; + }, {}), + checks: result.checks.reduce(function (out, check) { + if (check.metadata) { + out[check.id] = check.metadata.messages; + } + return out; + }, {}), + failureSummaries: result.misc.reduce(function (out, misc) { + out[misc.type] = misc.metadata; + return out; + }, {}), + incompleteFallbackMessage: result.misc.reduce(function (out, misc) { + out[misc.incompleteFallbackMessage] = misc.metadata; + return out; + }, {}) + }; - // update locale file if exists - var localeFile = './locales/' + options.lang + '.json'; - if (grunt.file.exists(localeFile)) { - var oldMessages = grunt.file.readJSON(localeFile); + // update locale file if exists + var localeFile = './locales/' + options.lang + '.json'; + if (grunt.file.exists(localeFile)) { + var oldMessages = grunt.file.readJSON(localeFile); - // mergeMessages mutates out - mergeMessages(out, oldMessages); - } + // mergeMessages mutates out + mergeMessages(out, oldMessages); + } - grunt.file.write(file.dest, JSON.stringify(out, null, ' ')); - console.log('created file at', file.dest); - }); - }); - }); + grunt.file.write(file.dest, JSON.stringify(out, null, ' ')); + console.log('created file at', file.dest); + }); + }); + } + ); }; diff --git a/build/tasks/configure.js b/build/tasks/configure.js index 1ce63c4b44..1bf3eee1ca 100644 --- a/build/tasks/configure.js +++ b/build/tasks/configure.js @@ -1,32 +1,33 @@ -/*jshint node: true */ +/*eslint-env node */ 'use strict'; var buildRules = require('../configure'); module.exports = function (grunt) { grunt.registerMultiTask('configure', - 'Task for configuring rules and checks', - function () { - var done = this.async(); - var options = this.options({ - rules: ['lib/rules/**/*.json'], - checks: ['lib/checks/**/*.json'], - tools: ['lib/tools/**/*.json'], - misc: ['lib/misc/**/*.json'], - blacklist: ['metadata'], - tags: '' - }); + 'Task for configuring rules and checks', + function () { + var done = this.async(); + var options = this.options({ + rules: ['lib/rules/**/*.json'], + checks: ['lib/checks/**/*.json'], + tools: ['lib/tools/**/*.json'], + misc: ['lib/misc/**/*.json'], + blacklist: ['metadata'], + tags: '' + }); - this.files.forEach(function (file) { - var commons = file.src[0]; - var match = file.dest.auto.match(/\.([a-z]{2,3})\.js/); - if (match) { - options.locale = match[1]; - } + this.files.forEach(function (file) { + var commons = file.src[0]; + var match = file.dest.auto.match(/\.([a-z]{2,3})\.js/); + if (match) { + options.locale = match[1]; + } - buildRules(grunt, options, commons, function (result) { - grunt.file.write(file.dest.auto, 'axe._load(' + result.auto + ');'); - grunt.file.write(file.dest.descriptions, result.descriptions); - done(); + buildRules(grunt, options, commons, function (result) { + grunt.file.write(file.dest.auto, 'axe._load(' + result.auto + ');'); + grunt.file.write(file.dest.descriptions, result.descriptions); + done(); + }); }); - }); - }); + } + ); }; diff --git a/build/tasks/fixture.js b/build/tasks/fixture.js index 45303d202e..42203ee2f8 100644 --- a/build/tasks/fixture.js +++ b/build/tasks/fixture.js @@ -1,31 +1,32 @@ -/*jshint node: true */ +/*eslint-env node */ 'use strict'; module.exports = function (grunt) { grunt.registerMultiTask('fixture', - 'Task for generating HTML test fixtures from a common template', - function () { - var options = this.options({ - fixture: 'test/runner.tmpl', - testCwd: 'test/core', - tests: ['**/*.js'], - data: {} - }); + 'Task for generating HTML test fixtures from a common template', + function () { + var options = this.options({ + fixture: 'test/runner.tmpl', + testCwd: 'test/core', + tests: ['**/*.js'], + data: {} + }); - this.files.forEach(function (f) { - var files = f.src.filter(function (file) { - return (/\.js$/).test(file); - }), - source = grunt.file.read(options.fixture), - result = grunt.template.process(source, { - data: { - files: files, - tests: grunt.file.expand({cwd: options.testCwd}, options.tests), - data: options.data - } - }); + this.files.forEach(function (f) { + var files = f.src.filter(function (file) { + return (/\.js$/).test(file); + }), + source = grunt.file.read(options.fixture), + result = grunt.template.process(source, { + data: { + files: files, + tests: grunt.file.expand({cwd: options.testCwd}, options.tests), + data: options.data + } + }); - grunt.file.write(f.dest, result); - }); - }); + grunt.file.write(f.dest, result); + }); + } + ); }; diff --git a/build/tasks/langs.js b/build/tasks/langs.js index d5f489710e..ccfca901bf 100644 --- a/build/tasks/langs.js +++ b/build/tasks/langs.js @@ -1,4 +1,4 @@ -/*jshint node: true */ +/*eslint-env node */ 'use strict'; var http = require('http'); var Promise = require('promise'); @@ -38,7 +38,6 @@ module.exports = function (grunt) { var path = checkPath + '.js'; var template = [ '/*global axe */\n', - '/*jshint -W109 */\n', 'var langs = ' + JSON.stringify(langs, null, '\t') + ';\n', 'axe.utils.validLangs = function () {\n', '\t\'use strict\';\n', @@ -48,48 +47,49 @@ module.exports = function (grunt) { grunt.file.write(path, template); } grunt.registerMultiTask('langs', - 'Task for generating commons language codes from IANA registry', - function () { - var done = this.async(); - var ianaLangsURL = 'http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry'; - if (!this.data.check) { - done(false); - return; - } - var check = this.data.check; - var langs = []; - new Promise(function (resolve, reject) { - var data = ''; - http.get(ianaLangsURL, function(res) { - res.on('data', function(chunk) { - data += chunk; - }).on('end', function () { - resolve(data); + 'Task for generating commons language codes from IANA registry', + function () { + var done = this.async(); + var ianaLangsURL = 'http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry'; + if (!this.data.check) { + done(false); + return; + } + var check = this.data.check; + var langs = []; + new Promise(function (resolve, reject) { + var data = ''; + http.get(ianaLangsURL, function(res) { + res.on('data', function(chunk) { + data += chunk; + }).on('end', function () { + resolve(data); + }); + }).on('error', function(e) { + grunt.log.error('Got error: ' + e.message); + reject(false); }); - }).on('error', function(e) { - grunt.log.error('Got error: ' + e.message); - reject(false); - }); - }).then(function (data) { - var entry = getEntry(data, 0); - var pos = entry.used; - while(true) { - entry = getEntry(data, pos); - pos += entry.used; - if (!entry.used) { - break; - } - if (entry[0] !== 'Type: language') { - continue; + }).then(function (data) { + var entry = getEntry(data, 0); + var pos = entry.used; + while(true) { + entry = getEntry(data, pos); + pos += entry.used; + if (!entry.used) { + break; + } + if (entry[0] !== 'Type: language') { + continue; + } + var lang = entry[1].replace('Subtag: ', '').trim(); + langs.push(lang); } - var lang = entry[1].replace('Subtag: ', '').trim(); - langs.push(lang); - } - generateOutput(langs, check); - }).then(function () { - done(); - }).catch(function (result) { - done(result); - }); - }); + generateOutput(langs, check); + }).then(function () { + done(); + }).catch(function (result) { + done(result); + }); + } + ); }; diff --git a/build/tasks/test-webdriver.js b/build/tasks/test-webdriver.js index 3c23fbf814..6c3340efeb 100644 --- a/build/tasks/test-webdriver.js +++ b/build/tasks/test-webdriver.js @@ -1,5 +1,5 @@ /*global window */ -/*jshint node: true */ +/*eslint-env node */ 'use strict'; var Promise = require('promise'); @@ -43,38 +43,38 @@ module.exports = function (grunt) { driver.manage().timeouts().setScriptTimeout(60000); return driver.get(url) - // Get results - .then(function () { - return collectTestResults(driver); + // Get results + .then(function () { + return collectTestResults(driver); - // And process them - }).then(function (result) { - grunt.log.writeln(url); + // And process them + }).then(function (result) { + grunt.log.writeln(url); + + // Remember the errors + (result.reports || []).forEach(function (err) { + grunt.log.error(err.message); + err.url = url; + errors.push(err); + }); + + // Log the result of the page tests + grunt.log[ (result.failures ? 'error' : 'ok') ]( + 'passes: ' + result.passes + ', ' + + 'failures: ' + result.failures + ', ' + + 'duration: ' + (result.duration / 1000) +'s' + ); + grunt.log.writeln(); - // Remember the errors - (result.reports || []).forEach(function (err) { - grunt.log.error(err.message); - err.url = url; - errors.push(err); + }).then(function () { + // Start the next job, if any + if (urls.length > 0) { + return runTestUrls(driver, urls, errors); + } else { + driver.quit(); + return Promise.resolve(errors); + } }); - - // Log the result of the page tests - grunt.log[ (result.failures ? 'error' : 'ok') ]( - 'passes: ' + result.passes + ', ' + - 'failures: ' + result.failures + ', ' + - 'duration: ' + (result.duration / 1000) +'s' - ); - grunt.log.writeln(); - - }).then(function () { - // Start the next job, if any - if (urls.length > 0) { - return runTestUrls(driver, urls, errors); - } else { - driver.quit(); - return Promise.resolve(errors); - } - }); } /* @@ -100,15 +100,15 @@ module.exports = function (grunt) { } if (process.env.REMOTE_SELENIUM_URL) { webdriver = new WebDriver.Builder() - .forBrowser(browser) - .withCapabilities(capabilities) - .usingServer(process.env.REMOTE_SELENIUM_URL) - .build(); + .forBrowser(browser) + .withCapabilities(capabilities) + .usingServer(process.env.REMOTE_SELENIUM_URL) + .build(); } else { webdriver = new WebDriver.Builder() - .withCapabilities(capabilities) - .forBrowser(browser) - .build(); + .withCapabilities(capabilities) + .forBrowser(browser) + .build(); } return webdriver; @@ -118,60 +118,61 @@ module.exports = function (grunt) { * Run all tests in a browser using webdriver */ grunt.registerMultiTask('test-webdriver', - 'Task for launching Webdriver with options and running tests against options URLs', - function () { - var driver; - var done = this.async(); - var options = this.options({ - browser: 'firefox' - }); - // yes, really, and this isn't documented anywhere either. - options.browser = (options.browser === 'edge') ? 'MicrosoftEdge' : options.browser; - - - 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) - ) { - grunt.log.writeln(); - grunt.log.writeln('Skipped ' + options.browser + ' as it is not supported on this platform'); - return done(); - } - - // try to load the browser - try { - driver = buildWebDriver(options.browser); + 'Task for launching Webdriver with options and running tests against options URLs', + function () { + var driver; + var done = this.async(); + var options = this.options({ + browser: 'firefox' + }); + // yes, really, and this isn't documented anywhere either. + options.browser = (options.browser === 'edge') ? 'MicrosoftEdge' : options.browser; - // If load fails, warn user and move to the next task - } catch (err) { - grunt.log.writeln(); - grunt.log.error(err.message); - grunt.log.writeln('Aborted testing using ' + options.browser); - return done(); - } - // Test all pages - runTestUrls(driver, options.urls) - .then(function (testErrors) { - // log each error and abort - testErrors.forEach(function(err) { - grunt.log.writeln(); - grunt.log.error('URL: ' + err.url); - grunt.log.error('Describe: ' + err.titles.join(' > ')); - grunt.log.error('it ' + err.name); - grunt.log.error(err.stack); + 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) + ) { grunt.log.writeln(); - }); + grunt.log.writeln('Skipped ' + options.browser + ' as it is not supported on this platform'); + return done(); + } - // Return the success to Grunt - done(testErrors.length === 0); + // try to load the browser + try { + driver = buildWebDriver(options.browser); - // catch any potential problems - }).catch(function (err) { - grunt.log.error(err); - done(false); - }); + // If load fails, warn user and move to the next task + } catch (err) { + grunt.log.writeln(); + grunt.log.error(err.message); + grunt.log.writeln('Aborted testing using ' + options.browser); + return done(); + } - }); + // Test all pages + runTestUrls(driver, options.urls) + .then(function (testErrors) { + // log each error and abort + testErrors.forEach(function(err) { + grunt.log.writeln(); + grunt.log.error('URL: ' + err.url); + grunt.log.error('Describe: ' + err.titles.join(' > ')); + grunt.log.error('it ' + err.name); + grunt.log.error(err.stack); + grunt.log.writeln(); + }); + + // Return the success to Grunt + done(testErrors.length === 0); + + // catch any potential problems + }).catch(function (err) { + grunt.log.error(err); + done(false); + }); + + } + ); }; diff --git a/build/tasks/testconfig.js b/build/tasks/testconfig.js index 87db90bf23..90b66e17fe 100644 --- a/build/tasks/testconfig.js +++ b/build/tasks/testconfig.js @@ -1,27 +1,28 @@ -/*jshint node: true */ +/*eslint-env node */ 'use strict'; module.exports = function (grunt) { grunt.registerMultiTask('testconfig', - 'This task creates a file with all the source test config and HTML fixtures in a single JS object `tests`', - function () { + 'This task creates a file with all the source test config and HTML fixtures in a single JS object `tests`', + function () { - var result = { - tests: {}, - urls: [] - }; + var result = { + tests: {}, + urls: [] + }; - this.files.forEach(function(f) { - f.src.forEach(function (filepath) { - var config = grunt.file.readJSON(filepath); - config.content = grunt.file.read(filepath.replace(/json$/, 'html')); - result.tests[config.rule] = result.tests[config.rule] || []; - result.tests[config.rule].push(config); + this.files.forEach(function(f) { + f.src.forEach(function (filepath) { + var config = grunt.file.readJSON(filepath); + config.content = grunt.file.read(filepath.replace(/json$/, 'html')); + result.tests[config.rule] = result.tests[config.rule] || []; + result.tests[config.rule].push(config); + }); + grunt.config(['testconfig', 'options', 'data'], result); + if (f.dest) { + grunt.file.write(f.dest, 'var tests = ' + JSON.stringify(result.tests)); + } }); - grunt.config(['testconfig', 'options', 'data'], result); - if (f.dest) { - grunt.file.write(f.dest, 'var tests = ' + JSON.stringify(result.tests)); - } - }); - }); + } + ); }; diff --git a/build/tasks/update-help.js b/build/tasks/update-help.js index ff8d8e99cb..fa107baa53 100644 --- a/build/tasks/update-help.js +++ b/build/tasks/update-help.js @@ -1,22 +1,23 @@ -/*jshint node: true */ +/*eslint-env node */ 'use strict'; module.exports = function (grunt) { grunt.registerMultiTask('update-help', - 'Task for updating Deque University helpUrls based on rule JSON files', - function () { - var options = this.options({ - version: '1.0.0' - }); - var v = options.version.split('.'); - v.pop(); - var baseUrl = 'https://dequeuniversity.com/rules/axe/' + v.join('.') + '/'; - this.files.forEach(function(f) { - f.src.forEach(function (filepath) { - var config = grunt.file.readJSON(filepath); - config.metadata.helpUrl = baseUrl + config.id; - grunt.file.write(filepath, JSON.stringify(config, null, ' ')); + 'Task for updating Deque University helpUrls based on rule JSON files', + function () { + var options = this.options({ + version: '1.0.0' }); - }); - }); + var v = options.version.split('.'); + v.pop(); + var baseUrl = 'https://dequeuniversity.com/rules/axe/' + v.join('.') + '/'; + this.files.forEach(function(f) { + f.src.forEach(function (filepath) { + var config = grunt.file.readJSON(filepath); + config.metadata.helpUrl = baseUrl + config.id; + grunt.file.write(filepath, JSON.stringify(config, null, ' ')); + }); + }); + } + ); }; diff --git a/build/tasks/validate.js b/build/tasks/validate.js index ed86863df4..db7fe87eb1 100644 --- a/build/tasks/validate.js +++ b/build/tasks/validate.js @@ -1,4 +1,4 @@ -/*jshint node: true */ +/*eslint-env node */ 'use strict'; var revalidator = require('revalidator').validate, @@ -214,14 +214,14 @@ function createSchemas() { function validateFiles(grunt, files, schema) { var valid = true; files.forEach(function (f) { - f.src.forEach(function (path) { - var file = grunt.file.readJSON(path); - file._path = path; + f.src.forEach(function (pathArg) { + var file = grunt.file.readJSON(pathArg); + file._path = pathArg; var result = revalidator(file, schema); if (!result.valid) { result.errors.forEach(function (err) { - grunt.log.error(path, err.property + ' ' + err.message); + grunt.log.error(pathArg, err.property + ' ' + err.message); }); valid = false; } else { @@ -234,15 +234,16 @@ function validateFiles(grunt, files, schema) { module.exports = function (grunt) { grunt.registerMultiTask('validate', - 'Task for validating API schema for tools, checks and rules', - function () { - var schemas = createSchemas(); - var options = this.options(); - if (!options.type || !schemas[options.type]) { - grunt.log.error('Please specify a valid type to validate: ' + Object.keys(schemas)); - return false; + 'Task for validating API schema for tools, checks and rules', + function () { + var schemas = createSchemas(); + var options = this.options(); + if (!options.type || !schemas[options.type]) { + grunt.log.error('Please specify a valid type to validate: ' + Object.keys(schemas)); + return false; + } + validateFiles(grunt, this.files, schemas[options.type]); + schemas[options.type].seen = {}; } - validateFiles(grunt, this.files, schemas[options.type]); - schemas[options.type].seen = {}; - }); + ); }; diff --git a/doc/examples/mocha/test/a11y.js b/doc/examples/mocha/test/a11y.js index c1d7f5b769..189272bc77 100644 --- a/doc/examples/mocha/test/a11y.js +++ b/doc/examples/mocha/test/a11y.js @@ -1,7 +1,7 @@ /* global describe, it, expect, axe, document */ describe('axe', function () { - /* jshint expr: true */ + /* eslint no-unused-expressions: 0 */ 'use strict'; it('should report that good HTML is good', function (done) { diff --git a/lib/.eslintrc b/lib/.eslintrc new file mode 100644 index 0000000000..c1217e824b --- /dev/null +++ b/lib/.eslintrc @@ -0,0 +1,69 @@ +{ + "env": { + "browser": true, + "es6": true + }, + "globals": { + "axe": true + }, + "rules": { + "no-bitwise": 2, + "camelcase": 2, + "curly": 2, + "eqeqeq": 2, + "guard-for-in": 2, + "wrap-iife": [ + 2, + "any" + ], + "no-use-before-define": [ + 2, + { + "functions": false + } + ], + "new-cap": 2, + "no-caller": 2, + "no-empty": 2, + "no-new": 2, + "no-plusplus": 0, + "no-undef": 2, + "no-unused-vars": 2, + "strict": 0, + "max-params": [ + 2, + 6 + ], + "max-depth": [ + 2, + 5 + ], + "max-statements": [ + 2, + 16 + ], + "max-len": [ + 2, + { + "code": 120, + "ignoreComments": true + } + ], + "semi": 0, + "no-cond-assign": 0, + "no-debugger": 0, + "no-eq-null": 0, + "no-eval": 0, + "no-unused-expressions": 0, + "block-scoped-var": 0, + "no-iterator": 0, + "linebreak-style": 0, + "no-loop-func": 0, + "no-multi-str": 0, + "no-proto": 0, + "no-script-url": 0, + "dot-notation": 2, + "no-new-func": 0, + "no-new-wrappers": 0 + } +} diff --git a/lib/checks/.eslintrc b/lib/checks/.eslintrc new file mode 100644 index 0000000000..2f6f8a3f3f --- /dev/null +++ b/lib/checks/.eslintrc @@ -0,0 +1,80 @@ +{ + "env": {}, + "globals": { + "results": true, + "node": true, + "options": true, + "virtualNode": true, + "axe": true, + "document": true, + "window": true + }, + "rules": { + "no-bitwise": 2, + "camelcase": 2, + "curly": 2, + "eqeqeq": 2, + "guard-for-in": 2, + "wrap-iife": [ + 2, + "any" + ], + "no-use-before-define": [ + 2, + { + "functions": false + } + ], + "new-cap": 2, + "no-caller": 2, + "no-empty": 2, + "no-new": 2, + "no-plusplus": 0, + "quotes": [ + 2, + "single" + ], + "no-undef": 2, + "no-unused-vars": 2, + "strict": 0, + "max-params": [ + 2, + 5 + ], + "max-depth": [ + 2, + 5 + ], + "max-statements": [ + 2, + 15 + ], + "complexity": [ + 2, + 10 + ], + "max-len": [ + 2, + { + "code": 120, + "ignoreComments": true + } + ], + "semi": 0, + "no-cond-assign": 0, + "no-debugger": 0, + "no-eq-null": 0, + "no-eval": 0, + "no-unused-expressions": 0, + "block-scoped-var": 0, + "no-iterator": 0, + "linebreak-style": 0, + "no-loop-func": 0, + "no-multi-str": 0, + "no-proto": 0, + "no-script-url": 0, + "dot-notation": 2, + "no-new-func": 0, + "no-new-wrappers": 0 + } +} diff --git a/lib/checks/aria/allowed-attr.js b/lib/checks/aria/allowed-attr.js index 63d889c5f3..60bd95d899 100644 --- a/lib/checks/aria/allowed-attr.js +++ b/lib/checks/aria/allowed-attr.js @@ -13,7 +13,7 @@ if (!role) { allowed = axe.commons.aria.allowedAttr(role); if (Array.isArray(options[role])) { - allowed = axe.utils.uniqueArray(options[role].concat(allowed)); + allowed = axe.utils.uniqueArray(options[role].concat(allowed)); } if (role && allowed) { @@ -31,4 +31,4 @@ if (invalid.length) { return false; } -return true; \ No newline at end of file +return true; diff --git a/lib/checks/aria/required-children.js b/lib/checks/aria/required-children.js index 47fcfb405e..91014cac4b 100644 --- a/lib/checks/aria/required-children.js +++ b/lib/checks/aria/required-children.js @@ -1,12 +1,12 @@ var requiredOwned = axe.commons.aria.requiredOwned, -implicitNodes = axe.commons.aria.implicitNodes, -matchesSelector = axe.commons.utils.matchesSelector, -idrefs = axe.commons.dom.idrefs; + implicitNodes = axe.commons.aria.implicitNodes, + matchesSelector = axe.commons.utils.matchesSelector, + idrefs = axe.commons.dom.idrefs; function owns(node, virtualTree, role, ariaOwned) { if (node === null) { return false; } var implicit = implicitNodes(role), - selector = ['[role="' + role + '"]']; + selector = ['[role="' + role + '"]']; if (implicit) { selector = selector.concat(implicit); @@ -31,11 +31,11 @@ function ariaOwns(nodes, role) { } function missingRequiredChildren(node, childRoles, all, role) { - //jshint maxstatements: 22, maxcomplexity: 13 + /* eslint max-statements: ["error", 22], complexity: ["error", 17] */ var i, - l = childRoles.length, - missing = [], - ownedElements = idrefs(node, 'aria-owns'); + l = childRoles.length, + missing = [], + ownedElements = idrefs(node, 'aria-owns'); for (i = 0; i < l; i++) { var r = childRoles[i]; diff --git a/lib/checks/aria/required-parent.js b/lib/checks/aria/required-parent.js index 15e042dc46..1723aae373 100644 --- a/lib/checks/aria/required-parent.js +++ b/lib/checks/aria/required-parent.js @@ -5,8 +5,8 @@ function getSelector(role) { function getMissingContext(virtualNode, requiredContext, includeElement) { var index, length, - role = virtualNode.actualNode.getAttribute('role'), - missing = []; + role = virtualNode.actualNode.getAttribute('role'), + missing = []; if (!requiredContext) { requiredContext = axe.commons.aria.requiredContext(role); diff --git a/lib/checks/aria/valid-scrollable-semantics.js b/lib/checks/aria/valid-scrollable-semantics.js index 2f7a891131..6e3c5d06b3 100644 --- a/lib/checks/aria/valid-scrollable-semantics.js +++ b/lib/checks/aria/valid-scrollable-semantics.js @@ -3,10 +3,10 @@ * appropriate for scrollable elements found in the focus order. */ const VALID_TAG_NAMES_FOR_SCROLLABLE_REGIONS = { - ARTICLE: true, - ASIDE: true, - NAV: true, - SECTION: true + ARTICLE: true, + ASIDE: true, + NAV: true, + SECTION: true }; /** @@ -14,48 +14,48 @@ const VALID_TAG_NAMES_FOR_SCROLLABLE_REGIONS = { * appropriate for scrollable elements found in the focus order. */ const VALID_ROLES_FOR_SCROLLABLE_REGIONS = { - banner: false, - complementary: true, - contentinfo: true, - form: true, - main: true, - navigation: true, - region: true, - search: false + banner: false, + complementary: true, + contentinfo: true, + form: true, + main: true, + navigation: true, + region: true, + search: false }; /** * @param {HTMLElement} node * @return {Boolean} Whether the element has a tag appropriate for a scrollable - * region. + * region. */ function validScrollableTagName(node) { - // Some elements with nonsensical roles will pass this check, but should be - // flagged by other checks. - var tagName = node.tagName.toUpperCase(); - return VALID_TAG_NAMES_FOR_SCROLLABLE_REGIONS[tagName] || false; + // Some elements with nonsensical roles will pass this check, but should be + // flagged by other checks. + var tagName = node.tagName.toUpperCase(); + return VALID_TAG_NAMES_FOR_SCROLLABLE_REGIONS[tagName] || false; } /** * @param {HTMLElement} node * @return {Boolean} Whether the node has a role appropriate for a scrollable - * region. + * region. */ function validScrollableRole(node) { - var role = node.getAttribute('role'); - if (!role) { - return false; - } - return VALID_ROLES_FOR_SCROLLABLE_REGIONS[role.toLowerCase()] || false; + var role = node.getAttribute('role'); + if (!role) { + return false; + } + return VALID_ROLES_FOR_SCROLLABLE_REGIONS[role.toLowerCase()] || false; } /** * @param {HTMLElement} node * @return {Boolean} Whether the element would have valid semantics if it were a - * scrollable region. + * scrollable region. */ function validScrollableSemantics(node) { - return validScrollableRole(node) || validScrollableTagName(node); + return validScrollableRole(node) || validScrollableTagName(node); } return validScrollableSemantics(node); diff --git a/lib/checks/lists/has-listitem.js b/lib/checks/lists/has-listitem.js index 05aff66304..dc6537938f 100644 --- a/lib/checks/lists/has-listitem.js +++ b/lib/checks/lists/has-listitem.js @@ -1,2 +1,2 @@ -return virtualNode.children.every(({ actualNode }) => - actualNode.nodeName.toUpperCase() !== 'LI'); +return virtualNode.children.every(({ actualNode }) => + actualNode.nodeName.toUpperCase() !== 'LI'); diff --git a/lib/checks/media/caption.js b/lib/checks/media/caption.js index d7d6090521..6d67091eab 100644 --- a/lib/checks/media/caption.js +++ b/lib/checks/media/caption.js @@ -1,10 +1,10 @@ var tracks = axe.utils.querySelectorAll(virtualNode, 'track'); if (tracks.length) { - // return false if any track has kind === 'caption' - return !tracks.some(({ actualNode }) => ( - (actualNode.getAttribute('kind') || '').toLowerCase() === 'captions' - )); + // return false if any track has kind === 'caption' + return !tracks.some(({ actualNode }) => ( + (actualNode.getAttribute('kind') || '').toLowerCase() === 'captions' + )); } // Undefined if there are no tracks - media may be decorative return undefined; diff --git a/lib/checks/media/description.js b/lib/checks/media/description.js index 529b75e0ee..15cc40af88 100644 --- a/lib/checks/media/description.js +++ b/lib/checks/media/description.js @@ -1,11 +1,11 @@ var tracks = axe.utils.querySelectorAll(virtualNode, 'track'); if (tracks.length) { - // return false if any track has kind === 'description' - var out = !tracks.some(({ actualNode }) => ( - (actualNode.getAttribute('kind') || '').toLowerCase() === 'descriptions' - )); - return out; + // return false if any track has kind === 'description' + var out = !tracks.some(({ actualNode }) => ( + (actualNode.getAttribute('kind') || '').toLowerCase() === 'descriptions' + )); + return out; } // Undefined if there are no tracks - media may be decorative return undefined; diff --git a/lib/checks/navigation/p-as-heading.js b/lib/checks/navigation/p-as-heading.js index 7c5d3dec93..ff17c53fc6 100644 --- a/lib/checks/navigation/p-as-heading.js +++ b/lib/checks/navigation/p-as-heading.js @@ -5,10 +5,10 @@ options = options || {}; let margins = options.margins || []; let nextSibling = siblings.slice(currentIndex+1) -.find(elm => elm.nodeName.toUpperCase() === 'P'); + .find(elm => elm.nodeName.toUpperCase() === 'P'); let prevSibling = siblings.slice(0, currentIndex).reverse() -.find(elm => elm.nodeName.toUpperCase() === 'P'); + .find(elm => elm.nodeName.toUpperCase() === 'P'); function getTextContainer(elm) { let nextNode = elm; @@ -33,6 +33,7 @@ function getTextContainer(elm) { } function normalizeFontWeight(weight) { + /* eslint indent: 0*/ switch (weight) { case 'lighter': return 100; case 'normal': return 400; @@ -79,4 +80,4 @@ if (prevStyle && !isHeaderStyle(currStyle, prevStyle, margins)) { return undefined; } -return false; \ No newline at end of file +return false; diff --git a/lib/checks/navigation/skip-link.js b/lib/checks/navigation/skip-link.js index 24e8c95456..f17c66e492 100644 --- a/lib/checks/navigation/skip-link.js +++ b/lib/checks/navigation/skip-link.js @@ -1,5 +1,5 @@ const target = axe.commons.dom.getElementByReference(node, 'href'); if (target) { - return axe.commons.dom.isVisible(target, true) || undefined; + return axe.commons.dom.isVisible(target, true) || undefined; } return false; diff --git a/lib/checks/shared/duplicate-id.js b/lib/checks/shared/duplicate-id.js index b7ef630c90..710a485c12 100644 --- a/lib/checks/shared/duplicate-id.js +++ b/lib/checks/shared/duplicate-id.js @@ -6,8 +6,8 @@ if (!id) { } const root = axe.commons.dom.getRootNode(node); const matchingNodes = Array.from(root.querySelectorAll( - `[id="${ axe.commons.utils.escapeSelector(id) }"]` - )).filter(foundNode => foundNode !== node); + `[id="${ axe.commons.utils.escapeSelector(id) }"]` +)).filter(foundNode => foundNode !== node); if (matchingNodes.length) { this.relatedNodes(matchingNodes); diff --git a/lib/checks/tables/td-headers-attr.js b/lib/checks/tables/td-headers-attr.js index 52f828f95a..6977c073b9 100644 --- a/lib/checks/tables/td-headers-attr.js +++ b/lib/checks/tables/td-headers-attr.js @@ -19,14 +19,14 @@ var badCells = cells.reduce(function (badCells, cell) { // Get a list all the values of the headers attribute var headers = (cell.getAttribute('headers') || '') - .split(/\s/) - .reduce(function (headers, header) { - header = header.trim(); - if (header) { - headers.push(header); - } - return headers; - }, []); + .split(/\s/) + .reduce(function (headers, header) { + header = header.trim(); + if (header) { + headers.push(header); + } + return headers; + }, []); if (headers.length !== 0) { // Check if the cell's id is in this list diff --git a/lib/checks/tables/th-has-data-cells.js b/lib/checks/tables/th-has-data-cells.js index 4b86b932b5..2c1c4609bf 100644 --- a/lib/checks/tables/th-has-data-cells.js +++ b/lib/checks/tables/th-has-data-cells.js @@ -41,23 +41,23 @@ var out = headers.reduce(function (res, header) { // Look for any data cells or row headers that this might refer to if (tableUtils.isColumnHeader(header)) { hasCell = tableUtils.traverse('down', pos, tableGrid) - .reduce((out, cell) => { - return (out || ( - axe.commons.dom.hasContent(cell) && - !tableUtils.isColumnHeader(cell)) - ); - }, false); + .reduce((out, cell) => { + return (out || ( + axe.commons.dom.hasContent(cell) && + !tableUtils.isColumnHeader(cell)) + ); + }, false); } // Look for any data cells or column headers that this might refer to if (!hasCell && tableUtils.isRowHeader(header)) { hasCell = tableUtils.traverse('right', pos, tableGrid) - .reduce((out, cell) => { - return out || ( - axe.commons.dom.hasContent(cell) && - !tableUtils.isRowHeader(cell) - ); - }, false); + .reduce((out, cell) => { + return out || ( + axe.commons.dom.hasContent(cell) && + !tableUtils.isRowHeader(cell) + ); + }, false); } // report the node as having failed diff --git a/lib/checks/visibility/hidden-content.js b/lib/checks/visibility/hidden-content.js index 9489ff4c7b..6a55d5f42a 100644 --- a/lib/checks/visibility/hidden-content.js +++ b/lib/checks/visibility/hidden-content.js @@ -1,17 +1,17 @@ const whitelist = ['SCRIPT', 'HEAD', 'TITLE', 'NOSCRIPT', 'STYLE', 'TEMPLATE']; if (!whitelist.includes(node.tagName.toUpperCase()) && - axe.commons.dom.hasContentVirtual(virtualNode)) { + axe.commons.dom.hasContentVirtual(virtualNode)) { - const styles = window.getComputedStyle(node); - if (styles.getPropertyValue('display') === 'none') { - return undefined; - } else if (styles.getPropertyValue('visibility') === 'hidden') { - // Check if visibility isn't inherited - const parent = axe.commons.dom.getComposedParent(node); - const parentStyle = parent && window.getComputedStyle(parent); - if (!parentStyle || parentStyle.getPropertyValue('visibility') !== 'hidden') { - return undefined; - } - } + const styles = window.getComputedStyle(node); + if (styles.getPropertyValue('display') === 'none') { + return undefined; + } else if (styles.getPropertyValue('visibility') === 'hidden') { + // Check if visibility isn't inherited + const parent = axe.commons.dom.getComposedParent(node); + const parentStyle = parent && window.getComputedStyle(parent); + if (!parentStyle || parentStyle.getPropertyValue('visibility') !== 'hidden') { + return undefined; + } + } } return true; diff --git a/lib/commons/.eslintrc b/lib/commons/.eslintrc new file mode 100644 index 0000000000..0b465730aa --- /dev/null +++ b/lib/commons/.eslintrc @@ -0,0 +1,69 @@ +{ + "env": { + "browser": true, + "es6": true + }, + "globals": { + "commons": true + }, + "rules": { + "no-bitwise": 2, + "camelcase": 2, + "curly": 2, + "eqeqeq": 2, + "guard-for-in": 2, + "wrap-iife": [ + 2, + "any" + ], + "no-use-before-define": [ + 2, + { + "functions": false + } + ], + "new-cap": 2, + "no-caller": 2, + "no-empty": 2, + "no-new": 2, + "no-plusplus": 0, + "no-undef": 2, + "no-unused-vars": 2, + "strict": 0, + "max-params": [ + 2, + 5 + ], + "max-depth": [ + 2, + 5 + ], + "max-statements": [ + 2, + 20 + ], + "max-len": [ + 2, + { + "code": 140, + "ignoreComments": true + } + ], + "semi": 0, + "no-cond-assign": 0, + "no-debugger": 0, + "no-eq-null": 0, + "no-eval": 0, + "no-unused-expressions": 0, + "block-scoped-var": 0, + "no-iterator": 0, + "linebreak-style": 0, + "no-loop-func": 0, + "no-multi-str": 0, + "no-proto": 0, + "no-script-url": 0, + "dot-notation": 2, + "no-new-func": 0, + "no-new-wrappers": 0 + } +} diff --git a/lib/commons/aria/attributes.js b/lib/commons/aria/attributes.js index e4395ba6a0..c9d8323d5a 100644 --- a/lib/commons/aria/attributes.js +++ b/lib/commons/aria/attributes.js @@ -55,7 +55,7 @@ aria.validateAttr = function (att) { * @return {Boolean} */ aria.validateAttrValue = function (node, attr) { - //jshint maxcomplexity: 13 + /*eslint complexity: ["error",15]*/ 'use strict'; var matches, list, value = node.getAttribute(attr), diff --git a/lib/commons/color/element-is-distinct.js b/lib/commons/color/element-is-distinct.js index 544b11542c..eff6fa4e35 100644 --- a/lib/commons/color/element-is-distinct.js +++ b/lib/commons/color/element-is-distinct.js @@ -8,10 +8,10 @@ */ function _getFonts(style) { return style.getPropertyValue('font-family') - .split(/[,;]/g) - .map(function (font) { - return font.trim().toLowerCase(); - }); + .split(/[,;]/g) + .map(function (font) { + return font.trim().toLowerCase(); + }); } /** @@ -33,19 +33,19 @@ function elementIsDistinct(node, ancestorNode) { // Check if the link has a border or outline var hasBorder = ['border-bottom', 'border-top', 'outline'] - .reduce(function (result, edge) { + .reduce(function (result, edge) { - var borderClr = new color.Color(); - borderClr.parseRgbString(nodeStyle.getPropertyValue(edge + '-color')); + var borderClr = new color.Color(); + borderClr.parseRgbString(nodeStyle.getPropertyValue(edge + '-color')); - // Check if a border/outline was specified - return result || ( - // or if the current border edge / outline - nodeStyle.getPropertyValue(edge + '-style') !== 'none' && - parseFloat(nodeStyle.getPropertyValue(edge + '-width')) > 0 && - borderClr.alpha !== 0 - ); - }, false); + // Check if a border/outline was specified + return result || ( + // or if the current border edge / outline + nodeStyle.getPropertyValue(edge + '-style') !== 'none' && + parseFloat(nodeStyle.getPropertyValue(edge + '-width')) > 0 && + borderClr.alpha !== 0 + ); + }, false); if (hasBorder) { return true; @@ -58,9 +58,9 @@ function elementIsDistinct(node, ancestorNode) { } var hasStyle = ['text-decoration-line', 'text-decoration-style', 'font-weight', 'font-style', 'font-size'] - .reduce(function (result, cssProp) { - return result || (nodeStyle.getPropertyValue(cssProp) !== parentStyle.getPropertyValue(cssProp)); - }, false); + .reduce(function (result, cssProp) { + return result || (nodeStyle.getPropertyValue(cssProp) !== parentStyle.getPropertyValue(cssProp)); + }, false); var tDec = nodeStyle.getPropertyValue('text-decoration'); if (tDec.split(' ').length < 3) { diff --git a/lib/commons/color/get-background-color.js b/lib/commons/color/get-background-color.js index ab93cc0124..1f51bbc0a9 100644 --- a/lib/commons/color/get-background-color.js +++ b/lib/commons/color/get-background-color.js @@ -121,12 +121,12 @@ function elmPartiallyObscured(elm, bgElm, bgColor) { * @param {Element} elm */ function includeMissingElements(elmStack, elm) { + /*eslint max-depth:["error",7]*/ const elementMap = {'TD': ['TR', 'TBODY'], 'TH': ['TR', 'THEAD'], 'INPUT': ['LABEL']}; const tagArray = elmStack.map((elm) => { return elm.tagName; }); let bgNodes = elmStack; - //jshint maxdepth:7 for (let candidate in elementMap) { // check that TR or LABEL has paired nodeName from elementMap, but don't expect elm to be that candidate if (tagArray.includes(candidate)) { @@ -195,11 +195,13 @@ color.getCoords = function(rect) { return; } x = Math.min( - Math.ceil(rect.left + (rect.width / 2)), - window.innerWidth - 1); + Math.ceil(rect.left + (rect.width / 2)), + window.innerWidth - 1 + ); y = Math.min( - Math.ceil(rect.top + (rect.height / 2)), - window.innerHeight - 1); + Math.ceil(rect.top + (rect.height / 2)), + window.innerHeight - 1 + ); return {x, y}; }; @@ -218,16 +220,16 @@ color.getRectStack = function(elm) { // allows inline elements spanning multiple lines to be evaluated let rects = Array.from(elm.getClientRects()); if (rects && rects.length > 1) { - let filteredArr = rects.filter((rect) => { + let filteredArr = rects.filter((rect) => { // exclude manual line breaks in Chrome/Safari return rect.width && rect.width > 0; }) - .map((rect) => { - let coords = color.getCoords(rect); - if (coords) { - return dom.shadowElementsFromPoint(coords.x, coords.y); - } - }); + .map((rect) => { + let coords = color.getCoords(rect); + if (coords) { + return dom.shadowElementsFromPoint(coords.x, coords.y); + } + }); // add bounding client rect stack for comparison later filteredArr.splice(0, 0, boundingStack); return filteredArr; @@ -307,10 +309,10 @@ color.getBackgroundStack = function(elm) { * Returns background color for element * Uses color.getBackgroundStack() to get all elements rendered underneath the current element to * help determine the background color. - * @param {Element} elm Element to determine background color - * @param {Array} [bgElms=[]] [description] - * @param {Boolean} [noScroll=false] [description] - * @return {Color} [description] + * @param {Element} elm Element to determine background color + * @param {Array} [bgElms=[]] [description] + * @param {Boolean} [noScroll=false] [description] + * @return {Color} [description] */ color.getBackgroundColor = function(elm, bgElms = [], noScroll = false) { if(noScroll !== true) { diff --git a/lib/commons/dom/find-elms-in-context.js b/lib/commons/dom/find-elms-in-context.js index 0c5333a323..b05bfeceb4 100644 --- a/lib/commons/dom/find-elms-in-context.js +++ b/lib/commons/dom/find-elms-in-context.js @@ -13,15 +13,15 @@ * @return {Array} */ dom.findElmsInContext = function ({ context, value, attr, elm = '' }) { - let root; - const escapedValue = axe.utils.escapeSelector(value); + let root; + const escapedValue = axe.utils.escapeSelector(value); - if (context.nodeType === 9 || context.nodeType === 11) { // It's already root - root = context; - } else { - root = dom.getRootNode(context); - } - return Array.from( - root.querySelectorAll(elm + '[' + attr + '=' + escapedValue + ']') - ); + if (context.nodeType === 9 || context.nodeType === 11) { // It's already root + root = context; + } else { + root = dom.getRootNode(context); + } + return Array.from( + root.querySelectorAll(elm + '[' + attr + '=' + escapedValue + ']') + ); }; diff --git a/lib/commons/dom/find-up.js b/lib/commons/dom/find-up.js index 5d5a2056a2..9ee495924f 100644 --- a/lib/commons/dom/find-up.js +++ b/lib/commons/dom/find-up.js @@ -26,6 +26,7 @@ dom.findUp = function (element, target) { * @return {HTMLElement|null} Either the matching HTMLElement or `null` if there was no match */ dom.findUpVirtual = function (element, target) { + /*eslint complexity: ["error", 12]*/ let parent; parent = element.actualNode; diff --git a/lib/commons/dom/get-composed-parent.js b/lib/commons/dom/get-composed-parent.js index 1d26b63e85..23a5aa0291 100644 --- a/lib/commons/dom/get-composed-parent.js +++ b/lib/commons/dom/get-composed-parent.js @@ -7,19 +7,19 @@ * @param {Node} element * @return {Node|null} Parent element or Null for root node */ -dom.getComposedParent = function getComposedParent (element) { - if (element.assignedSlot) { - // NOTE: If the display of a slot element isn't 'contents', - // the slot shouldn't be ignored. Chrome does not support this (yet) so, - // we'll skip this part for now. - return getComposedParent(element.assignedSlot); // parent of a shadow DOM slot - } else if (element.parentNode) { - var parentNode = element.parentNode; - if (parentNode.nodeType === 1) { - return parentNode; // Regular node - } else if (parentNode.host) { - return parentNode.host; // Shadow root - } - } - return null; // Root node +dom.getComposedParent = function getComposedParent (element) { + if (element.assignedSlot) { + // NOTE: If the display of a slot element isn't 'contents', + // the slot shouldn't be ignored. Chrome does not support this (yet) so, + // we'll skip this part for now. + return getComposedParent(element.assignedSlot); // parent of a shadow DOM slot + } else if (element.parentNode) { + var parentNode = element.parentNode; + if (parentNode.nodeType === 1) { + return parentNode; // Regular node + } else if (parentNode.host) { + return parentNode.host; // Shadow root + } + } + return null; // Root node }; diff --git a/lib/commons/dom/get-element-coordinates.js b/lib/commons/dom/get-element-coordinates.js index 38a125b1cb..9857171e63 100644 --- a/lib/commons/dom/get-element-coordinates.js +++ b/lib/commons/dom/get-element-coordinates.js @@ -9,7 +9,7 @@ * @return {elementObj} elementObj Returns a `Object` with the following properties, which * each hold a value representing the pixels for each of the */ - /** +/** * @typedef elementObj * @type {Object} * @property {Number} top The top coordinate of the element diff --git a/lib/commons/dom/get-scroll-offset.js b/lib/commons/dom/get-scroll-offset.js index ecf53d9cfb..29e11957d1 100644 --- a/lib/commons/dom/get-scroll-offset.js +++ b/lib/commons/dom/get-scroll-offset.js @@ -1,5 +1,5 @@ /* global dom */ - +/*eslint complexity: ["error", 14]*/ /** * Get the scroll offset of the document passed in * @method getScrollOffset diff --git a/lib/commons/dom/has-content-virtual.js b/lib/commons/dom/has-content-virtual.js index b01854b72c..d95aa90c20 100644 --- a/lib/commons/dom/has-content-virtual.js +++ b/lib/commons/dom/has-content-virtual.js @@ -1,15 +1,15 @@ /* global dom, aria, axe */ const hiddenTextElms = [ - 'HEAD', 'TITLE', 'TEMPLATE', 'SCRIPT','STYLE', - 'IFRAME', 'OBJECT', 'VIDEO', 'AUDIO', 'NOSCRIPT' + 'HEAD', 'TITLE', 'TEMPLATE', 'SCRIPT','STYLE', + 'IFRAME', 'OBJECT', 'VIDEO', 'AUDIO', 'NOSCRIPT' ]; function hasChildTextNodes (elm) { - if (!hiddenTextElms.includes(elm.actualNode.nodeName.toUpperCase())) { - return elm.children.some(({ actualNode }) => ( - actualNode.nodeType === 3 && actualNode.nodeValue.trim() - )); - } + if (!hiddenTextElms.includes(elm.actualNode.nodeName.toUpperCase())) { + return elm.children.some(({ actualNode }) => ( + actualNode.nodeType === 3 && actualNode.nodeValue.trim() + )); + } } /** @@ -18,23 +18,23 @@ function hasChildTextNodes (elm) { * @method hasContentVirtual * @memberof axe.commons.dom * @instance - * @param {VirtualNode} elm Virtual Node to search - * @param {Boolean} noRecursion If true, only the element is checked, otherwise it will search all child nodes + * @param {VirtualNode} elm Virtual Node to search + * @param {Boolean} noRecursion If true, only the element is checked, otherwise it will search all child nodes * @return {Boolean} */ dom.hasContentVirtual = function (elm, noRecursion) { - return ( - // It has text - hasChildTextNodes(elm) || - // It is a graphical element - dom.isVisualContent(elm.actualNode) || - // It has an ARIA label - !!aria.labelVirtual(elm) || - // or one of it's descendants does - (!noRecursion && elm.children.some(child => ( - child.actualNode.nodeType === 1 && dom.hasContentVirtual(child) - ))) - ); + return ( + // It has text + hasChildTextNodes(elm) || + // It is a graphical element + dom.isVisualContent(elm.actualNode) || + // It has an ARIA label + !!aria.labelVirtual(elm) || + // or one of it's descendants does + (!noRecursion && elm.children.some(child => ( + child.actualNode.nodeType === 1 && dom.hasContentVirtual(child) + ))) + ); }; /** @@ -45,12 +45,12 @@ dom.hasContentVirtual = function (elm, noRecursion) { * @memberof axe.commons.dom * @instance * @param {DOMNode} elm DOMNode element to check - * @param {Boolean} noRecursion If true, only the element is checked, otherwise it will search all child nodes + * @param {Boolean} noRecursion If true, only the element is checked, otherwise it will search all child nodes * @return {Boolean} */ dom.hasContent = function hasContent (elm, noRecursion) { - elm = axe.utils.getNodeFromTree(axe._tree[0], elm); - return dom.hasContentVirtual(elm, noRecursion); + elm = axe.utils.getNodeFromTree(axe._tree[0], elm); + return dom.hasContentVirtual(elm, noRecursion); }; /** diff --git a/lib/commons/dom/index.js b/lib/commons/dom/index.js index e3bda7cf4e..3549a3cfd4 100644 --- a/lib/commons/dom/index.js +++ b/lib/commons/dom/index.js @@ -1,5 +1,5 @@ /* exported dom */ - +/*eslint no-unused-vars: 0*/ /** * Namespace for dom-related utilities. * @namespace dom diff --git a/lib/commons/dom/is-focusable.js b/lib/commons/dom/is-focusable.js index 6ba5dc71c0..ea617925bd 100644 --- a/lib/commons/dom/is-focusable.js +++ b/lib/commons/dom/is-focusable.js @@ -1,5 +1,5 @@ /* global dom */ -/* jshint maxcomplexity: 20 */ +/* eslint complexity: ["error",20] */ /** * Determines if focusing has been disabled on an element. @@ -46,6 +46,7 @@ dom.isFocusable = function (el) { * if its tabindex were removed. Else, false. */ dom.isNativelyFocusable = function(el) { + /* eslint indent: 0*/ 'use strict'; if (!el || focusDisabled(el)) { diff --git a/lib/commons/dom/is-in-text-block.js b/lib/commons/dom/is-in-text-block.js index 4873d18526..3576f0c387 100644 --- a/lib/commons/dom/is-in-text-block.js +++ b/lib/commons/dom/is-in-text-block.js @@ -26,7 +26,7 @@ function getBlockParent (node) { * @return {Boolean} [description] */ dom.isInTextBlock = function isInTextBlock(node) { - // jshint maxcomplexity: 15 + /* eslint complexity: ["error",17]*/ if (isBlock(node)) { // Ignore if the link is a block return false; diff --git a/lib/commons/dom/is-offscreen.js b/lib/commons/dom/is-offscreen.js index 0b0d406f19..ede64907d9 100644 --- a/lib/commons/dom/is-offscreen.js +++ b/lib/commons/dom/is-offscreen.js @@ -27,7 +27,7 @@ dom.isOffscreen = function (element) { const docElement = document.documentElement; const styl = window.getComputedStyle(element); const dir = window.getComputedStyle(document.body || docElement) - .getPropertyValue('direction'); + .getPropertyValue('direction'); const coords = dom.getElementCoordinates(element); // bottom edge beyond diff --git a/lib/commons/dom/is-visible.js b/lib/commons/dom/is-visible.js index 7016582b1c..7c9a8ed1ad 100644 --- a/lib/commons/dom/is-visible.js +++ b/lib/commons/dom/is-visible.js @@ -1,5 +1,5 @@ /* global dom */ -/* jshint maxcomplexity: 11 */ +/* eslint complexity: ["error", 18] */ /** * Determines if an element is hidden with the clip rect technique @@ -32,7 +32,7 @@ function isClipped(clip) { * @return {Boolean} The element's visibilty status */ dom.isVisible = function (el, screenReader, recursed) { - //jshint maxcomplexity: 13 + //eslint complexity: 13 'use strict'; var style, nodeName, parent; diff --git a/lib/commons/dom/is-visual-content.js b/lib/commons/dom/is-visual-content.js index c7e99dfaed..99ba69587f 100644 --- a/lib/commons/dom/is-visual-content.js +++ b/lib/commons/dom/is-visual-content.js @@ -1,5 +1,5 @@ /*global dom */ -/*jshint maxcomplexity: 20 */ +/*eslint complexity: ["error",20] */ const visualRoles = [ 'checkbox', 'img', 'radio', 'range', @@ -15,6 +15,7 @@ const visualRoles = [ * @return {Boolean} */ dom.isVisualContent = function (element) { + /*eslint indent: 0*/ const role = element.getAttribute('role'); if (role) { return (visualRoles.indexOf(role) !== -1); diff --git a/lib/commons/dom/shadow-elements-from-point.js b/lib/commons/dom/shadow-elements-from-point.js index 343c1108a5..84765bc10e 100644 --- a/lib/commons/dom/shadow-elements-from-point.js +++ b/lib/commons/dom/shadow-elements-from-point.js @@ -10,19 +10,19 @@ * @return {Array} */ dom.shadowElementsFromPoint = function(nodeX, nodeY, root = document) { - return root.elementsFromPoint(nodeX, nodeY) - .reduce((stack, elm) => { - if (axe.utils.isShadowRoot(elm)) { - const shadowStack = dom.shadowElementsFromPoint(nodeX, nodeY, elm.shadowRoot); - stack = stack.concat(shadowStack); - // filter host nodes which get included regardless of overlap - // TODO: refactor multiline overlap checking inside shadow dom - if (stack.length && axe.commons.dom.visuallyContains(stack[0], elm)) { - stack.push(elm); - } - } else { - stack.push(elm); - } - return stack; - }, []); + return root.elementsFromPoint(nodeX, nodeY) + .reduce((stack, elm) => { + if (axe.utils.isShadowRoot(elm)) { + const shadowStack = dom.shadowElementsFromPoint(nodeX, nodeY, elm.shadowRoot); + stack = stack.concat(shadowStack); + // filter host nodes which get included regardless of overlap + // TODO: refactor multiline overlap checking inside shadow dom + if (stack.length && axe.commons.dom.visuallyContains(stack[0], elm)) { + stack.push(elm); + } + } else { + stack.push(elm); + } + return stack; + }, []); }; diff --git a/lib/commons/dom/visually-contains.js b/lib/commons/dom/visually-contains.js index d70216e4a5..8baefae347 100644 --- a/lib/commons/dom/visually-contains.js +++ b/lib/commons/dom/visually-contains.js @@ -1,5 +1,5 @@ /* global dom */ -/* jshint maxcomplexity: 12 */ +/* eslint complexity: ["error",17] */ /** * Checks whether a parent element visually contains its child, either directly or via scrolling. @@ -34,8 +34,8 @@ dom.visuallyContains = function (node, parent) { // if parent element is inline, scrollArea will be too unpredictable if (style.getPropertyValue('display') === 'inline') { - return true; - } + return true; + } //In theory, we should just be able to look at the scroll area as a superset of the parentRect, //but that's not true in Firefox diff --git a/lib/commons/dom/visually-overlaps.js b/lib/commons/dom/visually-overlaps.js index 87c035b5ad..d045351a9e 100644 --- a/lib/commons/dom/visually-overlaps.js +++ b/lib/commons/dom/visually-overlaps.js @@ -1,5 +1,5 @@ /* global dom */ -/* jshint maxcomplexity: 11 */ +/* eslint complexity: ["error",15] */ /** * Checks whether a parent element visually overlaps a rectangle, either directly or via scrolling. diff --git a/lib/commons/index.js b/lib/commons/index.js index 0c99f643fc..3cee9890a4 100644 --- a/lib/commons/index.js +++ b/lib/commons/index.js @@ -1,4 +1,5 @@ /*exported commons */ +/*eslint no-unused-vars: 0*/ /** @namespace axe */ /** diff --git a/lib/commons/table/get-headers.js b/lib/commons/table/get-headers.js index 15b641802b..2959bc2f6b 100644 --- a/lib/commons/table/get-headers.js +++ b/lib/commons/table/get-headers.js @@ -19,12 +19,12 @@ table.getHeaders = function (cell) { // TODO: RTL text var rowHeaders = table - .traverse('left', position, tableGrid) - .filter((cell) => table.isRowHeader(cell)); + .traverse('left', position, tableGrid) + .filter((cell) => table.isRowHeader(cell)); var colHeaders = table - .traverse('up', position, tableGrid) - .filter((cell) => table.isColumnHeader(cell)); + .traverse('up', position, tableGrid) + .filter((cell) => table.isColumnHeader(cell)); return [].concat(rowHeaders, colHeaders).reverse(); }; diff --git a/lib/commons/table/get-scope.js b/lib/commons/table/get-scope.js index 5b6d7d8466..f5b89630ff 100644 --- a/lib/commons/table/get-scope.js +++ b/lib/commons/table/get-scope.js @@ -44,9 +44,9 @@ table.getScope = function (cell) { // The element is in a column with all th elements, that makes it a row header var headerCol = tableGrid.map((col) => col[pos.x]) - .reduce((headerCol, cell) => { - return headerCol && cell.nodeName.toUpperCase() === 'TH'; - }, true); + .reduce((headerCol, cell) => { + return headerCol && cell.nodeName.toUpperCase() === 'TH'; + }, true); if (headerCol) { return 'row'; diff --git a/lib/commons/table/index.js b/lib/commons/table/index.js index 901a727159..9942a00116 100644 --- a/lib/commons/table/index.js +++ b/lib/commons/table/index.js @@ -1,5 +1,5 @@ /* exported table */ - +/*eslint no-unused-vars: 0*/ /** * Namespace for table-related utilities. * @namespace table diff --git a/lib/commons/table/is-data-table.js b/lib/commons/table/is-data-table.js index 5130b3a8d1..1ff11b20eb 100644 --- a/lib/commons/table/is-data-table.js +++ b/lib/commons/table/is-data-table.js @@ -1,5 +1,5 @@ /* global table, dom */ -/* jshint maxstatements: 70, maxcomplexity: 40 */ +/* eslint max-statements: ["error",70], complexity: ["error",47] */ /** * Determines whether a table is a data table diff --git a/lib/commons/table/traverse.js b/lib/commons/table/traverse.js index c971a82d33..e969135af4 100644 --- a/lib/commons/table/traverse.js +++ b/lib/commons/table/traverse.js @@ -34,6 +34,7 @@ * @return {NodeElement} If the callback returns true, the traversal will end and the cell will be returned */ table.traverse = function (dir, startPos, tableGrid, callback) { + /* eslint indent: 0 */ if (Array.isArray(startPos)) { callback = tableGrid; tableGrid = startPos; diff --git a/lib/commons/text/accessible-text-virtual.js b/lib/commons/text/accessible-text-virtual.js index 8b68dc2bc8..cf651e6a8d 100644 --- a/lib/commons/text/accessible-text-virtual.js +++ b/lib/commons/text/accessible-text-virtual.js @@ -1,5 +1,5 @@ /* global text, dom, aria, axe */ -/* jshint maxstatements: 27, maxcomplexity: 19 */ +/* eslint max-statements: ["error",27], complexity: ["error",19] */ var defaultButtonValues = { submit: 'Submit', @@ -107,6 +107,7 @@ function checkDescendant({ actualNode }, nodeName) { * @return {boolean} True if embedded control */ function isEmbeddedControl(elm) { + /* eslint indent: 0 */ if (!elm) { return false; } @@ -176,7 +177,7 @@ text.accessibleTextVirtual = function accessibleTextVirtual(element, inLabelledB returnText += ' '; } returnText += accessibleNameComputation(child, inLabelledByContext, - inControlContext); + inControlContext); } return returnText; }, ''); @@ -191,7 +192,7 @@ text.accessibleTextVirtual = function accessibleTextVirtual(element, inLabelledB } function checkNative (element, inLabelledByContext, inControlContext) { - // jshint maxstatements:30, maxcomplexity: 20 + /* eslint max-statements:["error",30], complexity: ["error",22] */ let returnText = ''; const { actualNode } = element; const nodeName = actualNode.nodeName.toUpperCase(); diff --git a/lib/commons/text/index.js b/lib/commons/text/index.js index e29297d09c..e7b1f1ffdc 100644 --- a/lib/commons/text/index.js +++ b/lib/commons/text/index.js @@ -1,5 +1,5 @@ /* exported text */ - +/*eslint no-unused-vars: 0*/ /** * Namespace for text-related utilities. * @namespace text diff --git a/lib/commons/utils/index.js b/lib/commons/utils/index.js index fb9a079292..1eab9a76f5 100644 --- a/lib/commons/utils/index.js +++ b/lib/commons/utils/index.js @@ -1,6 +1,6 @@ /* exported utils */ /* global axe */ - +/*eslint no-unused-vars: 0*/ /** * Namespace for general utilities. * @namespace utils diff --git a/lib/commons/utils/valid-langs.js b/lib/commons/utils/valid-langs.js index 68d140a6f9..dd5e72a191 100644 --- a/lib/commons/utils/valid-langs.js +++ b/lib/commons/utils/valid-langs.js @@ -1,5 +1,5 @@ /* global axe */ -/* jshint -W109 */ +/*eslint quotes: 0*/ var langs = [ "aa", "ab", diff --git a/lib/core/base/audit.js b/lib/core/base/audit.js index 23e8ccf973..17fdfcbde9 100644 --- a/lib/core/base/audit.js +++ b/lib/core/base/audit.js @@ -1,5 +1,5 @@ /*global Rule, Check, RuleResult, commons: true */ - +/*eslint no-unused-vars: 0*/ function getDefaultConfiguration(audit) { 'use strict'; var config; @@ -106,7 +106,7 @@ Audit.prototype.addRule = function (spec) { * @param {Object} spec Check specification object */ Audit.prototype.addCheck = function (spec) { - /*jshint evil:true */ + /*eslint no-eval: 0 */ 'use strict'; let metadata = spec.metadata; @@ -115,14 +115,14 @@ Audit.prototype.addCheck = function (spec) { // Transform messages into functions: if (typeof metadata.messages === 'object') { Object.keys(metadata.messages) - .filter( prop => - metadata.messages.hasOwnProperty(prop) && - typeof metadata.messages[prop] === 'string' - ).forEach( prop => { - if (metadata.messages[prop].indexOf('function') === 0) { - metadata.messages[prop] = (new Function('return ' + metadata.messages[prop] + ';'))(); - } - }); + .filter( prop => + metadata.messages.hasOwnProperty(prop) && + typeof metadata.messages[prop] === 'string' + ).forEach( prop => { + if (metadata.messages[prop].indexOf('function') === 0) { + metadata.messages[prop] = (new Function('return ' + metadata.messages[prop] + ';'))(); + } + }); } } @@ -258,11 +258,11 @@ Audit.prototype.validateOptions = function (options) { if (typeof options.rules === 'object') { Object.keys(options.rules) - .forEach(function (ruleId) { - if (!audit.getRule(ruleId)) { - throw new Error('unknown rule `' + ruleId + '` in options.rules'); - } - }); + .forEach(function (ruleId) { + if (!audit.getRule(ruleId)) { + throw new Error('unknown rule `' + ruleId + '` in options.rules'); + } + }); } return options; @@ -320,7 +320,7 @@ Audit.prototype._constructHelpUrls = function (previous = null) { * Reset the default rules, checks and meta data */ - Audit.prototype.resetRulesAndChecks = function () { +Audit.prototype.resetRulesAndChecks = function () { 'use strict'; - this._init(); - }; + this._init(); +}; diff --git a/lib/core/base/check-result.js b/lib/core/base/check-result.js index f7a0d578bc..e03a260f31 100644 --- a/lib/core/base/check-result.js +++ b/lib/core/base/check-result.js @@ -1,5 +1,5 @@ /*exported CheckResult */ - +/*eslint no-unused-vars: 0*/ /** * Constructor for the result of checks * @param {Check} check diff --git a/lib/core/base/check.js b/lib/core/base/check.js index 78ec64d74a..c9eafac0de 100644 --- a/lib/core/base/check.js +++ b/lib/core/base/check.js @@ -1,7 +1,7 @@ /*global CheckResult */ function createExecutionContext(spec) { - /*jshint evil:true */ + /*eslint no-eval:0 */ 'use strict'; if (typeof spec === 'string') { return new Function('return ' + spec + ';')(); @@ -96,10 +96,10 @@ Check.prototype.run = function (node, options, resolve, reject) { Check.prototype.configure = function (spec) { ['options', 'enabled'] - .filter( prop => spec.hasOwnProperty(prop) ) - .forEach( prop => this[prop] = spec[prop] ); + .filter( prop => spec.hasOwnProperty(prop) ) + .forEach( prop => this[prop] = spec[prop] ); ['evaluate', 'after'] - .filter( prop => spec.hasOwnProperty(prop) ) - .forEach( prop => this[prop] = createExecutionContext(spec[prop]) ); + .filter( prop => spec.hasOwnProperty(prop) ) + .forEach( prop => this[prop] = createExecutionContext(spec[prop]) ); }; diff --git a/lib/core/base/context.js b/lib/core/base/context.js index 48ad016a5e..2f85e9da02 100644 --- a/lib/core/base/context.js +++ b/lib/core/base/context.js @@ -70,6 +70,7 @@ function pushUniqueFrameSelector(context, type, selectorArray) { * @return {Object} Normalized context spec to include both `include` and `exclude` arrays */ function normalizeContext(context) { + /*eslint complexity: ["error", 13] */ 'use strict'; // typeof NodeList.length in PhantomJS === function @@ -127,7 +128,7 @@ function parseSelectorArray(context, type) { // selector if (typeof item === 'string') { nodeList = Array.from(document.querySelectorAll(item)); - //jshint loopfunc:true + //eslint no-loop-func:0 result = result.concat(nodeList.map((node) => { return axe.utils.getFlattenedTree(node)[0]; })); @@ -138,7 +139,7 @@ function parseSelectorArray(context, type) { pushUniqueFrameSelector(context, type, item); } else { nodeList = Array.from(document.querySelectorAll(item[0])); - //jshint loopfunc:true + //eslint no-loop-func:0 result = result.concat(nodeList.map((node) => { return axe.utils.getFlattenedTree(node)[0]; })); @@ -200,7 +201,7 @@ function validateContext(context) { * @param {Object} spec Configuration or "specification" object */ function Context(spec) { - //jshint maxstatements:18 + /* eslint max-statements:["error",19], no-unused-vars:0 */ 'use strict'; var self = this; diff --git a/lib/core/base/rule-result.js b/lib/core/base/rule-result.js index 03103b3e29..02fb681b6c 100644 --- a/lib/core/base/rule-result.js +++ b/lib/core/base/rule-result.js @@ -1,5 +1,5 @@ /*exported RuleResult */ - +/*eslint no-unused-vars:0*/ /** * Constructor for the result of Rules * @param {Rule} rule diff --git a/lib/core/base/rule.js b/lib/core/base/rule.js index d2c4589b5a..2fb4d92fa9 100644 --- a/lib/core/base/rule.js +++ b/lib/core/base/rule.js @@ -1,7 +1,7 @@ /*global RuleResult, createExecutionContext, SupportError */ function Rule(spec, parentAudit) { - /*jshint maxcomplexity:11 */ + /*eslint complexity: ["error", 11] */ 'use strict'; this._audit = parentAudit; @@ -127,7 +127,7 @@ Rule.prototype.runChecks = function (type, node, options, resolve, reject) { * @param {Function} callback Function to call when evaluate is complete; receives a RuleResult instance */ Rule.prototype.run = function (context, options, resolve, reject) { - //jshint maxstatements: 17 + /*eslint max-statements: ["error",17] */ const q = axe.utils.queue(); const ruleResult = new RuleResult(this); const markStart = 'mark_runchecks_start_' + this.id; @@ -137,7 +137,7 @@ Rule.prototype.run = function (context, options, resolve, reject) { try { // Matches throws an error when it lacks support for document methods nodes = this.gather(context) - .filter(node => this.matches(node.actualNode, node)); + .filter(node => this.matches(node.actualNode, node)); } catch (error) { // Exit the rule execution if matches fails reject(new SupportError({cause: error, ruleId: this.id})); @@ -190,7 +190,7 @@ Rule.prototype.run = function (context, options, resolve, reject) { } q.then(() => resolve(ruleResult)) - .catch(error => reject(error)); + .catch(error => reject(error)); }; /** @@ -296,9 +296,7 @@ Rule.prototype.after = function (result, options) { * @param {Object} spec - the attributes to be reconfigured */ Rule.prototype.configure = function (spec) { - /*jshint maxcomplexity:14 */ - /*jshint maxstatements:20 */ - /*jshint evil:true */ + /*eslint complexity:["error",14], max-statements:["error",22], no-eval:0 */ 'use strict'; if (spec.hasOwnProperty('selector')) { diff --git a/lib/core/constants.js b/lib/core/constants.js index a9e7684b4c..d49b5a5f1d 100644 --- a/lib/core/constants.js +++ b/lib/core/constants.js @@ -1,64 +1,64 @@ (function (axe) { -var definitions = [{ - name: 'NA', - value: 'inapplicable', - priority: 0, - group: 'inapplicable' -}, { - name: 'PASS', - value: 'passed', - priority: 1, - group: 'passes' -}, { - name: 'CANTTELL', - value: 'cantTell', - priority: 2, - group: 'incomplete' -}, { - name: 'FAIL', - value: 'failed', - priority: 3, - group: 'violations' -}]; + var definitions = [{ + name: 'NA', + value: 'inapplicable', + priority: 0, + group: 'inapplicable' + }, { + name: 'PASS', + value: 'passed', + priority: 1, + group: 'passes' + }, { + name: 'CANTTELL', + value: 'cantTell', + priority: 2, + group: 'incomplete' + }, { + name: 'FAIL', + value: 'failed', + priority: 3, + group: 'violations' + }]; -var constants = { - helpUrlBase: 'https://dequeuniversity.com/rules/', - results: [], - resultGroups: [], - resultGroupMap: {}, - impact: Object.freeze(['minor', 'moderate', 'serious', 'critical']) -}; + var constants = { + helpUrlBase: 'https://dequeuniversity.com/rules/', + results: [], + resultGroups: [], + resultGroupMap: {}, + impact: Object.freeze(['minor', 'moderate', 'serious', 'critical']) + }; -definitions.forEach(function (definition) { - var name = definition.name; - var value = definition.value; - var priority = definition.priority; - var group = definition.group; + definitions.forEach(function (definition) { + var name = definition.name; + var value = definition.value; + var priority = definition.priority; + var group = definition.group; - constants[name] = value; - constants[name + '_PRIO'] = priority; - constants[name + '_GROUP'] = group; + constants[name] = value; + constants[name + '_PRIO'] = priority; + constants[name + '_GROUP'] = group; - constants.results[priority] = value; - constants.resultGroups[priority] = group; + constants.results[priority] = value; + constants.resultGroups[priority] = group; - constants.resultGroupMap[value] = group; -}); + constants.resultGroupMap[value] = group; + }); -// Freeze everything -Object.freeze(constants.results); -Object.freeze(constants.resultGroups); -Object.freeze(constants.resultGroupMap); -Object.freeze(constants); + // Freeze everything + Object.freeze(constants.results); + Object.freeze(constants.resultGroups); + Object.freeze(constants.resultGroupMap); + Object.freeze(constants); -// Ensure that constants can not be changed -Object.defineProperty(axe, 'constants', { - value: constants, - enumerable: true, - configurable: false, - writable: false -}); + // Ensure that constants can not be changed + Object.defineProperty(axe, 'constants', { + value: constants, + enumerable: true, + configurable: false, + writable: false + }); -}(axe)); \ No newline at end of file +}(axe)); diff --git a/lib/core/index.js b/lib/core/index.js index 4ecf70e9e5..2e021a3fa3 100644 --- a/lib/core/index.js +++ b/lib/core/index.js @@ -1,6 +1,7 @@ /*exported axe, commons */ /*global axeFunction, module, define */ // exported namespace for aXe +/*eslint no-use-before-define: 0, no-unused-vars: 0*/ var axe = axe || {}; axe.version = '<%= pkg.version %>'; @@ -11,11 +12,11 @@ if (typeof define === 'function' && define.amd) { }); } if (typeof module === 'object' && module.exports && typeof axeFunction.toString === 'function') { - axe.source = '(' + axeFunction.toString() + ')(typeof window === "object" ? window : this);'; - module.exports = axe; + axe.source = '(' + axeFunction.toString() + ')(typeof window === "object" ? window : this);'; + module.exports = axe; } if (typeof window.getComputedStyle === 'function') { - window.axe = axe; + window.axe = axe; } // local namespace for common functions var commons; diff --git a/lib/core/log.js b/lib/core/log.js index 811b9c24c0..8ce1cc255f 100644 --- a/lib/core/log.js +++ b/lib/core/log.js @@ -1,4 +1,4 @@ -/*jshint devel: true */ +/*eslint no-console: 0 */ /** * Logs a message to the developer console (if it exists and is active). diff --git a/lib/core/public/cleanup-plugins.js b/lib/core/public/cleanup-plugins.js index cd7d256b8d..bfe7a25b5b 100644 --- a/lib/core/public/cleanup-plugins.js +++ b/lib/core/public/cleanup-plugins.js @@ -1,48 +1,47 @@ function cleanupPlugins(resolve, reject) { - 'use strict'; - resolve = resolve || function() {}; - reject = reject || axe.log; + 'use strict'; + resolve = resolve || function() {}; + reject = reject || axe.log; - if (!axe._audit) { - throw new Error('No audit configured'); - } + if (!axe._audit) { + throw new Error('No audit configured'); + } - var q = axe.utils.queue(); - // If a plugin fails it's cleanup, we still want the others to run - var cleanupErrors = []; + var q = axe.utils.queue(); + // If a plugin fails it's cleanup, we still want the others to run + var cleanupErrors = []; - Object.keys(axe.plugins).forEach(function (key) { - q.defer(function (res) { - var rej = function (err) { - cleanupErrors.push(err); - res(); - }; - try { - axe.plugins[key].cleanup(res, rej); - } catch(err) { - rej(err); - } - }); - }); + Object.keys(axe.plugins).forEach(function (key) { + q.defer(function (res) { + var rej = function (err) { + cleanupErrors.push(err); + res(); + }; + try { + axe.plugins[key].cleanup(res, rej); + } catch(err) { + rej(err); + } + }); + }); - var flattenedTree = axe.utils.getFlattenedTree(document.body); + var flattenedTree = axe.utils.getFlattenedTree(document.body); - axe.utils.querySelectorAll(flattenedTree, 'iframe, frame').forEach(function (node) { - q.defer(function (res, rej) { - return axe.utils.sendCommandToFrame(node.actualNode, { - command: 'cleanup-plugin' - }, res, rej); - }); - }); + axe.utils.querySelectorAll(flattenedTree, 'iframe, frame').forEach(function (node) { + q.defer(function (res, rej) { + return axe.utils.sendCommandToFrame(node.actualNode, { + command: 'cleanup-plugin' + }, res, rej); + }); + }); - q.then(function (results) { - if (cleanupErrors.length === 0) { - resolve(results); - } else { - reject(cleanupErrors); - } - }) - .catch(reject); + q.then(function (results) { + if (cleanupErrors.length === 0) { + resolve(results); + } else { + reject(cleanupErrors); + } + }).catch(reject); } axe.cleanup = cleanupPlugins; diff --git a/lib/core/public/configure.js b/lib/core/public/configure.js index 43db70624f..0a0d12111f 100644 --- a/lib/core/public/configure.js +++ b/lib/core/public/configure.js @@ -1,6 +1,6 @@ /* global reporters */ function configureChecksRulesAndBranding(spec) { - //jshint maxstatements: 18 + /*eslint max-statements: ["error",20]*/ 'use strict'; var audit; diff --git a/lib/core/public/load.js b/lib/core/public/load.js index d0f8f2ea50..58f23a2eaf 100644 --- a/lib/core/public/load.js +++ b/lib/core/public/load.js @@ -1,4 +1,5 @@ /*global Audit, runRules, cleanupPlugins */ +/*eslint indent: 0*/ function runCommand(data, keepalive, callback) { 'use strict'; var resolve = callback; diff --git a/lib/core/public/plugins.js b/lib/core/public/plugins.js index ba71f9e40a..a43a0eef89 100644 --- a/lib/core/public/plugins.js +++ b/lib/core/public/plugins.js @@ -1,3 +1,4 @@ +/*eslint no-use-before-define:0 */ var axe = axe || {}; axe.plugins = {}; diff --git a/lib/core/public/run.js b/lib/core/public/run.js index aedb19b718..8fb69c0b95 100644 --- a/lib/core/public/run.js +++ b/lib/core/public/run.js @@ -1,5 +1,5 @@ /* global Promise */ - +/*eslint indent: 0, complexity:["error", 12]*/ function isContext(potential) { 'use strict'; switch (true) { @@ -84,6 +84,7 @@ function normalizeRunParams(context, options, callback) { * @return {Promise} Resolves with the axe results. Only available when natively supported */ axe.run = function (context, options, callback) { + /*eslint max-statements:["error",18] */ 'use strict'; if (!axe._audit) { throw new Error('No audit configured'); @@ -142,4 +143,4 @@ axe.run = function (context, options, callback) { }); return p; -}; \ No newline at end of file +}; diff --git a/lib/core/reporters/helpers/failure-summary.js b/lib/core/reporters/helpers/failure-summary.js index aaea0a6fe6..8b7be75932 100644 --- a/lib/core/reporters/helpers/failure-summary.js +++ b/lib/core/reporters/helpers/failure-summary.js @@ -21,9 +21,9 @@ helpers.failureSummary = function failureSummary(nodeData) { var sum = axe._audit.data.failureSummaries[key]; if (sum && typeof sum.failureMessage === 'function') { return sum.failureMessage(failingChecks[key] - .map(function (check) { - return check.message || ''; - })); + .map(function (check) { + return check.message || ''; + })); } }).filter(function (i) { diff --git a/lib/core/reporters/helpers/index.js b/lib/core/reporters/helpers/index.js index 1f01cc415d..38a2ffe12c 100644 --- a/lib/core/reporters/helpers/index.js +++ b/lib/core/reporters/helpers/index.js @@ -1,2 +1,3 @@ +/*eslint no-unused-vars: 0*/ /*exported helpers */ var helpers = {}; diff --git a/lib/core/reporters/helpers/process-aggregate.js b/lib/core/reporters/helpers/process-aggregate.js index 1f534fd3d3..2c736dc598 100644 --- a/lib/core/reporters/helpers/process-aggregate.js +++ b/lib/core/reporters/helpers/process-aggregate.js @@ -6,23 +6,23 @@ function normalizeRelatedNodes(node, options) { return; } node[type].filter((checkRes) => Array.isArray(checkRes.relatedNodes)) - .forEach((checkRes) => { - checkRes.relatedNodes = checkRes.relatedNodes.map((relatedNode) => { - var res = { - html: relatedNode.source - }; - if (options.elementRef && !relatedNode.fromFrame) { - res.element = relatedNode.element; - } - if (options.selectors !== false || relatedNode.fromFrame) { - res.target = relatedNode.selector; - } - if (options.xpath) { - res.xpath = relatedNode.xpath; - } - return res; + .forEach((checkRes) => { + checkRes.relatedNodes = checkRes.relatedNodes.map((relatedNode) => { + var res = { + html: relatedNode.source + }; + if (options.elementRef && !relatedNode.fromFrame) { + res.element = relatedNode.element; + } + if (options.selectors !== false || relatedNode.fromFrame) { + res.target = relatedNode.selector; + } + if (options.xpath) { + res.xpath = relatedNode.xpath; + } + return res; + }); }); - }); }); } @@ -46,8 +46,8 @@ var resultKeys = axe.constants.resultGroups; * * @method processAggregate * @memberof helpers - * @param {Array} results - * @param {ProcessOptions} options + * @param {Array} results + * @param {ProcessOptions} options * @return {Object} * */ diff --git a/lib/core/utils/aggregate.js b/lib/core/utils/aggregate.js index 3315d68fdc..229ab62bb1 100644 --- a/lib/core/utils/aggregate.js +++ b/lib/core/utils/aggregate.js @@ -14,9 +14,8 @@ axe.utils.aggregate = function (map, values, initial) { } var sorting = values - .map((val) => map.indexOf(val)) - .sort(); // Stupid NodeJS array.sort functor doesn't work!! + .map((val) => map.indexOf(val)) + .sort(); // Stupid NodeJS array.sort functor doesn't work!! return map[sorting.pop()]; }; - diff --git a/lib/core/utils/aggregateNodeResults.js b/lib/core/utils/aggregateNodeResults.js index 650ecc5e93..ce927b0957 100644 --- a/lib/core/utils/aggregateNodeResults.js +++ b/lib/core/utils/aggregateNodeResults.js @@ -2,61 +2,61 @@ /** * Calculates the result of a Rule based on its types and the result of its child Checks - * @param {Array} nodeResults The array of nodes tested by the Rule + * @param {Array} nodeResults The array of nodes tested by the Rule */ -axe.utils.aggregateNodeResults = function (nodeResults) { - let ruleResult = {}; + axe.utils.aggregateNodeResults = function (nodeResults) { + let ruleResult = {}; + + // For each node, retrieve the result and impact + nodeResults = nodeResults.map(function (nodeResult) { + // Known result + if (nodeResult.any && nodeResult.all && nodeResult.none) { + return axe.utils.aggregateChecks(nodeResult); + + } else if (Array.isArray(nodeResult.node)) { + return axe.utils.finalizeRuleResult(nodeResult); + + } else { + throw new TypeError('Invalid Result type'); + } + }); + + // Aggregate the result + // If there were no nodes passed in, mark the test as inapplicable + if (nodeResults && nodeResults.length) { + let resultList = nodeResults.map((node) => node.result); + ruleResult.result = axe.utils.aggregate(axe.constants.results, resultList, ruleResult.result); + } else { + ruleResult.result = 'inapplicable'; + } + + // Create an array for each type + axe.constants.resultGroups + .forEach((group) => ruleResult[group] = []); - // For each node, retrieve the result and impact - nodeResults = nodeResults.map(function (nodeResult) { - // Known result - if (nodeResult.any && nodeResult.all && nodeResult.none) { - return axe.utils.aggregateChecks(nodeResult); + // Fill the array with nodes + nodeResults.forEach(function (nodeResult) { + var groupName = axe.constants.resultGroupMap[nodeResult.result]; + ruleResult[groupName].push(nodeResult); + }); - } else if (Array.isArray(nodeResult.node)) { - return axe.utils.finalizeRuleResult(nodeResult); + // Take the highest impact of failed or canttell rules + var impactGroup = axe.constants.FAIL_GROUP; + if (ruleResult[impactGroup].length === 0) { + impactGroup = axe.constants.CANTTELL_GROUP; + } + + if (ruleResult[impactGroup].length > 0) { + // Get the impact of all issues + let impactList = ruleResult[impactGroup] + .map((failure) => failure.impact); + ruleResult.impact = axe.utils.aggregate(axe.constants.impact, impactList) || null; } else { - throw new TypeError('Invalid Result type'); + ruleResult.impact = null; } - }); - - // Aggregate the result - // If there were no nodes passed in, mark the test as inapplicable - if (nodeResults && nodeResults.length) { - let resultList = nodeResults.map((node) => node.result); - ruleResult.result = axe.utils.aggregate(axe.constants.results, resultList, ruleResult.result); - } else { - ruleResult.result = 'inapplicable'; - } - - // Create an array for each type - axe.constants.resultGroups - .forEach((group) => ruleResult[group] = []); - - // Fill the array with nodes - nodeResults.forEach(function (nodeResult) { - var groupName = axe.constants.resultGroupMap[nodeResult.result]; - ruleResult[groupName].push(nodeResult); - }); - - // Take the highest impact of failed or canttell rules - var impactGroup = axe.constants.FAIL_GROUP; - if (ruleResult[impactGroup].length === 0) { - impactGroup = axe.constants.CANTTELL_GROUP; - } - - if (ruleResult[impactGroup].length > 0) { - // Get the impact of all issues - let impactList = ruleResult[impactGroup] - .map((failure) => failure.impact); - - ruleResult.impact = axe.utils.aggregate(axe.constants.impact, impactList) || null; - } else { - ruleResult.impact = null; - } - - return ruleResult; -}; + + return ruleResult; + }; }()); diff --git a/lib/core/utils/aggregateResult.js b/lib/core/utils/aggregateResult.js index 8b993e4260..7413941c04 100644 --- a/lib/core/utils/aggregateResult.js +++ b/lib/core/utils/aggregateResult.js @@ -16,7 +16,7 @@ axe.utils.aggregateResult = function (results) { // Create an array for each type axe.constants.resultGroups - .forEach((groupName) => resultObject[groupName] = []); + .forEach((groupName) => resultObject[groupName] = []); // Fill the array with nodes results.forEach(function (subResult) { @@ -28,11 +28,11 @@ axe.utils.aggregateResult = function (results) { } else { axe.constants.resultGroups - .forEach(function (group) { - if (Array.isArray(subResult[group]) && subResult[group].length > 0 ) { - copyToGroup(resultObject, subResult, group); - } - }); + .forEach(function (group) { + if (Array.isArray(subResult[group]) && subResult[group].length > 0 ) { + copyToGroup(resultObject, subResult, group); + } + }); } }); diff --git a/lib/core/utils/clone.js b/lib/core/utils/clone.js index 46104bd9fe..30519b053b 100644 --- a/lib/core/utils/clone.js +++ b/lib/core/utils/clone.js @@ -4,6 +4,7 @@ * @return {Mixed} A clone of the initial object or array */ axe.utils.clone = function (obj) { + /* eslint guard-for-in: 0*/ 'use strict'; var index, length, out = obj; @@ -16,7 +17,6 @@ axe.utils.clone = function (obj) { } } else { out = {}; - // jshint forin: false for (index in obj) { out[index] = axe.utils.clone(obj[index]); } diff --git a/lib/core/utils/contains.js b/lib/core/utils/contains.js index 676b1bb882..1b96bea2eb 100644 --- a/lib/core/utils/contains.js +++ b/lib/core/utils/contains.js @@ -9,7 +9,7 @@ * @return {Boolean} Whether `node` contains `otherNode` */ axe.utils.contains = function (node, otherNode) { - //jshint bitwise: false + /*eslint no-bitwise: 0*/ 'use strict'; function containsShadowChild(node, otherNode) { if (node.shadowId === otherNode.shadowId) { diff --git a/lib/core/utils/css-parser.js b/lib/core/utils/css-parser.js index 2915734413..216a99e278 100644 --- a/lib/core/utils/css-parser.js +++ b/lib/core/utils/css-parser.js @@ -1,4 +1,4 @@ -/* jshint ignore:start */ +/* eslint-disable */ (function (axe) { /*! * The copyright below covers the code within this function block only diff --git a/lib/core/utils/dq-element.js b/lib/core/utils/dq-element.js index e3fa051464..c687cb6c00 100644 --- a/lib/core/utils/dq-element.js +++ b/lib/core/utils/dq-element.js @@ -67,8 +67,8 @@ DqElement.prototype = { axe.utils.getXpath(this.element) ]; }, - - /** + + /** * Direct reference to the `HTMLElement` wrapped by this `DQElement`. */ get element() { @@ -90,9 +90,9 @@ DqElement.prototype = { }; DqElement.fromFrame = function (node, options, frame) { - node.selector.unshift(frame.selector); - node.xpath.unshift(frame.xpath); - return new axe.utils.DqElement(frame.element, options, node); + node.selector.unshift(frame.selector); + node.xpath.unshift(frame.xpath); + return new axe.utils.DqElement(frame.element, options, node); }; axe.utils.DqElement = DqElement; diff --git a/lib/core/utils/element-matches.js b/lib/core/utils/element-matches.js index 4588f42178..432109cf43 100644 --- a/lib/core/utils/element-matches.js +++ b/lib/core/utils/element-matches.js @@ -13,7 +13,13 @@ axe.utils.matchesSelector = (function () { var index, candidate, elProto = win.Element.prototype, - candidates = ['matches', 'matchesSelector', 'mozMatchesSelector', 'webkitMatchesSelector', 'msMatchesSelector'], + candidates = [ + 'matches', + 'matchesSelector', + 'mozMatchesSelector', + 'webkitMatchesSelector', + 'msMatchesSelector' + ], length = candidates.length; for (index = 0; index < length; index++) { diff --git a/lib/core/utils/escape-selector.js b/lib/core/utils/escape-selector.js index 093aa29e16..8d6b53ac72 100644 --- a/lib/core/utils/escape-selector.js +++ b/lib/core/utils/escape-selector.js @@ -7,7 +7,8 @@ */ axe.utils.escapeSelector = function (value) { 'use strict'; - /*jshint bitwise: true, eqeqeq: false, maxcomplexity: 14, maxstatements: 23, onevar: false, -W041: false */ + /*eslint no-bitwise: 0, eqeqeq: 0, complexity: ["error",27], + max-statements:["error", 23], one-var: 0, -W041: 0 */ var string = String(value); var length = string.length; var index = -1; diff --git a/lib/core/utils/extend-meta-data.js b/lib/core/utils/extend-meta-data.js index 75b9c8087b..e968e111ef 100644 --- a/lib/core/utils/extend-meta-data.js +++ b/lib/core/utils/extend-meta-data.js @@ -1,4 +1,4 @@ - +/*eslint no-empty: 0*/ /** * Extends metadata onto result object and executes any functions * @param {Object} to The target of the extend @@ -7,10 +7,10 @@ axe.utils.extendMetaData = function (to, from) { Object.assign(to, from); Object.keys(from).filter( prop => typeof from[prop] === 'function' ) - .forEach( prop => { - to[prop] = null; - try { - to[prop] = from[prop](to); - } catch(e) { } - }); -}; \ No newline at end of file + .forEach( prop => { + to[prop] = null; + try { + to[prop] = from[prop](to); + } catch(e) { } + }); +}; diff --git a/lib/core/utils/flattened-tree.js b/lib/core/utils/flattened-tree.js index 60d302daf3..786390fc7e 100644 --- a/lib/core/utils/flattened-tree.js +++ b/lib/core/utils/flattened-tree.js @@ -1,3 +1,4 @@ +/*eslint no-use-before-define: 0*/ var axe = axe || { utils: {} }; /** @@ -61,7 +62,7 @@ function getSlotChildren(node) { */ axe.utils.getFlattenedTree = function (node, shadowId) { // using a closure here and therefore cannot easily refactor toreduce the statements - //jshint maxstatements: false + /*eslint max-statements: ["error", 31] */ var retVal, realArray, nodeName; function reduceShadowDOM (res, child) { var replacements = axe.utils.getFlattenedTree(child, shadowId); diff --git a/lib/core/utils/get-check-option.js b/lib/core/utils/get-check-option.js index 06e33f1058..b7ee5e55d3 100644 --- a/lib/core/utils/get-check-option.js +++ b/lib/core/utils/get-check-option.js @@ -1,4 +1,4 @@ - +/*eslint complexity: ["error", 12]*/ /** * Determines which CheckOption to use, either defined on the rule options, global check options or the check itself * @param {Check} check The Check object @@ -37,4 +37,4 @@ axe.utils.getCheckOption = function (check, ruleID, options) { options: opts, absolutePaths: options.absolutePaths }; -}; \ No newline at end of file +}; diff --git a/lib/core/utils/get-friendly-uri-end.js b/lib/core/utils/get-friendly-uri-end.js index e80dc97d88..69b6dbe8c8 100644 --- a/lib/core/utils/get-friendly-uri-end.js +++ b/lib/core/utils/get-friendly-uri-end.js @@ -1,21 +1,22 @@ +/* eslint max-statements:["error",18], complexity:["error",27], no-script-url:0 */ /** * Check if a string contains mostly numbers */ function isMostlyNumbers (str = '') { - return ( - str.length !== 0 && - (str.match(/[0-9]/g) || '').length >= str.length / 2 - ); + return ( + str.length !== 0 && + (str.match(/[0-9]/g) || '').length >= str.length / 2 + ); } /** * Spit a string into an array with two pieces, at a given index - * @param String string to split - * @param Number index at which to split + * @param String string to split + * @param Number index at which to split * @return Array */ function splitString (str, splitIndex) { - return [str.substring(0, splitIndex), str.substring(splitIndex)]; + return [str.substring(0, splitIndex), str.substring(splitIndex)]; } /** @@ -23,103 +24,101 @@ function splitString (str, splitIndex) { * * @param url (string) * @return urlPieces - * .protocol The protocol used, e.g. 'https://' - * .domain Domain name including sub domains and TLD, e.g. 'docs.deque.com' - * .port The port number, e.g. ':8080' - * .path Path after the domain, e.g. '/home.html' - * .query Query string, e.g. '?user=admin&password=pass' - * .hash Hash / internal reference, e.g. '#footer' + * .protocol The protocol used, e.g. 'https://' + * .domain Domain name including sub domains and TLD, e.g. 'docs.deque.com' + * .port The port number, e.g. ':8080' + * .path Path after the domain, e.g. '/home.html' + * .query Query string, e.g. '?user=admin&password=pass' + * .hash Hash / internal reference, e.g. '#footer' */ function uriParser (url) { - // jshint maxstatements:19 - let original = url; - let protocol = '', domain = '', port = '', path = '', query = '', hash = ''; - if (url.includes('#')) { - [url, hash] = splitString(url, url.indexOf('#')); - } + let original = url; + let protocol = '', domain = '', port = '', path = '', query = '', hash = ''; + if (url.includes('#')) { + [url, hash] = splitString(url, url.indexOf('#')); + } - if (url.includes('?')) { - [url, query] = splitString(url, url.indexOf('?')); - } + if (url.includes('?')) { + [url, query] = splitString(url, url.indexOf('?')); + } - if (url.includes('://')) { - [protocol, url] = url.split('://'); - [domain, url] = splitString(url, url.indexOf('/')); - } else if (url.substr(0,2) === '//') { - url = url.substr(2); - [domain, url] = splitString(url, url.indexOf('/')); - } + if (url.includes('://')) { + [protocol, url] = url.split('://'); + [domain, url] = splitString(url, url.indexOf('/')); + } else if (url.substr(0,2) === '//') { + url = url.substr(2); + [domain, url] = splitString(url, url.indexOf('/')); + } - if (domain.substr(0,4) === 'www.') { - domain = domain.substr(4); - } + if (domain.substr(0,4) === 'www.') { + domain = domain.substr(4); + } - if (domain && domain.includes(':')) { - [domain, port] = splitString(domain, domain.indexOf(':')); - } + if (domain && domain.includes(':')) { + [domain, port] = splitString(domain, domain.indexOf(':')); + } - path = url; // Whatever is left, must be the path - return { original, protocol, domain, port, path, query, hash }; + path = url; // Whatever is left, must be the path + return { original, protocol, domain, port, path, query, hash }; } /** * Try to, at the end of the URI, find a string that a user can identify the URI by * - * @param uri The URI to use + * @param uri The URI to use * @param options - * .currentDomain The current domain name (optional) - * .maxLength Max length of the returned string (default: 25) - * @return string A portion at the end of the uri, no longer than maxLength + * .currentDomain The current domain name (optional) + * .maxLength Max length of the returned string (default: 25) + * @return string A portion at the end of the uri, no longer than maxLength */ axe.utils.getFriendlyUriEnd = function getFriendlyUriEnd (uri = '', options = {}) { - // jshint maxstatements: 16, maxcomplexity: 13, scripturl: true - if (// Skip certain URIs: - uri.length <= 1 || // very short - uri.substr(0, 5) === 'data:' || // data URIs are unreadable - uri.substr(0, 11) === 'javascript:' || // JS isn't a URL - uri.includes('?') // query strings aren't very readable either - ) { - return; - } + if (// Skip certain URIs: + uri.length <= 1 || // very short + uri.substr(0, 5) === 'data:' || // data URIs are unreadable + uri.substr(0, 11) === 'javascript:' || // JS isn't a URL + uri.includes('?') // query strings aren't very readable either + ) { + return; + } - const { currentDomain, maxLength = 25 } = options; - const { path, domain, hash } = uriParser(uri); - // Split the path at the last / that has text after it - const pathEnd = path.substr( - path.substr(0, path.length-2).lastIndexOf('/') + 1 - ); + const { currentDomain, maxLength = 25 } = options; + const { path, domain, hash } = uriParser(uri); + // Split the path at the last / that has text after it + const pathEnd = path.substr( + path.substr(0, path.length-2).lastIndexOf('/') + 1 + ); - if (hash) { - if (pathEnd && (pathEnd + hash).length <= maxLength) { - return pathEnd + hash; - } else if (pathEnd.length < 2 && hash.length > 2 && hash.length <= maxLength) { - return hash; - } else { - return; - } - } else if (domain && domain.length < maxLength && path.length <= 1) {// '' or '/' - return domain + path; - } + if (hash) { + if (pathEnd && (pathEnd + hash).length <= maxLength) { + return pathEnd + hash; + } else if (pathEnd.length < 2 && hash.length > 2 && hash.length <= maxLength) { + return hash; + } else { + return; + } + } else if (domain && domain.length < maxLength && path.length <= 1) {// '' or '/' + return domain + path; + } - // See if the domain should be returned - if (path === '/' + pathEnd && - domain && currentDomain && - domain !== currentDomain && - (domain + path).length <= maxLength - ) { - return domain + path; - } - - const lastDotIndex = pathEnd.lastIndexOf('.'); - if (// Exclude very short or very long string - (lastDotIndex === -1 || lastDotIndex > 1) && - (lastDotIndex !== -1 || pathEnd.length > 2) && - pathEnd.length <= maxLength && - // Exclude index files - !pathEnd.match(/index(\.[a-zA-Z]{2-4})?/) && - // Exclude files that are likely to be database IDs - !isMostlyNumbers(pathEnd) - ) { - return pathEnd; - } + // See if the domain should be returned + if (path === '/' + pathEnd && + domain && currentDomain && + domain !== currentDomain && + (domain + path).length <= maxLength + ) { + return domain + path; + } + + const lastDotIndex = pathEnd.lastIndexOf('.'); + if (// Exclude very short or very long string + (lastDotIndex === -1 || lastDotIndex > 1) && + (lastDotIndex !== -1 || pathEnd.length > 2) && + pathEnd.length <= maxLength && + // Exclude index files + !pathEnd.match(/index(\.[a-zA-Z]{2-4})?/) && + // Exclude files that are likely to be database IDs + !isMostlyNumbers(pathEnd) + ) { + return pathEnd; + } }; diff --git a/lib/core/utils/get-selector.js b/lib/core/utils/get-selector.js index 32932c16b2..f3b3f6fe5b 100644 --- a/lib/core/utils/get-selector.js +++ b/lib/core/utils/get-selector.js @@ -1,234 +1,233 @@ const escapeSelector = axe.utils.escapeSelector; let isXHTML; const ignoredAttributes = [ - 'class', 'style', 'id', - 'selected', 'checked', - 'disabled', 'tabindex', - 'aria-checked', 'aria-selected', - 'aria-invalid', 'aria-activedescendant', - 'aria-busy', 'aria-disabled', 'aria-expanded', - 'aria-grabbed', 'aria-pressed', 'aria-valuenow' - ]; + 'class', 'style', 'id', + 'selected', 'checked', + 'disabled', 'tabindex', + 'aria-checked', 'aria-selected', + 'aria-invalid', 'aria-activedescendant', + 'aria-busy', 'aria-disabled', 'aria-expanded', + 'aria-grabbed', 'aria-pressed', 'aria-valuenow' +]; const MAXATTRIBUTELENGTH = 31; /** * get the attribute name and value as a string - * @param {Element} node The element that has the attribute - * @param {Attribute} at The attribute + * @param {Element} node The element that has the attribute + * @param {Attribute} at The attribute * @return {String} */ function getAttributeNameValue(node, at) { - const name = at.name; - let atnv; - - if (name.indexOf('href') !== -1 || name.indexOf('src') !== -1) { - let value = encodeURI(axe.utils.getFriendlyUriEnd(node.getAttribute(name))); - if (value) { - atnv = escapeSelector(at.name) + '$="' + value + '"'; - } else { - return; - } - } else { - atnv = escapeSelector(name) + '="' + escapeSelector(at.value) + '"'; - } - return atnv; + const name = at.name; + let atnv; + + if (name.indexOf('href') !== -1 || name.indexOf('src') !== -1) { + let value = encodeURI(axe.utils.getFriendlyUriEnd(node.getAttribute(name))); + if (value) { + atnv = escapeSelector(at.name) + '$="' + value + '"'; + } else { + return; + } + } else { + atnv = escapeSelector(name) + '="' + escapeSelector(at.value) + '"'; + } + return atnv; } function countSort(a, b) { - return (a.count < b.count) ? -1 : (a.count === b.count) ? 0 : 1; + return (a.count < b.count) ? -1 : (a.count === b.count) ? 0 : 1; } /** * Filter the attributes - * @param {Attribute} The potential attribute - * @return {Boolean} Whether to include or exclude + * @param {Attribute} The potential attribute + * @return {Boolean} Whether to include or exclude */ function filterAttributes(at) { - return !ignoredAttributes.includes(at.name) && at.name.indexOf(':') === -1 && - (!at.value || at.value.length < MAXATTRIBUTELENGTH); + return !ignoredAttributes.includes(at.name) && at.name.indexOf(':') === -1 && + (!at.value || at.value.length < MAXATTRIBUTELENGTH); } /** * Calculate the statistics for the classes, attributes and tags on the page, using * the virtual DOM tree - * @param {Object} domTree The root node of the virtual DOM tree - * @returns {Object} The statistics consisting of three maps, one for classes, - * one for tags and one for attributes. The map values are - * the counts for how many elements with that feature exist + * @param {Object} domTree The root node of the virtual DOM tree + * @returns {Object} The statistics consisting of three maps, one for classes, + * one for tags and one for attributes. The map values are + * the counts for how many elements with that feature exist */ axe.utils.getSelectorData = function (domTree) { - // jshint maxstatements:22 - // jshint loopfunc:true + /* eslint max-statements:["error", 22], no-loop-func:0*/ + + // Initialize the return structure with the three maps + let data = { + classes: {}, + tags: {}, + attributes: {} + }; - // Initialize the return structure with the three maps - let data = { - classes: {}, - tags: {}, - attributes: {} - }; - - domTree = Array.isArray(domTree) ? domTree : [domTree]; - let currentLevel = domTree.slice(); - let stack = []; - while (currentLevel.length) { - let current = currentLevel.pop(); - let node = current.actualNode; + domTree = Array.isArray(domTree) ? domTree : [domTree]; + let currentLevel = domTree.slice(); + let stack = []; + while (currentLevel.length) { + let current = currentLevel.pop(); + let node = current.actualNode; - if (!!node.querySelectorAll) { // ignore #text nodes + if (!!node.querySelectorAll) { // ignore #text nodes - // count the tag - let tag = node.nodeName; - if (data.tags[tag]) { - data.tags[tag]++; - } else { - data.tags[tag] = 1; - } + // count the tag + let tag = node.nodeName; + if (data.tags[tag]) { + data.tags[tag]++; + } else { + data.tags[tag] = 1; + } - // count all the classes - if (node.classList) { - Array.from(node.classList).forEach((cl) => { - const ind = escapeSelector(cl); - if (data.classes[ind]) { - data.classes[ind]++; - } else { - data.classes[ind] = 1; - } - }); - } + // count all the classes + if (node.classList) { + Array.from(node.classList).forEach((cl) => { + const ind = escapeSelector(cl); + if (data.classes[ind]) { + data.classes[ind]++; + } else { + data.classes[ind] = 1; + } + }); + } - // count all the filtered attributes - if (node.attributes) { - Array.from(node.attributes).filter(filterAttributes).forEach((at) => { - let atnv = getAttributeNameValue(node, at); - if (atnv) { - if (data.attributes[atnv]) { - data.attributes[atnv]++; - } else { - data.attributes[atnv] = 1; - } - } - }); - } - } - if (current.children.length) { - // "recurse" - stack.push(currentLevel); - currentLevel = current.children.slice(); - } - while (!currentLevel.length && stack.length) { - currentLevel = stack.pop(); - } - } - return data; + // count all the filtered attributes + if (node.attributes) { + Array.from(node.attributes).filter(filterAttributes).forEach((at) => { + let atnv = getAttributeNameValue(node, at); + if (atnv) { + if (data.attributes[atnv]) { + data.attributes[atnv]++; + } else { + data.attributes[atnv] = 1; + } + } + }); + } + } + if (current.children.length) { + // "recurse" + stack.push(currentLevel); + currentLevel = current.children.slice(); + } + while (!currentLevel.length && stack.length) { + currentLevel = stack.pop(); + } + } + return data; }; /** * Given a node and the statistics on class frequency on the page, * return all its uncommon class data sorted in order of decreasing uniqueness - * @param {Element} node The node - * @param {Object} classData The map of classes to counts - * @return {Array} The sorted array of uncommon class data + * @param {Element} node The node + * @param {Object} classData The map of classes to counts + * @return {Array} The sorted array of uncommon class data */ function uncommonClasses(node, selectorData) { - // jshint loopfunc:true - let retVal = []; - let classData = selectorData.classes; - let tagData = selectorData.tags; + // eslint no-loop-func:false + let retVal = []; + let classData = selectorData.classes; + let tagData = selectorData.tags; - if (node.classList) { - Array.from(node.classList).forEach((cl) => { - let ind = escapeSelector(cl); - if (classData[ind] < tagData[node.nodeName]) { - retVal.push({ - name: ind, - count: classData[ind], - species: 'class' - }); - } - }); - } - return retVal.sort(countSort); + if (node.classList) { + Array.from(node.classList).forEach((cl) => { + let ind = escapeSelector(cl); + if (classData[ind] < tagData[node.nodeName]) { + retVal.push({ + name: ind, + count: classData[ind], + species: 'class' + }); + } + }); + } + return retVal.sort(countSort); } /** * Given an element and a selector that finds that element (but possibly other sibling elements) * return the :nth-child(n) pseudo selector that uniquely finds the node within its siblings - * @param {Element} elm The Element - * @param {String} selector The selector - * @return {String} The nth-child selector + * @param {Element} elm The Element + * @param {String} selector The selector + * @return {String} The nth-child selector */ function getNthChildString (elm, selector) { - const siblings = elm.parentNode && Array.from(elm.parentNode.children || '') || []; - const hasMatchingSiblings = siblings.find(sibling => ( - sibling !== elm && - axe.utils.matchesSelector(sibling, selector) - )); - if (hasMatchingSiblings) { - const nthChild = 1 + siblings.indexOf(elm); - return ':nth-child(' + nthChild + ')'; - } else { - return ''; - } + const siblings = elm.parentNode && Array.from(elm.parentNode.children || '') || []; + const hasMatchingSiblings = siblings.find(sibling => ( + sibling !== elm && + axe.utils.matchesSelector(sibling, selector) + )); + if (hasMatchingSiblings) { + const nthChild = 1 + siblings.indexOf(elm); + return ':nth-child(' + nthChild + ')'; + } else { + return ''; + } } /** * Get ID selector */ function getElmId (elm) { - if (!elm.getAttribute('id')) { - return; - } - let doc = (elm.getRootNode && elm.getRootNode()) || document; - const id = '#' + escapeSelector(elm.getAttribute('id') || ''); - if ( - // Don't include youtube's uid values, they change on reload - !id.match(/player_uid_/) && - // Don't include IDs that occur more then once on the page - doc.querySelectorAll(id).length === 1 - ) { - return id; - } + if (!elm.getAttribute('id')) { + return; + } + let doc = (elm.getRootNode && elm.getRootNode()) || document; + const id = '#' + escapeSelector(elm.getAttribute('id') || ''); + if ( + // Don't include youtube's uid values, they change on reload + !id.match(/player_uid_/) && + // Don't include IDs that occur more then once on the page + doc.querySelectorAll(id).length === 1 + ) { + return id; + } } /** * Return the base CSS selector for a given element * - * @param {HTMLElement} elm The element to get the selector for - * @return {String | Array[String]} Base CSS selector for the node + * @param {HTMLElement} elm The element to get the selector for + * @return {String | Array[String]} Base CSS selector for the node */ function getBaseSelector(elm) { - if (typeof isXHTML === 'undefined') { - isXHTML = axe.utils.isXHTML(document); - } - return escapeSelector(isXHTML ? elm.localName : elm.nodeName.toLowerCase()); + if (typeof isXHTML === 'undefined') { + isXHTML = axe.utils.isXHTML(document); + } + return escapeSelector(isXHTML ? elm.localName : elm.nodeName.toLowerCase()); } /** * Given a node and the statistics on attribute frequency on the page, * return all its uncommon attribute data sorted in order of decreasing uniqueness - * @param {Element} node The node - * @param {Object} attData The map of attributes to counts - * @return {Array} The sorted array of uncommon attribute data + * @param {Element} node The node + * @param {Object} attData The map of attributes to counts + * @return {Array} The sorted array of uncommon attribute data */ function uncommonAttributes(node, selectorData) { - let retVal = []; - let attData = selectorData.attributes; - let tagData = selectorData.tags; - - if (node.attributes) { - Array.from(node.attributes).filter(filterAttributes).forEach((at) => { - const atnv = getAttributeNameValue(node, at); - - if (atnv && attData[atnv] < tagData[node.nodeName]) { - retVal.push({ - name: atnv, - count: attData[atnv], - species: 'attribute' - }); - } - }); - } - return retVal.sort(countSort); + let retVal = []; + let attData = selectorData.attributes; + let tagData = selectorData.tags; + + if (node.attributes) { + Array.from(node.attributes).filter(filterAttributes).forEach((at) => { + const atnv = getAttributeNameValue(node, at); + + if (atnv && attData[atnv] < tagData[node.nodeName]) { + retVal.push({ + name: atnv, + count: attData[atnv], + species: 'attribute' + }); + } + }); + } + return retVal.sort(countSort); } /** @@ -239,136 +238,136 @@ function uncommonAttributes(node, selectorData) { * a selector made up of the three least common features statistically. A feature will * also only be used if it is less common than the tag of the element itself. * - * @param {Element} elm The element for which to generate a selector - * @param {Object} options Options for how to generate the selector - * @param {RootNode} doc The root node of the document or document fragment - * @returns {String} The selector + * @param {Element} elm The element for which to generate a selector + * @param {Object} options Options for how to generate the selector + * @param {RootNode} doc The root node of the document or document fragment + * @returns {String} The selector */ function getThreeLeastCommonFeatures(elm, selectorData) { - let selector = ''; - let features; - let clss = uncommonClasses(elm, selectorData); - let atts = uncommonAttributes(elm, selectorData); + let selector = ''; + let features; + let clss = uncommonClasses(elm, selectorData); + let atts = uncommonAttributes(elm, selectorData); - if (clss.length && clss[0].count === 1) { - // only use the unique class - features = [clss[0]]; - } else if (atts.length && atts[0].count === 1) { - // only use the unique attribute value - features = [atts[0]]; - // if no class, add the tag - selector = getBaseSelector(elm); - } else { - features = clss.concat(atts); - // sort by least common - features.sort(countSort); + if (clss.length && clss[0].count === 1) { + // only use the unique class + features = [clss[0]]; + } else if (atts.length && atts[0].count === 1) { + // only use the unique attribute value + features = [atts[0]]; + // if no class, add the tag + selector = getBaseSelector(elm); + } else { + features = clss.concat(atts); + // sort by least common + features.sort(countSort); - // select three least common features - features = features.slice(0, 3); + // select three least common features + features = features.slice(0, 3); - // if no class, add the tag - if (!features.some((feat) => { return feat.species === 'class'; })) { - // has no class - selector = getBaseSelector(elm); - } else { - // put the classes at the front of the selector - features.sort((a, b) => { - return (a.species !== b.species && a.species === 'class') ? -1 : (a.species === b.species) ? 0 : 1; - }); - } - } + // if no class, add the tag + if (!features.some((feat) => { return feat.species === 'class'; })) { + // has no class + selector = getBaseSelector(elm); + } else { + // put the classes at the front of the selector + features.sort((a, b) => { + return (a.species !== b.species && a.species === 'class') ? -1 : (a.species === b.species) ? 0 : 1; + }); + } + } - // construct the return value - return selector += features.reduce((val, feat) => { - switch(feat.species) { - case 'class': - return val + '.' + feat.name; - case 'attribute': - return val + '[' + feat.name + ']'; - } - return val; // should never happen - }, ''); + // construct the return value + return selector += features.reduce((val, feat) => { + /*eslint indent: 0*/ + switch(feat.species) { + case 'class': + return val + '.' + feat.name; + case 'attribute': + return val + '[' + feat.name + ']'; + } + return val; // should never happen + }, ''); } /** * generates a single selector for an element - * @param {Element} elm The element for which to generate a selector - * @param {Object} options Options for how to generate the selector - * @param {RootNode} doc The root node of the document or document fragment - * @returns {String} The selector + * @param {Element} elm The element for which to generate a selector + * @param {Object} options Options for how to generate the selector + * @param {RootNode} doc The root node of the document or document fragment + * @returns {String} The selector */ function generateSelector (elm, options, doc) { - //jshint maxstatements:21 - //jshint loopfunc:true - if (!axe._selectorData) { - axe._selectorData = axe.utils.getSelectorData(axe._tree); - } - const { - toRoot = false - } = options; - let selector; - let similar; + /*eslint max-statements:["error", 22], no-loop-func:0*/ + if (!axe._selectorData) { + axe._selectorData = axe.utils.getSelectorData(axe._tree); + } + const { + toRoot = false + } = options; + let selector; + let similar; - /** - * Try to find a unique selector by filtering out all the clashing - * nodes by adding ancestor selectors iteratively. - * This loop is much faster than recursing and using querySelectorAll - */ - do { - let features = getElmId(elm); - if (!features) { - features = getThreeLeastCommonFeatures(elm, axe._selectorData); - features += getNthChildString(elm, features); - } - if (selector) { - selector = features + ' > ' + selector; - } else { - selector = features; - } - if (!similar) { - similar = Array.from(doc.querySelectorAll(selector)); - } else { - similar = similar.filter((item) => { - return axe.utils.matchesSelector(item, selector); - }); - } - elm = elm.parentElement; - } while ((similar.length > 1 || toRoot) && elm && elm.nodeType !== 11); + /** + * Try to find a unique selector by filtering out all the clashing + * nodes by adding ancestor selectors iteratively. + * This loop is much faster than recursing and using querySelectorAll + */ + do { + let features = getElmId(elm); + if (!features) { + features = getThreeLeastCommonFeatures(elm, axe._selectorData); + features += getNthChildString(elm, features); + } + if (selector) { + selector = features + ' > ' + selector; + } else { + selector = features; + } + if (!similar) { + similar = Array.from(doc.querySelectorAll(selector)); + } else { + similar = similar.filter((item) => { + return axe.utils.matchesSelector(item, selector); + }); + } + elm = elm.parentElement; + } while ((similar.length > 1 || toRoot) && elm && elm.nodeType !== 11); - if (similar.length === 1) { - return selector; - } else if (selector.indexOf(' > ') !== -1) { - // For the odd case that document doesn't have a unique selector - return ':root' + selector.substring(selector.indexOf(' > ')); - } - return ':root'; + if (similar.length === 1) { + return selector; + } else if (selector.indexOf(' > ') !== -1) { + // For the odd case that document doesn't have a unique selector + return ':root' + selector.substring(selector.indexOf(' > ')); + } + return ':root'; } /** * Gets a unique CSS selector - * @param {HTMLElement} node The element to get the selector for + * @param {HTMLElement} node The element to get the selector for * @param {Object} optional options - * @return {String | Array[String]} Unique CSS selector for the node + * @return {String | Array[String]} Unique CSS selector for the node */ axe.utils.getSelector = function createUniqueSelector (elm, options = {}) { - if (!elm) { - return ''; - } - let doc = (elm.getRootNode && elm.getRootNode()) || document; - if (doc.nodeType === 11) { // DOCUMENT_FRAGMENT - let stack = []; - while (doc.nodeType === 11) { - stack.push({elm: elm, doc: doc}); - elm = doc.host; - doc = elm.getRootNode(); - } - stack.push({elm: elm, doc: doc}); - return stack.reverse().map((comp) => { - return generateSelector(comp.elm, options, comp.doc); - }); - } else { - return generateSelector(elm, options, doc); - } + if (!elm) { + return ''; + } + let doc = (elm.getRootNode && elm.getRootNode()) || document; + if (doc.nodeType === 11) { // DOCUMENT_FRAGMENT + let stack = []; + while (doc.nodeType === 11) { + stack.push({elm: elm, doc: doc}); + elm = doc.host; + doc = elm.getRootNode(); + } + stack.push({elm: elm, doc: doc}); + return stack.reverse().map((comp) => { + return generateSelector(comp.elm, options, comp.doc); + }); + } else { + return generateSelector(elm, options, doc); + } }; diff --git a/lib/core/utils/get-xpath.js b/lib/core/utils/get-xpath.js index 8ae0f59c28..a04ad0b5e3 100644 --- a/lib/core/utils/get-xpath.js +++ b/lib/core/utils/get-xpath.js @@ -1,6 +1,6 @@ /*global axe */ -//jshint maxstatements: false, maxcomplexity: false +/*eslint max-statements: ["error", 36], complexity: ["error", 22]*/ function getXPathArray(node, path) { var sibling, count; // Gets an XPath for an element which describes its hierarchical location. diff --git a/lib/core/utils/index.js b/lib/core/utils/index.js index aee1e38fe6..7be5d80d90 100644 --- a/lib/core/utils/index.js +++ b/lib/core/utils/index.js @@ -1,3 +1,4 @@ +/*eslint no-unused-vars: 0*/ /* exported utils */ /** diff --git a/lib/core/utils/is-shadow-root.js b/lib/core/utils/is-shadow-root.js index 7699147fda..d578cd6a8f 100644 --- a/lib/core/utils/is-shadow-root.js +++ b/lib/core/utils/is-shadow-root.js @@ -1,8 +1,8 @@ /* global axe */ -const possibleShadowRoots = ['article', 'aside', 'blockquote', - 'body', 'div', 'footer', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', - 'header', 'main', 'nav', 'p', 'section', 'span']; +const possibleShadowRoots = ['article', 'aside', 'blockquote', + 'body', 'div', 'footer', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', + 'header', 'main', 'nav', 'p', 'section', 'span']; /** * Test a node to see if it has a spec-conforming shadow root * diff --git a/lib/core/utils/merge-results.js b/lib/core/utils/merge-results.js index dfb3fe13a0..1374b56891 100644 --- a/lib/core/utils/merge-results.js +++ b/lib/core/utils/merge-results.js @@ -2,106 +2,106 @@ /** * Adds the owning frame's CSS selector onto each instance of DqElement * @private -* @param {Array} resultSet `nodes` array on a `RuleResult` -* @param {HTMLElement} frameElement The frame element -* @param {String} frameSelector Unique CSS selector for the frame +* @param {Array} resultSet `nodes` array on a `RuleResult` +* @param {HTMLElement} frameElement The frame element +* @param {String} frameSelector Unique CSS selector for the frame */ function pushFrame(resultSet, options, frameElement, frameSelector) { - 'use strict'; - var frameXpath = axe.utils.getXpath(frameElement); - var frameSpec = { - element: frameElement, - selector: frameSelector, - xpath: frameXpath - }; + 'use strict'; + var frameXpath = axe.utils.getXpath(frameElement); + var frameSpec = { + element: frameElement, + selector: frameSelector, + xpath: frameXpath + }; - resultSet.forEach(function (res) { - res.node = axe.utils.DqElement.fromFrame(res.node, options, frameSpec); + resultSet.forEach(function (res) { + res.node = axe.utils.DqElement.fromFrame(res.node, options, frameSpec); - var checks = axe.utils.getAllChecks(res); - if (checks.length) { - checks.forEach(function (check) { - check.relatedNodes = check.relatedNodes.map( - (node) => axe.utils.DqElement.fromFrame(node, options, frameSpec) - ); - }); - } - }); + var checks = axe.utils.getAllChecks(res); + if (checks.length) { + checks.forEach(function (check) { + check.relatedNodes = check.relatedNodes.map( + (node) => axe.utils.DqElement.fromFrame(node, options, frameSpec) + ); + }); + } + }); } /** * Adds `to` to `from` and then re-sorts by DOM order * @private -* @param {Array} target `nodes` array on a `RuleResult` -* @param {Array} to `nodes` array on a `RuleResult` -* @return {Array} The merged and sorted result +* @param {Array} target `nodes` array on a `RuleResult` +* @param {Array} to `nodes` array on a `RuleResult` +* @return {Array} The merged and sorted result */ function spliceNodes(target, to) { - 'use strict'; + 'use strict'; - var firstFromFrame = to[0].node, - sorterResult, t; - for (var i = 0, l = target.length; i < l; i++) { - t = target[i].node; - sorterResult = axe.utils.nodeSorter({ actualNode: t.element }, - { actualNode: firstFromFrame.element }); - if (sorterResult > 0 || (sorterResult === 0 && firstFromFrame.selector.length < t.selector.length)) { - target.splice.apply(target, [i, 0].concat(to)); - return; - } - } + var firstFromFrame = to[0].node, + sorterResult, t; + for (var i = 0, l = target.length; i < l; i++) { + t = target[i].node; + sorterResult = axe.utils.nodeSorter({ actualNode: t.element }, + { actualNode: firstFromFrame.element }); + if (sorterResult > 0 || (sorterResult === 0 && firstFromFrame.selector.length < t.selector.length)) { + target.splice.apply(target, [i, 0].concat(to)); + return; + } + } - target.push.apply(target, to); + target.push.apply(target, to); } function normalizeResult(result) { - 'use strict'; + 'use strict'; - if (!result || !result.results) { - return null; - } + if (!result || !result.results) { + return null; + } - if (!Array.isArray(result.results)) { - return [result.results]; - } + if (!Array.isArray(result.results)) { + return [result.results]; + } - if (!result.results.length) { - return null; - } + if (!result.results.length) { + return null; + } - return result.results; + return result.results; } /** * Merges one or more RuleResults (possibly from different frames) into one RuleResult * @private -* @param {Array} frameResults Array of objects including the RuleResults as `results` and frame as `frame` -* @return {Array} The merged RuleResults; should only have one result per rule +* @param {Array} frameResults Array of objects including the RuleResults as `results` and frame as `frame` +* @return {Array} The merged RuleResults; should only have one result per rule */ axe.utils.mergeResults = function mergeResults(frameResults, options) { - 'use strict'; - var result = []; - frameResults.forEach(function (frameResult) { - var results = normalizeResult(frameResult); - if (!results || !results.length) { - return; - } + 'use strict'; + var result = []; + frameResults.forEach(function (frameResult) { + var results = normalizeResult(frameResult); + if (!results || !results.length) { + return; + } - results.forEach(function (ruleResult) { - if (ruleResult.nodes && frameResult.frame) { - pushFrame(ruleResult.nodes, options, frameResult.frameElement, frameResult.frame); - } + results.forEach(function (ruleResult) { + if (ruleResult.nodes && frameResult.frame) { + pushFrame(ruleResult.nodes, options, frameResult.frameElement, frameResult.frame); + } - var res = axe.utils.findBy(result, 'id', ruleResult.id); - if (!res) { - result.push(ruleResult); - } else { - if (ruleResult.nodes.length) { - spliceNodes(res.nodes, ruleResult.nodes); - } - } - }); - }); - return result; + var res = axe.utils.findBy(result, 'id', ruleResult.id); + if (!res) { + result.push(ruleResult); + } else { + if (ruleResult.nodes.length) { + spliceNodes(res.nodes, ruleResult.nodes); + } + } + }); + }); + return result; }; diff --git a/lib/core/utils/node-sorter.js b/lib/core/utils/node-sorter.js index d4aa8972fe..2e60c26e44 100644 --- a/lib/core/utils/node-sorter.js +++ b/lib/core/utils/node-sorter.js @@ -6,7 +6,7 @@ * @return {Integer} @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Sort */ axe.utils.nodeSorter = function nodeSorter(a, b) { - /*jshint bitwise: false */ + /*eslint no-bitwise: 0 */ 'use strict'; @@ -20,4 +20,4 @@ axe.utils.nodeSorter = function nodeSorter(a, b) { return 1; // b before a -}; \ No newline at end of file +}; diff --git a/lib/core/utils/pollyfills.js b/lib/core/utils/pollyfills.js index 4fb10147f3..18e2b3c53f 100644 --- a/lib/core/utils/pollyfills.js +++ b/lib/core/utils/pollyfills.js @@ -1,272 +1,272 @@ -// jshint ignore: start +/* eslint-disable */ /* These pollyfills came directly from the ES Specification it's self Contained within: - - Object.assign - - Array.prototype.find + - Object.assign + - Array.prototype.find */ if (typeof Object.assign !== 'function') { - (function () { - Object.assign = function (target) { - 'use strict'; - if (target === undefined || target === null) { - throw new TypeError('Cannot convert undefined or null to object'); - } - - var output = Object(target); - for (var index = 1; index < arguments.length; index++) { - var source = arguments[index]; - if (source !== undefined && source !== null) { - for (var nextKey in source) { - if (source.hasOwnProperty(nextKey)) { - output[nextKey] = source[nextKey]; - } - } - } - } - return output; - }; - })(); + (function () { + Object.assign = function (target) { + 'use strict'; + if (target === undefined || target === null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + + var output = Object(target); + for (var index = 1; index < arguments.length; index++) { + var source = arguments[index]; + if (source !== undefined && source !== null) { + for (var nextKey in source) { + if (source.hasOwnProperty(nextKey)) { + output[nextKey] = source[nextKey]; + } + } + } + } + return output; + }; + })(); } if (!Array.prototype.find) { - Object.defineProperty(Array.prototype, "find", { - value: function (predicate) { - if (this === null) { - throw new TypeError('Array.prototype.find called on null or undefined'); - } - if (typeof predicate !== 'function') { - throw new TypeError('predicate must be a function'); - } - var list = Object(this); - var length = list.length >>> 0; - var thisArg = arguments[1]; - var value; - - for (var i = 0; i < length; i++) { - value = list[i]; - if (predicate.call(thisArg, value, i, list)) { - return value; - } - } - return undefined; - } - }); + Object.defineProperty(Array.prototype, "find", { + value: function (predicate) { + if (this === null) { + throw new TypeError('Array.prototype.find called on null or undefined'); + } + if (typeof predicate !== 'function') { + throw new TypeError('predicate must be a function'); + } + var list = Object(this); + var length = list.length >>> 0; + var thisArg = arguments[1]; + var value; + + for (var i = 0; i < length; i++) { + value = list[i]; + if (predicate.call(thisArg, value, i, list)) { + return value; + } + } + return undefined; + } + }); } axe.utils.pollyfillElementsFromPoint = function () { - if (document.elementsFromPoint) return document.elementsFromPoint; - if (document.msElementsFromPoint) return document.msElementsFromPoint; - - var usePointer = (function () { - var element = document.createElement('x'); - element.style.cssText = 'pointer-events:auto'; - return element.style.pointerEvents === 'auto'; - }()); - - var cssProp = usePointer ? 'pointer-events' : 'visibility'; - var cssDisableVal = usePointer ? 'none' : 'hidden'; - - var style = document.createElement('style'); - style.innerHTML = usePointer ? - '* { pointer-events: all }' : '* { visibility: visible }'; - - return function (x, y) { - var current, i, d; - var elements = []; - var previousPointerEvents = []; - - // startup - document.head.appendChild(style); - - while ((current = document.elementFromPoint(x, y)) && elements.indexOf(current) === -1) { - // push the element and its current style - elements.push(current); - - previousPointerEvents.push({ - value: current.style.getPropertyValue(cssProp), - priority: current.style.getPropertyPriority(cssProp) - }); - - // add "pointer-events: none", to get to the underlying element - current.style.setProperty(cssProp, cssDisableVal, 'important'); - } - - // Due to negative index, documentElement could actually not be the last, - // so we'll simply move it to the end - if (elements.indexOf(document.documentElement) < elements.length - 1) { - elements.splice(elements.indexOf(document.documentElement), 1); - elements.push(document.documentElement); - } - - // restore the previous pointer-events values - for (i = previousPointerEvents.length; !!(d = previousPointerEvents[--i]);) { - elements[i].style.setProperty(cssProp, d.value ? d.value : '', d.priority); - } - - // teardown; - document.head.removeChild(style); - - return elements; - } + if (document.elementsFromPoint) return document.elementsFromPoint; + if (document.msElementsFromPoint) return document.msElementsFromPoint; + + var usePointer = (function () { + var element = document.createElement('x'); + element.style.cssText = 'pointer-events:auto'; + return element.style.pointerEvents === 'auto'; + }()); + + var cssProp = usePointer ? 'pointer-events' : 'visibility'; + var cssDisableVal = usePointer ? 'none' : 'hidden'; + + var style = document.createElement('style'); + style.innerHTML = usePointer ? + '* { pointer-events: all }' : '* { visibility: visible }'; + + return function (x, y) { + var current, i, d; + var elements = []; + var previousPointerEvents = []; + + // startup + document.head.appendChild(style); + + while ((current = document.elementFromPoint(x, y)) && elements.indexOf(current) === -1) { + // push the element and its current style + elements.push(current); + + previousPointerEvents.push({ + value: current.style.getPropertyValue(cssProp), + priority: current.style.getPropertyPriority(cssProp) + }); + + // add "pointer-events: none", to get to the underlying element + current.style.setProperty(cssProp, cssDisableVal, 'important'); + } + + // Due to negative index, documentElement could actually not be the last, + // so we'll simply move it to the end + if (elements.indexOf(document.documentElement) < elements.length - 1) { + elements.splice(elements.indexOf(document.documentElement), 1); + elements.push(document.documentElement); + } + + // restore the previous pointer-events values + for (i = previousPointerEvents.length; !!(d = previousPointerEvents[--i]);) { + elements[i].style.setProperty(cssProp, d.value ? d.value : '', d.priority); + } + + // teardown; + document.head.removeChild(style); + + return elements; + } }; if (typeof window.addEventListener === 'function') { - document.elementsFromPoint = axe.utils.pollyfillElementsFromPoint(); + document.elementsFromPoint = axe.utils.pollyfillElementsFromPoint(); } if (!Array.prototype.includes) { - Object.defineProperty(Array.prototype, "includes", { - value: function (searchElement) { - 'use strict'; - var O = Object(this); - var len = parseInt(O.length, 10) || 0; - if (len === 0) { - return false; - } - var n = parseInt(arguments[1], 10) || 0; - var k; - if (n >= 0) { - k = n; - } else { - k = len + n; - if (k < 0) { k = 0; } - } - var currentElement; - while (k < len) { - currentElement = O[k]; - if (searchElement === currentElement || - (searchElement !== searchElement && currentElement !== currentElement)) { // NaN !== NaN - return true; - } - k++; - } - return false; - } - }); + Object.defineProperty(Array.prototype, "includes", { + value: function (searchElement) { + 'use strict'; + var O = Object(this); + var len = parseInt(O.length, 10) || 0; + if (len === 0) { + return false; + } + var n = parseInt(arguments[1], 10) || 0; + var k; + if (n >= 0) { + k = n; + } else { + k = len + n; + if (k < 0) { k = 0; } + } + var currentElement; + while (k < len) { + currentElement = O[k]; + if (searchElement === currentElement || + (searchElement !== searchElement && currentElement !== currentElement)) { // NaN !== NaN + return true; + } + k++; + } + return false; + } + }); } // Production steps of ECMA-262, Edition 5, 15.4.4.17 // Reference: http://es5.github.io/#x15.4.4.17 if (!Array.prototype.some) { - Object.defineProperty(Array.prototype, "some", { - value: function (fun) { - 'use strict'; - - if (this == null) { - throw new TypeError('Array.prototype.some called on null or undefined'); - } - - if (typeof fun !== 'function') { - throw new TypeError(); - } - - var t = Object(this); - var len = t.length >>> 0; - - var thisArg = arguments.length >= 2 ? arguments[1] : void 0; - for (var i = 0; i < len; i++) { - if (i in t && fun.call(thisArg, t[i], i, t)) { - return true; - } - } - - return false; - } - }); + Object.defineProperty(Array.prototype, "some", { + value: function (fun) { + 'use strict'; + + if (this == null) { + throw new TypeError('Array.prototype.some called on null or undefined'); + } + + if (typeof fun !== 'function') { + throw new TypeError(); + } + + var t = Object(this); + var len = t.length >>> 0; + + var thisArg = arguments.length >= 2 ? arguments[1] : void 0; + for (var i = 0; i < len; i++) { + if (i in t && fun.call(thisArg, t[i], i, t)) { + return true; + } + } + + return false; + } + }); } if (!Array.from) { - Object.defineProperty(Array, "from", { - value: function () { - var toStr = Object.prototype.toString; - var isCallable = function (fn) { - return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; - }; - var toInteger = function (value) { - var number = Number(value); - if (isNaN(number)) { return 0; } - if (number === 0 || !isFinite(number)) { return number; } - return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); - }; - var maxSafeInteger = Math.pow(2, 53) - 1; - var toLength = function (value) { - var len = toInteger(value); - return Math.min(Math.max(len, 0), maxSafeInteger); - }; - - // The length property of the from method is 1. - return function from(arrayLike/*, mapFn, thisArg */) { - // 1. Let C be the this value. - var C = this; - - // 2. Let items be ToObject(arrayLike). - var items = Object(arrayLike); - - // 3. ReturnIfAbrupt(items). - if (arrayLike == null) { - throw new TypeError("Array.from requires an array-like object - not null or undefined"); - } - - // 4. If mapfn is undefined, then let mapping be false. - var mapFn = arguments.length > 1 ? arguments[1] : void undefined; - var T; - if (typeof mapFn !== 'undefined') { - // 5. else - // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. - if (!isCallable(mapFn)) { - throw new TypeError('Array.from: when provided, the second argument must be a function'); - } - - // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. - if (arguments.length > 2) { - T = arguments[2]; - } - } - - // 10. Let lenValue be Get(items, "length"). - // 11. Let len be ToLength(lenValue). - var len = toLength(items.length); - - // 13. If IsConstructor(C) is true, then - // 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len. - // 14. a. Else, Let A be ArrayCreate(len). - var A = isCallable(C) ? Object(new C(len)) : new Array(len); - - // 16. Let k be 0. - var k = 0; - // 17. Repeat, while k < len… (also steps a - h) - var kValue; - while (k < len) { - kValue = items[k]; - if (mapFn) { - A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); - } else { - A[k] = kValue; - } - k += 1; - } - // 18. Let putStatus be Put(A, "length", len, true). - A.length = len; - // 20. Return A. - return A; - }; - }() - }); + Object.defineProperty(Array, "from", { + value: function () { + var toStr = Object.prototype.toString; + var isCallable = function (fn) { + return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; + }; + var toInteger = function (value) { + var number = Number(value); + if (isNaN(number)) { return 0; } + if (number === 0 || !isFinite(number)) { return number; } + return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); + }; + var maxSafeInteger = Math.pow(2, 53) - 1; + var toLength = function (value) { + var len = toInteger(value); + return Math.min(Math.max(len, 0), maxSafeInteger); + }; + + // The length property of the from method is 1. + return function from(arrayLike/*, mapFn, thisArg */) { + // 1. Let C be the this value. + var C = this; + + // 2. Let items be ToObject(arrayLike). + var items = Object(arrayLike); + + // 3. ReturnIfAbrupt(items). + if (arrayLike == null) { + throw new TypeError("Array.from requires an array-like object - not null or undefined"); + } + + // 4. If mapfn is undefined, then let mapping be false. + var mapFn = arguments.length > 1 ? arguments[1] : void undefined; + var T; + if (typeof mapFn !== 'undefined') { + // 5. else + // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. + if (!isCallable(mapFn)) { + throw new TypeError('Array.from: when provided, the second argument must be a function'); + } + + // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. + if (arguments.length > 2) { + T = arguments[2]; + } + } + + // 10. Let lenValue be Get(items, "length"). + // 11. Let len be ToLength(lenValue). + var len = toLength(items.length); + + // 13. If IsConstructor(C) is true, then + // 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len. + // 14. a. Else, Let A be ArrayCreate(len). + var A = isCallable(C) ? Object(new C(len)) : new Array(len); + + // 16. Let k be 0. + var k = 0; + // 17. Repeat, while k < len… (also steps a - h) + var kValue; + while (k < len) { + kValue = items[k]; + if (mapFn) { + A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); + } else { + A[k] = kValue; + } + k += 1; + } + // 18. Let putStatus be Put(A, "length", len, true). + A.length = len; + // 20. Return A. + return A; + }; + }() + }); } if (!String.prototype.includes) { - String.prototype.includes = function(search, start) { - if (typeof start !== 'number') { - start = 0; - } - if (start + search.length > this.length) { - return false; - } else { - return this.indexOf(search, start) !== -1; - } - }; + String.prototype.includes = function(search, start) { + if (typeof start !== 'number') { + start = 0; + } + if (start + search.length > this.length) { + return false; + } else { + return this.indexOf(search, start) !== -1; + } + }; } diff --git a/lib/core/utils/qsa.js b/lib/core/utils/qsa.js index e2c9cfa05f..0cee8955f6 100644 --- a/lib/core/utils/qsa.js +++ b/lib/core/utils/qsa.js @@ -50,12 +50,13 @@ var escapeRegExp = (function(){ var reUnescape = /\\/g; function convertAttributes (atts) { + /*eslint indent:0*/ /*! Credit Mootools Copyright Mootools, MIT License */ if (!atts) { return; } return atts.map((att) => { - // jshint maxcomplexity:12 + // eslint complexity:["error", 13] var attributeKey = att.name.replace(reUnescape, ''); var attributeValue = (att.value || '').replace(reUnescape, ''); var test, regexp; @@ -73,7 +74,7 @@ function convertAttributes (atts) { case '|=' : regexp = new RegExp('^'+ escapeRegExp(attributeValue) +'(-|$)'); break; - case '=' : + case '=' : test = function(value){ return attributeValue === value; }; @@ -88,7 +89,7 @@ function convertAttributes (atts) { return attributeValue !== value; }; break; - default : + default : test = function(value){ return !!value; }; @@ -193,9 +194,8 @@ function matchesSelector (node, exp) { ); } -matchExpressions = function (domTree, expressions, recurse, filter) { - //jshint maxstatements:34 - //jshint maxcomplexity:15 +matchExpressions = function (domTree, expressions, recurse, filter) { + /*eslint max-statements:["error", 34], complexity:["error", 22]*/ let stack = []; let nodes = Array.isArray(domTree) ? domTree : [domTree]; let currentLevel = createLocalVariables(nodes, expressions, [], domTree[0].shadowId); @@ -220,7 +220,10 @@ matchExpressions = function (domTree, expressions, recurse, filter) { } else { let rest = exp.slice(1); if ([' ', '>'].includes(rest[0].combinator) === false) { - throw new Error('axe.utils.querySelectorAll does not support the combinator: ' + exp[1].combinator); + throw new Error( + 'axe.utils.querySelectorAll does not support the combinator: ' + + exp[1].combinator + ); } if (rest[0].combinator === '>') { // add the rest to the childOnly array @@ -254,8 +257,8 @@ matchExpressions = function (domTree, expressions, recurse, filter) { * @method querySelectorAll * @memberof axe.utils * @instance - * @param {NodeList} domTree flattened tree collection to search - * @param {String} selector String containing one or more CSS selectors separated by commas + * @param {NodeList} domTree flattened tree collection to search + * @param {String} selector String containing one or more CSS selectors separated by commas * @return {NodeList} Elements matched by any of the selectors */ axe.utils.querySelectorAll = function (domTree, selector) { @@ -269,9 +272,9 @@ axe.utils.querySelectorAll = function (domTree, selector) { * @method querySelectorAllFilter * @memberof axe.utils * @instance - * @param {NodeList} domTree flattened tree collection to search - * @param {String} selector String containing one or more CSS selectors separated by commas - * @param {Function} filter function (optional) + * @param {NodeList} domTree flattened tree collection to search + * @param {String} selector String containing one or more CSS selectors separated by commas + * @param {Function} filter function (optional) * @return {Array} Elements matched by any of the selectors and filtered by the filter function */ diff --git a/lib/core/utils/respondable.js b/lib/core/utils/respondable.js index 73c5ce93fa..ae00ddd8e3 100644 --- a/lib/core/utils/respondable.js +++ b/lib/core/utils/respondable.js @@ -3,7 +3,7 @@ 'use strict'; var messages = {}, subscribers = {}, - errorTypes = Object.freeze(['EvalError', 'RangeError', 'ReferenceError', + errorTypes = Object.freeze(['EvalError', 'RangeError', 'ReferenceError', 'SyntaxError', 'TypeError', 'URIError']); /** @@ -171,6 +171,7 @@ * @return {object} Object to be used for pub/sub */ function parseMessage(dataString) { + /*eslint no-empty: 0*/ var data; if (typeof dataString !== 'string') { return; @@ -194,7 +195,7 @@ if ( typeof window.addEventListener === 'function') { window.addEventListener('message', function (e) { - // jshint maxstatements: 20 + /* eslint max-statements: ["error", 20]*/ var data = parseMessage(e.data); if (!data) { return; diff --git a/lib/core/utils/rule-should-run.js b/lib/core/utils/rule-should-run.js index de86379a46..e54f3ccec0 100644 --- a/lib/core/utils/rule-should-run.js +++ b/lib/core/utils/rule-should-run.js @@ -5,8 +5,8 @@ * @param {object} runOnly Value of runOnly with type=tags * @return {bool} */ +/* eslint complexity: ["error", 14]*/ function matchTags(rule, runOnly) { - // jshint maxcomplexity: 11 'use strict'; var include, exclude, matching; var defaultExclude = (axe._audit && axe._audit.tagExclude) ? axe._audit.tagExclude : []; @@ -79,4 +79,4 @@ axe.utils.ruleShouldRun = function (rule, context, options) { return matchTags(rule, []); } -}; \ No newline at end of file +}; diff --git a/lib/core/utils/scroll-state.js b/lib/core/utils/scroll-state.js index 00df66fe6f..b6af71b0f1 100644 --- a/lib/core/utils/scroll-state.js +++ b/lib/core/utils/scroll-state.js @@ -2,68 +2,68 @@ * Return the scroll position of scrollable elements */ function getScroll (elm) { - const style = window.getComputedStyle(elm); - const visibleOverflowY = style.getPropertyValue('overflow-y') === 'visible'; - const visibleOverflowX = style.getPropertyValue('overflow-x') === 'visible'; + const style = window.getComputedStyle(elm); + const visibleOverflowY = style.getPropertyValue('overflow-y') === 'visible'; + const visibleOverflowX = style.getPropertyValue('overflow-x') === 'visible'; - if (// See if the element hides overflowing content - (!visibleOverflowY && elm.scrollHeight > elm.clientHeight) || - (!visibleOverflowX && elm.scrollWidth > elm.clientWidth) - ) { - return { elm, top: elm.scrollTop, left: elm.scrollLeft }; - } + if (// See if the element hides overflowing content + (!visibleOverflowY && elm.scrollHeight > elm.clientHeight) || + (!visibleOverflowX && elm.scrollWidth > elm.clientWidth) + ) { + return { elm, top: elm.scrollTop, left: elm.scrollLeft }; + } } /** * set the scroll position of an element */ function setScroll (elm, top, left) { - if (elm === window) { - return elm.scroll(top, left); - } else { - elm.scrollTop = top; - elm.scrollLeft = left; - } + if (elm === window) { + return elm.scroll(top, left); + } else { + elm.scrollTop = top; + elm.scrollLeft = left; + } } /** * Create an array scroll positions from descending elements */ function getElmScrollRecursive (root) { - return Array.from(root.children).reduce((scrolls, elm) => { - const scroll = getScroll(elm); - if (scroll) { - scrolls.push(scroll); - } - return scrolls.concat(getElmScrollRecursive(elm)); - }, []); + return Array.from(root.children).reduce((scrolls, elm) => { + const scroll = getScroll(elm); + if (scroll) { + scrolls.push(scroll); + } + return scrolls.concat(getElmScrollRecursive(elm)); + }, []); } /** * Get the scroll position of all scrollable elements in a page */ axe.utils.getScrollState = function getScrollState (win = window) { - const root = win.document.documentElement; - const windowScroll = [(win.pageXOffset !== undefined ? { - elm: win, - top: win.pageYOffset, - left: win.pageXOffset - } : { - elm: root, - top: root.scrollTop, - left: root.scrollLeft - })]; + const root = win.document.documentElement; + const windowScroll = [(win.pageXOffset !== undefined ? { + elm: win, + top: win.pageYOffset, + left: win.pageXOffset + } : { + elm: root, + top: root.scrollTop, + left: root.scrollLeft + })]; - return windowScroll.concat( - getElmScrollRecursive(document.body) - ); + return windowScroll.concat( + getElmScrollRecursive(document.body) + ); }; /** * set the scroll position of all items in the scrollState array */ axe.utils.setScrollState = function setScrollState (scrollState) { - scrollState.forEach( - ({ elm, top, left }) => setScroll(elm, top, left) - ); + scrollState.forEach( + ({ elm, top, left }) => setScroll(elm, top, left) + ); }; diff --git a/lib/core/utils/select.js b/lib/core/utils/select.js index a8e7aa192c..3f8315a8a1 100644 --- a/lib/core/utils/select.js +++ b/lib/core/utils/select.js @@ -87,8 +87,8 @@ function reduceIncludes(includes) { * @param {Context} context The "resolved" context object, @see Context * @return {Array} Matching virtual DOM nodes sorted by DOM order */ +/*eslint max-statements:["error", 20]*/ axe.utils.select = function select(selector, context) { - //jshint maxstatements:20 'use strict'; var result = [], candidate; @@ -99,7 +99,7 @@ axe.utils.select = function select(selector, context) { if (item.selector === selector) { return item.result; } - } + } } var curried = (function (context) { return function (node) { diff --git a/lib/core/utils/to-array.js b/lib/core/utils/to-array.js index 394972cd88..c6fbc4e3f3 100644 --- a/lib/core/utils/to-array.js +++ b/lib/core/utils/to-array.js @@ -1,7 +1,7 @@ /** * Converts array-like (numerical indicies and `length` property) structures to actual, real arrays - * @param {Mixed} thing Array-like thing to convert + * @param {Mixed} thing Array-like thing to convert * @return {Array} */ axe.utils.toArray = function (thing) { @@ -12,12 +12,12 @@ axe.utils.toArray = function (thing) { /** * Creates an array without duplicate values from 2 array inputs - * @param {Array} arr1 First array - * @param {Array} arr2 Second array + * @param {Array} arr1 First array + * @param {Array} arr2 Second array * @return {Array} */ axe.utils.uniqueArray = (arr1, arr2) => { - return arr1.concat(arr2).filter((elem, pos, arr) => { - return arr.indexOf(elem) === pos; - }); + return arr1.concat(arr2).filter((elem, pos, arr) => { + return arr.indexOf(elem) === pos; + }); }; diff --git a/lib/core/utils/uuid.js b/lib/core/utils/uuid.js index 6c278cc5c3..efa290e24a 100644 --- a/lib/core/utils/uuid.js +++ b/lib/core/utils/uuid.js @@ -1,221 +1,221 @@ -/*jshint bitwise: false, eqeqeq: false, curly: false, strict: false, eqnull: true, -maxstatements: false, maxcomplexity: false */ -// uuid.js +/*eslint no-bitwise: 0, eqeqeq: 0, curly: 0, strict: 0, no-eq-null: 0, +max-statements: 0, complexity: 0, no-shadow: 0, no-undef: 0 */ +// uuid.js // -// Copyright (c) 2010-2012 Robert Kieffer -// MIT License - http://opensource.org/licenses/mit-license.php +// Copyright (c) 2010-2012 Robert Kieffer +// MIT License - http://opensource.org/licenses/mit-license.php var uuid; (function(_global) { - // Unique ID creation requires a high quality random # generator. We feature - // detect to determine the best RNG source, normalizing to a function that - // returns 128-bits of randomness, since that's what's usually required - var _rng; - - // Allow for MSIE11 msCrypto - var _crypto = _global.crypto || _global.msCrypto; - - if (!_rng && _crypto && _crypto.getRandomValues) { - // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto - // - // Moderately fast, high quality - var _rnds8 = new Uint8Array(16); - _rng = function whatwgRNG() { - _crypto.getRandomValues(_rnds8); - return _rnds8; - }; - } - - if (!_rng) { - // Math.random()-based (RNG) - // - // If all else fails, use Math.random(). It's fast, but is of unspecified - // quality. - var _rnds = new Array(16); - _rng = function() { - for (var i = 0, r; i < 16; i++) { - if ((i & 0x03) === 0) r = Math.random() * 0x100000000; - _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; - } - - return _rnds; - }; - } - - // Buffer class to use - var BufferClass = typeof(_global.Buffer) == 'function' ? _global.Buffer : Array; - - // Maps for number <-> hex string conversion - var _byteToHex = []; - var _hexToByte = {}; - for (var i = 0; i < 256; i++) { - _byteToHex[i] = (i + 0x100).toString(16).substr(1); - _hexToByte[_byteToHex[i]] = i; - } - - // **`parse()` - Parse a UUID into it's component bytes** - function parse(s, buf, offset) { - var i = (buf && offset) || 0, ii = 0; - - buf = buf || []; - s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) { - if (ii < 16) { // Don't overflow! - buf[i + ii++] = _hexToByte[oct]; - } - }); - - // Zero out remaining bytes if string was short - while (ii < 16) { - buf[i + ii++] = 0; - } - - return buf; - } - - // **`unparse()` - Convert UUID byte array (ala parse()) into a string** - function unparse(buf, offset) { - var i = offset || 0, bth = _byteToHex; - return bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + '-' + - bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]] + - bth[buf[i++]] + bth[buf[i++]]; - } - - // **`v1()` - Generate time-based UUID** - // - // Inspired by https://github.com/LiosK/UUID.js - // and http://docs.python.org/library/uuid.html - - // random #'s we need to init node and clockseq - var _seedBytes = _rng(); - - // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) - var _nodeId = [ - _seedBytes[0] | 0x01, - _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5] - ]; - - // Per 4.2.2, randomize (14 bit) clockseq - var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; - - // Previous uuid creation time - var _lastMSecs = 0, _lastNSecs = 0; - - // See https://github.com/broofa/node-uuid for API details - function v1(options, buf, offset) { - var i = buf && offset || 0; - var b = buf || []; - - options = options || {}; - - var clockseq = options.clockseq != null ? options.clockseq : _clockseq; - - // UUID timestamps are 100 nano-second units since the Gregorian epoch, - // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so - // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' - // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. - var msecs = options.msecs != null ? options.msecs : new Date().getTime(); - - // Per 4.2.1.2, use count of uuid's generated during the current clock - // cycle to simulate higher resolution clock - var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1; - - // Time since last uuid creation (in msecs) - var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; - - // Per 4.2.1.2, Bump clockseq on clock regression - if (dt < 0 && options.clockseq == null) { - clockseq = clockseq + 1 & 0x3fff; - } - - // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new - // time interval - if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) { - nsecs = 0; - } - - // Per 4.2.1.2 Throw error if too many uuids are requested - if (nsecs >= 10000) { - throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); - } - - _lastMSecs = msecs; - _lastNSecs = nsecs; - _clockseq = clockseq; - - // Per 4.1.4 - Convert from unix epoch to Gregorian epoch - msecs += 12219292800000; - - // `time_low` - var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; - b[i++] = tl >>> 24 & 0xff; - b[i++] = tl >>> 16 & 0xff; - b[i++] = tl >>> 8 & 0xff; - b[i++] = tl & 0xff; - - // `time_mid` - var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; - b[i++] = tmh >>> 8 & 0xff; - b[i++] = tmh & 0xff; - - // `time_high_and_version` - b[i++] = tmh >>> 24 & 0xf | 0x10; // include version - b[i++] = tmh >>> 16 & 0xff; - - // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) - b[i++] = clockseq >>> 8 | 0x80; - - // `clock_seq_low` - b[i++] = clockseq & 0xff; - - // `node` - var node = options.node || _nodeId; - for (var n = 0; n < 6; n++) { - b[i + n] = node[n]; - } - - return buf ? buf : unparse(b); - } - - // **`v4()` - Generate random UUID** - - // See https://github.com/broofa/node-uuid for API details - function v4(options, buf, offset) { - // Deprecated - 'format' argument, as supported in v1.2 - var i = buf && offset || 0; - - if (typeof(options) == 'string') { - buf = options == 'binary' ? new BufferClass(16) : null; - options = null; - } - options = options || {}; - - var rnds = options.random || (options.rng || _rng)(); - - // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - rnds[6] = (rnds[6] & 0x0f) | 0x40; - rnds[8] = (rnds[8] & 0x3f) | 0x80; - - // Copy bytes to buffer, if provided - if (buf) { - for (var ii = 0; ii < 16; ii++) { - buf[i + ii] = rnds[ii]; - } - } - - return buf || unparse(rnds); - } - - // Export public API - uuid = v4; - uuid.v1 = v1; - uuid.v4 = v4; - uuid.parse = parse; - uuid.unparse = unparse; - uuid.BufferClass = BufferClass; + // Unique ID creation requires a high quality random # generator. We feature + // detect to determine the best RNG source, normalizing to a function that + // returns 128-bits of randomness, since that's what's usually required + var _rng; + + // Allow for MSIE11 msCrypto + var _crypto = _global.crypto || _global.msCrypto; + + if (!_rng && _crypto && _crypto.getRandomValues) { + // WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto + // + // Moderately fast, high quality + var _rnds8 = new Uint8Array(16); + _rng = function whatwgRNG() { + _crypto.getRandomValues(_rnds8); + return _rnds8; + }; + } + + if (!_rng) { + // Math.random()-based (RNG) + // + // If all else fails, use Math.random(). It's fast, but is of unspecified + // quality. + var _rnds = new Array(16); + _rng = function() { + for (var i = 0, r; i < 16; i++) { + if ((i & 0x03) === 0) r = Math.random() * 0x100000000; + _rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; + } + + return _rnds; + }; + } + + // Buffer class to use + var BufferClass = typeof(_global.Buffer) == 'function' ? _global.Buffer : Array; + + // Maps for number <-> hex string conversion + var _byteToHex = []; + var _hexToByte = {}; + for (var i = 0; i < 256; i++) { + _byteToHex[i] = (i + 0x100).toString(16).substr(1); + _hexToByte[_byteToHex[i]] = i; + } + + // **`parse()` - Parse a UUID into it's component bytes** + function parse(s, buf, offset) { + var i = (buf && offset) || 0, ii = 0; + + buf = buf || []; + s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) { + if (ii < 16) { // Don't overflow! + buf[i + ii++] = _hexToByte[oct]; + } + }); + + // Zero out remaining bytes if string was short + while (ii < 16) { + buf[i + ii++] = 0; + } + + return buf; + } + + // **`unparse()` - Convert UUID byte array (ala parse()) into a string** + function unparse(buf, offset) { + var i = offset || 0, bth = _byteToHex; + return bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + '-' + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]] + + bth[buf[i++]] + bth[buf[i++]]; + } + + // **`v1()` - Generate time-based UUID** + // + // Inspired by https://github.com/LiosK/UUID.js + // and http://docs.python.org/library/uuid.html + + // random #'s we need to init node and clockseq + var _seedBytes = _rng(); + + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + var _nodeId = [ + _seedBytes[0] | 0x01, + _seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5] + ]; + + // Per 4.2.2, randomize (14 bit) clockseq + var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; + + // Previous uuid creation time + var _lastMSecs = 0, _lastNSecs = 0; + + // See https://github.com/broofa/node-uuid for API details + function v1(options, buf, offset) { + var i = buf && offset || 0; + var b = buf || []; + + options = options || {}; + + var clockseq = options.clockseq != null ? options.clockseq : _clockseq; + + // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + var msecs = options.msecs != null ? options.msecs : new Date().getTime(); + + // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1; + + // Time since last uuid creation (in msecs) + var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; + + // Per 4.2.1.2, Bump clockseq on clock regression + if (dt < 0 && options.clockseq == null) { + clockseq = clockseq + 1 & 0x3fff; + } + + // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) { + nsecs = 0; + } + + // Per 4.2.1.2 Throw error if too many uuids are requested + if (nsecs >= 10000) { + throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; + + // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + msecs += 12219292800000; + + // `time_low` + var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; + + // `time_mid` + var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; + + // `time_high_and_version` + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + b[i++] = tmh >>> 16 & 0xff; + + // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + b[i++] = clockseq >>> 8 | 0x80; + + // `clock_seq_low` + b[i++] = clockseq & 0xff; + + // `node` + var node = options.node || _nodeId; + for (var n = 0; n < 6; n++) { + b[i + n] = node[n]; + } + + return buf ? buf : unparse(b); + } + + // **`v4()` - Generate random UUID** + + // See https://github.com/broofa/node-uuid for API details + function v4(options, buf, offset) { + // Deprecated - 'format' argument, as supported in v1.2 + var i = buf && offset || 0; + + if (typeof(options) == 'string') { + buf = options == 'binary' ? new BufferClass(16) : null; + options = null; + } + options = options || {}; + + var rnds = options.random || (options.rng || _rng)(); + + // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + rnds[6] = (rnds[6] & 0x0f) | 0x40; + rnds[8] = (rnds[8] & 0x3f) | 0x80; + + // Copy bytes to buffer, if provided + if (buf) { + for (var ii = 0; ii < 16; ii++) { + buf[i + ii] = rnds[ii]; + } + } + + return buf || unparse(rnds); + } + + // Export public API + uuid = v4; + uuid.v1 = v1; + uuid.v4 = v4; + uuid.parse = parse; + uuid.unparse = unparse; + uuid.BufferClass = BufferClass; }(window)); diff --git a/lib/rules/.eslintrc b/lib/rules/.eslintrc new file mode 100644 index 0000000000..6873155ff9 --- /dev/null +++ b/lib/rules/.eslintrc @@ -0,0 +1,80 @@ +{ + "env": { + "es6": true + }, + "globals": { + "results": true, + "node": true, + "virtualNode": true, + "options": true, + "axe": true + }, + "rules": { + "no-bitwise": 2, + "camelcase": 2, + "curly": 2, + "eqeqeq": 2, + "guard-for-in": 2, + "wrap-iife": [ + 2, + "any" + ], + "no-use-before-define": [ + 2, + { + "functions": false + } + ], + "new-cap": 2, + "no-caller": 2, + "no-empty": 2, + "no-new": 2, + "no-plusplus": 0, + "quotes": [ + 2, + "single" + ], + "no-undef": 2, + "no-unused-vars": 2, + "strict": 0, + "max-params": [ + 2, + 5 + ], + "max-depth": [ + 2, + 5 + ], + "max-statements": [ + 2, + 15 + ], + "complexity": [ + 2, + 10 + ], + "max-len": [ + 2, + { + "code": 120, + "ignoreComments": true + } + ], + "semi": 0, + "no-cond-assign": 0, + "no-debugger": 0, + "no-eq-null": 0, + "no-eval": 0, + "no-unused-expressions": 0, + "block-scoped-var": 0, + "no-iterator": 0, + "linebreak-style": 0, + "no-loop-func": 0, + "no-multi-str": 0, + "no-proto": 0, + "no-script-url": 0, + "dot-notation": 2, + "no-new-func": 0, + "no-new-wrappers": 0 + } +} diff --git a/lib/rules/heading-matches.js b/lib/rules/heading-matches.js index 0edcd1599b..85daed465c 100644 --- a/lib/rules/heading-matches.js +++ b/lib/rules/heading-matches.js @@ -1,13 +1,13 @@ // Get all valid roles let explicitRoles; if (node.hasAttribute('role')) { - explicitRoles = node.getAttribute('role').split(/\s+/i) - .filter(axe.commons.aria.isValidRole); + explicitRoles = node.getAttribute('role').split(/\s+/i) + .filter(axe.commons.aria.isValidRole); } // Check valid roles if there are any, otherwise fall back to the inherited role if (explicitRoles && explicitRoles.length > 0) { - return explicitRoles.includes('heading'); -} else { - return axe.commons.aria.implicitRole(node) === 'heading'; + return explicitRoles.includes('heading'); +} else { + return axe.commons.aria.implicitRole(node) === 'heading'; } diff --git a/lib/rules/p-as-heading-matches.js b/lib/rules/p-as-heading-matches.js index 8895bc2449..4edaac58a3 100644 --- a/lib/rules/p-as-heading-matches.js +++ b/lib/rules/p-as-heading-matches.js @@ -9,9 +9,9 @@ if (nodeText.length === 0 || (nodeText.match(isSentence) || []).length >= 2) { // Grab sibling p element following the current node const siblingsAfter = children.slice( children.indexOf(node) + 1) -.filter(elm => - elm.nodeName.toUpperCase() === 'P' && - elm.textContent.trim() !== '' -); + .filter(elm => + elm.nodeName.toUpperCase() === 'P' && + elm.textContent.trim() !== '' + ); -return siblingsAfter.length !== 0; \ No newline at end of file +return siblingsAfter.length !== 0; diff --git a/package.json b/package.json index 7818dbb7f2..99804828cd 100644 --- a/package.json +++ b/package.json @@ -75,9 +75,9 @@ "grunt-contrib-concat": "^1.0.1", "grunt-contrib-connect": "^1.0.2", "grunt-contrib-copy": "^1.0.0", - "grunt-contrib-jshint": "^1.1.0", "grunt-contrib-uglify": "^2.1.0", "grunt-contrib-watch": "^1.0.0", + "grunt-eslint": "^20.1.0", "grunt-mocha": "^1.0.4", "grunt-parallel": "^0.5.1", "grunt-retire": "^1.0.7", diff --git a/test/.eslintrc b/test/.eslintrc new file mode 100644 index 0000000000..164bc497e3 --- /dev/null +++ b/test/.eslintrc @@ -0,0 +1,81 @@ +{ + "env": { + "browser": true + }, + "globals": { + "describe": true, + "it": true, + "xit": true, + "before": true, + "beforeEach": true, + "after": true, + "afterEach": true, + "chai": true, + "assert": true, + "axe": true, + "helpers": true + }, + "rules": { + "no-bitwise": 2, + "camelcase": 2, + "curly": 2, + "eqeqeq": 2, + "guard-for-in": 2, + "wrap-iife": [ + 2, + "any" + ], + "no-use-before-define": 0, + "new-cap": 2, + "no-caller": 2, + "no-empty": 2, + "no-new": 2, + "no-plusplus": 0, + "quotes": [ + 2, + "single" + ], + "no-undef": 2, + "no-unused-vars": 2, + "strict": 0, + "max-params": [ + 2, + 8 + ], + "max-depth": [ + 2, + 15 + ], + "max-statements": [ + 2, + 250 + ], + "complexity": [ + 2, + 50 + ], + "max-len": [ + 2, + { + "code": 180, + "ignoreComments": true + } + ], + "semi": 0, + "no-cond-assign": 0, + "no-debugger": 0, + "no-eq-null": 0, + "no-eval": 0, + "no-unused-expressions": 0, + "block-scoped-var": 0, + "no-iterator": 0, + "linebreak-style": 0, + "no-loop-func": 0, + "no-multi-str": 0, + "no-proto": 0, + "no-script-url": 0, + "dot-notation": 2, + "no-new-func": 0, + "no-new-wrappers": 0 + } +} diff --git a/test/checks/.eslintrc b/test/checks/.eslintrc new file mode 100644 index 0000000000..30fc37dd49 --- /dev/null +++ b/test/checks/.eslintrc @@ -0,0 +1,81 @@ +{ + "env": { + "browser": true + }, + "globals": { + "describe": true, + "it": true, + "xit": true, + "before": true, + "beforeEach": true, + "after": true, + "afterEach": true, + "chai": true, + "assert": true, + "checks": true, + "dqreRules": true, + "axe": true + }, + "rules": { + "no-bitwise": 2, + "camelcase": 2, + "curly": 2, + "eqeqeq": 2, + "guard-for-in": 2, + "wrap-iife": [ + 2, + "any" + ], + "no-use-before-define": 0, + "new-cap": 0, + "no-caller": 2, + "no-empty": 2, + "no-new": 2, + "no-plusplus": 0, + "quotes": [ + 2, + "single" + ], + "no-undef": 2, + "no-unused-vars": 2, + "max-params": [ + 2, + 8 + ], + "max-depth": [ + 2, + 15 + ], + "max-statements": [ + 2, + 250 + ], + "complexity": [ + 2, + 50 + ], + "max-len": [ + 2, + { + "code": 1000, + "ignoreComments": true + } + ], + "semi": 0, + "no-cond-assign": 0, + "no-debugger": 0, + "no-eq-null": 0, + "no-eval": 0, + "no-unused-expressions": 0, + "block-scoped-var": 0, + "no-iterator": 0, + "linebreak-style": 0, + "no-loop-func": 0, + "no-multi-str": 0, + "no-proto": 0, + "no-script-url": 0, + "dot-notation": 2, + "no-new-func": 0, + "no-new-wrappers": 0 + } +} diff --git a/test/checks/color/link-in-text-block.js b/test/checks/color/link-in-text-block.js index 4b5e478046..fb2a338ec8 100644 --- a/test/checks/color/link-in-text-block.js +++ b/test/checks/color/link-in-text-block.js @@ -49,14 +49,14 @@ describe('link-in-text-block', function () { var cssLines = Object.keys(styleObj).map(function (prop) { // Make camelCase prop dash separated var cssPropName = prop.trim() - .split(/(?=[A-Z])/g) - .reduce(function (prop, propPiece) { - if (!prop) { - return propPiece; - } else { - return prop + '-' + propPiece.toLowerCase(); - } - }, null); + .split(/(?=[A-Z])/g) + .reduce(function (prop, propPiece) { + if (!prop) { + return propPiece; + } else { + return prop + '-' + propPiece.toLowerCase(); + } + }, null); // Return indented line of style code return ' ' + cssPropName + ':' + styleObj[prop] + ';'; @@ -115,9 +115,9 @@ describe('link-in-text-block', function () { it('passes the selected node and closest ancestral block element', function () { fixture.innerHTML = '
' + - '

' + - ' link text ' + - ' inside block

inside block' + + '

' + + ' link text ' + + ' inside block

inside block' + '
outside block
'; var orig = axe.commons.color.elementIsDistinct; @@ -250,4 +250,4 @@ describe('link-in-text-block', function () { linkElm.parentNode ); }); -}); \ No newline at end of file +}); diff --git a/test/checks/navigation/p-as-heading.js b/test/checks/navigation/p-as-heading.js index af3f1b7ef5..f8f215880f 100644 --- a/test/checks/navigation/p-as-heading.js +++ b/test/checks/navigation/p-as-heading.js @@ -157,6 +157,7 @@ describe('p-as-heading', function () { }); it('returns true if none of the set margins is passed', function () { + /*eslint indent: 0*/ var options = { margins: [ { size: 1.2, weight: 100 }, @@ -188,4 +189,4 @@ describe('p-as-heading', function () { testOptions); assert.isTrue(checks['p-as-heading'].evaluate.apply(checkContext, params)); }); -}); \ No newline at end of file +}); diff --git a/test/checks/navigation/unique-frame-title-after.js b/test/checks/navigation/unique-frame-title-after.js index 4337289bd1..4da9bf281c 100644 --- a/test/checks/navigation/unique-frame-title-after.js +++ b/test/checks/navigation/unique-frame-title-after.js @@ -1,3 +1,4 @@ +/*eslint indent: 0*/ describe('unique-frame-title-after', function () { 'use strict'; diff --git a/test/commons/color/element-is-distinct.js b/test/commons/color/element-is-distinct.js index 931ce33471..819efe4622 100644 --- a/test/commons/color/element-is-distinct.js +++ b/test/commons/color/element-is-distinct.js @@ -22,27 +22,27 @@ describe('color.elementIsDistinct', function () { if (defaultStyle.hasOwnProperty(prop)) { styleObj[prop] = defaultStyle[prop]; } - } + } for (prop in outerStyle) { if (outerStyle.hasOwnProperty(prop)) { styleObj[prop] = outerStyle[prop]; } - } + } var cssLines = Object.keys(styleObj).map(function (prop) { // Make camelCase prop dash separated var cssPropName = prop.trim() - .split(/(?=[A-Z])/g) - .reduce(function (prop, propPiece) { - if (!prop) { - return propPiece; - } else { - return prop + '-' + propPiece.toLowerCase(); - } - }, null); + .split(/(?=[A-Z])/g) + .reduce(function (prop, propPiece) { + if (!prop) { + return propPiece; + } else { + return prop + '-' + propPiece.toLowerCase(); + } + }, null); // Return indented line of style code - return ' ' + cssPropName + ':' + styleObj[prop] + ';'; + return ' ' + cssPropName + ':' + styleObj[prop] + ';'; }).join('\n'); // Add to the style element @@ -238,4 +238,4 @@ describe('color.elementIsDistinct', function () { assert.isFalse(result); }); -}); \ No newline at end of file +}); diff --git a/test/commons/color/get-background-color.js b/test/commons/color/get-background-color.js index 36f452bf8c..d297db7d8e 100644 --- a/test/commons/color/get-background-color.js +++ b/test/commons/color/get-background-color.js @@ -264,7 +264,7 @@ describe('color.getBackgroundColor', function () { '' + ''; var target = fixture.querySelector('#target'), - parent = fixture.querySelector('#parent'); + parent = fixture.querySelector('#parent'); var bgNodes = []; axe._tree = axe.utils.getFlattenedTree(fixture.firstChild); var actual = axe.commons.color.getBackgroundColor(target, bgNodes); @@ -285,7 +285,7 @@ describe('color.getBackgroundColor', function () { '' + ''; var target = fixture.querySelector('#target'), - parent = fixture.querySelector('#parent'); + parent = fixture.querySelector('#parent'); var bgNodes = []; axe._tree = axe.utils.getFlattenedTree(fixture.firstChild); var actual = axe.commons.color.getBackgroundColor(target, bgNodes); @@ -306,7 +306,7 @@ describe('color.getBackgroundColor', function () { '' + ''; var target = fixture.querySelector('#target'), - parent = fixture.querySelector('#parent'); + parent = fixture.querySelector('#parent'); var bgNodes = []; axe._tree = axe.utils.getFlattenedTree(fixture.firstChild); var actual = axe.commons.color.getBackgroundColor(target, bgNodes); @@ -375,14 +375,14 @@ describe('color.getBackgroundColor', function () { '' + '' + '' + - '' + - '' + - '
' + + '' + 'Cell content
' + - '' + - ''; + '' + + '' + + '' + + ''; var target = fixture.querySelector('#target'), - parent = fixture.querySelector('#parent'); + parent = fixture.querySelector('#parent'); var bgNodes = []; axe._tree = axe.utils.getFlattenedTree(fixture.firstChild); var actual = axe.commons.color.getBackgroundColor(target, bgNodes); @@ -421,8 +421,8 @@ describe('color.getBackgroundColor', function () { fixture.innerHTML = '
' + - '
' + - '
' + + '
' + + '
' + '
'; var target = fixture.querySelector('#target'); var parent = fixture.querySelector('#parent'); @@ -470,7 +470,7 @@ describe('color.getBackgroundColor', function () { '
' + '
' + '
'+ '
'; @@ -623,13 +623,13 @@ describe('color.getBackgroundColor', function () { it('avoids scrolling elements with overflow:hidden', function () { fixture.innerHTML = '
' + - '
' + - '
' + - '
Some text here
' + - '
' + - '
' + - '
' + - '
R_20
' + + '
' + + '
' + + '
Some text here
' + + '
' + + '
' + + '
' + + '
R_20
' + '
'; // This shouldn't cause a scroll @@ -687,7 +687,7 @@ describe('color.getBackgroundColor', function () { var shadow = container.attachShadow({ mode: 'open' }); shadow.innerHTML = 'Text'; axe._tree = axe.utils.getFlattenedTree(fixture.firstChild); - + var target = shadow.querySelector('#shadowTarget'); var actual = axe.commons.color.getBackgroundColor(target, [], false); @@ -703,7 +703,7 @@ describe('color.getBackgroundColor', function () { var container = fixture.querySelector('#container'); var shadow = container.attachShadow({ mode: 'open' }); shadow.innerHTML = '
'; - + var target = shadow.querySelector('#target'); axe._tree = axe.utils.getFlattenedTree(fixture.firstChild); var actual = axe.commons.color.getBackgroundColor(target, []); diff --git a/test/commons/dom/find-elms-in-context.js b/test/commons/dom/find-elms-in-context.js index ca5470b0e8..24eb8d795a 100644 --- a/test/commons/dom/find-elms-in-context.js +++ b/test/commons/dom/find-elms-in-context.js @@ -1,53 +1,53 @@ describe('dom.findElmsInContext', function () { - 'use strict'; - - var shadowSupport = axe.testUtils.shadowSupport; - var fixtureSetup = axe.testUtils.fixtureSetup; - var findElmsInContext = axe.commons.dom.findElmsInContext; - - afterEach(function () { - fixtureSetup(''); - }); - - it('returns an array or elements in the same context', function () { - var fixture = fixtureSetup( - '1' + - '2' + - '3' + - '4'); - - assert.deepEqual( - findElmsInContext({ elm: 'b', attr: 'name', value: 'foo', context: fixture }), - Array.from( document.querySelectorAll('b[name=foo]') ) - ); - }); - - (shadowSupport.v1 ? it : xit)('ignores elements inside shadow tree', function () { - var node = document.createElement('div'); - node.innerHTML = '1'; - var shadow = node.attachShadow({ mode: 'open' }); - shadow.innerHTML = '2 '; - var fixture = fixtureSetup(node); - - var result = findElmsInContext({ - elm: 'b', attr: 'name', value: 'foo', context: fixture - }); - assert.lengthOf(result, 1); - assert.equal(result[0].innerText, '1'); - }); - - (shadowSupport.v1 ? it : xit)('can search elements limited to the shadow tree', function () { - var node = document.createElement('div'); - node.innerHTML = '1'; - var shadow = node.attachShadow({ mode: 'open' }); - shadow.innerHTML = '2'; - fixtureSetup(node); - - var result = findElmsInContext({ - elm: 'b', attr: 'name', value: 'foo', context: shadow - }); - - assert.lengthOf(result, 1); - assert.equal(result[0].innerText, '2'); - }); + 'use strict'; + + var shadowSupport = axe.testUtils.shadowSupport; + var fixtureSetup = axe.testUtils.fixtureSetup; + var findElmsInContext = axe.commons.dom.findElmsInContext; + + afterEach(function () { + fixtureSetup(''); + }); + + it('returns an array or elements in the same context', function () { + var fixture = fixtureSetup( + '1' + + '2' + + '3' + + '4'); + + assert.deepEqual( + findElmsInContext({ elm: 'b', attr: 'name', value: 'foo', context: fixture }), + Array.from( document.querySelectorAll('b[name=foo]') ) + ); + }); + + (shadowSupport.v1 ? it : xit)('ignores elements inside shadow tree', function () { + var node = document.createElement('div'); + node.innerHTML = '1'; + var shadow = node.attachShadow({ mode: 'open' }); + shadow.innerHTML = '2 '; + var fixture = fixtureSetup(node); + + var result = findElmsInContext({ + elm: 'b', attr: 'name', value: 'foo', context: fixture + }); + assert.lengthOf(result, 1); + assert.equal(result[0].innerText, '1'); + }); + + (shadowSupport.v1 ? it : xit)('can search elements limited to the shadow tree', function () { + var node = document.createElement('div'); + node.innerHTML = '1'; + var shadow = node.attachShadow({ mode: 'open' }); + shadow.innerHTML = '2'; + fixtureSetup(node); + + var result = findElmsInContext({ + elm: 'b', attr: 'name', value: 'foo', context: shadow + }); + + assert.lengthOf(result, 1); + assert.equal(result[0].innerText, '2'); + }); }); diff --git a/test/commons/dom/get-composed-parent.js b/test/commons/dom/get-composed-parent.js index 60923a1fe0..255d25db39 100644 --- a/test/commons/dom/get-composed-parent.js +++ b/test/commons/dom/get-composed-parent.js @@ -1,72 +1,72 @@ /* global xit */ describe('dom.getComposedParent', function () { - 'use strict'; - var getComposedParent = axe.commons.dom.getComposedParent; - var fixture = document.getElementById('fixture'); - var shadowSupport = axe.testUtils.shadowSupport.v1; + 'use strict'; + var getComposedParent = axe.commons.dom.getComposedParent; + var fixture = document.getElementById('fixture'); + var shadowSupport = axe.testUtils.shadowSupport.v1; - afterEach(function () { - fixture.innerHTML = ''; - }); + afterEach(function () { + fixture.innerHTML = ''; + }); - it('returns the parentNode normally', function () { - fixture.innerHTML = '
'; + it('returns the parentNode normally', function () { + fixture.innerHTML = '
'; - var actual = getComposedParent(document.getElementById('target')); - assert.instanceOf(actual, Node); - assert.equal(actual, document.getElementById('parent')); - }); + var actual = getComposedParent(document.getElementById('target')); + assert.instanceOf(actual, Node); + assert.equal(actual, document.getElementById('parent')); + }); - it('returns null from the documentElement', function () { - assert.isNull( - getComposedParent(document.documentElement) - ); - }); + it('returns null from the documentElement', function () { + assert.isNull( + getComposedParent(document.documentElement) + ); + }); - (shadowSupport ? it : xit)('skip the slot node for slotted content', function () { - fixture.innerHTML = '
'; - var shadowRoot = document.getElementById('shadow').attachShadow({ mode: 'open' }); - shadowRoot.innerHTML = '
' + - '' + - '
'; + (shadowSupport ? it : xit)('skip the slot node for slotted content', function () { + fixture.innerHTML = '
'; + var shadowRoot = document.getElementById('shadow').attachShadow({ mode: 'open' }); + shadowRoot.innerHTML = '
' + + '' + + '
'; - var actual = getComposedParent(fixture.querySelector('#target')); - assert.instanceOf(actual, Node); - assert.equal(actual, shadowRoot.querySelector('#grand-parent')); - }); + var actual = getComposedParent(fixture.querySelector('#target')); + assert.instanceOf(actual, Node); + assert.equal(actual, shadowRoot.querySelector('#grand-parent')); + }); - (shadowSupport ? it : xit)('understands explicitly slotted nodes', function () { - fixture.innerHTML = '
'; - var shadowRoot = document.getElementById('shadow').attachShadow({ mode: 'open' }); - shadowRoot.innerHTML = '
' + - '' + - '
' + - '
'; + (shadowSupport ? it : xit)('understands explicitly slotted nodes', function () { + fixture.innerHTML = '
'; + var shadowRoot = document.getElementById('shadow').attachShadow({ mode: 'open' }); + shadowRoot.innerHTML = '
' + + '' + + '
' + + '
'; - var actual = getComposedParent(fixture.querySelector('#target')); - assert.instanceOf(actual, Node); - assert.equal(actual, shadowRoot.querySelector('#parent')); - }); + var actual = getComposedParent(fixture.querySelector('#target')); + assert.instanceOf(actual, Node); + assert.equal(actual, shadowRoot.querySelector('#parent')); + }); - (shadowSupport ? it : xit)('returns elements within a shadow tree', function () { - fixture.innerHTML = '
content
'; - var shadowRoot = document.getElementById('shadow').attachShadow({ mode: 'open' }); - shadowRoot.innerHTML = '
' + - '' + - '
'; + (shadowSupport ? it : xit)('returns elements within a shadow tree', function () { + fixture.innerHTML = '
content
'; + var shadowRoot = document.getElementById('shadow').attachShadow({ mode: 'open' }); + shadowRoot.innerHTML = '
' + + '' + + '
'; - var actual = getComposedParent(shadowRoot.querySelector('#target')); - assert.instanceOf(actual, Node); - assert.equal(actual, shadowRoot.querySelector('#parent')); - }); + var actual = getComposedParent(shadowRoot.querySelector('#target')); + assert.instanceOf(actual, Node); + assert.equal(actual, shadowRoot.querySelector('#parent')); + }); - (shadowSupport ? it : xit)('returns the host when it reaches the shadow root', function () { - fixture.innerHTML = '
content
'; - var shadowRoot = document.getElementById('parent').attachShadow({ mode: 'open' }); - shadowRoot.innerHTML = '
'; + (shadowSupport ? it : xit)('returns the host when it reaches the shadow root', function () { + fixture.innerHTML = '
content
'; + var shadowRoot = document.getElementById('parent').attachShadow({ mode: 'open' }); + shadowRoot.innerHTML = '
'; - var actual = getComposedParent(shadowRoot.querySelector('#target')); - assert.instanceOf(actual, Node); - assert.equal(actual, fixture.querySelector('#parent')); - }); + var actual = getComposedParent(shadowRoot.querySelector('#target')); + assert.instanceOf(actual, Node); + assert.equal(actual, fixture.querySelector('#parent')); + }); }); diff --git a/test/commons/dom/get-scroll-offset.js b/test/commons/dom/get-scroll-offset.js index 15bed1f9e9..e5aaa2a560 100644 --- a/test/commons/dom/get-scroll-offset.js +++ b/test/commons/dom/get-scroll-offset.js @@ -30,17 +30,17 @@ describe('dom.getScrollOffset', function () { it('should get the scroll from the document.body if a document is passed in and it has no documentElement', function () { - var offset = axe.commons.dom.getScrollOffset({ - nodeType: 9, - body: { - scrollTop: 42, - scrollLeft: 98 - } - }); + var offset = axe.commons.dom.getScrollOffset({ + nodeType: 9, + body: { + scrollTop: 42, + scrollLeft: 98 + } + }); - assert.equal(offset.left, 98); - assert.equal(offset.top, 42); - }); + assert.equal(offset.left, 98); + assert.equal(offset.top, 42); + }); it('should work on a window object', function () { var offset = axe.commons.dom.getScrollOffset({ diff --git a/test/commons/dom/has-content-virtual.js b/test/commons/dom/has-content-virtual.js index e0798b6eb1..db76e3cd28 100644 --- a/test/commons/dom/has-content-virtual.js +++ b/test/commons/dom/has-content-virtual.js @@ -1,104 +1,104 @@ /* global xit */ describe('dom.hasContentVirtual', function () { - 'use strict'; - var hasContentVirtual = axe.commons.dom.hasContentVirtual; - var fixture = document.getElementById('fixture'); - var shadowSupport = axe.testUtils.shadowSupport.v1; - var tree; + 'use strict'; + var hasContentVirtual = axe.commons.dom.hasContentVirtual; + var fixture = document.getElementById('fixture'); + var shadowSupport = axe.testUtils.shadowSupport.v1; + var tree; - it('returns false if there is no content', function () { - fixture.innerHTML = '
'; - tree = axe.utils.getFlattenedTree(fixture); - assert.isFalse( - hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) - ); - }); + it('returns false if there is no content', function () { + fixture.innerHTML = '
'; + tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse( + hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) + ); + }); - it('returns false if there are non-visual elements', function () { - fixture.innerHTML = '
'; - tree = axe.utils.getFlattenedTree(fixture); - assert.isFalse( - hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) - ); - }); + it('returns false if there are non-visual elements', function () { + fixture.innerHTML = '
'; + tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse( + hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) + ); + }); - it('is true if the element has non-empty text', function () { - fixture.innerHTML = '
text
'; - tree = axe.utils.getFlattenedTree(fixture); - assert.isTrue( - hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) - ); - }); + it('is true if the element has non-empty text', function () { + fixture.innerHTML = '
text
'; + tree = axe.utils.getFlattenedTree(fixture); + assert.isTrue( + hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) + ); + }); - it('is true if the element has an aria label', function () { - fixture.innerHTML = '
'; - tree = axe.utils.getFlattenedTree(fixture); - assert.isTrue( - hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) - ); - }); + it('is true if the element has an aria label', function () { + fixture.innerHTML = '
'; + tree = axe.utils.getFlattenedTree(fixture); + assert.isTrue( + hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) + ); + }); - it('is true if the element contains visual content', function () { - fixture.innerHTML = '
'; - tree = axe.utils.getFlattenedTree(fixture); - assert.isTrue( - hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) - ); - }); + it('is true if the element contains visual content', function () { + fixture.innerHTML = '
'; + tree = axe.utils.getFlattenedTree(fixture); + assert.isTrue( + hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) + ); + }); - it('is true if the element contains a node with a aria-label', function () { - fixture.innerHTML = '
'; - tree = axe.utils.getFlattenedTree(fixture); - assert.isTrue( - hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) - ); - }); + it('is true if the element contains a node with a aria-label', function () { + fixture.innerHTML = '
'; + tree = axe.utils.getFlattenedTree(fixture); + assert.isTrue( + hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) + ); + }); - it('is false if the element does not show text', function () { - fixture.innerHTML = ''; - tree = axe.utils.getFlattenedTree(fixture); - assert.isFalse( - hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) - ); - }); + it('is false if the element does not show text', function () { + fixture.innerHTML = ''; + tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse( + hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) + ); + }); - it('is called through hasContent, with a DOM node', function () { - var hasContent = axe.commons.dom.hasContent; - fixture.innerHTML = '
text
'; - axe._tree = axe.utils.getFlattenedTree(fixture); - assert.isTrue(hasContent(fixture.querySelector('#target'))); + it('is called through hasContent, with a DOM node', function () { + var hasContent = axe.commons.dom.hasContent; + fixture.innerHTML = '
text
'; + axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isTrue(hasContent(fixture.querySelector('#target'))); - fixture.innerHTML = '
'; - axe._tree = axe.utils.getFlattenedTree(fixture); - assert.isFalse(hasContent(fixture.querySelector('#target'))); - }); + fixture.innerHTML = '
'; + axe._tree = axe.utils.getFlattenedTree(fixture); + assert.isFalse(hasContent(fixture.querySelector('#target'))); + }); - it('is false if noRecursion is true and the content is not in a child', function () { - fixture.innerHTML = '
text
'; - tree = axe.utils.getFlattenedTree(fixture); + it('is false if noRecursion is true and the content is not in a child', function () { + fixture.innerHTML = '
text
'; + tree = axe.utils.getFlattenedTree(fixture); - assert.isFalse(hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0], true)); - }); + assert.isFalse(hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0], true)); + }); - (shadowSupport ? it : xit)('looks at content of shadow dom elements', function () { - fixture.innerHTML = '
'; - var shadow = fixture.querySelector('#target').attachShadow({ mode: 'open' }); - shadow.innerHTML = 'Some text'; - tree = axe.utils.getFlattenedTree(fixture); + (shadowSupport ? it : xit)('looks at content of shadow dom elements', function () { + fixture.innerHTML = '
'; + var shadow = fixture.querySelector('#target').attachShadow({ mode: 'open' }); + shadow.innerHTML = 'Some text'; + tree = axe.utils.getFlattenedTree(fixture); - assert.isTrue( - hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) - ); - }); + assert.isTrue( + hasContentVirtual(axe.utils.querySelectorAll(tree, '#target')[0]) + ); + }); - (shadowSupport ? it : xit)('looks at the slots in a shadow tree', function () { - fixture.innerHTML = '
some text
'; - var shadow = fixture.querySelector('#shadow').attachShadow({ mode: 'open' }); - shadow.innerHTML = '
'; - tree = axe.utils.getFlattenedTree(fixture); + (shadowSupport ? it : xit)('looks at the slots in a shadow tree', function () { + fixture.innerHTML = '
some text
'; + var shadow = fixture.querySelector('#shadow').attachShadow({ mode: 'open' }); + shadow.innerHTML = '
'; + tree = axe.utils.getFlattenedTree(fixture); - assert.isTrue( - hasContentVirtual(axe.utils.querySelectorAll(tree, '.target')[0]) - ); - }); + assert.isTrue( + hasContentVirtual(axe.utils.querySelectorAll(tree, '.target')[0]) + ); + }); }); diff --git a/test/commons/table/traverse.js b/test/commons/table/traverse.js index 31035c2760..70c57a09b5 100644 --- a/test/commons/table/traverse.js +++ b/test/commons/table/traverse.js @@ -22,10 +22,11 @@ describe('table.traverse', function () { var expect = ['1b', '1c']; table.traverse({ x:1, y:0 }, topRight, dummyTable, - function (cell) { - assert.equal(cell, expect[iterations]); - iterations += 1; - }); + function (cell) { + assert.equal(cell, expect[iterations]); + iterations += 1; + } + ); assert.equal(iterations, expect.length); }); @@ -40,10 +41,11 @@ describe('table.traverse', function () { var expect = ['2a', '3a']; table.traverse({ x:0, y:1 }, topRight, dummyTable, - function (cell) { - assert.equal(cell, expect[iterations]); - iterations += 1; - }); + function (cell) { + assert.equal(cell, expect[iterations]); + iterations += 1; + } + ); assert.equal(iterations, expect.length); }); @@ -52,10 +54,11 @@ describe('table.traverse', function () { var expect = ['3b', '3a']; table.traverse({ x:-1, y:0 }, bottomLeft, dummyTable, - function (cell) { - assert.equal(cell, expect[iterations]); - iterations += 1; - }); + function (cell) { + assert.equal(cell, expect[iterations]); + iterations += 1; + } + ); assert.equal(iterations, expect.length); }); @@ -64,10 +67,11 @@ describe('table.traverse', function () { var expect = ['2c', '1c']; table.traverse({ x:0, y:-1 }, bottomLeft, dummyTable, - function (cell) { - assert.equal(cell, expect[iterations]); - iterations += 1; - }); + function (cell) { + assert.equal(cell, expect[iterations]); + iterations += 1; + } + ); assert.equal(iterations, expect.length); }); @@ -75,44 +79,49 @@ describe('table.traverse', function () { var iterations = 0; var expect = ['1b', '1c']; table.traverse('right', topRight, dummyTable, - function (cell) { - assert.equal(cell, expect[iterations]); - iterations += 1; - }); + function (cell) { + assert.equal(cell, expect[iterations]); + iterations += 1; + } + ); iterations = 0; expect = ['2a', '3a']; table.traverse('down', topRight, dummyTable, - function (cell) { - assert.equal(cell, expect[iterations]); - iterations += 1; - }); + function (cell) { + assert.equal(cell, expect[iterations]); + iterations += 1; + } + ); iterations = 0; expect = ['3b', '3a']; table.traverse('left', bottomLeft, dummyTable, - function (cell) { - assert.equal(cell, expect[iterations]); - iterations += 1; - }); + function (cell) { + assert.equal(cell, expect[iterations]); + iterations += 1; + } + ); iterations = 0; expect = ['2c', '1c']; table.traverse('up', bottomLeft, dummyTable, - function (cell) { - assert.equal(cell, expect[iterations]); - iterations += 1; - }); + function (cell) { + assert.equal(cell, expect[iterations]); + iterations += 1; + } + ); }); it('stops when the callback returned true', function () { var iterations = 0; table.traverse({ x:1, y:1 }, topRight, dummyTable, - function (cell) { - assert.equal(cell, '2b'); // or not, to be? - iterations += 1; - return true; - }); + function (cell) { + assert.equal(cell, '2b'); // or not, to be? + iterations += 1; + return true; + } + ); assert.equal(iterations, 1); }); @@ -128,4 +137,4 @@ describe('table.traverse', function () { }); -}); \ No newline at end of file +}); diff --git a/test/core/base/audit.js b/test/core/base/audit.js index 3c78a18b8f..518102e470 100644 --- a/test/core/base/audit.js +++ b/test/core/base/audit.js @@ -691,6 +691,7 @@ describe('Audit', function () { }); describe('Audit#after', function () { it('should run Rule#after on any rule whose result is passed in', function () { + /*eslint no-unused-vars:0*/ var audit = new Audit(); var success = false; var options = [{ id: 'hehe', enabled: true, monkeys: 'bananas' }]; diff --git a/test/core/base/context.js b/test/core/base/context.js index e15bc8de0f..5a94227d96 100644 --- a/test/core/base/context.js +++ b/test/core/base/context.js @@ -1,4 +1,5 @@ /*global Context, axe */ +/*eslint no-unused-vars:0*/ describe('Context', function() { 'use strict'; @@ -298,7 +299,6 @@ describe('Context', function() { }); describe('throwing errors', function () { - // jshint unused:false var isInFrame; beforeEach(function () { @@ -427,7 +427,6 @@ describe('Context', function() { // document.hasOwnProperty is undefined in Firefox content scripts it('should not throw given really weird circumstances when hasOwnProperty is deleted from a document node?', function() { - //jshint -W001 var spec = document.implementation.createHTMLDocument('ie is dumb'); spec.hasOwnProperty = undefined; var result = new Context(spec); diff --git a/test/core/public/cleanup-plugins.js b/test/core/public/cleanup-plugins.js index 1f1ae28faf..bd179e4cb7 100644 --- a/test/core/public/cleanup-plugins.js +++ b/test/core/public/cleanup-plugins.js @@ -1,104 +1,105 @@ /*global cleanupPlugins */ describe('cleanupPlugins', function () { - 'use strict'; + 'use strict'; - function createFrames(callback) { - var frame; - frame = document.createElement('iframe'); - frame.src = '../mock/frames/nested1.html'; - frame.addEventListener('load', function () { - setTimeout(callback, 500); - }); - fixture.appendChild(frame); - } + function createFrames(callback) { + var frame; + frame = document.createElement('iframe'); + frame.src = '../mock/frames/nested1.html'; + frame.addEventListener('load', function () { + setTimeout(callback, 500); + }); + fixture.appendChild(frame); + } - var fixture = document.getElementById('fixture'); + var fixture = document.getElementById('fixture'); - var assertNotCalled = function () { - assert.ok(false, 'Should not be called'); - }; + var assertNotCalled = function () { + assert.ok(false, 'Should not be called'); + }; - afterEach(function () { - fixture.innerHTML = ''; - axe.plugins = {}; - }); + afterEach(function () { + fixture.innerHTML = ''; + axe.plugins = {}; + }); - beforeEach(function () { - axe._audit = null; - }); + beforeEach(function () { + axe._audit = null; + }); - it('should throw if no audit is configured', function () { - assert.throws(function () { - cleanupPlugins(document, {}); - }, Error, /^No audit configured/); - }); + it('should throw if no audit is configured', function () { + assert.throws(function () { + cleanupPlugins(document, {}); + }, Error, /^No audit configured/); + }); - it('should call cleanup on all plugins', function (done) { - var cleaned = false; - axe._load({ - rules: [] - }); - axe.registerPlugin({ - id: 'p', - run: function () {}, - add: function (impl) { - this._registry[impl.id] = impl; - }, - commands: [] - }); - axe.plugins.p.cleanup = function (res) { - cleaned = true; - res(); - }; - cleanupPlugins(function () { - assert.equal(cleaned, true); - done(); - }, assertNotCalled); - }); + it('should call cleanup on all plugins', function (done) { + /*eslint no-unused-vars: 0*/ + var cleaned = false; + axe._load({ + rules: [] + }); + axe.registerPlugin({ + id: 'p', + run: function () {}, + add: function (impl) { + this._registry[impl.id] = impl; + }, + commands: [] + }); + axe.plugins.p.cleanup = function (res) { + cleaned = true; + res(); + }; + cleanupPlugins(function () { + assert.equal(cleaned, true); + done(); + }, assertNotCalled); + }); - it('should not throw exception if no arguments are provided', function(done) { - var cleaned = false; - axe._load({ - rules: [] - }); - axe.registerPlugin({ - id: 'p', - run: function () {}, - add: function (impl) { - this._registry[impl.id] = impl; - }, - commands: [] - }); - axe.plugins.p.cleanup = function (res) { - cleaned = true; - res(); - }; - assert.doesNotThrow(function () { - cleanupPlugins(); - done(); - }); - }); + it('should not throw exception if no arguments are provided', function(done) { + var cleaned = false; + axe._load({ + rules: [] + }); + axe.registerPlugin({ + id: 'p', + run: function () {}, + add: function (impl) { + this._registry[impl.id] = impl; + }, + commands: [] + }); + axe.plugins.p.cleanup = function (res) { + cleaned = true; + res(); + }; + assert.doesNotThrow(function () { + cleanupPlugins(); + done(); + }); + }); - it('should send command to frames to cleanup', function (done) { - createFrames(function () { - axe._load({}); - var orig = axe.utils.sendCommandToFrame; - var frame = document.querySelector('iframe'); - axe.utils.sendCommandToFrame = function (node, opts, resolve) { - assert.equal(node, frame); - assert.deepEqual(opts, { - command: 'cleanup-plugin' - }); - axe.utils.sendCommandToFrame = orig; - resolve(); - done(); - }; - cleanupPlugins(function () {}, assertNotCalled); - }); - }); + it('should send command to frames to cleanup', function (done) { + createFrames(function () { + axe._load({}); + var orig = axe.utils.sendCommandToFrame; + var frame = document.querySelector('iframe'); + axe.utils.sendCommandToFrame = function (node, opts, resolve) { + assert.equal(node, frame); + assert.deepEqual(opts, { + command: 'cleanup-plugin' + }); + axe.utils.sendCommandToFrame = orig; + resolve(); + done(); + }; + cleanupPlugins(function () {}, assertNotCalled); + }); + }); }); diff --git a/test/core/public/configure.js b/test/core/public/configure.js index f49dfc00b2..50edc56a65 100644 --- a/test/core/public/configure.js +++ b/test/core/public/configure.js @@ -13,8 +13,8 @@ describe('axe.configure', function() { it('should throw if audit is not configured', function() { assert.throws(function () { - axe.configure({}); - }, Error, /^No audit configured/); + axe.configure({}); + }, Error, /^No audit configured/); }); it('should override an audit\'s reporter - string', function() { diff --git a/test/core/public/plugins.js b/test/core/public/plugins.js index 79ac780431..111c4d7ad4 100644 --- a/test/core/public/plugins.js +++ b/test/core/public/plugins.js @@ -1,172 +1,172 @@ describe('plugins', function () { - 'use strict'; + 'use strict'; - function createFrames(callback) { - var frame, num = 2, - loaded = 0; + function createFrames(callback) { + var frame, num = 2, + loaded = 0; - function onLoad() { - loaded++; - if (loaded >= (num)) { - callback(); - } - } + function onLoad() { + loaded++; + if (loaded >= (num)) { + callback(); + } + } - frame = document.createElement('iframe'); - frame.id = 'target'; - frame.src = '../mock/frames/frame-frame.html'; + frame = document.createElement('iframe'); + frame.id = 'target'; + frame.src = '../mock/frames/frame-frame.html'; - frame.addEventListener('load', onLoad); - fixture.appendChild(frame); + frame.addEventListener('load', onLoad); + fixture.appendChild(frame); - frame = document.createElement('iframe'); - frame.src = '../mock/frames/frame-frame.html'; - frame.addEventListener('load', onLoad); - fixture.appendChild(frame); - } + frame = document.createElement('iframe'); + frame.src = '../mock/frames/frame-frame.html'; + frame.addEventListener('load', onLoad); + fixture.appendChild(frame); + } - var fixture = document.getElementById('fixture'); + var fixture = document.getElementById('fixture'); - afterEach(function () { - fixture.innerHTML = ''; - axe._audit = null; - }); + afterEach(function () { + fixture.innerHTML = ''; + axe._audit = null; + }); - beforeEach(function () { - axe._load({ - rules: [] - }); - }); + beforeEach(function () { + axe._load({ + rules: [] + }); + }); - it('Should have registerPlugin function', function () { - assert.ok(axe.registerPlugin); - assert.equal(typeof axe.registerPlugin, 'function'); - }); + it('Should have registerPlugin function', function () { + assert.ok(axe.registerPlugin); + assert.equal(typeof axe.registerPlugin, 'function'); + }); - it('should have an empty set of plugins', function () { - assert.deepEqual({}, axe.plugins); - }); + it('should have an empty set of plugins', function () { + assert.deepEqual({}, axe.plugins); + }); - it('should add a plugin to the plugins list and a command to the audit commands', function () { - axe.registerPlugin({ - id: 'my-plugin', - run: 'run', - commands: [{ - id: 'my-command', - callback: 'callback' - }] - }); - assert.ok(axe.plugins['my-plugin']); - assert.equal(axe.plugins['my-plugin']._run, 'run'); - assert.equal(axe._audit.commands['my-command'], 'callback'); - }); - describe('Plugin class', function () { - it('should call the run function of the registered plugin, when run is called', function () { - var called = false; - axe.registerPlugin({ - id: 'my-plugin', - run: function (id, action, options) { - called = { - id: id, - action: action, - options: options - }; - }, - commands: [{ - id: 'my-command', - callback: 'callback' - }] - }); - axe.plugins['my-plugin'].run('id', 'action', 'options'); - assert.deepEqual({id: 'id', action: 'action', options: 'options'}, called); - }); - }); - describe('Plugin.protoype.run', function () { - afterEach(function () { - fixture.innerHTML = ''; - axe._audit = null; - axe.plugins = {}; - }); - beforeEach(function () { - axe._load({ - rules: [] - }); - axe.registerPlugin({ - id: 'multi', - run: function (id, action, options, callback) { - this._registry[id][action].call(this._registry[id], options, callback); - }, - commands: [{ - id: 'run-multi', - callback: function (data, callback) { - return axe.plugins.multi.run(data.parameter, data.action, data.options, callback); - } - }] - }); - axe.plugins.multi.add({ - id: 'hideall', - cleanup: function (done) { - done(); - }, - run: function (options, callback) { - var frames; - var q = axe.utils.queue(); + it('should add a plugin to the plugins list and a command to the audit commands', function () { + axe.registerPlugin({ + id: 'my-plugin', + run: 'run', + commands: [{ + id: 'my-command', + callback: 'callback' + }] + }); + assert.ok(axe.plugins['my-plugin']); + assert.equal(axe.plugins['my-plugin']._run, 'run'); + assert.equal(axe._audit.commands['my-command'], 'callback'); + }); + describe('Plugin class', function () { + it('should call the run function of the registered plugin, when run is called', function () { + var called = false; + axe.registerPlugin({ + id: 'my-plugin', + run: function (id, action, options) { + called = { + id: id, + action: action, + options: options + }; + }, + commands: [{ + id: 'my-command', + callback: 'callback' + }] + }); + axe.plugins['my-plugin'].run('id', 'action', 'options'); + assert.deepEqual({id: 'id', action: 'action', options: 'options'}, called); + }); + }); + describe('Plugin.protoype.run', function () { + afterEach(function () { + fixture.innerHTML = ''; + axe._audit = null; + axe.plugins = {}; + }); + beforeEach(function () { + axe._load({ + rules: [] + }); + axe.registerPlugin({ + id: 'multi', + run: function (id, action, options, callback) { + this._registry[id][action].call(this._registry[id], options, callback); + }, + commands: [{ + id: 'run-multi', + callback: function (data, callback) { + return axe.plugins.multi.run(data.parameter, data.action, data.options, callback); + } + }] + }); + axe.plugins.multi.add({ + id: 'hideall', + cleanup: function (done) { + done(); + }, + run: function (options, callback) { + var frames; + var q = axe.utils.queue(); - frames = axe.utils.toArray(document.querySelectorAll('iframe, frame')); - frames.forEach(function (frame) { - q.defer(function (resolve, reject) { - axe.utils.sendCommandToFrame(frame, { - options: options, - command: 'run-multi', - parameter: 'hideall', - action: 'run' - }, resolve, reject); - }); - }); + frames = axe.utils.toArray(document.querySelectorAll('iframe, frame')); + frames.forEach(function (frame) { + q.defer(function (resolve, reject) { + axe.utils.sendCommandToFrame(frame, { + options: options, + command: 'run-multi', + parameter: 'hideall', + action: 'run' + }, resolve, reject); + }); + }); - q.defer(function (done) { - // implementation - done('ola!'); - }); - q.then(function (data) { - // done with all the frames - var results = []; - data.forEach(function (datum) { - if (datum) { - results = results.concat(datum); - } - }); - callback(results); - }).catch(callback); - } - }); - }); - it('should work without frames', function (done) { - axe.plugins.multi.run('hideall', 'run', {}, function (results) { - assert.deepEqual(results, ['ola!']); - done(); - }); - }); - it('should work with frames', function (done) { - createFrames(function () { - setTimeout(function () { - axe.plugins.multi.run('hideall', 'run', {}, function (results) { - assert.deepEqual(results, ['ola!', 'ola!', 'ola!', 'ola!', 'ola!']); - done(); - }); - }, 500); - }); - }); - it('should call the implementation\'s cleanup function', function (done) { - var called = false; - axe.plugins.multi.cleanup = function(done) { - called = true; - done(); - }; - axe.plugins.multi.cleanup(function () { - assert.ok(called); - done(); - }); - }); - }); + q.defer(function (done) { + // implementation + done('ola!'); + }); + q.then(function (data) { + // done with all the frames + var results = []; + data.forEach(function (datum) { + if (datum) { + results = results.concat(datum); + } + }); + callback(results); + }).catch(callback); + } + }); + }); + it('should work without frames', function (done) { + axe.plugins.multi.run('hideall', 'run', {}, function (results) { + assert.deepEqual(results, ['ola!']); + done(); + }); + }); + it('should work with frames', function (done) { + createFrames(function () { + setTimeout(function () { + axe.plugins.multi.run('hideall', 'run', {}, function (results) { + assert.deepEqual(results, ['ola!', 'ola!', 'ola!', 'ola!', 'ola!']); + done(); + }); + }, 500); + }); + }); + it('should call the implementation\'s cleanup function', function (done) { + var called = false; + axe.plugins.multi.cleanup = function(done) { + called = true; + done(); + }; + axe.plugins.multi.cleanup(function () { + assert.ok(called); + done(); + }); + }); + }); }); diff --git a/test/core/public/run-rules.js b/test/core/public/run-rules.js index 6d8ea0a652..0bedda2830 100644 --- a/test/core/public/run-rules.js +++ b/test/core/public/run-rules.js @@ -380,72 +380,72 @@ describe('runRules', function () { fixture.innerHTML = '
Target!
ok
'; runRules('#fixture', {}, function (results) { assert.deepEqual(JSON.parse(JSON.stringify(results)), [{ - id: 'div#target', - helpUrl: 'https://dequeuniversity.com/rules/axe/x.y/div#target?application=axeAPI', - pageLevel: false, - foo: 'bar', - stuff: 'blah', + id: 'div#target', + helpUrl: 'https://dequeuniversity.com/rules/axe/x.y/div#target?application=axeAPI', + pageLevel: false, + foo: 'bar', + stuff: 'blah', + impact: 'moderate', + passes: [], + inapplicable: [], + incomplete: [], + violations: [{ + result: 'failed', + node: { + selector: ['#target'], + xpath: ['/div[@id=\'target\']'], + source: '
Target!
' + }, impact: 'moderate', - passes: [], - inapplicable: [], - incomplete: [], - violations: [{ - result: 'failed', - node: { - selector: ['#target'], - xpath: ['/div[@id=\'target\']'], - source: '
Target!
' - }, + any: [{ impact: 'moderate', - any: [{ - impact: 'moderate', - otherThingy: true, - message: 'failing is not good', - id: 'has-target', - data: null, - relatedNodes: [] - }], - all: [], - none: [] + otherThingy: true, + message: 'failing is not good', + id: 'has-target', + data: null, + relatedNodes: [] }], - result: 'failed', - tags: [] - }, { - id: 'first-div', - helpUrl: 'https://dequeuniversity.com/rules/axe/x.y/first-div?application=axeAPI', - pageLevel: false, - bar: 'foo', - stuff: 'no', + all: [], + none: [] + }], + result: 'failed', + tags: [] + }, { + id: 'first-div', + helpUrl: 'https://dequeuniversity.com/rules/axe/x.y/first-div?application=axeAPI', + pageLevel: false, + bar: 'foo', + stuff: 'no', + impact: null, + inapplicable: [], + incomplete: [], + violations: [], + passes: [{ + result: 'passed', impact: null, - inapplicable: [], - incomplete: [], - violations: [], - passes: [{ - result: 'passed', - impact: null, - node: { + node: { + selector: ['#target'], + xpath: ['/div[@id=\'target\']'], + source: '
Target!
' + }, + any: [{ + impact: 'serious', + id: 'first-div', + thingy: true, + message: 'passing is good', + data: null, + relatedNodes: [{ selector: ['#target'], xpath: ['/div[@id=\'target\']'], source: '
Target!
' - }, - any: [{ - impact: 'serious', - id: 'first-div', - thingy: true, - message: 'passing is good', - data: null, - relatedNodes: [{ - selector: ['#target'], - xpath: ['/div[@id=\'target\']'], - source: '
Target!
' - }] - }], - all: [], - none: [] + }] }], - result: 'passed', - tags: [] - }]); + all: [], + none: [] + }], + result: 'passed', + tags: [] + }]); done(); }, isNotCalled); }); @@ -502,7 +502,7 @@ describe('runRules', function () { assert.equal(results.incomplete[1].id, 'incomplete-2'); assert.include(results.incomplete[1].description, - 'An error occured while running this rule'); + 'An error occured while running this rule'); done(); }); }); @@ -539,7 +539,7 @@ describe('runRules', function () { assert.equal(results.incomplete[1].id, 'incomplete-2'); assert.include(results.incomplete[1].description, - 'An error occured while running this rule'); + 'An error occured while running this rule'); done(); }); }); diff --git a/test/core/public/run.js b/test/core/public/run.js index 2262b0250a..ce1f2a7b42 100644 --- a/test/core/public/run.js +++ b/test/core/public/run.js @@ -159,6 +159,7 @@ describe('axe.run', function () { describe('promise result', function () { + /*eslint indent: 0*/ it('returns an error to catch if axe fails', (!window.Promise) ? undefined : function (done) { axe._runRules = function (ctxt, opt, resolve, reject) { @@ -421,7 +422,7 @@ describe('axe.run iframes', function () { return node.target.length === 1 && node.target[0] === '#target'; }), 'one result from top frame'); assert.isTrue(violation.nodes.some(function(node) { - return node.target.length === 2 && + return node.target.length === 2 && node.target[0] === '#fixture > iframe'; }), 'one result from iframe'); window.clearTimeout(safetyTimeout); @@ -455,5 +456,5 @@ describe('axe.run iframes', function () { frame.src = '../mock/frames/test.html'; fixture.appendChild(frame); - }); + }); }); diff --git a/test/core/reporters/helpers/process-aggregate.js b/test/core/reporters/helpers/process-aggregate.js index e8dcf5bab9..734f0e06cb 100644 --- a/test/core/reporters/helpers/process-aggregate.js +++ b/test/core/reporters/helpers/process-aggregate.js @@ -1,290 +1,290 @@ describe('helpers.processAggregate', function () { - 'use strict'; - var results, options; - - beforeEach(function () { - results = [{ - id: 'passed-rule', - passes: [{ - result: 'passed', - node: { - element: document.createElement('div'), - selector: 'header > .thing', - source: '
Thing
', - xpath: '/header/div[@class="thing"]' - }, - any: [{ - id: 'passed-rule', - relatedNodes: [{ - element: document.createElement('div'), - selector: 'footer > .thing', - source: '
Thing
', - xpath: '/footer/div[@class="thing"]', - }] - }], - all: [], - none: [] - }, { - result: 'passed', - node: { - element: document.createElement('div'), - selector: 'main > .thing', - source: '
Thing
', - xpath: '/main/div[@class="thing"]' - }, - any: [{ - id: 'passed-rule', - relatedNodes: [{ - element: document.createElement('div'), - selector: 'footer > .thing', - source: '
Thing
', - xpath: '/footer/div[@class="thing"]', - }] - }], - all: [], - none: [] - }], - inapplicable: [], - incomplete: [], - violations: [] - }, { - id: 'failed-rule', - violations: [{ - result: 'failed', - node: { - selector: '#dopel', - source: '', - xpath: '/main/input[@id="dopel"]', - fromFrame: true - }, - any: [{ - id: 'failed-rule', - relatedNodes: [{ - element: document.createElement('input'), - selector: '#dopel', - source: '', - xpath: '/main/input[@id="dopel"]', - fromFrame: true - }] - }], - all: [], - none: [] - }, { - result: 'failed', - node: { - selector: '#dopell', - source: '', - xpath: '/header/input[@id="dopell"]', - fromFrame: true - }, - any: [{ - id: 'failed-rule', - relatedNodes: [{ - element: document.createElement('input'), - selector: '#dopell', - source: '', - xpath: '/header/input[@id="dopell"]', - fromFrame: true - }] - }], - all: [], - none: [] - }], - inapplicable: [], - passes: [], - incomplete: [] - }]; - }); - - it('should add a `timestamp` property to the `resultObject`', function () { - var resultObject = helpers.processAggregate(results, {}); - assert.isDefined(resultObject.timestamp); - }); - - it('should add a `url` property to the `resultObject`', function () { - var resultObject = helpers.processAggregate(results, {}); - assert.isDefined(resultObject.url); - }); - - it('should remove the `result` property from each node in each ruleResult', function () { - assert.isDefined(results.find(function (r) { - return r.id === 'passed-rule'; - }).passes[0].result); - - var resultObject = helpers.processAggregate(results, {}); - var ruleResult = resultObject.passes.find(function (r) { - return r.id === 'passed-rule'; - }); - assert.isUndefined(ruleResult.nodes[0].result); - }); - - it('should remove the `node` property from each node in each ruleResult', function () { - assert.isDefined(results.find(function (r) { - return r.id === 'passed-rule'; - }).passes[0].node); - - var resultObject = helpers.processAggregate(results, {}); - var ruleResult = resultObject.passes.find(function (r) { - return r.id === 'passed-rule'; - }); - assert.isUndefined(ruleResult.nodes[0].node); - }); - - describe('`options` argument', function () { - - describe('`resultTypes` option', function () { - - it('should reduce the unwanted result types to 1 in the `resultObject`', function () { - var resultObject = helpers.processAggregate(results, { resultTypes: ['violations'] }); - assert.isDefined(resultObject.passes); - assert.equal(resultObject.passes[0].nodes.length, 1); - assert.isDefined(resultObject.violations); - assert.equal(resultObject.violations[0].nodes.length, 2); - resultObject = helpers.processAggregate(results, { resultTypes: ['passes'] }); - assert.equal(resultObject.passes[0].nodes.length, 2); - assert.equal(resultObject.violations[0].nodes.length, 1); - assert.isDefined(resultObject.incomplete); - assert.isDefined(resultObject.inapplicable); - }); - }); - - describe('`elementRef` option', function () { - - describe('when set to true', function () { - - before(function () { - options = { elementRef: true }; - }); - - describe('when node\'s, or relatedNode\'s, `fromFrame` equals false', function () { - it('should add an `element` property to the subResult nodes or relatedNodes', function () { - var resultObject = helpers.processAggregate(results, options); - assert.isDefined(resultObject.passes[0].nodes[0].element); - assert.isDefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].element); - }); - }); - - describe('when node\'s, or relatedNode\'s, `fromFrame` equals true', function () { - it('should NOT add an `element` property to the subResult nodes or relatedNodes', function () { - var resultObject = helpers.processAggregate(results, options); - assert.isUndefined(resultObject.violations[0].nodes[0].element); - assert.isUndefined(resultObject.violations[0].nodes[0].any[0].relatedNodes[0].element); - }); - }); - }); - - describe('when set to false', function () { - - before(function () { - options = { elementRef: false }; - }); - - it('should NOT add an `element` property to the subResult nodes or relatedNodes', function () { - var resultObject = helpers.processAggregate(results, options); - assert.isUndefined(resultObject.passes[0].nodes[0].element); - assert.isUndefined(resultObject.violations[0].nodes[0].element); - assert.isUndefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].element); - assert.isUndefined(resultObject.violations[0].nodes[0].any[0].relatedNodes[0].element); - }); - }); - - describe('when not set at all', function () { - - it('should NOT add an `element` property to the subResult nodes or relatedNodes', function () { - var resultObject = helpers.processAggregate(results, {}); - assert.isUndefined(resultObject.passes[0].nodes[0].element); - assert.isUndefined(resultObject.violations[0].nodes[0].element); - assert.isUndefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].element); - assert.isUndefined(resultObject.violations[0].nodes[0].any[0].relatedNodes[0].element); - }); - }); - }); - - describe('`selectors` option', function () { - - describe('when set to false', function () { - - before(function () { - options = { selectors: false }; - }); - - describe('when node\'s, or relatedNode\'s, `fromFrame` equals true', function () { - it('should add a `target` property to the subResult nodes or relatedNodes', function () { - var resultObject = helpers.processAggregate(results, options); - assert.isDefined(resultObject.violations[0].nodes[0].target); - assert.isDefined(resultObject.violations[0].nodes[0].any[0].relatedNodes[0].target); - }); - }); - - describe('when node\'s, or relatedNode\'s, `fromFrame` equals false', function () { - it('should NOT add a `target` property to the subResult nodes or relatedNodes', function () { - var resultObject = helpers.processAggregate(results, options); - assert.isUndefined(resultObject.passes[0].nodes[0].target); - assert.isUndefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].target); - }); - }); - }); - - describe('when set to true', function () { - - before(function () { - options = { selectors: true }; - }); - - it('should add a `target` property to the subResult nodes or relatedNodes', function () { - var resultObject = helpers.processAggregate(results, options); - assert.isDefined(resultObject.passes[0].nodes[0].target); - assert.isDefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].target); - }); - }); - - describe('when not set at all', function () { - - it('should add a `target` property to the subResult nodes or relatedNodes', function () { - var resultObject = helpers.processAggregate(results, {}); - assert.isDefined(resultObject.passes[0].nodes[0].target); - assert.isDefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].target); - }); - }); - }); - - describe('`xpath` option', function () { - - describe('when set to true', function () { - - before(function () { - options = { xpath: true }; - }); - - it('should add an `xpath` property to the subResult nodes or relatedNodes', function () { - var resultObject = helpers.processAggregate(results, options); - assert.isDefined(resultObject.passes[0].nodes[0].xpath); - assert.isDefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].xpath); - }); - }); - - describe('when set to false', function () { - - before(function () { - options = { xpath: false }; - }); - - it('should NOT add an `xpath` property to the subResult nodes or relatedNodes', function () { - var resultObject = helpers.processAggregate(results, options); - assert.isUndefined(resultObject.passes[0].nodes[0].xpath); - assert.isUndefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].xpath); - }); - }); - - describe('when not set at all', function () { - - it('should NOT add an `xpath` property to the subResult nodes or relatedNodes', function () { - var resultObject = helpers.processAggregate(results, {}); - assert.isUndefined(resultObject.passes[0].nodes[0].xpath); - assert.isUndefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].xpath); - }); - }); - }); - }); + 'use strict'; + var results, options; + + beforeEach(function () { + results = [{ + id: 'passed-rule', + passes: [{ + result: 'passed', + node: { + element: document.createElement('div'), + selector: 'header > .thing', + source: '
Thing
', + xpath: '/header/div[@class="thing"]' + }, + any: [{ + id: 'passed-rule', + relatedNodes: [{ + element: document.createElement('div'), + selector: 'footer > .thing', + source: '
Thing
', + xpath: '/footer/div[@class="thing"]', + }] + }], + all: [], + none: [] + }, { + result: 'passed', + node: { + element: document.createElement('div'), + selector: 'main > .thing', + source: '
Thing
', + xpath: '/main/div[@class="thing"]' + }, + any: [{ + id: 'passed-rule', + relatedNodes: [{ + element: document.createElement('div'), + selector: 'footer > .thing', + source: '
Thing
', + xpath: '/footer/div[@class="thing"]', + }] + }], + all: [], + none: [] + }], + inapplicable: [], + incomplete: [], + violations: [] + }, { + id: 'failed-rule', + violations: [{ + result: 'failed', + node: { + selector: '#dopel', + source: '', + xpath: '/main/input[@id="dopel"]', + fromFrame: true + }, + any: [{ + id: 'failed-rule', + relatedNodes: [{ + element: document.createElement('input'), + selector: '#dopel', + source: '', + xpath: '/main/input[@id="dopel"]', + fromFrame: true + }] + }], + all: [], + none: [] + }, { + result: 'failed', + node: { + selector: '#dopell', + source: '', + xpath: '/header/input[@id="dopell"]', + fromFrame: true + }, + any: [{ + id: 'failed-rule', + relatedNodes: [{ + element: document.createElement('input'), + selector: '#dopell', + source: '', + xpath: '/header/input[@id="dopell"]', + fromFrame: true + }] + }], + all: [], + none: [] + }], + inapplicable: [], + passes: [], + incomplete: [] + }]; + }); + + it('should add a `timestamp` property to the `resultObject`', function () { + var resultObject = helpers.processAggregate(results, {}); + assert.isDefined(resultObject.timestamp); + }); + + it('should add a `url` property to the `resultObject`', function () { + var resultObject = helpers.processAggregate(results, {}); + assert.isDefined(resultObject.url); + }); + + it('should remove the `result` property from each node in each ruleResult', function () { + assert.isDefined(results.find(function (r) { + return r.id === 'passed-rule'; + }).passes[0].result); + + var resultObject = helpers.processAggregate(results, {}); + var ruleResult = resultObject.passes.find(function (r) { + return r.id === 'passed-rule'; + }); + assert.isUndefined(ruleResult.nodes[0].result); + }); + + it('should remove the `node` property from each node in each ruleResult', function () { + assert.isDefined(results.find(function (r) { + return r.id === 'passed-rule'; + }).passes[0].node); + + var resultObject = helpers.processAggregate(results, {}); + var ruleResult = resultObject.passes.find(function (r) { + return r.id === 'passed-rule'; + }); + assert.isUndefined(ruleResult.nodes[0].node); + }); + + describe('`options` argument', function () { + + describe('`resultTypes` option', function () { + + it('should reduce the unwanted result types to 1 in the `resultObject`', function () { + var resultObject = helpers.processAggregate(results, { resultTypes: ['violations'] }); + assert.isDefined(resultObject.passes); + assert.equal(resultObject.passes[0].nodes.length, 1); + assert.isDefined(resultObject.violations); + assert.equal(resultObject.violations[0].nodes.length, 2); + resultObject = helpers.processAggregate(results, { resultTypes: ['passes'] }); + assert.equal(resultObject.passes[0].nodes.length, 2); + assert.equal(resultObject.violations[0].nodes.length, 1); + assert.isDefined(resultObject.incomplete); + assert.isDefined(resultObject.inapplicable); + }); + }); + + describe('`elementRef` option', function () { + + describe('when set to true', function () { + + before(function () { + options = { elementRef: true }; + }); + + describe('when node\'s, or relatedNode\'s, `fromFrame` equals false', function () { + it('should add an `element` property to the subResult nodes or relatedNodes', function () { + var resultObject = helpers.processAggregate(results, options); + assert.isDefined(resultObject.passes[0].nodes[0].element); + assert.isDefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].element); + }); + }); + + describe('when node\'s, or relatedNode\'s, `fromFrame` equals true', function () { + it('should NOT add an `element` property to the subResult nodes or relatedNodes', function () { + var resultObject = helpers.processAggregate(results, options); + assert.isUndefined(resultObject.violations[0].nodes[0].element); + assert.isUndefined(resultObject.violations[0].nodes[0].any[0].relatedNodes[0].element); + }); + }); + }); + + describe('when set to false', function () { + + before(function () { + options = { elementRef: false }; + }); + + it('should NOT add an `element` property to the subResult nodes or relatedNodes', function () { + var resultObject = helpers.processAggregate(results, options); + assert.isUndefined(resultObject.passes[0].nodes[0].element); + assert.isUndefined(resultObject.violations[0].nodes[0].element); + assert.isUndefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].element); + assert.isUndefined(resultObject.violations[0].nodes[0].any[0].relatedNodes[0].element); + }); + }); + + describe('when not set at all', function () { + + it('should NOT add an `element` property to the subResult nodes or relatedNodes', function () { + var resultObject = helpers.processAggregate(results, {}); + assert.isUndefined(resultObject.passes[0].nodes[0].element); + assert.isUndefined(resultObject.violations[0].nodes[0].element); + assert.isUndefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].element); + assert.isUndefined(resultObject.violations[0].nodes[0].any[0].relatedNodes[0].element); + }); + }); + }); + + describe('`selectors` option', function () { + + describe('when set to false', function () { + + before(function () { + options = { selectors: false }; + }); + + describe('when node\'s, or relatedNode\'s, `fromFrame` equals true', function () { + it('should add a `target` property to the subResult nodes or relatedNodes', function () { + var resultObject = helpers.processAggregate(results, options); + assert.isDefined(resultObject.violations[0].nodes[0].target); + assert.isDefined(resultObject.violations[0].nodes[0].any[0].relatedNodes[0].target); + }); + }); + + describe('when node\'s, or relatedNode\'s, `fromFrame` equals false', function () { + it('should NOT add a `target` property to the subResult nodes or relatedNodes', function () { + var resultObject = helpers.processAggregate(results, options); + assert.isUndefined(resultObject.passes[0].nodes[0].target); + assert.isUndefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].target); + }); + }); + }); + + describe('when set to true', function () { + + before(function () { + options = { selectors: true }; + }); + + it('should add a `target` property to the subResult nodes or relatedNodes', function () { + var resultObject = helpers.processAggregate(results, options); + assert.isDefined(resultObject.passes[0].nodes[0].target); + assert.isDefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].target); + }); + }); + + describe('when not set at all', function () { + + it('should add a `target` property to the subResult nodes or relatedNodes', function () { + var resultObject = helpers.processAggregate(results, {}); + assert.isDefined(resultObject.passes[0].nodes[0].target); + assert.isDefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].target); + }); + }); + }); + + describe('`xpath` option', function () { + + describe('when set to true', function () { + + before(function () { + options = { xpath: true }; + }); + + it('should add an `xpath` property to the subResult nodes or relatedNodes', function () { + var resultObject = helpers.processAggregate(results, options); + assert.isDefined(resultObject.passes[0].nodes[0].xpath); + assert.isDefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].xpath); + }); + }); + + describe('when set to false', function () { + + before(function () { + options = { xpath: false }; + }); + + it('should NOT add an `xpath` property to the subResult nodes or relatedNodes', function () { + var resultObject = helpers.processAggregate(results, options); + assert.isUndefined(resultObject.passes[0].nodes[0].xpath); + assert.isUndefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].xpath); + }); + }); + + describe('when not set at all', function () { + + it('should NOT add an `xpath` property to the subResult nodes or relatedNodes', function () { + var resultObject = helpers.processAggregate(results, {}); + assert.isUndefined(resultObject.passes[0].nodes[0].xpath); + assert.isUndefined(resultObject.passes[0].nodes[0].any[0].relatedNodes[0].xpath); + }); + }); + }); + }); }); diff --git a/test/core/utils/aggregateNodeResults.js b/test/core/utils/aggregateNodeResults.js index a5aaef0660..b3e64d2ccd 100644 --- a/test/core/utils/aggregateNodeResults.js +++ b/test/core/utils/aggregateNodeResults.js @@ -11,24 +11,24 @@ describe('axe.utils.aggregateNodeResults', function() { var args = [].slice.call(arguments); return args.map(function (node) { ['any','all','none'] - .forEach(function (type) { - if (typeof node[type] === 'undefined') { - node[type] = []; - } else if (Array.isArray(node[type])) { - node[type] = node[type].map(function (val) { - if (typeof val !== 'object') { - return { result: val }; - } else { - return val; + .forEach(function (type) { + if (typeof node[type] === 'undefined') { + node[type] = []; + } else if (Array.isArray(node[type])) { + node[type] = node[type].map(function (val) { + if (typeof val !== 'object') { + return { result: val }; + } else { + return val; + } + }); + } else { + if (typeof node[type] !== 'object') { + node[type] = { result: node[type] }; } - }); - } else { - if (typeof node[type] !== 'object') { - node[type] = { result: node[type] }; + node[type] = [ node[type] ]; } - node[type] = [ node[type] ]; - } - }); + }); return node; }); } @@ -111,6 +111,7 @@ describe('axe.utils.aggregateNodeResults', function() { }); it('should raise the highest "raisedMetadata" on failing checks', function() { + /*eslint indent:0 */ var ruleResult = axe.utils.aggregateNodeResults( createTestResults({ none: { result: true, impact: 'moderate' }, any: { result: true, impact: 'minor' }, diff --git a/test/core/utils/aggregateResult.js b/test/core/utils/aggregateResult.js index 0ba024d915..c93dd43820 100644 --- a/test/core/utils/aggregateResult.js +++ b/test/core/utils/aggregateResult.js @@ -2,122 +2,122 @@ describe('axe.utils.aggregateResult', function () { 'use strict'; var results, - _results = [{ - id: 'gimmeLabel', - helpUrl: 'things', - description: 'something nifty', - tags: ['tag1'], - result: 'passed', - violations: [], - passes: [{ + _results = [{ + id: 'gimmeLabel', + helpUrl: 'things', + description: 'something nifty', + tags: ['tag1'], result: 'passed', - any: [{ - result: true, - data: 'minkey' - }], - all: [], - none: [], - node: { - selector: ['minkey'], - frames: [], - source: 'chimp' - } - }] - }, { - id: 'bypass', - description: 'something even more nifty', - tags: ['tag3'], - impact: 'monkeys', - result: 'failed', - passes: [], - violations: [{ - result: 'failed', + violations: [], + passes: [{ + result: 'passed', + any: [{ + result: true, + data: 'minkey' + }], + all: [], + none: [], + node: { + selector: ['minkey'], + frames: [], + source: 'chimp' + } + }] + }, { + id: 'bypass', + description: 'something even more nifty', + tags: ['tag3'], impact: 'monkeys', - none: [{ - data: 'foon', + result: 'failed', + passes: [], + violations: [{ + result: 'failed', impact: 'monkeys', - result: true - }], - any: [], - all: [], - node: { - selector: ['foon'], - source: 'telephone' - } - }] - }, { - id: 'idkStuff', - description: 'something more nifty', - pageLevel: true, - result: 'failed', - impact: 'cats', - tags: ['tag2'], - passes: [{ - result: 'passed', - any: [{ - result: true, - data: 'minkey' - }], - all: [], - none: [], - node: { - selector: ['minkey'], - frames: [], - source: 'chimp' - } - }], - violations: [{ + none: [{ + data: 'foon', + impact: 'monkeys', + result: true + }], + any: [], + all: [], + node: { + selector: ['foon'], + source: 'telephone' + } + }] + }, { + id: 'idkStuff', + description: 'something more nifty', + pageLevel: true, result: 'failed', - all: [{ - result: false, - data: 'pillock', - impact: 'cats' + impact: 'cats', + tags: ['tag2'], + passes: [{ + result: 'passed', + any: [{ + result: true, + data: 'minkey' + }], + all: [], + none: [], + node: { + selector: ['minkey'], + frames: [], + source: 'chimp' + } }], - any: [], - none: [], - node: { - selector: ['q', 'r', 'pillock'], - source: 'george bush' - }, - impact: 'cats' - }], - incomplete: [{ - result: 'cantTell', - any: [{ - result: 0, - data: 'minkey' + violations: [{ + result: 'failed', + all: [{ + result: false, + data: 'pillock', + impact: 'cats' + }], + any: [], + none: [], + node: { + selector: ['q', 'r', 'pillock'], + source: 'george bush' + }, + impact: 'cats' }], - all: [], - none: [], - node: { - selector: ['minkey'], - frames: [], - source: 'chimp' - } - }] - }, { - id: 'blinky', - description: 'something awesome', - tags: ['tag4'], - result: 'inapplicable', - passes: [{ - result: 'passed', - any: [{ - shouldIBeHere: 'no, this should be inapplicable!', - result: true, - data: 'minkey' + incomplete: [{ + result: 'cantTell', + any: [{ + result: 0, + data: 'minkey' + }], + all: [], + none: [], + node: { + selector: ['minkey'], + frames: [], + source: 'chimp' + } + }] + }, { + id: 'blinky', + description: 'something awesome', + tags: ['tag4'], + result: 'inapplicable', + passes: [{ + result: 'passed', + any: [{ + shouldIBeHere: 'no, this should be inapplicable!', + result: true, + data: 'minkey' + }], + all: [], + none: [], + node: { + selector: ['minkey'], + frames: [], + source: 'chimp' + } }], - all: [], - none: [], - node: { - selector: ['minkey'], - frames: [], - source: 'chimp' - } - }], - violations: [], - incomplete: [] - }]; + violations: [], + incomplete: [] + }]; beforeEach(function() { results = JSON.parse(JSON.stringify(_results)); @@ -181,4 +181,4 @@ describe('axe.utils.aggregateResult', function () { assert.equal(resultObject.inapplicable[0].description, input[0].description); }); -}); \ No newline at end of file +}); diff --git a/test/core/utils/check-helper.js b/test/core/utils/check-helper.js index ef5baad70f..04f660112f 100644 --- a/test/core/utils/check-helper.js +++ b/test/core/utils/check-helper.js @@ -70,50 +70,50 @@ describe('axe.utils.checkHelper', function () { }); it('should accept NodeList', function () { fixture.innerHTML = '
'; - var target = {}, - helper = axe.utils.checkHelper(target, noop); - helper.relatedNodes(fixture.children); - assert.lengthOf(target.relatedNodes, 2); - assert.instanceOf(target.relatedNodes[0], DqElement); - assert.instanceOf(target.relatedNodes[1], DqElement); - assert.equal(target.relatedNodes[0].element, fixture.children[0]); - assert.equal(target.relatedNodes[1].element, fixture.children[1]); + var target = {}, + helper = axe.utils.checkHelper(target, noop); + helper.relatedNodes(fixture.children); + assert.lengthOf(target.relatedNodes, 2); + assert.instanceOf(target.relatedNodes[0], DqElement); + assert.instanceOf(target.relatedNodes[1], DqElement); + assert.equal(target.relatedNodes[0].element, fixture.children[0]); + assert.equal(target.relatedNodes[1].element, fixture.children[1]); }); it('should accept a single Node', function () { fixture.innerHTML = '
'; - var target = {}, - helper = axe.utils.checkHelper(target, noop); - helper.relatedNodes(fixture.firstChild); - assert.lengthOf(target.relatedNodes, 1); - assert.instanceOf(target.relatedNodes[0], DqElement); - assert.equal(target.relatedNodes[0].element, fixture.firstChild); + var target = {}, + helper = axe.utils.checkHelper(target, noop); + helper.relatedNodes(fixture.firstChild); + assert.lengthOf(target.relatedNodes, 1); + assert.instanceOf(target.relatedNodes[0], DqElement); + assert.equal(target.relatedNodes[0].element, fixture.firstChild); }); it('should accept an Array', function () { fixture.innerHTML = '
'; - var target = {}, - helper = axe.utils.checkHelper(target, noop); - helper.relatedNodes(Array.prototype.slice.call(fixture.children)); - assert.lengthOf(target.relatedNodes, 2); - assert.instanceOf(target.relatedNodes[0], DqElement); - assert.instanceOf(target.relatedNodes[1], DqElement); - assert.equal(target.relatedNodes[0].element, fixture.children[0]); - assert.equal(target.relatedNodes[1].element, fixture.children[1]); + var target = {}, + helper = axe.utils.checkHelper(target, noop); + helper.relatedNodes(Array.prototype.slice.call(fixture.children)); + assert.lengthOf(target.relatedNodes, 2); + assert.instanceOf(target.relatedNodes[0], DqElement); + assert.instanceOf(target.relatedNodes[1], DqElement); + assert.equal(target.relatedNodes[0].element, fixture.children[0]); + assert.equal(target.relatedNodes[1].element, fixture.children[1]); }); it('should accept an array-like Object', function () { fixture.innerHTML = '
'; - var target = {}, - helper = axe.utils.checkHelper(target, noop); - var nodes = { - 0: fixture.children[0], - 1: fixture.children[1], - length: 2 - }; - helper.relatedNodes(nodes); - assert.lengthOf(target.relatedNodes, 2); - assert.instanceOf(target.relatedNodes[0], DqElement); - assert.instanceOf(target.relatedNodes[1], DqElement); - assert.equal(target.relatedNodes[0].element, fixture.children[0]); - assert.equal(target.relatedNodes[1].element, fixture.children[1]); + var target = {}, + helper = axe.utils.checkHelper(target, noop); + var nodes = { + 0: fixture.children[0], + 1: fixture.children[1], + length: 2 + }; + helper.relatedNodes(nodes); + assert.lengthOf(target.relatedNodes, 2); + assert.instanceOf(target.relatedNodes[0], DqElement); + assert.instanceOf(target.relatedNodes[1], DqElement); + assert.equal(target.relatedNodes[0].element, fixture.children[0]); + assert.equal(target.relatedNodes[1].element, fixture.children[1]); }); }); diff --git a/test/core/utils/collect-results-from-frames.js b/test/core/utils/collect-results-from-frames.js index 208ac8851a..66564a1575 100644 --- a/test/core/utils/collect-results-from-frames.js +++ b/test/core/utils/collect-results-from-frames.js @@ -28,12 +28,13 @@ describe('axe.utils.collectResultsFromFrames', function () { var context = new Context(document); axe._tree = axe.utils.getFlattenedTree(document.documentElement); axe.utils.collectResultsFromFrames(context, {}, 'stuff', 'morestuff', noop, - function (err) { - assert.instanceOf(err, Error); - assert.equal(err.message.split(/: /)[0], 'Axe in frame timed out'); - window.setTimeout = orig; - done(); - }); + function (err) { + assert.instanceOf(err, Error); + assert.equal(err.message.split(/: /)[0], 'Axe in frame timed out'); + window.setTimeout = orig; + done(); + } + ); }); frame.id = 'level0'; @@ -60,12 +61,13 @@ describe('axe.utils.collectResultsFromFrames', function () { var params = { frameWaitTime: 90000 }; axe._tree = axe.utils.getFlattenedTree(document.documentElement); axe.utils.collectResultsFromFrames(context, params, 'stuff', 'morestuff', noop, - function (err) { - assert.instanceOf(err, Error); - assert.equal(err.message.split(/: /)[0], 'Axe in frame timed out'); - window.setTimeout = orig; - done(); - }); + function (err) { + assert.instanceOf(err, Error); + assert.equal(err.message.split(/: /)[0], 'Axe in frame timed out'); + window.setTimeout = orig; + done(); + } + ); }); frame.id = 'level0'; @@ -113,12 +115,12 @@ describe('axe.utils.collectResultsFromFrames', function () { var context = new Context(document); axe._tree = axe.utils.getFlattenedTree(document.documentElement); axe.utils.collectResultsFromFrames(context, {}, 'command', 'params', noop, - function (err) { - - assert.instanceOf(err, Error); - assert.equal(err.message.split(/\n/)[0], 'error in axe.throw'); - done(); - }); + function (err) { + assert.instanceOf(err, Error); + assert.equal(err.message.split(/\n/)[0], 'error in axe.throw'); + done(); + } + ); }); diff --git a/test/core/utils/contains.js b/test/core/utils/contains.js index e7cf49174e..0f849aa390 100644 --- a/test/core/utils/contains.js +++ b/test/core/utils/contains.js @@ -89,11 +89,11 @@ describe('axe.utils.contains', function () { it('should work with slotted elements inside shadow DOM', function () { var tree, node1, node2; - function createContentSlotted() { - var group = document.createElement('div'); - group.innerHTML = '
Stuff
'; - return group; - } + function createContentSlotted() { + var group = document.createElement('div'); + group.innerHTML = '
Stuff
'; + return group; + } function makeShadowTree(node) { var root = node.attachShadow({mode: 'open'}); var div = document.createElement('div'); @@ -120,4 +120,4 @@ describe('axe.utils.contains', function () { assert.isTrue(axe.utils.contains(outer, inner)); assert.isFalse(axe.utils.contains(inner, outer)); }); -}); \ No newline at end of file +}); diff --git a/test/core/utils/dq-element.js b/test/core/utils/dq-element.js index c47ad9fcef..b36323c136 100644 --- a/test/core/utils/dq-element.js +++ b/test/core/utils/dq-element.js @@ -85,6 +85,7 @@ describe('DqElement', function () { describe('selector', function () { it('should call axe.utils.getSelector', function () { + /*eslint no-unused-vars: 0*/ var orig = axe.utils.getSelector; var success = false; var expected = { monkeys: 'bananas' }; @@ -113,6 +114,7 @@ describe('DqElement', function () { describe('xpath', function () { it('should call axe.utils.getXpath', function () { + /*eslint no-unused-vars: 0*/ var orig = axe.utils.getXpath; var success = false; var expected = { monkeys: 'bananas' }; diff --git a/test/core/utils/escape-selector.js b/test/core/utils/escape-selector.js index 3d72c36d30..f2c25fc127 100644 --- a/test/core/utils/escape-selector.js +++ b/test/core/utils/escape-selector.js @@ -1,4 +1,4 @@ -/*jshint maxstatements: false */ +/*eslint max-statements: 0 */ describe('utils.escapeSelector', function () { 'use strict'; var escapeSelector = axe.utils.escapeSelector; diff --git a/test/core/utils/find-by.js b/test/core/utils/find-by.js index 0abcb1603a..f84d16e2e4 100644 --- a/test/core/utils/find-by.js +++ b/test/core/utils/find-by.js @@ -3,28 +3,28 @@ describe('axe.utils.findBy', function () { it('should find the first matching object', function () { var array = [{ - id: 'monkeys', - foo: 'bar' - }, { - id: 'bananas' - }, { - id: 'monkeys', - bar: 'baz' - }]; + id: 'monkeys', + foo: 'bar' + }, { + id: 'bananas' + }, { + id: 'monkeys', + bar: 'baz' + }]; assert.equal(axe.utils.findBy(array, 'id', 'monkeys'), array[0]); }); it('should return undefined with no match', function () { var array = [{ - id: 'monkeys', - foo: 'bar' - }, { - id: 'bananas' - }, { - id: 'monkeys', - bar: 'baz' - }]; + id: 'monkeys', + foo: 'bar' + }, { + id: 'bananas' + }, { + id: 'monkeys', + bar: 'baz' + }]; assert.isUndefined(axe.utils.findBy(array, 'id', 'macaque')); @@ -34,4 +34,4 @@ describe('axe.utils.findBy', function () { assert.isUndefined(axe.utils.findBy(null, 'id', 'macaque')); }); -}); \ No newline at end of file +}); diff --git a/test/core/utils/get-all-checks.js b/test/core/utils/get-all-checks.js index 02f257b96e..d721ddbbd1 100644 --- a/test/core/utils/get-all-checks.js +++ b/test/core/utils/get-all-checks.js @@ -6,52 +6,52 @@ describe('axe.utils.getAllChecks', function () { assert.isFunction(axe.utils.getAllChecks); }); - it('should concatenate all 3 check collections', function () { - var r = { - any: ['any:foo', 'any:bar'], - all: ['all:foo', 'all:bar'], - none: ['none:foo', 'none:bar'] - }; - assert.deepEqual(axe.utils.getAllChecks(r), [ - 'any:foo', 'any:bar', - 'all:foo', 'all:bar', - 'none:foo', 'none:bar' - ]); - }); + it('should concatenate all 3 check collections', function () { + var r = { + any: ['any:foo', 'any:bar'], + all: ['all:foo', 'all:bar'], + none: ['none:foo', 'none:bar'] + }; + assert.deepEqual(axe.utils.getAllChecks(r), [ + 'any:foo', 'any:bar', + 'all:foo', 'all:bar', + 'none:foo', 'none:bar' + ]); + }); it('should safely ignore missing collections - all', function () { - var r = { - any: ['any:foo', 'any:bar'], - none: ['none:foo', 'none:bar'] - }; - assert.deepEqual(axe.utils.getAllChecks(r), [ - 'any:foo', 'any:bar', - 'none:foo', 'none:bar' - ]); + var r = { + any: ['any:foo', 'any:bar'], + none: ['none:foo', 'none:bar'] + }; + assert.deepEqual(axe.utils.getAllChecks(r), [ + 'any:foo', 'any:bar', + 'none:foo', 'none:bar' + ]); }); it('should safely ignore missing collections - any', function () { - var r = { - all: ['all:foo', 'all:bar'], - none: ['none:foo', 'none:bar'] - }; - assert.deepEqual(axe.utils.getAllChecks(r), [ - 'all:foo', 'all:bar', - 'none:foo', 'none:bar' - ]); + var r = { + all: ['all:foo', 'all:bar'], + none: ['none:foo', 'none:bar'] + }; + assert.deepEqual(axe.utils.getAllChecks(r), [ + 'all:foo', 'all:bar', + 'none:foo', 'none:bar' + ]); }); it('should safely ignore missing collections - none', function () { - var r = { - any: ['any:foo', 'any:bar'], - all: ['all:foo', 'all:bar'] - }; - assert.deepEqual(axe.utils.getAllChecks(r), [ - 'any:foo', 'any:bar', - 'all:foo', 'all:bar' - ]); + var r = { + any: ['any:foo', 'any:bar'], + all: ['all:foo', 'all:bar'] + }; + assert.deepEqual(axe.utils.getAllChecks(r), [ + 'any:foo', 'any:bar', + 'all:foo', 'all:bar' + ]); }); }); diff --git a/test/core/utils/get-check-option.js b/test/core/utils/get-check-option.js index 0ac9be7151..46dce1a1aa 100644 --- a/test/core/utils/get-check-option.js +++ b/test/core/utils/get-check-option.js @@ -4,89 +4,89 @@ describe('axe.utils.getCheckOption', function () { it('should prefer options from rules', function () { assert.deepEqual(axe.utils.getCheckOption({ - id: 'bananas', - enabled: 'fail', - options: 'fail' - }, 'monkeys', { - rules: { - monkeys: { - checks: { - bananas: { - enabled: 'yes', - options: 'please' - } + id: 'bananas', + enabled: 'fail', + options: 'fail' + }, 'monkeys', { + rules: { + monkeys: { + checks: { + bananas: { + enabled: 'yes', + options: 'please' } } - }, - checks: { - bananas: { - enabled: 'nope', - options: 'jerk' - } } - }), { - enabled: 'yes', - options: 'please', - absolutePaths: undefined - }); + }, + checks: { + bananas: { + enabled: 'nope', + options: 'jerk' + } + } + }), { + enabled: 'yes', + options: 'please', + absolutePaths: undefined + }); }); it('should fallback to global check options if not defined on the rule', function () { assert.deepEqual(axe.utils.getCheckOption({ - id: 'bananas', - enabled: 'fail', - options: 'fail' - }, 'monkeys', { - rules: { - monkeys: { - checks: { - bananas: { - enabled: 'yes' - } + id: 'bananas', + enabled: 'fail', + options: 'fail' + }, 'monkeys', { + rules: { + monkeys: { + checks: { + bananas: { + enabled: 'yes' } } - }, - checks: { - bananas: { - enabled: 'nope', - options: 'please' - } } - }), { - enabled: 'yes', - options: 'please', - absolutePaths: undefined - }); + }, + checks: { + bananas: { + enabled: 'nope', + options: 'please' + } + } + }), { + enabled: 'yes', + options: 'please', + absolutePaths: undefined + }); }); it('should prefer fallback to global check options if not defined on the rule', function () { assert.deepEqual(axe.utils.getCheckOption({ - id: 'bananas', - enabled: 'fail', - options: 'fail' - }, 'monkeys', { - checks: { - bananas: { - enabled: 'yes', - options: 'please' - } + id: 'bananas', + enabled: 'fail', + options: 'fail' + }, 'monkeys', { + checks: { + bananas: { + enabled: 'yes', + options: 'please' } - }), { - enabled: 'yes', - options: 'please', - absolutePaths: undefined - }); + } + }), { + enabled: 'yes', + options: 'please', + absolutePaths: undefined + }); }); it('should otherwise use the check', function () { assert.deepEqual(axe.utils.getCheckOption({ - id: 'bananas', - enabled: 'yes', - options: 'please' - }, 'monkeys', {}), { - enabled: 'yes', - options: 'please', - absolutePaths: undefined - }); + id: 'bananas', + enabled: 'yes', + options: 'please' + }, 'monkeys', {}), { + enabled: 'yes', + options: 'please', + absolutePaths: undefined + }); }); it('passes absolutePaths option along', function () { @@ -103,4 +103,4 @@ describe('axe.utils.getCheckOption', function () { }); }); -}); \ No newline at end of file +}); diff --git a/test/core/utils/get-friendly-uri-end.js b/test/core/utils/get-friendly-uri-end.js index ddb220b670..49a1f959dd 100644 --- a/test/core/utils/get-friendly-uri-end.js +++ b/test/core/utils/get-friendly-uri-end.js @@ -1,52 +1,52 @@ describe('axe.utils.getFriendlyUriEnd', function () { - 'use strict'; - var getFriendlyUriEnd = axe.utils.getFriendlyUriEnd; - - it('returns a domain name', function () { - assert.equal('deque.com', getFriendlyUriEnd('http://deque.com')); - assert.equal('deque.com/', getFriendlyUriEnd('https://www.deque.com/')); - assert.equal('docs.deque.com/', getFriendlyUriEnd('//docs.deque.com/')); - }); - - it('returns a filename', function () { - assert.equal('contact/', getFriendlyUriEnd('../../contact/')); - assert.equal('contact/', getFriendlyUriEnd('http://deque.com/contact/')); - assert.equal('contact', getFriendlyUriEnd('/contact')); - assert.equal('contact.html', getFriendlyUriEnd('/contact.html')); - }); - - it('returns a hash URI', function () { - assert.equal('#footer', getFriendlyUriEnd('#footer')); - assert.equal('contact.html#footer', getFriendlyUriEnd('/contact.html#footer')); - }); - - it('returns undef when there is a query', function () { - assert.isUndefined(getFriendlyUriEnd('/contact?')); - assert.isUndefined(getFriendlyUriEnd('/contact?foo=bar')); - }); - - it('returns undef for index files', function () { - assert.isUndefined(getFriendlyUriEnd('/index.cfs')); - assert.isUndefined(getFriendlyUriEnd('/index')); - }); - - it('returns undef when the result is too short', function () { - assert.isUndefined(getFriendlyUriEnd('/i.html')); - assert.isUndefined(getFriendlyUriEnd('/dq')); - }); - - it('returns undef when the result is too long', function () { - assert.isDefined(getFriendlyUriEnd('/abcd.html', { maxLength: 50 })); - assert.isDefined(getFriendlyUriEnd('#foo-bar-baz', { maxLength: 50 })); - assert.isDefined(getFriendlyUriEnd('//deque.com', { maxLength: 50 })); - - assert.isUndefined(getFriendlyUriEnd('/abcd.html', { maxLength: 5 })); - assert.isUndefined(getFriendlyUriEnd('#foo-bar-baz', { maxLength: 5 })); - assert.isUndefined(getFriendlyUriEnd('//deque.com', { maxLength: 5 })); - }); - - it('returns undef when the result has too many numbers', function () { - assert.isUndefined(getFriendlyUriEnd('123456.html')); - }); + 'use strict'; + var getFriendlyUriEnd = axe.utils.getFriendlyUriEnd; + + it('returns a domain name', function () { + assert.equal('deque.com', getFriendlyUriEnd('http://deque.com')); + assert.equal('deque.com/', getFriendlyUriEnd('https://www.deque.com/')); + assert.equal('docs.deque.com/', getFriendlyUriEnd('//docs.deque.com/')); + }); + + it('returns a filename', function () { + assert.equal('contact/', getFriendlyUriEnd('../../contact/')); + assert.equal('contact/', getFriendlyUriEnd('http://deque.com/contact/')); + assert.equal('contact', getFriendlyUriEnd('/contact')); + assert.equal('contact.html', getFriendlyUriEnd('/contact.html')); + }); + + it('returns a hash URI', function () { + assert.equal('#footer', getFriendlyUriEnd('#footer')); + assert.equal('contact.html#footer', getFriendlyUriEnd('/contact.html#footer')); + }); + + it('returns undef when there is a query', function () { + assert.isUndefined(getFriendlyUriEnd('/contact?')); + assert.isUndefined(getFriendlyUriEnd('/contact?foo=bar')); + }); + + it('returns undef for index files', function () { + assert.isUndefined(getFriendlyUriEnd('/index.cfs')); + assert.isUndefined(getFriendlyUriEnd('/index')); + }); + + it('returns undef when the result is too short', function () { + assert.isUndefined(getFriendlyUriEnd('/i.html')); + assert.isUndefined(getFriendlyUriEnd('/dq')); + }); + + it('returns undef when the result is too long', function () { + assert.isDefined(getFriendlyUriEnd('/abcd.html', { maxLength: 50 })); + assert.isDefined(getFriendlyUriEnd('#foo-bar-baz', { maxLength: 50 })); + assert.isDefined(getFriendlyUriEnd('//deque.com', { maxLength: 50 })); + + assert.isUndefined(getFriendlyUriEnd('/abcd.html', { maxLength: 5 })); + assert.isUndefined(getFriendlyUriEnd('#foo-bar-baz', { maxLength: 5 })); + assert.isUndefined(getFriendlyUriEnd('//deque.com', { maxLength: 5 })); + }); + + it('returns undef when the result has too many numbers', function () { + assert.isUndefined(getFriendlyUriEnd('123456.html')); + }); }); diff --git a/test/core/utils/get-selector.js b/test/core/utils/get-selector.js index 15b7d66b99..957a6912d4 100644 --- a/test/core/utils/get-selector.js +++ b/test/core/utils/get-selector.js @@ -476,10 +476,10 @@ describe('axe.utils.getSelector', function () { it('should work on complex namespaced elements', function () { fixture.innerHTML = '' + - 'x' + - '' + - 'x' + - '' + + 'x' + + '' + + 'x' + + '' + ''; axe._tree = axe.utils.getFlattenedTree(document.documentElement); @@ -493,14 +493,14 @@ describe('axe.utils.getSelector', function () { it('should not use ignored attributes', function () { var node = document.createElement('div'); var ignoredAttributes = [ - 'style', - 'selected', 'checked', - 'disabled', 'tabindex', - 'aria-checked', 'aria-selected', - 'aria-invalid', 'aria-activedescendant', - 'aria-busy', 'aria-disabled', 'aria-expanded', - 'aria-grabbed', 'aria-pressed', 'aria-valuenow' - ]; + 'style', + 'selected', 'checked', + 'disabled', 'tabindex', + 'aria-checked', 'aria-selected', + 'aria-invalid', 'aria-activedescendant', + 'aria-busy', 'aria-disabled', 'aria-expanded', + 'aria-grabbed', 'aria-pressed', 'aria-valuenow' + ]; ignoredAttributes.forEach(function (att) { node.setAttribute(att, 'true'); }); diff --git a/test/core/utils/merge-results.js b/test/core/utils/merge-results.js index f8c83bcfb9..e9238b8771 100644 --- a/test/core/utils/merge-results.js +++ b/test/core/utils/merge-results.js @@ -1,11 +1,11 @@ describe('axe.utils.mergeResults', function () { - 'use strict'; - - it('should normalize empty results', function () { - var result = axe.utils.mergeResults([{ results: [] }, { results: [{ id: 'a', result: 'b'}]}]); - assert.deepEqual(result, [{ - id: 'a', - result: 'b' - }]); - }); + 'use strict'; + + it('should normalize empty results', function () { + var result = axe.utils.mergeResults([{ results: [] }, { results: [{ id: 'a', result: 'b'}]}]); + assert.deepEqual(result, [{ + id: 'a', + result: 'b' + }]); + }); }); diff --git a/test/core/utils/qsa.js b/test/core/utils/qsa.js index 4326315a27..246acaeffe 100644 --- a/test/core/utils/qsa.js +++ b/test/core/utils/qsa.js @@ -18,56 +18,56 @@ Vnode.prototype.getAttribute = function (att) { function getTestDom() { 'use strict'; return [{ - actualNode: new Vnode('html'), + actualNode: new Vnode('html'), + children: [{ + actualNode: new Vnode('body'), children: [{ - actualNode: new Vnode('body'), + actualNode: new Vnode('div', 'first',[{ + key: 'data-a11yhero', + value: 'faulkner' + }]), + shadowId: 'a', children: [{ - actualNode: new Vnode('div', 'first',[{ - key: 'data-a11yhero', - value: 'faulkner' - }]), + actualNode: new Vnode('ul'), shadowId: 'a', children: [{ - actualNode: new Vnode('ul'), + actualNode: new Vnode('li', 'breaking'), shadowId: 'a', - children: [{ - actualNode: new Vnode('li', 'breaking'), - shadowId: 'a', - children: [] - },{ - actualNode: new Vnode('li', 'breaking'), - shadowId: 'a', - children: [] - }] + children: [] + },{ + actualNode: new Vnode('li', 'breaking'), + shadowId: 'a', + children: [] }] - }, { - actualNode: new Vnode('div', '', [], 'one'), - children: [] - }, { - actualNode: new Vnode('div', 'second third'), + }] + }, { + actualNode: new Vnode('div', '', [], 'one'), + children: [] + }, { + actualNode: new Vnode('div', 'second third'), + shadowId: 'b', + children: [{ + actualNode: new Vnode('ul'), shadowId: 'b', children: [{ - actualNode: new Vnode('ul'), + actualNode: new Vnode('li', undefined, [{ + key: 'role', + value: 'tab' + }], 'one'), shadowId: 'b', - children: [{ - actualNode: new Vnode('li', undefined, [{ - key: 'role', - value: 'tab' - }], 'one'), - shadowId: 'b', - children: [] - },{ - actualNode: new Vnode('li', undefined, [{ - key: 'role', - value: 'button' - }], 'one'), - shadowId: 'c', - children: [] - }] + children: [] + },{ + actualNode: new Vnode('li', undefined, [{ + key: 'role', + value: 'button' + }], 'one'), + shadowId: 'c', + children: [] }] }] }] - }]; + }] + }]; } describe('axe.utils.querySelectorAllFilter', function () { diff --git a/test/core/utils/queue.js b/test/core/utils/queue.js index 1fb7e7badd..48240ec4bb 100644 --- a/test/core/utils/queue.js +++ b/test/core/utils/queue.js @@ -200,6 +200,7 @@ describe('axe.utils.queue', function () { }); it('is called when the reject method is called', function (done) { + /*eslint no-unused-vars: 0*/ var q = axe.utils.queue(); var errorsCaught = 0; @@ -269,4 +270,4 @@ describe('axe.utils.queue', function () { }); -}); \ No newline at end of file +}); diff --git a/test/core/utils/respondable.js b/test/core/utils/respondable.js index f1cfce45db..d13249b72d 100644 --- a/test/core/utils/respondable.js +++ b/test/core/utils/respondable.js @@ -458,13 +458,14 @@ describe('axe.utils.respondable', function () { }); axe.utils.respondable(window, 'owlman', 'help!', true, - function (data) { - if (!wait) { - assert.instanceOf(data, TypeError); - assert.equal(data.message.split(/\n/)[0], expected); - done(); + function (data) { + if (!wait) { + assert.instanceOf(data, TypeError); + assert.equal(data.message.split(/\n/)[0], expected); + done(); + } } - }); + ); }); it('returns an error if the subscribe method throws', function (done) { @@ -479,13 +480,14 @@ describe('axe.utils.respondable', function () { // otherwise it would delete the response before subscribe // gets to react axe.utils.respondable(window, 'owlman', null, true, - function (data) { - if (!wait) { - assert.instanceOf(data, TypeError); - assert.equal(data.message.split(/\n/)[0], expected); - done(); + function (data) { + if (!wait) { + assert.instanceOf(data, TypeError); + assert.equal(data.message.split(/\n/)[0], expected); + done(); + } } - }); + ); }); }); diff --git a/test/core/utils/scroll-state.js b/test/core/utils/scroll-state.js index 85e01eb135..c97ba80c85 100644 --- a/test/core/utils/scroll-state.js +++ b/test/core/utils/scroll-state.js @@ -1,163 +1,163 @@ describe('axe.utils.getScrollState', function () { - 'use strict'; - var mockWin; - var getScrollState = axe.utils.getScrollState; - - var fixture = document.getElementById('fixture'); - - beforeEach(function () { - mockWin = { - pageXOffset: 1, - pageYOffset: 3, - document: { - documentElement: { - children: [], - scrollTop: 3, - scrollHeight: 4 - } - }, - body: { children: [] } - }; - fixture.innerHTML = ''; - }); - - it('should be a function', function () { - assert.isFunction(getScrollState); - }); - - it('takes the window object as an optional argument', function () { - assert.deepEqual( - getScrollState(), - getScrollState(window) - ); - }); - - it('returns the window as the first item, if pageXOffset is supported', function () { - assert.deepEqual( - getScrollState(mockWin)[0], - { - elm: mockWin, - top: mockWin.pageYOffset, - left: mockWin.pageXOffset - } - ); - }); - - it('returns the html as the first item, if pageXOffset is not supported', function () { - mockWin.pageYOffset = undefined; - mockWin.pageXOffset = undefined; - var html = mockWin.document.documentElement; - - assert.deepEqual( - getScrollState(mockWin)[0], - { - elm: html, - top: html.scrollTop, - left: html.scrollLeft - } - ); - }); - - it('grabs scrollTop and scrollLeft from all descendants of body', function () { - fixture.innerHTML = - '
' + - '
Han Solo
' + - '
' + - '
Chewbacca
' + - '
' + - '
'; - - var tgt1 = document.getElementById('tgt1'); - var tgt2 = document.getElementById('tgt2'); - tgt1.scrollTop = 10; - tgt2.scrollTop = 20; - - var scrollState = getScrollState(); - - assert.deepEqual( - scrollState.find(function (scroll) { return scroll.elm === tgt1; }), - { elm: tgt1, top: 10, left: 0 } - ); - assert.deepEqual( - scrollState.find(function (scroll) { return scroll.elm === tgt2; }), - { elm: tgt2, top: 20, left: 0 } - ); - }); - - it('ignores elements with overflow visible', function () { - fixture.innerHTML = - '
' + - '
Han Solo
' + - '
'; - - var tgt1 = document.getElementById('tgt1'); - var tgt2 = document.getElementById('tgt2'); - var scrollState = getScrollState(); - - assert.isUndefined( - scrollState.find(function (scroll) { return scroll.elm === tgt1; }) - ); - assert.isUndefined( - scrollState.find(function (scroll) { return scroll.elm === tgt2; }) - ); - }); - - it('ignores elements that do not overflow', function () { - fixture.innerHTML = - '
' + - '
Han Solo
' + - '
' + - '
Chewbacca
' + - '
' + - '
'; - - var tgt1 = document.getElementById('tgt1'); - var tgt2 = document.getElementById('tgt2'); - var scrollState = getScrollState(); - - assert.isUndefined( - scrollState.find(function (scroll) { return scroll.elm === tgt1; }) - ); - assert.isUndefined( - scrollState.find(function (scroll) { return scroll.elm === tgt2; }) - ); - }); + 'use strict'; + var mockWin; + var getScrollState = axe.utils.getScrollState; + + var fixture = document.getElementById('fixture'); + + beforeEach(function () { + mockWin = { + pageXOffset: 1, + pageYOffset: 3, + document: { + documentElement: { + children: [], + scrollTop: 3, + scrollHeight: 4 + } + }, + body: { children: [] } + }; + fixture.innerHTML = ''; + }); + + it('should be a function', function () { + assert.isFunction(getScrollState); + }); + + it('takes the window object as an optional argument', function () { + assert.deepEqual( + getScrollState(), + getScrollState(window) + ); + }); + + it('returns the window as the first item, if pageXOffset is supported', function () { + assert.deepEqual( + getScrollState(mockWin)[0], + { + elm: mockWin, + top: mockWin.pageYOffset, + left: mockWin.pageXOffset + } + ); + }); + + it('returns the html as the first item, if pageXOffset is not supported', function () { + mockWin.pageYOffset = undefined; + mockWin.pageXOffset = undefined; + var html = mockWin.document.documentElement; + + assert.deepEqual( + getScrollState(mockWin)[0], + { + elm: html, + top: html.scrollTop, + left: html.scrollLeft + } + ); + }); + + it('grabs scrollTop and scrollLeft from all descendants of body', function () { + fixture.innerHTML = + '
' + + '
Han Solo
' + + '
' + + '
Chewbacca
' + + '
' + + '
'; + + var tgt1 = document.getElementById('tgt1'); + var tgt2 = document.getElementById('tgt2'); + tgt1.scrollTop = 10; + tgt2.scrollTop = 20; + + var scrollState = getScrollState(); + + assert.deepEqual( + scrollState.find(function (scroll) { return scroll.elm === tgt1; }), + { elm: tgt1, top: 10, left: 0 } + ); + assert.deepEqual( + scrollState.find(function (scroll) { return scroll.elm === tgt2; }), + { elm: tgt2, top: 20, left: 0 } + ); + }); + + it('ignores elements with overflow visible', function () { + fixture.innerHTML = + '
' + + '
Han Solo
' + + '
'; + + var tgt1 = document.getElementById('tgt1'); + var tgt2 = document.getElementById('tgt2'); + var scrollState = getScrollState(); + + assert.isUndefined( + scrollState.find(function (scroll) { return scroll.elm === tgt1; }) + ); + assert.isUndefined( + scrollState.find(function (scroll) { return scroll.elm === tgt2; }) + ); + }); + + it('ignores elements that do not overflow', function () { + fixture.innerHTML = + '
' + + '
Han Solo
' + + '
' + + '
Chewbacca
' + + '
' + + '
'; + + var tgt1 = document.getElementById('tgt1'); + var tgt2 = document.getElementById('tgt2'); + var scrollState = getScrollState(); + + assert.isUndefined( + scrollState.find(function (scroll) { return scroll.elm === tgt1; }) + ); + assert.isUndefined( + scrollState.find(function (scroll) { return scroll.elm === tgt2; }) + ); + }); }); describe('axe.utils.setScrollState', function () { - 'use strict'; - var setScrollState = axe.utils.setScrollState; - - var fixture = document.getElementById('fixture'); - afterEach(function () { - fixture.innerHTML = ''; - }); - - it('should be a function', function () { - assert.isFunction(setScrollState); - }); - - it('sets scrollTop and scrollLeft for regular nodes', function () { - var elm1 = {}, elm2 = {}; - setScrollState([ - { elm: elm1, top: 10, left: 20 }, - { elm: elm2, top: 30, left: 40 }, - ]); - - assert.deepEqual(elm1, { scrollTop: 10, scrollLeft: 20 }); - assert.deepEqual(elm2, { scrollTop: 30, scrollLeft: 40 }); - }); - - it('calls scroll() for the window element', function () { - var called; - var winScroll = window.scroll; - window.scroll = function (top, left) { - called = { top: top, left: left }; - }; - setScrollState([ - { elm: window, top: 10, left: 20 } - ]); - assert.deepEqual(called, { top: 10, left: 20 }); - window.scroll = winScroll; - }); + 'use strict'; + var setScrollState = axe.utils.setScrollState; + + var fixture = document.getElementById('fixture'); + afterEach(function () { + fixture.innerHTML = ''; + }); + + it('should be a function', function () { + assert.isFunction(setScrollState); + }); + + it('sets scrollTop and scrollLeft for regular nodes', function () { + var elm1 = {}, elm2 = {}; + setScrollState([ + { elm: elm1, top: 10, left: 20 }, + { elm: elm2, top: 30, left: 40 }, + ]); + + assert.deepEqual(elm1, { scrollTop: 10, scrollLeft: 20 }); + assert.deepEqual(elm2, { scrollTop: 30, scrollLeft: 40 }); + }); + + it('calls scroll() for the window element', function () { + var called; + var winScroll = window.scroll; + window.scroll = function (top, left) { + called = { top: top, left: left }; + }; + setScrollState([ + { elm: window, top: 10, left: 20 } + ]); + assert.deepEqual(called, { top: 10, left: 20 }); + window.scroll = winScroll; + }); }); diff --git a/test/core/utils/select.js b/test/core/utils/select.js index 6629024aae..140dc0064e 100644 --- a/test/core/utils/select.js +++ b/test/core/utils/select.js @@ -130,7 +130,7 @@ describe('axe.utils.select', function () { '
'; var result = axe.utils.select('.bananas', { include: [axe.utils.getFlattenedTree($id('zero'))[0], - axe.utils.getFlattenedTree($id('one'))[0]] }); + axe.utils.getFlattenedTree($id('one'))[0]] }); assert.deepEqual(result.map(function (n) { return n.actualNode; }), [$id('target1'), $id('target2')]); @@ -151,4 +151,4 @@ describe('axe.utils.select', function () { }); -}); \ No newline at end of file +}); diff --git a/test/core/utils/send-command-to-frame.js b/test/core/utils/send-command-to-frame.js index e320696925..4fb2ac044f 100644 --- a/test/core/utils/send-command-to-frame.js +++ b/test/core/utils/send-command-to-frame.js @@ -1,110 +1,110 @@ describe('axe.utils.sendCommandToFrame', function () { - 'use strict'; + 'use strict'; - var fixture = document.getElementById('fixture'); + var fixture = document.getElementById('fixture'); afterEach(function () { - fixture.innerHTML = ''; - axe._tree = undefined; - axe._selectorData = undefined; - }); - - var assertNotCalled = function () { - assert.ok(false, 'should not be called'); - }; - - it('should timeout if there is no response from frame', function (done) { - var orig = window.setTimeout; - window.setTimeout = function (fn, to) { - if (to === 30000) { - assert.ok('timeout set'); - fn(); - } else { // ping timeout - return orig(fn, to); - } - return 'cats'; - }; - - var frame = document.createElement('iframe'); - frame.addEventListener('load', function () { - axe._tree = axe.utils.getFlattenedTree(document.documentElement); - axe.utils.sendCommandToFrame(frame, {}, function (result) { - assert.equal(result, null); - done(); - }, assertNotCalled); - window.setTimeout = orig; - }); - - frame.id = 'level0'; - frame.src = '../mock/frames/zombie-frame.html'; - fixture.appendChild(frame); - - }); - - it('should respond once when no keepalive', function (done) { - var frame = document.createElement('iframe'); - frame.addEventListener('load', function () { - axe.utils.sendCommandToFrame(frame, { - number: 1 - }, function () { - assert.isTrue(true); - done(); - }, assertNotCalled); - }); - - frame.id = 'level0'; - frame.src = '../mock/frames/responder.html'; - fixture.appendChild(frame); - - }); - - it('should respond multiple times when keepalive', function (done) { - var number = 3; - var called = 0; - var frame = document.createElement('iframe'); - frame.addEventListener('load', function () { - setTimeout(function () { - axe.utils.sendCommandToFrame(frame, { - number: number, - keepalive: true - }, function () { - called += 1; - if (called === number) { - assert.isTrue(true); - done(); - } - }, assertNotCalled); - }, 500); - }); - - frame.id = 'level0'; - frame.src = '../mock/frames/responder.html'; - fixture.appendChild(frame); - - }); - - it('should respond once when no keepalive', function (done) { - var number = 1; - var called = 0; - var frame = document.createElement('iframe'); - frame.addEventListener('load', function () { - axe.utils.sendCommandToFrame(frame, { - number: number - }, function () { - called += 1; - if (called === number) { - assert.isTrue(true); - done(); - } else { - throw new Error ('should not have been called'); - } - }, assertNotCalled); - }); - - frame.id = 'level0'; - frame.src = '../mock/frames/responder.html'; - fixture.appendChild(frame); - - }); + fixture.innerHTML = ''; + axe._tree = undefined; + axe._selectorData = undefined; + }); + + var assertNotCalled = function () { + assert.ok(false, 'should not be called'); + }; + + it('should timeout if there is no response from frame', function (done) { + var orig = window.setTimeout; + window.setTimeout = function (fn, to) { + if (to === 30000) { + assert.ok('timeout set'); + fn(); + } else { // ping timeout + return orig(fn, to); + } + return 'cats'; + }; + + var frame = document.createElement('iframe'); + frame.addEventListener('load', function () { + axe._tree = axe.utils.getFlattenedTree(document.documentElement); + axe.utils.sendCommandToFrame(frame, {}, function (result) { + assert.equal(result, null); + done(); + }, assertNotCalled); + window.setTimeout = orig; + }); + + frame.id = 'level0'; + frame.src = '../mock/frames/zombie-frame.html'; + fixture.appendChild(frame); + + }); + + it('should respond once when no keepalive', function (done) { + var frame = document.createElement('iframe'); + frame.addEventListener('load', function () { + axe.utils.sendCommandToFrame(frame, { + number: 1 + }, function () { + assert.isTrue(true); + done(); + }, assertNotCalled); + }); + + frame.id = 'level0'; + frame.src = '../mock/frames/responder.html'; + fixture.appendChild(frame); + + }); + + it('should respond multiple times when keepalive', function (done) { + var number = 3; + var called = 0; + var frame = document.createElement('iframe'); + frame.addEventListener('load', function () { + setTimeout(function () { + axe.utils.sendCommandToFrame(frame, { + number: number, + keepalive: true + }, function () { + called += 1; + if (called === number) { + assert.isTrue(true); + done(); + } + }, assertNotCalled); + }, 500); + }); + + frame.id = 'level0'; + frame.src = '../mock/frames/responder.html'; + fixture.appendChild(frame); + + }); + + it('should respond once when no keepalive', function (done) { + var number = 1; + var called = 0; + var frame = document.createElement('iframe'); + frame.addEventListener('load', function () { + axe.utils.sendCommandToFrame(frame, { + number: number + }, function () { + called += 1; + if (called === number) { + assert.isTrue(true); + done(); + } else { + throw new Error ('should not have been called'); + } + }, assertNotCalled); + }); + + frame.id = 'level0'; + frame.src = '../mock/frames/responder.html'; + fixture.appendChild(frame); + + }); }); diff --git a/test/integration/full/async/async.js b/test/integration/full/async/async.js index 2d867d2a9c..3cedfe7ba6 100644 --- a/test/integration/full/async/async.js +++ b/test/integration/full/async/async.js @@ -1,102 +1,103 @@ describe('async rule test', function () { - 'use strict'; - var results; + 'use strict'; + var results; - function AsyncCheck (node) { - var check = this; - var done = check.async(); - setTimeout(function () { - var dataOut = node.getAttribute('data-out'); - check.data(dataOut); - switch (dataOut) { - case 'true': - return done(true); + function AsyncCheck (node) { + /*eslint indent: 0*/ + var check = this; + var done = check.async(); + setTimeout(function () { + var dataOut = node.getAttribute('data-out'); + check.data(dataOut); + switch (dataOut) { + case 'true': + return done(true); - case 'false': - return done(false); + case 'false': + return done(false); - default: - return done(undefined); - } - }, 10); - } + default: + return done(undefined); + } + }, 10); + } - before(function (done) { - axe.configure({ - rules: [{ - id: 'my-async', - metadata: { - description: '', - help: '', - helpUrl: 'https://example.com/dylang' - }, - selector: '.async', - any: ['my-async'], - all: [], - none: [], - tags: ['wcag2aa'] - }], - checks: [{ - id: 'my-async', - options: [], - evaluate: AsyncCheck.toString(), - metadata: { - impact: 'critical', - messages: { - pass: 'function (out) { return "passed with " + out.data }', - fail: 'function (out) { return "failed with " + out.data }', - incomplete: 'function (out) { return "incomplete with " + out.data }' - } - } - }] - }); + before(function (done) { + axe.configure({ + rules: [{ + id: 'my-async', + metadata: { + description: '', + help: '', + helpUrl: 'https://example.com/dylang' + }, + selector: '.async', + any: ['my-async'], + all: [], + none: [], + tags: ['wcag2aa'] + }], + checks: [{ + id: 'my-async', + options: [], + evaluate: AsyncCheck.toString(), + metadata: { + impact: 'critical', + messages: { + pass: 'function (out) { return "passed with " + out.data }', + fail: 'function (out) { return "failed with " + out.data }', + incomplete: 'function (out) { return "incomplete with " + out.data }' + } + } + }] + }); - axe.run({ runOnly: { type: 'rule', values: ['my-async'] } }, function (err, r) { - assert.isNull(err); - results = r; - done(); - }); - }); + axe.run({ runOnly: { type: 'rule', values: ['my-async'] } }, function (err, r) { + assert.isNull(err); + results = r; + done(); + }); + }); - describe('violations', function () { - it('should find 1', function () { - assert.lengthOf(results.violations, 1); - assert.lengthOf(results.violations[0].nodes, 1); - }); + describe('violations', function () { + it('should find 1', function () { + assert.lengthOf(results.violations, 1); + assert.lengthOf(results.violations[0].nodes, 1); + }); - it('should find #violation', function () { - assert.equal( - results.violations[0].nodes[0].any[0].message, - 'failed with false'); - assert.deepEqual(results.violations[0].nodes[0].target, ['#violation']); - }); - }); + it('should find #violation', function () { + assert.equal( + results.violations[0].nodes[0].any[0].message, + 'failed with false'); + assert.deepEqual(results.violations[0].nodes[0].target, ['#violation']); + }); + }); - describe('passes', function () { - it('should find 1', function () { - assert.lengthOf(results.passes, 1); - assert.lengthOf(results.passes[0].nodes, 1); - }); + describe('passes', function () { + it('should find 1', function () { + assert.lengthOf(results.passes, 1); + assert.lengthOf(results.passes[0].nodes, 1); + }); - it('should find #pass', function () { - assert.equal( - results.passes[0].nodes[0].any[0].message, - 'passed with true'); - assert.deepEqual(results.passes[0].nodes[0].target, ['#pass']); - }); - }); + it('should find #pass', function () { + assert.equal( + results.passes[0].nodes[0].any[0].message, + 'passed with true'); + assert.deepEqual(results.passes[0].nodes[0].target, ['#pass']); + }); + }); - describe('incomplete', function () { - it('should find 1', function () { - assert.lengthOf(results.incomplete, 1); - assert.lengthOf(results.incomplete[0].nodes, 1); - }); + describe('incomplete', function () { + it('should find 1', function () { + assert.lengthOf(results.incomplete, 1); + assert.lengthOf(results.incomplete[0].nodes, 1); + }); - it('should find #incomplete', function () { - assert.equal( - results.incomplete[0].nodes[0].any[0].message, - 'incomplete with undefined'); - assert.deepEqual(results.incomplete[0].nodes[0].target, ['#incomplete']); - }); - }); + it('should find #incomplete', function () { + assert.equal( + results.incomplete[0].nodes[0].any[0].message, + 'incomplete with undefined'); + assert.deepEqual(results.incomplete[0].nodes[0].target, ['#incomplete']); + }); + }); }); diff --git a/test/integration/full/frame-wait-time/frame-wait-time.js b/test/integration/full/frame-wait-time/frame-wait-time.js index af0df787cb..920cb493c0 100644 --- a/test/integration/full/frame-wait-time/frame-wait-time.js +++ b/test/integration/full/frame-wait-time/frame-wait-time.js @@ -1,43 +1,43 @@ describe('frame-wait-time option', function () { - 'use strict'; + 'use strict'; - before(function (done) { - if (document.readyState !== 'complete') { - window.addEventListener('load', done.bind(this, null)); - } else { - done(); - } - }); + before(function (done) { + if (document.readyState !== 'complete') { + window.addEventListener('load', done.bind(this, null)); + } else { + done(); + } + }); - describe('when set', function () { - var opts = { - frameWaitTime: 1 - }; + 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(); - }); - }); - }); + 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(); + }); + }); + }); - describe('when not set', function () { + describe('when not set', function () { - it('should use the default frame timeout', function (done) { - axe.run('main', function (err, res) { - assert.isNull(err); - assert.isAbove(res.violations.length, 0); - done(); - }); - }); - }); + it('should use the default frame timeout', function (done) { + axe.run('main', function (err, res) { + assert.isNull(err); + assert.isAbove(res.violations.length, 0); + done(); + }); + }); + }); }); diff --git a/test/integration/full/umd/mock-define.js b/test/integration/full/umd/mock-define.js index eaad645499..d17b8e47db 100644 --- a/test/integration/full/umd/mock-define.js +++ b/test/integration/full/umd/mock-define.js @@ -1,4 +1,4 @@ -/* jshint unused: false */ +/* eslint no-unused-vars: 0 */ // Mock define method to collect calls to define var defineCalls = []; diff --git a/test/integration/full/umd/mock-module-exports.js b/test/integration/full/umd/mock-module-exports.js index 8a5a6af294..cf8971a249 100644 --- a/test/integration/full/umd/mock-module-exports.js +++ b/test/integration/full/umd/mock-module-exports.js @@ -1,4 +1,4 @@ -/* jshint unused: false */ +/* eslint no-unused-vars: 0 */ // Mock module object to test module.export being set var module = { diff --git a/test/integration/rules/runner.js b/test/integration/rules/runner.js index 616b2f119f..82f779a81f 100644 --- a/test/integration/rules/runner.js +++ b/test/integration/rules/runner.js @@ -48,37 +48,37 @@ }); test[collection] - .forEach(function (selector) { - it('should find ' + JSON.stringify(selector), function () { - if (!nodes) { - assert(false, 'there are no ' + collection); - return; - } + .forEach(function (selector) { + it('should find ' + JSON.stringify(selector), function () { + if (!nodes) { + assert(false, 'there are no ' + collection); + return; + } - var matches = nodes.filter(function (node) { - for (var i=0; i < selector.length; i++) { - if (node.target[i] !== selector[i]) { - return false; - } - } - return node.target.length === selector.length; - }); - matches.forEach(function (node) { - // remove each node we find - nodes.splice(nodes.indexOf(node), 1); - }); + var matches = nodes.filter(function (node) { + for (var i=0; i < selector.length; i++) { + if (node.target[i] !== selector[i]) { + return false; + } + } + return node.target.length === selector.length; + }); + matches.forEach(function (node) { + // remove each node we find + nodes.splice(nodes.indexOf(node), 1); + }); - if (matches.length === 0) { - assert(false, 'Element not found'); + if (matches.length === 0) { + assert(false, 'Element not found'); - } else if (matches.length === 1) { - assert(true, 'Element found'); + } else if (matches.length === 1) { + assert(true, 'Element found'); - } else { - assert(false, 'Found ' + matches.length + ' elements which match the target'); - } + } else { + assert(false, 'Found ' + matches.length + ' elements which match the target'); + } + }); }); - }); it('should not return other results', function () { if (typeof nodes !== 'undefined') { diff --git a/test/rule-matches/heading-matches.js b/test/rule-matches/heading-matches.js index efb4946553..9a6df66535 100644 --- a/test/rule-matches/heading-matches.js +++ b/test/rule-matches/heading-matches.js @@ -1,55 +1,55 @@ describe('heading-matches', function () { - 'use strict'; - - var fixture = document.getElementById('fixture'); - var rule; - - beforeEach(function () { - rule = axe._audit.rules.find(function (rule) { - return rule.id === 'empty-heading'; - }); - }); - - afterEach(function () { - fixture.innerHTML = ''; - }); - - it('is a function', function () { - assert.isFunction(rule.matches); - }); - - it('should return false on elements that are not headings', function () { - var div = document.createElement('div'); - assert.isFalse(rule.matches(div)); - }); - - it('should return true on elements with "heading" in the role', function () { - var div = document.createElement('div'); - div.setAttribute('role', 'heading'); - assert.isTrue(rule.matches(div)); - - div.setAttribute('role', 'slider heading'); - assert.isTrue(rule.matches(div)); - }); - - it('should return true on regular headings without roles', function () { - var h1 = document.createElement('h1'); - var h2 = document.createElement('h2'); - var h3 = document.createElement('h3'); - assert.isTrue(rule.matches(h1)); - assert.isTrue(rule.matches(h2)); - assert.isTrue(rule.matches(h3)); - }); - - it('should return false on headings with their role changes', function () { - var h1 = document.createElement('h1'); - h1.setAttribute('role', 'banner'); - assert.isFalse(rule.matches(h1)); - }); - - it('should return true on headings with their role changes to an invalid role', function () { - var h1 = document.createElement('h1'); - h1.setAttribute('role', 'bruce'); - assert.isTrue(rule.matches(h1)); - }); -}); \ No newline at end of file + 'use strict'; + + var fixture = document.getElementById('fixture'); + var rule; + + beforeEach(function () { + rule = axe._audit.rules.find(function (rule) { + return rule.id === 'empty-heading'; + }); + }); + + afterEach(function () { + fixture.innerHTML = ''; + }); + + it('is a function', function () { + assert.isFunction(rule.matches); + }); + + it('should return false on elements that are not headings', function () { + var div = document.createElement('div'); + assert.isFalse(rule.matches(div)); + }); + + it('should return true on elements with "heading" in the role', function () { + var div = document.createElement('div'); + div.setAttribute('role', 'heading'); + assert.isTrue(rule.matches(div)); + + div.setAttribute('role', 'slider heading'); + assert.isTrue(rule.matches(div)); + }); + + it('should return true on regular headings without roles', function () { + var h1 = document.createElement('h1'); + var h2 = document.createElement('h2'); + var h3 = document.createElement('h3'); + assert.isTrue(rule.matches(h1)); + assert.isTrue(rule.matches(h2)); + assert.isTrue(rule.matches(h3)); + }); + + it('should return false on headings with their role changes', function () { + var h1 = document.createElement('h1'); + h1.setAttribute('role', 'banner'); + assert.isFalse(rule.matches(h1)); + }); + + it('should return true on headings with their role changes to an invalid role', function () { + var h1 = document.createElement('h1'); + h1.setAttribute('role', 'bruce'); + assert.isTrue(rule.matches(h1)); + }); +}); diff --git a/test/rule-matches/label-matches.js b/test/rule-matches/label-matches.js index c3d163ba96..a98e06721b 100644 --- a/test/rule-matches/label-matches.js +++ b/test/rule-matches/label-matches.js @@ -1,60 +1,60 @@ describe('label-matches', function () { - 'use strict'; - - var fixture = document.getElementById('fixture'); - var rule; - - beforeEach(function () { - rule = axe._audit.rules.find(function (rule) { - return rule.id === 'label'; - }); - }); - - it('returns true for non-input elements', function () { - fixture.innerHTML = ''; - var target = fixture.querySelector('textarea'); - - assert.isTrue(rule.matches(target)); - }); - - it('returns true for input elements without type', function () { - fixture.innerHTML = ''; - var target = fixture.querySelector('input'); - - assert.isTrue(rule.matches(target)); - }); - - it('returns false for input buttons', function () { - fixture.innerHTML = '' + - '' + - '' + - ''; - - var targets = Array.from(fixture.querySelectorAll('input')); - targets.forEach(function (target) { - assert.isFalse(rule.matches(target)); - }); - }); - - it('returns false for input elements type=hidden', function () { - fixture.innerHTML = ''; - var target = fixture.querySelector('input'); - - assert.isFalse(rule.matches(target)); - }); - - it('returns true for other input types', function () { - fixture.innerHTML = '' + - '' + - '' + - '' + - '' + - '' + - ''; - - var targets = Array.from(fixture.querySelectorAll('input')); - targets.forEach(function (target) { - assert.isTrue(rule.matches(target)); - }); - }); -}); \ No newline at end of file + 'use strict'; + + var fixture = document.getElementById('fixture'); + var rule; + + beforeEach(function () { + rule = axe._audit.rules.find(function (rule) { + return rule.id === 'label'; + }); + }); + + it('returns true for non-input elements', function () { + fixture.innerHTML = ''; + var target = fixture.querySelector('textarea'); + + assert.isTrue(rule.matches(target)); + }); + + it('returns true for input elements without type', function () { + fixture.innerHTML = ''; + var target = fixture.querySelector('input'); + + assert.isTrue(rule.matches(target)); + }); + + it('returns false for input buttons', function () { + fixture.innerHTML = '' + + '' + + '' + + ''; + + var targets = Array.from(fixture.querySelectorAll('input')); + targets.forEach(function (target) { + assert.isFalse(rule.matches(target)); + }); + }); + + it('returns false for input elements type=hidden', function () { + fixture.innerHTML = ''; + var target = fixture.querySelector('input'); + + assert.isFalse(rule.matches(target)); + }); + + it('returns true for other input types', function () { + fixture.innerHTML = '' + + '' + + '' + + '' + + '' + + '' + + ''; + + var targets = Array.from(fixture.querySelectorAll('input')); + targets.forEach(function (target) { + assert.isTrue(rule.matches(target)); + }); + }); +}); diff --git a/test/testutils.js b/test/testutils.js index 1fbcb342ad..b39377079d 100644 --- a/test/testutils.js +++ b/test/testutils.js @@ -1,10 +1,11 @@ +/*eslint indent: 0*/ var testUtils = {}; /** - * Create a check context for mocking/resetting data and relatedNodes in tests - * - * @return Object - */ + * Create a check context for mocking/resetting data and relatedNodes in tests + * + * @return Object + */ testUtils.MockCheckContext = function () { 'use strict'; return { @@ -24,12 +25,12 @@ testUtils.MockCheckContext = function () { }; /** - * Provide an API for determining Shadow DOM v0 and v1 support in tests. - * PhantomJS doesn't have Shadow DOM support, while some browsers do. - * - * @param HTMLDocumentElement The document of the current context - * @return Object - */ + * Provide an API for determining Shadow DOM v0 and v1 support in tests. + * PhantomJS doesn't have Shadow DOM support, while some browsers do. + * + * @param HTMLDocumentElement The document of the current context + * @return Object + */ testUtils.shadowSupport = (function(document) { 'use strict'; var v0 = document.body && typeof document.body.createShadowRoot === 'function', @@ -47,12 +48,12 @@ testUtils.shadowSupport = (function(document) { })(document); /** - * Method for injecting content into a fixture and caching - * the flattened DOM tree (light and Shadow DOM together) - * - * @param Node|String Stuff to go into the fixture (html or DOM node) - * @return HTMLElement - */ + * Method for injecting content into a fixture and caching + * the flattened DOM tree (light and Shadow DOM together) + * + * @param Node|String Stuff to go into the fixture (html or DOM node) + * @return HTMLElement + */ testUtils.fixtureSetup = function (content) { 'use strict'; var fixture = document.querySelector('#fixture'); @@ -66,13 +67,13 @@ testUtils.fixtureSetup = function (content) { return fixture; }; /** - * Create check arguments - * - * @param Node|String Stuff to go into the fixture (html or node) - * @param Object Options argument for the check (optional, default: {}) - * @param String Target for the check, CSS selector (default: '#target') - * @return Array - */ + * Create check arguments + * + * @param Node|String Stuff to go into the fixture (html or node) + * @param Object Options argument for the check (optional, default: {}) + * @param String Target for the check, CSS selector (default: '#target') + * @return Array + */ testUtils.checkSetup = function (content, options, target) { 'use strict'; // Normalize the params @@ -96,15 +97,15 @@ testUtils.checkSetup = function (content, options, target) { }; /** - * Create check arguments with Shadow DOM. Target can be inside or outside of Shadow DOM, queried by - * adding `id="target"` to a fragment. Or specify a custom selector as the `targetSelector` argument. - * - * @param Node|String Stuff to go into the fixture (html string or DOM Node) - * @param Node|String Stuff to go into the shadow boundary (html or node) - * @param Object Options argument for the check (optional, default: {}) - * @param String Target selector for the check, can be inside or outside of Shadow DOM (optional, default: '#target') - * @return Array - */ + * Create check arguments with Shadow DOM. Target can be inside or outside of Shadow DOM, queried by + * adding `id="target"` to a fragment. Or specify a custom selector as the `targetSelector` argument. + * + * @param Node|String Stuff to go into the fixture (html string or DOM Node) + * @param Node|String Stuff to go into the shadow boundary (html or node) + * @param Object Options argument for the check (optional, default: {}) + * @param String Target selector for the check, can be inside or outside of Shadow DOM (optional, default: '#target') + * @return Array + */ testUtils.shadowCheckSetup = function (content, shadowContent, options, targetSelector) { 'use strict'; @@ -150,40 +151,40 @@ testUtils.shadowCheckSetup = function (content, shadowContent, options, targetSe }; /** - * Wait for all nested frames to be loaded - * - * @param Object Window to wait for (optional) - * @param function Callback, called once resolved - */ + * Wait for all nested frames to be loaded + * + * @param Object Window to wait for (optional) + * @param function Callback, called once resolved + */ testUtils.awaitNestedLoad = function awaitNestedLoad(win, cb) { 'use strict'; - if (typeof win === 'function') { - cb = win; - win = window; - } - var document = win.document; - var q = axe.utils.queue(); - - // Wait for page load - q.defer(function (resolve) { - if (document.readyState === 'complete') { - resolve(); - } else { - win.addEventListener('load', resolve); - } - }); - - // Wait for all frames to be loaded - Array.from(document.querySelectorAll('iframe')).forEach(function (frame) { - q.defer(function (resolve) { - return awaitNestedLoad(frame.contentWindow, resolve); - }); - }); - - // Complete (don't pass the args on to the callback) - q.then(function () { - cb(); - }); + if (typeof win === 'function') { + cb = win; + win = window; + } + var document = win.document; + var q = axe.utils.queue(); + + // Wait for page load + q.defer(function (resolve) { + if (document.readyState === 'complete') { + resolve(); + } else { + win.addEventListener('load', resolve); + } + }); + + // Wait for all frames to be loaded + Array.from(document.querySelectorAll('iframe')).forEach(function (frame) { + q.defer(function (resolve) { + return awaitNestedLoad(frame.contentWindow, resolve); + }); + }); + + // Complete (don't pass the args on to the callback) + q.then(function () { + cb(); + }); }; axe.testUtils = testUtils; From 3deb9f85a1e40212374fecc11dd525fcbf0d07ef Mon Sep 17 00:00:00 2001 From: Marcy Sutton Date: Fri, 2 Mar 2018 14:39:48 -0800 Subject: [PATCH 3/5] chore: Update Grunt to latest version Removes vulnerability in grunt-legacy-log/lodash --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 99804828cd..781d5e83b9 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "clone": "~1.0.2", "dot": "~1.0.3", "fs-extra": "^4.0.1", - "grunt": "^1.0.1", + "grunt": "^1.0.2", "grunt-babel": "^6.0.0", "grunt-contrib-clean": "^1.0.0", "grunt-contrib-concat": "^1.0.1", From f5994664557ba1e76de1c9b8658755fe2b5fdc69 Mon Sep 17 00:00:00 2001 From: Marcy Sutton Date: Fri, 2 Mar 2018 14:40:01 -0800 Subject: [PATCH 4/5] chore: Ignore phantomjs-prebuilt in retire.js --- .retireignore.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.retireignore.json b/.retireignore.json index 9629ca5eed..89dbbf5d76 100644 --- a/.retireignore.json +++ b/.retireignore.json @@ -30,5 +30,9 @@ { "path": "node_modules/growl", "justification": "Temporary disabling until vuln is fixed" + }, + { + "path": "node_modules/phantomjs-prebuilt", + "justification": "Temporary disabling until we switch to headless chrome" } ] \ No newline at end of file From 04459649e4a5b2928547d18920b1da197488cb81 Mon Sep 17 00:00:00 2001 From: Marcy Sutton Date: Fri, 2 Mar 2018 14:51:52 -0800 Subject: [PATCH 5/5] chore: Add devDependencies to retireignore.json --- .retireignore.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.retireignore.json b/.retireignore.json index 89dbbf5d76..eba3029354 100644 --- a/.retireignore.json +++ b/.retireignore.json @@ -34,5 +34,29 @@ { "path": "node_modules/phantomjs-prebuilt", "justification": "Temporary disabling until we switch to headless chrome" + }, + { + "path": "node_modules/hawk", + "justification": "Sub-dependency of retire.js, which is being ignored" + }, + { + "path": "node_modules/cryptiles", + "justification": "Sub-dependency of retire.js, which is being ignored" + }, + { + "path": "node_modules/sntp", + "justification": "Sub-dependency of retire.js, which is being ignored" + }, + { + "path": "node_modules/boom", + "justification": "Sub-dependency of retire.js, which is being ignored" + }, + { + "path": "node_modules/hoek", + "justification": "Sub-dependency of retire.js, which is being ignored" + }, + { + "path": "node_modules/grunt-contrib-watch", + "justification": "Ignoring until a new release is out" } ] \ No newline at end of file