Skip to content

Commit

Permalink
fix(aria-required-children): set related nodes for invalid children (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
WilcoFiers committed May 24, 2023
1 parent cb51be4 commit 377f72b
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 51 deletions.
23 changes: 15 additions & 8 deletions lib/core/utils/check-helper.js
@@ -1,5 +1,6 @@
import toArray from './to-array';
import DqElement from './dq-element';
import AbstractVirtualNode from '../base/virtual-node/abstract-virtual-node';

/**
* Helper to denote which checks are asyncronous and provide callbacks and pass data back to the CheckResult
Expand Down Expand Up @@ -28,17 +29,23 @@ function checkHelper(checkResult, options, resolve, reject) {
if (!window.Node) {
return;
}

nodes = nodes instanceof window.Node ? [nodes] : toArray(nodes);

if (
!nodes.every(node => node instanceof window.Node || node.actualNode)
nodes instanceof window.Node ||
nodes instanceof AbstractVirtualNode
) {
return;
nodes = [nodes];
} else {
nodes = toArray(nodes);
}

checkResult.relatedNodes = nodes.map(element => {
return new DqElement(element, options);
checkResult.relatedNodes = [];
nodes.forEach(node => {
if (node instanceof AbstractVirtualNode) {
node = node.actualNode;
}
if (node instanceof window.Node) {
const dqElm = new DqElement(node, options);
checkResult.relatedNodes.push(dqElm);
}
});
}
};
Expand Down
139 changes: 96 additions & 43 deletions test/core/utils/check-helper.js
@@ -1,60 +1,61 @@
describe('axe.utils.checkHelper', function () {
'use strict';

var DqElement = axe.utils.DqElement;
describe('axe.utils.checkHelper', () => {
const { queryFixture } = axe.testUtils;
const DqElement = axe.utils.DqElement;
function noop() {}

it('should be a function', function () {
it('should be a function', () => {
assert.isFunction(axe.utils.checkHelper);
});

it('should accept 4 named parameters', function () {
it('should accept 4 named parameters', () => {
assert.lengthOf(axe.utils.checkHelper, 4);
});

it('should return an object', function () {
it('should return an object', () => {
assert.isObject(axe.utils.checkHelper());
});

describe('return value', function () {
describe('async', function () {
it('should set isAsync property on returned object to `true` when called', function () {
var target = {},
describe('return value', () => {
describe('async', () => {
it('should set isAsync property on returned object to `true` when called', () => {
const target = {},
helper = axe.utils.checkHelper(target, noop);

helper.async();
assert.isTrue(helper.isAsync);
});
it('should call the third parameter of `axe.utils.checkHelper` when invoked', function () {

it('should call the third parameter of `axe.utils.checkHelper` when invoked', () => {
function fn() {
success = true;
}
var success = false,
helper = axe.utils.checkHelper({}, {}, fn);
let success = false;
const helper = axe.utils.checkHelper({}, {}, fn);

var done = helper.async();
const done = helper.async();
done();

assert.isTrue(success);
});

it('should call the fourth parameter of `axe.utils.checkHelper` when returning an error', function () {
var success = false;
it('should call the fourth parameter of `axe.utils.checkHelper` when returning an error', () => {
let success = false;
function reject(e) {
success = true;
assert.equal(e.message, 'Concrete donkey!');
}

var helper = axe.utils.checkHelper({}, {}, noop, reject);
var done = helper.async();
const helper = axe.utils.checkHelper({}, {}, noop, reject);
const done = helper.async();
done(new Error('Concrete donkey!'));

assert.isTrue(success);
});
});
describe('data', function () {
it('should set data property on target when called', function () {
var target = {},

describe('data', () => {
it('should set data property on target when called', () => {
const target = {},
expected = { monkeys: 'bananas' },
helper = axe.utils.checkHelper(target, noop);

Expand All @@ -63,47 +64,52 @@ describe('axe.utils.checkHelper', function () {
assert.equal(target.data, expected);
});
});
describe('relatedNodes', function () {
var fixture = document.getElementById('fixture');
afterEach(function () {

describe('relatedNodes', () => {
const fixture = document.getElementById('fixture');
afterEach(() => {
fixture.innerHTML = '';
});
it('should accept NodeList', function () {

it('should accept NodeList', () => {
fixture.innerHTML = '<div id="t1"></div><div id="t2"></div>';
var target = {},
helper = axe.utils.checkHelper(target, noop);
const target = {};
const 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 () {

it('should accept a single Node', () => {
fixture.innerHTML = '<div id="t1"></div><div id="t2"></div>';
var target = {},
helper = axe.utils.checkHelper(target, noop);
const target = {};
const 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 () {

it('should accept an Array', () => {
fixture.innerHTML = '<div id="t1"></div><div id="t2"></div>';
var target = {},
helper = axe.utils.checkHelper(target, noop);
const target = {};
const 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 () {

it('should accept an array-like Object', () => {
fixture.innerHTML = '<div id="t1"></div><div id="t2"></div>';
var target = {},
helper = axe.utils.checkHelper(target, noop);
var nodes = {
const target = {};
const helper = axe.utils.checkHelper(target, noop);
const nodes = {
0: fixture.children[0],
1: fixture.children[1],
length: 2
Expand All @@ -115,13 +121,60 @@ describe('axe.utils.checkHelper', function () {
assert.equal(target.relatedNodes[0].element, fixture.children[0]);
assert.equal(target.relatedNodes[1].element, fixture.children[1]);
});
it('should noop for non-node-like objects', function () {
var target = {},
helper = axe.utils.checkHelper(target, noop);
var nodes = new axe.SerialVirtualNode({

it('should accept a VirtualNode', () => {
const vNode = queryFixture('<a id="target"></a>');
const target = {};
const helper = axe.utils.checkHelper(target, noop);
helper.relatedNodes(vNode);
assert.lengthOf(target.relatedNodes, 1);
assert.instanceOf(target.relatedNodes[0], DqElement);
assert.equal(target.relatedNodes[0].element.nodeName, 'A');
});

it('should accept an array of VirtualNodes', () => {
const vNode = queryFixture(`
<div id="target"><a></a><b></b></div>
`);
const target = {};
const helper = axe.utils.checkHelper(target, noop);
helper.relatedNodes(vNode.children);
assert.lengthOf(target.relatedNodes, 2);
assert.instanceOf(target.relatedNodes[0], DqElement);
assert.equal(target.relatedNodes[0].element.nodeName, 'A');
assert.equal(target.relatedNodes[1].element.nodeName, 'B');
});

it('should filter out non-nodes', () => {
const vNode = queryFixture(`
<div><a id="target"></a><b></b></div>
`);
const target = {};
const helper = axe.utils.checkHelper(target, noop);
const nodes = [
null,
vNode,
true,
fixture.querySelector('b'),
'hello world',
new axe.SerialVirtualNode({
nodeName: 's'
})
];
helper.relatedNodes(nodes);
assert.lengthOf(target.relatedNodes, 2);
assert.instanceOf(target.relatedNodes[0], DqElement);
assert.equal(target.relatedNodes[0].element.nodeName, 'A');
assert.equal(target.relatedNodes[1].element.nodeName, 'B');
});

it('should noop for non-node-like objects', () => {
const target = {};
const helper = axe.utils.checkHelper(target, noop);
const nodes = new axe.SerialVirtualNode({
nodeName: 'div'
});
assert.doesNotThrow(function () {
assert.doesNotThrow(() => {
helper.relatedNodes(nodes);
});
assert.lengthOf(target.relatedNodes, 0);
Expand Down

0 comments on commit 377f72b

Please sign in to comment.