Skip to content

Commit

Permalink
fix(aria-valid-attr-value): allow aria-controls to pass when element …
Browse files Browse the repository at this point in the history
…is not in the DOM

fix(aria-valid-attr-value): allow aria-controls to pass when element is not in the DOM
  • Loading branch information
straker authored Apr 25, 2019
1 parent 50cbdad commit a7842e5
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 17 deletions.
43 changes: 26 additions & 17 deletions lib/checks/aria/valid-attr-value.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
options = Array.isArray(options) ? options : [];

var invalid = [],
aria = /^aria-/;
const invalid = [];
const aria = /^aria-/;
const attrs = axe.utils.getNodeAttributes(node);

var attr,
attrName,
attrs = axe.utils.getNodeAttributes(node);
const skipAttrs = ['aria-errormessage'];

var skipAttrs = ['aria-errormessage'];
// aria-controls should only check if element exists if the element
// doesn't have aria-expanded=false or aria-selected=false (tabs)
// @see https://github.com/dequelabs/axe-core/issues/1463
const preChecks = {
'aria-controls': function() {
return (
node.getAttribute('aria-expanded') !== 'false' &&
node.getAttribute('aria-selected') !== 'false'
);
}
};

for (var i = 0, l = attrs.length; i < l; i++) {
attr = attrs[i];
attrName = attr.name;
for (let i = 0, l = attrs.length; i < l; i++) {
const attr = attrs[i];
const attrName = attr.name;
// skip any attributes handled elsewhere
if (!skipAttrs.includes(attrName)) {
if (
options.indexOf(attrName) === -1 &&
aria.test(attrName) &&
!axe.commons.aria.validateAttrValue(node, attrName)
) {
invalid.push(attrName + '="' + attr.nodeValue + '"');
}
if (
!skipAttrs.includes(attrName) &&
options.indexOf(attrName) === -1 &&
aria.test(attrName) &&
(preChecks[attrName] ? preChecks[attrName]() : true) &&
!axe.commons.aria.validateAttrValue(node, attrName)
) {
invalid.push(`${attrName}="${attr.nodeValue}"`);
}
}

Expand Down
48 changes: 48 additions & 0 deletions test/checks/aria/valid-attr-value.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,54 @@ describe('aria-valid-attr-value', function() {
);
});

it('should pass on aria-controls and aria-expanded=false when the element is not in the DOM', function() {
fixtureSetup(
'<button aria-controls="test" aria-expanded="false">Button</button>'
);
var passing1 = fixture.querySelector('button');
assert.isTrue(
checks['aria-valid-attr-value'].evaluate.call(checkContext, passing1)
);
});

it('should pass on aria-controls and aria-selected=false when the element is not in the DOM', function() {
fixtureSetup(
'<button aria-controls="test" aria-selected="false">Button</button>'
);
var passing1 = fixture.querySelector('button');
assert.isTrue(
checks['aria-valid-attr-value'].evaluate.call(checkContext, passing1)
);
});

it('should fail on aria-controls and aria-expanded=true when the element is not in the DOM', function() {
fixtureSetup(
'<button aria-controls="test" aria-expanded="true">Button</button>'
);
var failing1 = fixture.querySelector('button');
assert.isFalse(
checks['aria-valid-attr-value'].evaluate.call(checkContext, failing1)
);
});

it('should fail on aria-controls and aria-selected=true when the element is not in the DOM', function() {
fixtureSetup(
'<button aria-controls="test" aria-selected="true">Button</button>'
);
var failing1 = fixture.querySelector('button');
assert.isFalse(
checks['aria-valid-attr-value'].evaluate.call(checkContext, failing1)
);
});

it('should fail on aria-controls when the element is not in the DOM', function() {
fixtureSetup('<button aria-controls="test">Button</button>');
var failing1 = fixture.querySelector('button');
assert.isFalse(
checks['aria-valid-attr-value'].evaluate.call(checkContext, failing1)
);
});

describe('options', function() {
it('should exclude supplied attributes', function() {
fixture.innerHTML =
Expand Down

0 comments on commit a7842e5

Please sign in to comment.