Skip to content

Commit

Permalink
fix: Ignore shadowRoots on elements that don't allow them
Browse files Browse the repository at this point in the history
  • Loading branch information
WilcoFiers authored and marcysutton committed Sep 1, 2017
1 parent 9402a7c commit 7f66ee8
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 2 deletions.
Binary file added lib/checks/.DS_Store
Binary file not shown.
18 changes: 16 additions & 2 deletions lib/core/utils/flattened-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ function getSlotChildren(node) {
return retVal;
}

const possibleShadowRoots = ['article', 'aside', 'blockquote',
'body', 'div', 'footer', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
'header', 'main', 'nav', 'p', 'section', 'span'];
axe.utils.isShadowRoot = function isShadowRoot (node) {
const nodeName = node.nodeName.toLowerCase();
if (node.shadowRoot) {
if (/^[a-z][a-z0-9_.-]*-[a-z0-9_.-]*$/.test(nodeName) ||
possibleShadowRoots.includes(nodeName)) {
return true;
}
}
return false;
};

/**
* Recursvely returns an array of the virtual DOM nodes at this level
* excluding comment nodes and the shadow DOM nodes <content> and <slot>
Expand All @@ -75,8 +89,8 @@ axe.utils.getFlattenedTree = function (node, shadowId) {
node = node.documentElement;
}
nodeName = node.nodeName.toLowerCase();
// for some reason Chrome's marquee element has an open shadow DOM
if (node.shadowRoot && nodeName !== 'marquee') {

if (axe.utils.isShadowRoot(node)) {
// generate an ID for this shadow root and overwrite the current
// closure shadowId with this value so that it cascades down the tree
retVal = virtualDOMfromNode(node, shadowId);
Expand Down
46 changes: 46 additions & 0 deletions test/core/utils/flattened-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,32 @@ function shadowIdAssertions () {

}

describe('isShadowRoot', function () {
'use strict';
var isShadowRoot = axe.utils.isShadowRoot;

it('returns false if the node has no shadowRoot', function () {
assert.isFalse(isShadowRoot({ nodeName: 'DIV', shadowRoot: undefined }));
});
it('returns true if the native element allows shadow DOM', function () {
assert.isTrue(isShadowRoot({ nodeName: 'DIV', shadowRoot: {} }));
assert.isTrue(isShadowRoot({ nodeName: 'H1', shadowRoot: {} }));
assert.isTrue(isShadowRoot({ nodeName: 'ASIDE', shadowRoot: {} }));
});
it('returns true if a custom element with shadowRoot', function () {
assert.isTrue(isShadowRoot({ nodeName: 'X-BUTTON', shadowRoot: {} }));
assert.isTrue(isShadowRoot({ nodeName: 'T1000-SCHWARZENEGGER', shadowRoot: {} }));
});
it('returns true if an invalid custom element with shadowRoot', function () {
assert.isFalse(isShadowRoot({ nodeName: '0-BUZZ', shadowRoot: {} }));
assert.isFalse(isShadowRoot({ nodeName: '--ELM--', shadowRoot: {} }));
});
it('returns false if the native element does not allow shadow DOM', function () {
assert.isFalse(isShadowRoot({ nodeName: 'IFRAME', shadowRoot: {} }));
assert.isFalse(isShadowRoot({ nodeName: 'STRONG', shadowRoot: {} }));
});
});

if (shadowSupport.v0) {
describe('flattened-tree shadow DOM v0', function () {
'use strict';
Expand Down Expand Up @@ -154,6 +180,26 @@ if (shadowSupport.v1) {
assert.isTrue(virtualDOM[0].children[2].children[1].children[0].children[0].actualNode.textContent === 'fallback content');
assert.isTrue(virtualDOM[0].children[2].children[1].children[0].children[1].actualNode.nodeName === 'LI');
});
it('calls isShadowRoot to identify a shadow root', function () {
var isShadowRoot = axe.utils.isShadowRoot;
fixture.innerHTML = '<div></div>';
var div = fixture.querySelector('div');
var shadowRoot = div.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = '<h1>Just a man in the back</h1>';

// Test without isShqdowRoot overwritten
assert.equal(axe.utils.getFlattenedTree(div)[0].children.length, 1);

var called = false;
axe.utils.isShadowRoot = function () {
called = true;
return false;
};
// Test with isShadowRoot overwritten
assert.equal(axe.utils.getFlattenedTree(div)[0].children.length, 0);
assert.isTrue(called);
axe.utils.isShadowRoot = isShadowRoot;
});
});
describe('flattened-tree shadow DOM v1: boxed slots', function () {
'use strict';
Expand Down

0 comments on commit 7f66ee8

Please sign in to comment.