diff --git a/lib/checks/aria/required-parent.js b/lib/checks/aria/required-parent.js index d227f0635d..5a4ef3614f 100644 --- a/lib/checks/aria/required-parent.js +++ b/lib/checks/aria/required-parent.js @@ -36,7 +36,8 @@ function getAriaOwners(element) { while (element) { if (element.getAttribute('id')) { const id = axe.commons.utils.escapeSelector(element.getAttribute('id')); - o = document.querySelector(`[aria-owns~=${id}]`); + let doc = axe.commons.dom.getRootNode(element); + o = doc.querySelector(`[aria-owns~=${id}]`); if (o) { owners.push(o); } } element = element.parentElement; diff --git a/test/checks/aria/required-parent.js b/test/checks/aria/required-parent.js index aef8f598ae..e105231c9f 100644 --- a/test/checks/aria/required-parent.js +++ b/test/checks/aria/required-parent.js @@ -2,6 +2,7 @@ describe('aria-required-parent', function () { 'use strict'; var fixture = document.getElementById('fixture'); + var shadowSupported = axe.testUtils.shadowSupport.v1; var checkContext = { _data: null, @@ -10,47 +11,93 @@ describe('aria-required-parent', function () { } }; + var checkSetup = axe.testUtils.checkSetup; + afterEach(function () { fixture.innerHTML = ''; checkContext._data = null; }); it('should detect missing required parent', function () { - fixture.innerHTML = '
Nothing here.
Nothing here.
Nothing here.
'; + + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + var shadowContent = shadowRoot.querySelector('#target'); + var virtualTarget = axe.utils.getNodeFromTree(tree[0], shadowContent); + + var params = [shadowContent, undefined, virtualTarget]; + assert.isFalse(checks['aria-required-parent'].evaluate.apply(checkContext, params)); assert.deepEqual(checkContext._data, ['list']); }); it('should pass when required parent is present in an ancestral aria-owns context', function () { - fixture.innerHTML = 'Nothing here.
Nothing here.
Nothing here.
Nothing here.
Nothing here.
Nothing here.
Nothing here.
Nothing here.
Nothing here.
Nothing here.
Nothing here.
'; + + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + var shadowContent = shadowRoot.querySelector('#target'); + var virtualTarget = axe.utils.getNodeFromTree(tree[0], shadowContent); + + var params = [shadowContent, undefined, virtualTarget]; + assert.isTrue(checks['aria-required-parent'].evaluate.apply(checkContext, params)); + }); + + (shadowSupported ? it : xit) + ('should fail when aria-owns context crosses shadow boundary', function () { + fixture.innerHTML = 'Nothing here.
'; + + var tree = axe._tree = axe.utils.getFlattenedTree(fixture); + var shadowContent = shadowRoot.querySelector('#target'); + var virtualTarget = axe.utils.getNodeFromTree(tree[0], shadowContent); + + var params = [shadowContent, undefined, virtualTarget]; + assert.isFalse(checks['aria-required-parent'].evaluate.apply(checkContext, params)); + }); });