Skip to content

Commit

Permalink
fix(aria-valid-attr-value): add note about element id being in a diff…
Browse files Browse the repository at this point in the history
…erent shadow DOM tree (#3421)

* fix(aria-valid-attr-value): add note about element id being in a different shadow DOM tree

* only mention shadow tree if one exists

* fix test
  • Loading branch information
straker authored Apr 12, 2022
1 parent 0a4397d commit 5a4babb
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 3 deletions.
8 changes: 6 additions & 2 deletions lib/checks/aria/aria-valid-attr-value-evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ function ariaValidAttrValueEvaluate(node, options, virtualNode) {
needsReview = `aria-describedby="${virtualNode.attr(
'aria-describedby'
)}"`;
messageKey = 'noId';
// TODO: es-modules_tree
messageKey =
axe._tree && axe._tree[0]._hasShadowRoot ? 'noIdShadow' : 'noId';
}

return;
Expand All @@ -80,7 +82,9 @@ function ariaValidAttrValueEvaluate(node, options, virtualNode) {
needsReview = `aria-labelledby="${virtualNode.attr(
'aria-labelledby'
)}"`;
messageKey = 'noId';
// TODO: es-modules_tree
messageKey =
axe._tree && axe._tree[0]._hasShadowRoot ? 'noIdShadow' : 'noId';
}
}
};
Expand Down
1 change: 1 addition & 0 deletions lib/checks/aria/aria-valid-attr-value.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
},
"incomplete": {
"noId": "ARIA attribute element ID does not exist on the page: ${data.needsReview}",
"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}"
}
Expand Down
13 changes: 12 additions & 1 deletion lib/core/utils/get-flattened-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import cache from '../base/cache';
* the spec for this)
*/

let hasShadowRoot;

/**
* find all the fallback content for a <slot> and return these as an array
* this array will also include any #text nodes
Expand Down Expand Up @@ -65,6 +67,8 @@ function flattenTree(node, shadowId, parent) {
nodeName = node.nodeName.toLowerCase();

if (isShadowRoot(node)) {
hasShadowRoot = true;

// generate an ID for this shadow root and overwrite the current
// closure shadowId with this value so that it cascades down the tree
retVal = new VirtualNode(node, parent, shadowId);
Expand Down Expand Up @@ -140,12 +144,19 @@ function flattenTree(node, shadowId, parent) {
* ancestor of the node
*/
function getFlattenedTree(node = document.documentElement, shadowId) {
hasShadowRoot = false;
cache.set('nodeMap', new WeakMap());

// specifically pass `null` to the parent to designate the top
// node of the tree. if parent === undefined then we know
// we are in a disconnected tree
return flattenTree(node, shadowId, null);
const tree = flattenTree(node, shadowId, null);

// allow rules and checks to know if there is a shadow root attached
// to the current tree
tree[0]._hasShadowRoot = hasShadowRoot;

return tree;
}

export default getFlattenedTree;
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 @@ -5,6 +5,8 @@ describe('aria-valid-attr-value', function() {
var queryFixture = axe.testUtils.queryFixture;
var checkContext = axe.testUtils.MockCheckContext();
var fixtureSetup = axe.testUtils.fixtureSetup;
var shadowCheckSetup = axe.testUtils.shadowCheckSetup;
var shadowSupported = axe.testUtils.shadowSupport.v1;

afterEach(function() {
fixture.innerHTML = '';
Expand Down Expand Up @@ -210,8 +212,31 @@ describe('aria-valid-attr-value', function() {
.getCheckEvaluate('aria-valid-attr-value')
.call(checkContext, null, null, vNode)
);
assert.deepEqual(checkContext._data, {
messageKey: 'noId',
needsReview: 'aria-describedby="test"'
});
});

(shadowSupported ? it : xit)(
'should return undefined on aria-describedby when the element is in a different shadow tree',
function() {
var params = shadowCheckSetup(
'<div></div>',
'<button id="target" aria-describedby="test">Button</button>'
);
assert.isUndefined(
axe.testUtils
.getCheckEvaluate('aria-valid-attr-value')
.apply(checkContext, params)
);
assert.deepEqual(checkContext._data, {
messageKey: 'noIdShadow',
needsReview: 'aria-describedby="test"'
});
}
);

it('should return undefined on aria-labelledby when the element is not in the DOM', function() {
var vNode = queryFixture(
'<button id="target" aria-labelledby="test">Button</button>'
Expand All @@ -221,8 +246,31 @@ describe('aria-valid-attr-value', function() {
.getCheckEvaluate('aria-valid-attr-value')
.call(checkContext, null, null, vNode)
);
assert.deepEqual(checkContext._data, {
messageKey: 'noId',
needsReview: 'aria-labelledby="test"'
});
});

(shadowSupported ? it : xit)(
'should return undefined on aria-labelledby when the element is in a different shadow tree',
function() {
var params = shadowCheckSetup(
'<div></div>',
'<button id="target" aria-labelledby="test">Button</button>'
);
assert.isUndefined(
axe.testUtils
.getCheckEvaluate('aria-valid-attr-value')
.apply(checkContext, params)
);
assert.deepEqual(checkContext._data, {
messageKey: 'noIdShadow',
needsReview: 'aria-labelledby="test"'
});
}
);

it('should return undefined on aria-current with invalid value', function() {
var vNode = queryFixture(
'<button id="target" aria-current="test">Button</button>'
Expand Down

0 comments on commit 5a4babb

Please sign in to comment.