Last active
August 23, 2021 08:20
-
-
Save marcysutton/835c2fd90fadb631414b39523d5bda61 to your computer and use it in GitHub Desktop.
React A11y Testing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {expect} from 'chai'; | |
import App from '../app/components/App'; | |
import a11yHelper from "./a11yHelper"; | |
describe('Accessibility', function () { | |
this.timeout(10000); | |
it('Has no errors', function () { | |
let config = {}; | |
// let config = { | |
// "rules": { | |
// "color-contrast": { enabled: false } | |
// } | |
// }; | |
a11yHelper.testEnzymeComponent(<App/>, config, function (results) { | |
expect(results.violations.length).to.equal(0); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import {findDOMNode, render} from 'react-dom'; | |
import {mount} from 'enzyme'; | |
import axeCore from 'axe-core'; | |
var a11yHelper = {}; | |
/** | |
* Test a component with React's Test Utils. | |
* | |
* @param {any} app - Your app reference. | |
* @param {object} config (optional) - An aXe config object to enable/disable rules. See | |
* [axe.a11yCheck](https://github.com/dequelabs/axe-core/blob/master/doc/API.md#options-parameter). | |
* @param {function} callback - A callback function to execute when aXe returns. | |
*/ | |
a11yHelper.testReactComponent = function(app, config, callback) { | |
let div = document.createElement('div'); | |
document.body.appendChild(div); | |
this.wrapper = render(app, div); | |
let node = findDOMNode(div); | |
if (typeof config === 'function') { | |
config = {}; | |
} | |
this.run(node, config, callback); | |
document.body.removeChild(div); | |
} | |
/** | |
* Test a component with Enzyme. | |
* | |
* @param {any} app - Your app reference. | |
* @param {object} config (optional) - An aXe config object to enable/disable rules. See | |
* [axe.a11yCheck](https://github.com/dequelabs/axe-core/blob/master/doc/API.md#options-parameter). | |
* @param {function} callback - A callback function to execute when aXe returns. | |
*/ | |
a11yHelper.testEnzymeComponent = function (app, config, callback) { | |
let div = document.createElement('div'); | |
document.body.appendChild(div); | |
let wrapper = mount(app, { attachTo: div }); | |
let node = findDOMNode(wrapper.component); | |
if (typeof config === 'function') { | |
config = {}; | |
} | |
this.run(node, config, callback); | |
document.body.removeChild(div); | |
} | |
/** | |
* Run an aXe audit. | |
* @private | |
* | |
* @param {object} node - A node reference from your app. | |
* @param {object} config - An aXe config or empty object. | |
* @param {function} callback - A callback function to execute when aXe returns. | |
*/ | |
a11yHelper.run = function(node, config, callback) { | |
var oldNode = global.Node; | |
global.Node = node.ownerDocument.defaultView.Node; | |
axeCore.run(node, config, function(err, results) { | |
global.Node = oldNode; | |
if (err instanceof Error) { | |
return err; | |
} | |
a11yHelper.report(results); | |
// return to the test expectation | |
callback(results); | |
}); | |
} | |
/** | |
* Report results in a readable fashion. | |
* @private | |
* @param {object} results - The aXe [results object](https://github.com/dequelabs/axe-core/blob/master/doc/API.md#results-object). | |
*/ | |
a11yHelper.report = function(results) { | |
// output some useful information | |
let failureNotice = ''; | |
if (results.violations.length > 0) { | |
failureNotice += 'Accessibility violations:\n'; | |
results.violations.forEach(function(violation) { | |
failureNotice += violation.description + '\n'; | |
failureNotice += 'HTML Nodes: \n'; | |
violation.nodes.forEach(function(node) { | |
failureNotice += node.html + '\n'; | |
}); | |
}); | |
console.log(failureNotice); | |
} | |
} | |
module.exports = a11yHelper; |
What is global.Node
and why is it being set to node.ownerDocument.defaultView.Node
?
I changed line 43 to let node = wrapper.getDOMNode();
and then this worked! Thanks Marcy.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a very clear and helpful. Thank you!