From b6ccb80eebba48cb85fdb7297a5906412f3ad46d Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Mon, 24 Sep 2018 12:51:43 -0700 Subject: [PATCH] Axe-core v3.1.2 update --- .travis.yml | 2 +- addon/services/concurrent-axe.js | 41 ++++++ app/instance-initializers/axe-component.js | 17 ++- app/services/concurrent-axe.js | 1 + package.json | 2 +- tests/acceptance/a11y-audit-test.js | 2 +- tests/dummy/app/components/x-text-input.js | 3 +- .../app/templates/components/x-text-input.hbs | 2 +- tests/dummy/app/templates/violations.hbs | 16 +-- .../axe-component-test.js | 118 +++++++++++------- tests/unit/services/concurrent-axe-test.js | 73 +++++++++++ yarn.lock | 6 +- 12 files changed, 222 insertions(+), 61 deletions(-) create mode 100644 addon/services/concurrent-axe.js create mode 100644 app/services/concurrent-axe.js create mode 100644 tests/unit/services/concurrent-axe-test.js diff --git a/.travis.yml b/.travis.yml index 51474a55..d5d5b4b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: node_js node_js: # we recommend testing addons with the same minimum supported node version as Ember CLI # so that your addon works for all apps - - "4" + - "6" sudo: required dist: trusty diff --git a/addon/services/concurrent-axe.js b/addon/services/concurrent-axe.js new file mode 100644 index 00000000..4342fedd --- /dev/null +++ b/addon/services/concurrent-axe.js @@ -0,0 +1,41 @@ +/* global axe */ +import Service from '@ember/service'; +import { next } from '@ember/runloop'; + +export default Service.extend({ + init() { + this._super(...arguments); + this._timer = null; + this._queue = []; + }, + + /** + * Axe v3 contains a concurrency issue which breaks the component auditing feature. + * This service defers axe.run calls on onto the next loop so that concurrent + * axe executions do not occur. + * + * @see(https://github.com/dequelabs/axe-core/issues/1041) + * @public + * @param {HTMLElement} element axe context + * @param {Object} options axe configuration options + * @param {Function} callback axe audit callback + * @return {Void} + */ + run(element, options, callback) { + if (this._timer) { + this._queue.push(arguments); + } else { + this._timer = next(() => { + if (element && element.parentNode) { + axe.run(element, options, callback); + } + + this._timer = null; + + if (this._queue.length) { + this.run(...this._queue.shift()); + } + }); + } + } +}); diff --git a/app/instance-initializers/axe-component.js b/app/instance-initializers/axe-component.js index 629700ac..e56b1994 100644 --- a/app/instance-initializers/axe-component.js +++ b/app/instance-initializers/axe-component.js @@ -9,6 +9,7 @@ import ENV from '../config/environment'; import isBackgroundReplacedElement from 'ember-a11y-testing/utils/is-background-replaced-element'; import formatViolation from 'ember-a11y-testing/utils/format-violation'; import violationsHelper from 'ember-a11y-testing/utils/violations-helper'; +import { inject as service } from '@ember/service'; const VIOLATION_CLASS__LEVEL_1 = 'axe-violation--level-1'; const VIOLATION_CLASS__LEVEL_2 = 'axe-violation--level-2'; @@ -54,6 +55,15 @@ export function initialize() { let turnAuditOff = configuredTurnAuditOff || false; Component.reopen({ + /** + * An Ember service which resolves concurrent axe.run v3 issue. + * + * @public + * @type {Object} + * @see(https://github.com/dequelabs/axe-core/issues/1041) + */ + concurrentAxe: service('concurrent-axe'), + /** * An optional callback to process the results from the a11yCheck. * Defaults to `undefined` if not set in the application's configuration. @@ -138,12 +148,15 @@ export function initialize() { */ audit() { if (this.get('tagName') !== '') { - - axe.a11yCheck(this.$(), this.axeOptions, (results) => { + this.get('concurrentAxe').run(this.element, this.axeOptions, (error, results) => { if (this.get('isDestroyed')) { return; } + if (error) { + throw error; + } + const violations = results.violations; const violationClasses = this.get('violationClasses') || []; const visualNoiseLevel = this.get('visualNoiseLevel'); diff --git a/app/services/concurrent-axe.js b/app/services/concurrent-axe.js new file mode 100644 index 00000000..4a7e7fed --- /dev/null +++ b/app/services/concurrent-axe.js @@ -0,0 +1 @@ +export { default } from 'ember-a11y-testing/services/concurrent-axe'; diff --git a/package.json b/package.json index f69b0804..bdd69571 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "test": "ember try:each" }, "dependencies": { - "axe-core": "^2.6.1", + "axe-core": "^3.1.2", "broccoli-funnel": "^2.0.1", "ember-cli-babel": "^6.8.2", "ember-cli-version-checker": "^2.1.0", diff --git a/tests/acceptance/a11y-audit-test.js b/tests/acceptance/a11y-audit-test.js index 6a8f3de2..4387311b 100644 --- a/tests/acceptance/a11y-audit-test.js +++ b/tests/acceptance/a11y-audit-test.js @@ -93,7 +93,7 @@ test('a11yAudit can accept an options hash as a single argument', function(asser a11yAudit({ runOnly: { type: "rule", - values: [] + values: ["accesskeys"] } }); diff --git a/tests/dummy/app/components/x-text-input.js b/tests/dummy/app/components/x-text-input.js index 264b747f..c0980ff5 100644 --- a/tests/dummy/app/components/x-text-input.js +++ b/tests/dummy/app/components/x-text-input.js @@ -2,6 +2,5 @@ import Component from '@ember/component'; export default Component.extend({ - classNames: ['c-text-input'], - tagName: 'input', + classNames: ['c-text-input'] }); diff --git a/tests/dummy/app/templates/components/x-text-input.hbs b/tests/dummy/app/templates/components/x-text-input.hbs index 330ee755..1e5ebdd7 100644 --- a/tests/dummy/app/templates/components/x-text-input.hbs +++ b/tests/dummy/app/templates/components/x-text-input.hbs @@ -1,6 +1,6 @@ diff --git a/tests/dummy/app/templates/violations.hbs b/tests/dummy/app/templates/violations.hbs index 94cdbc48..3b1ac0c7 100644 --- a/tests/dummy/app/templates/violations.hbs +++ b/tests/dummy/app/templates/violations.hbs @@ -55,7 +55,7 @@ value=3 name="noise-level" class="c-radio-track__item-input" - radioId="noise-level-3" + id="noise-level-3" changed="updateCurrentNoiseLevel" }} Level 3 @@ -74,7 +74,7 @@