Skip to content

Commit

Permalink
fix(aria-valid-attr-value): aria-controls & aria-haspopup incomplete (#…
Browse files Browse the repository at this point in the history
…4418)

if an element has both aria-controls and aria-haspopup mark it
incomplete as we are unsure if the DOM element will be added dynamically
later

**dev note**: this is my first time adding some language locale for an
incomplete, how's it look?

fix: #4363
  • Loading branch information
gaiety-deque committed Apr 29, 2024
2 parents 5c5ede0 + a823712 commit ef1e09d
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 5 deletions.
15 changes: 13 additions & 2 deletions lib/checks/aria/aria-valid-attr-value-evaluate.js
Expand Up @@ -36,12 +36,23 @@ export default function ariaValidAttrValueEvaluate(node, options, virtualNode) {

const preChecks = {
// aria-controls should only check if element exists if the element
// doesn't have aria-expanded=false or aria-selected=false (tabs)
// doesn't have aria-expanded=false, aria-selected=false (tabs),
// or aria-haspopup (may load later)
// @see https://github.com/dequelabs/axe-core/issues/1463
// @see https://github.com/dequelabs/axe-core/issues/4363
'aria-controls': () => {
const hasPopup =
['false', null].includes(virtualNode.attr('aria-haspopup')) === false;

if (hasPopup) {
needsReview = `aria-controls="${virtualNode.attr('aria-controls')}"`;
messageKey = 'controlsWithinPopup';
}

return (
virtualNode.attr('aria-expanded') !== 'false' &&
virtualNode.attr('aria-selected') !== 'false'
virtualNode.attr('aria-selected') !== 'false' &&
hasPopup === false
);
},
// aria-current should mark as needs review if any value is used that is
Expand Down
3 changes: 2 additions & 1 deletion lib/checks/aria/aria-valid-attr-value.json
Expand Up @@ -15,7 +15,8 @@
"noIdShadow": "ARIA attribute element ID does not exist on the page or is a descendant of a different shadow DOM tree: ${data.needsReview}",
"ariaCurrent": "ARIA attribute value is invalid and will be treated as \"aria-current=true\": ${data.needsReview}",
"idrefs": "Unable to determine if ARIA attribute element ID exists on the page: ${data.needsReview}",
"empty": "ARIA attribute value is ignored while empty: ${data.needsReview}"
"empty": "ARIA attribute value is ignored while empty: ${data.needsReview}",
"controlsWithinPopup": "Unable to determine if aria-controls referenced ID exists on the page while using aria-haspopup: ${data.needsReview}"
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion locales/_template.json
Expand Up @@ -538,7 +538,8 @@
"noIdShadow": "ARIA attribute element ID does not exist on the page or is a descendant of a different shadow DOM tree: ${data.needsReview}",
"ariaCurrent": "ARIA attribute value is invalid and will be treated as \"aria-current=true\": ${data.needsReview}",
"idrefs": "Unable to determine if ARIA attribute element ID exists on the page: ${data.needsReview}",
"empty": "ARIA attribute value is ignored while empty: ${data.needsReview}"
"empty": "ARIA attribute value is ignored while empty: ${data.needsReview}",
"controlsWithinPopup": "Unable to determine if aria-controls referenced ID exists on the page while using aria-haspopup: ${data.needsReview}"
}
},
"aria-valid-attr": {
Expand Down
13 changes: 13 additions & 0 deletions test/checks/aria/valid-attr-value.js
Expand Up @@ -110,6 +110,19 @@ describe('aria-valid-attr-value', function () {
assert.isFalse(validAttrValueCheck.call(checkContext, null, null, vNode));
});

it('should return undefined on aria-controls with aria-haspopup as we cannot determine if it is in the DOM later', function () {
var vNode = queryFixture(
'<button id="target" aria-controls="test" aria-haspopup="true">Button</button>'
);
assert.isUndefined(
validAttrValueCheck.call(checkContext, null, null, vNode)
);
assert.deepEqual(checkContext._data, {
messageKey: 'controlsWithinPopup',
needsReview: 'aria-controls="test"'
});
});

it('should pass on aria-owns and aria-expanded=false when the element is not in the DOM', function () {
var vNode = queryFixture(
'<button id="target" aria-owns="test" aria-expanded="false">Button</button>'
Expand Down
Expand Up @@ -360,4 +360,7 @@ <h2>Possible False Positives</h2>
<div role="checkbox" id="incomplete6" aria-checked>I'm not checked</div>
<div role="textbox" id="incomplete7" aria-invalid="">I'm actually valid</div>
<div role="textbox" id="incomplete8" aria-hidden>I'm not really gone</div>
<div id="incomplete9" aria-controls="stuff" aria-haspopup="true">
May have injected html to control dynamically later, who knows!
</div>
</div>
Expand Up @@ -236,6 +236,7 @@
["#incomplete5"],
["#incomplete6"],
["#incomplete7"],
["#incomplete8"]
["#incomplete8"],
["#incomplete9"]
]
}

0 comments on commit ef1e09d

Please sign in to comment.