diff --git a/lib/checks/label/explicit.js b/lib/checks/label/explicit.js
index bff93e1482..eee064f700 100644
--- a/lib/checks/label/explicit.js
+++ b/lib/checks/label/explicit.js
@@ -1,6 +1,7 @@
if (node.getAttribute('id')) {
+ const root = axe.commons.dom.getRootNode(node);
const id = axe.commons.utils.escapeSelector(node.getAttribute('id'));
- const label = document.querySelector(`label[for="${id}"]`);
+ const label = root.querySelector(`label[for="${id}"]`);
if (label) {
return !!axe.commons.text.accessibleText(label);
diff --git a/lib/commons/dom/find-up.js b/lib/commons/dom/find-up.js
index 06e20ffe05..8f2db7f8f9 100644
--- a/lib/commons/dom/find-up.js
+++ b/lib/commons/dom/find-up.js
@@ -9,25 +9,16 @@
* @return {HTMLElement|null} Either the matching HTMLElement or `null` if there was no match
*/
dom.findUp = function (element, target) {
- 'use strict';
- /*jslint browser:true*/
+ let doc, matches,
+ parent = element;
- var parent,
- doc = axe.commons.dom.getRootNode(element),
- matches;
-
- matches = doc.querySelectorAll(target);
- matches = axe.utils.toArray(matches);
- if (doc === document && !matches.length) {
- return null;
- }
-
- // recursively walk up the DOM, checking each parent node
- parent = dom.getComposedParent(element);
- while (parent && matches.indexOf(parent) === -1) {
- parent = (parent.assignedSlot) ? parent.assignedSlot : parent.parentNode;
+ do {// recursively walk up the DOM, checking each parent node
+ parent = (parent.assignedSlot ? parent.assignedSlot : parent.parentNode);
if (parent && parent.nodeType === 11) {
+ matches = null;
parent = parent.host;
+ }
+ if (!matches) {
doc = axe.commons.dom.getRootNode(parent);
matches = doc.querySelectorAll(target);
matches = axe.utils.toArray(matches);
@@ -35,7 +26,7 @@ dom.findUp = function (element, target) {
return null;
}
}
- }
+ } while (parent && !matches.includes(parent));
return parent;
};
diff --git a/test/checks/lists/dlitem.js b/test/checks/lists/dlitem.js
index 827e6a6405..56f7596b36 100644
--- a/test/checks/lists/dlitem.js
+++ b/test/checks/lists/dlitem.js
@@ -21,7 +21,7 @@ describe('dlitem', function () {
assert.isFalse(checks.dlitem.evaluate.apply(null, checkArgs));
});
- (shadowSupport ? it : xit)('should return true in a shadow DOM pass', function () {
+ (shadowSupport.v1 ? it : xit)('should return true in a shadow DOM pass', function () {
var node = document.createElement('div');
node.innerHTML = '
My list item
';
var shadow = node.attachShadow({ mode: 'open' });
@@ -31,7 +31,7 @@ describe('dlitem', function () {
assert.isTrue(checks.dlitem.evaluate.apply(null, checkArgs));
});
- (shadowSupport ? it : xit)('should return false in a shadow DOM fail', function () {
+ (shadowSupport.v1 ? it : xit)('should return false in a shadow DOM fail', function () {
var node = document.createElement('div');
node.innerHTML = '
My list item
';
var shadow = node.attachShadow({ mode: 'open' });
diff --git a/test/checks/lists/has-listitem.js b/test/checks/lists/has-listitem.js
index 87ca1f5865..b3b2087a60 100644
--- a/test/checks/lists/has-listitem.js
+++ b/test/checks/lists/has-listitem.js
@@ -33,7 +33,7 @@ describe('has-listitem', function () {
assert.isFalse(checks['has-listitem'].evaluate.apply(null, checkArgs));
});
- (shadowSupport ? it : xit)('should return true in a shadow DOM pass', function () {
+ (shadowSupport.v1 ? it : xit)('should return true in a shadow DOM pass', function () {
var node = document.createElement('div');
node.innerHTML = '
My list item
';
var shadow = node.attachShadow({ mode: 'open' });
@@ -43,7 +43,7 @@ describe('has-listitem', function () {
assert.isFalse(checks['has-listitem'].evaluate.apply(null, checkArgs));
});
- (shadowSupport ? it : xit)('should return false in a shadow DOM fail', function () {
+ (shadowSupport.v1 ? it : xit)('should return false in a shadow DOM fail', function () {
var node = document.createElement('div');
node.innerHTML = '
Not a list
';
var shadow = node.attachShadow({ mode: 'open' });
diff --git a/test/checks/lists/listitem.js b/test/checks/lists/listitem.js
index 179a631cd6..e543634883 100644
--- a/test/checks/lists/listitem.js
+++ b/test/checks/lists/listitem.js
@@ -33,7 +33,7 @@ describe('listitem', function () {
assert.isFalse(checks.listitem.evaluate.apply(null, checkArgs));
});
- (shadowSupport ? it : xit)('should return true in a shadow DOM pass', function () {
+ (shadowSupport.v1 ? it : xit)('should return true in a shadow DOM pass', function () {
var node = document.createElement('div');
node.innerHTML = '
My list item
';
var shadow = node.attachShadow({ mode: 'open' });
@@ -43,7 +43,7 @@ describe('listitem', function () {
assert.isTrue(checks.listitem.evaluate.apply(null, checkArgs));
});
- (shadowSupport ? it : xit)('should return false in a shadow DOM fail', function () {
+ (shadowSupport.v1 ? it : xit)('should return false in a shadow DOM fail', function () {
var node = document.createElement('div');
node.innerHTML = '
My list item
';
var shadow = node.attachShadow({ mode: 'open' });
diff --git a/test/checks/lists/only-dlitems.js b/test/checks/lists/only-dlitems.js
index efca12bc64..e0b890f514 100644
--- a/test/checks/lists/only-dlitems.js
+++ b/test/checks/lists/only-dlitems.js
@@ -104,7 +104,7 @@ describe('only-dlitems', function () {
assert.isFalse(checks['only-dlitems'].evaluate.apply(checkContext, checkArgs));
});
- (shadowSupport ? it : xit)('should return false in a shadow DOM pass', function () {
+ (shadowSupport.v1 ? it : xit)('should return false in a shadow DOM pass', function () {
var node = document.createElement('div');
node.innerHTML = '
My list item
';
var shadow = node.attachShadow({ mode: 'open' });
@@ -114,7 +114,7 @@ describe('only-dlitems', function () {
assert.isFalse(checks['only-dlitems'].evaluate.apply(checkContext, checkArgs));
});
- (shadowSupport ? it : xit)('should return true in a shadow DOM fail', function () {
+ (shadowSupport.v1 ? it : xit)('should return true in a shadow DOM fail', function () {
var node = document.createElement('div');
node.innerHTML = '
Not a list
';
var shadow = node.attachShadow({ mode: 'open' });
diff --git a/test/checks/lists/only-listitems.js b/test/checks/lists/only-listitems.js
index ad283c26b6..9150cad922 100644
--- a/test/checks/lists/only-listitems.js
+++ b/test/checks/lists/only-listitems.js
@@ -97,7 +97,7 @@ describe('only-listitems', function () {
assert.isFalse(checks['only-listitems'].evaluate.apply(checkContext, checkArgs));
});
- (shadowSupport ? it : xit)('should return false in a shadow DOM pass', function () {
+ (shadowSupport.v1 ? it : xit)('should return false in a shadow DOM pass', function () {
var node = document.createElement('div');
node.innerHTML = '
My list item
';
var shadow = node.attachShadow({ mode: 'open' });
@@ -107,7 +107,7 @@ describe('only-listitems', function () {
assert.isFalse(checks['only-listitems'].evaluate.apply(checkContext, checkArgs));
});
- (shadowSupport ? it : xit)('should return true in a shadow DOM fail', function () {
+ (shadowSupport.v1 ? it : xit)('should return true in a shadow DOM fail', function () {
var node = document.createElement('div');
node.innerHTML = '
Not a list item
';
var shadow = node.attachShadow({ mode: 'open' });
diff --git a/test/checks/lists/structured-dlitems.js b/test/checks/lists/structured-dlitems.js
index 953b47acd6..09d3898504 100644
--- a/test/checks/lists/structured-dlitems.js
+++ b/test/checks/lists/structured-dlitems.js
@@ -49,7 +49,7 @@ describe('structured-dlitems', function () {
assert.isFalse(checks['structured-dlitems'].evaluate.apply(null, checkArgs));
});
- (shadowSupport ? it : xit)('should return false in a shadow DOM pass', function () {
+ (shadowSupport.v1 ? it : xit)('should return false in a shadow DOM pass', function () {
var node = document.createElement('div');
node.innerHTML = '
Grayhound bus
at dawn
';
var shadow = node.attachShadow({ mode: 'open' });
@@ -59,7 +59,7 @@ describe('structured-dlitems', function () {
assert.isFalse(checks['structured-dlitems'].evaluate.apply(null, checkArgs));
});
- (shadowSupport ? it : xit)('should return true in a shadow DOM fail', function () {
+ (shadowSupport.v1 ? it : xit)('should return true in a shadow DOM fail', function () {
var node = document.createElement('div');
node.innerHTML = '
Galileo
Figaro
';
var shadow = node.attachShadow({ mode: 'open' });
diff --git a/test/checks/navigation/landmark.js b/test/checks/navigation/landmark.js
index 0d679d8913..81747751f0 100644
--- a/test/checks/navigation/landmark.js
+++ b/test/checks/navigation/landmark.js
@@ -24,7 +24,7 @@ describe('landmark', function () {
assert.isFalse(checks.landmark.evaluate.apply(null, checkArgs));
});
- (shadowSupport ? it : xit)('should not automatically pass if there is a shadow tree', function () {
+ (shadowSupport.v1 ? it : xit)('should not automatically pass if there is a shadow tree', function () {
var node = document.createElement('div');
var shadow = node.attachShadow({ mode: 'open' });
shadow.innerHTML = '';
@@ -33,7 +33,7 @@ describe('landmark', function () {
assert.isFalse(checks.landmark.evaluate.apply(null, checkArgs));
});
- (shadowSupport ? it : xit)('should find elements inside shadow trees', function () {
+ (shadowSupport.v1 ? it : xit)('should find elements inside shadow trees', function () {
var node = document.createElement('div');
var shadow = node.attachShadow({ mode: 'open' });
shadow.innerHTML = '';
@@ -42,7 +42,7 @@ describe('landmark', function () {
assert.isTrue(checks.landmark.evaluate.apply(null, checkArgs));
});
- (shadowSupport ? it : xit)('should find elements slotted in shadow trees', function () {
+ (shadowSupport.v1 ? it : xit)('should find elements slotted in shadow trees', function () {
var node = document.createElement('div');
node.innerHTML = '';
var shadow = node.attachShadow({ mode: 'open' });
diff --git a/test/checks/shared/button-has-visible-text.js b/test/checks/shared/button-has-visible-text.js
index fb3d0fa565..3526aea46b 100644
--- a/test/checks/shared/button-has-visible-text.js
+++ b/test/checks/shared/button-has-visible-text.js
@@ -2,7 +2,7 @@ describe('button-has-visible-text', function () {
'use strict';
var fixture = document.getElementById('fixture');
-
+ var checkSetup = axe.testUtils.checkSetup;
var checkContext = {
_data: null,
data: function (d) {
@@ -16,32 +16,28 @@ describe('button-has-visible-text', function () {
});
it('should return false if button element is empty', function () {
- fixture.innerHTML = '';
+ var checkArgs = checkSetup('', 'button');
- var node = fixture.querySelector('button');
- assert.isFalse(checks['button-has-visible-text'].evaluate.call(checkContext, node));
+ assert.isFalse(checks['button-has-visible-text'].evaluate.apply(checkContext, checkArgs));
});
it('should return true if a button element has text', function () {
- fixture.innerHTML = '';
+ var checkArgs = checkSetup('', 'button');
- var node = fixture.querySelector('button');
- assert.isTrue(checks['button-has-visible-text'].evaluate.call(checkContext, node));
+ assert.isTrue(checks['button-has-visible-text'].evaluate.apply(checkContext, checkArgs));
assert.deepEqual(checkContext._data, 'Name');
});
it('should return true if ARIA button has text', function () {
- fixture.innerHTML = '
Text
';
+ var checkArgs = checkSetup('
Text
>', '[role=button]');
- var node = fixture.querySelector('div');
- assert.isTrue(checks['button-has-visible-text'].evaluate.call(checkContext, node));
+ assert.isTrue(checks['button-has-visible-text'].evaluate.apply(checkContext, checkArgs));
assert.deepEqual(checkContext._data, 'Text');
});
it('should return false if ARIA button has no text', function () {
- fixture.innerHTML = '';
+ var checkArgs = checkSetup('>', '[role=button]');
- var node = fixture.querySelector('div');
- assert.isFalse(checks['button-has-visible-text'].evaluate.call(checkContext, node));
+ assert.isFalse(checks['button-has-visible-text'].evaluate.apply(checkContext, checkArgs));
});
});
\ No newline at end of file
diff --git a/test/commons/dom/find-up.js b/test/commons/dom/find-up.js
index e96f4983ed..2463d30537 100644
--- a/test/commons/dom/find-up.js
+++ b/test/commons/dom/find-up.js
@@ -74,7 +74,18 @@ describe('dom.findUp', function () {
assert.equal(axe.commons.dom.findUp(el.actualNode, 'label'), fixture.firstChild);
});
- it('should walk up the assigned slot', function () {
+ (shadowSupport.v0 ? it : xit)('should work on shadow root children', function () {
+ fixture.innerHTML = '';
+ var shadow = fixture.querySelector('#something').createShadowRoot();
+
+ shadow.innerHTML = '
item 1
';
+ var listItem = shadow.querySelector('[role=listitem]');
+
+ assert.equal(axe.commons.dom.findUp(listItem, '[role=list]'),
+ fixture.firstChild);
+ });
+
+ (shadowSupport.v1 ? it : xit)('should walk up the assigned slot', function () {
function createContentSlotted() {
var group = document.createElement('div');
group.innerHTML = '
Stuff
';
@@ -86,16 +97,15 @@ describe('dom.findUp', function () {
root.appendChild(div);
div.appendChild(createContentSlotted());
}
- if (shadowSupport.v1) {
- fixture.innerHTML = '';
- makeShadowTree(fixture.querySelector('div'));
- var tree = axe.utils.getFlattenedTree(fixture.firstChild);
- var el = axe.utils.querySelectorAll(tree, 'a')[0];
- assert.equal(axe.commons.dom.findUp(el.actualNode, 'label'), fixture.firstChild);
- }
+
+ fixture.innerHTML = '';
+ makeShadowTree(fixture.querySelector('div'));
+ var tree = axe.utils.getFlattenedTree(fixture.firstChild);
+ var el = axe.utils.querySelectorAll(tree, 'a')[0];
+ assert.equal(axe.commons.dom.findUp(el.actualNode, 'label'), fixture.firstChild);
});
- it('should walk up the shadow DOM', function () {
+ (shadowSupport.v1 ? it : xit)('should walk up the shadow DOM', function () {
function createContent() {
var group = document.createElement('div');
group.innerHTML = 'thing';
@@ -107,12 +117,22 @@ describe('dom.findUp', function () {
root.appendChild(div);
div.appendChild(createContent());
}
- if (shadowSupport.v1) {
- fixture.innerHTML = '';
- makeShadowTree(fixture.querySelector('div'));
- var tree = axe.utils.getFlattenedTree(fixture.firstChild);
- var el = axe.utils.querySelectorAll(tree, 'a')[0];
- assert.equal(axe.commons.dom.findUp(el.actualNode, 'label'), fixture.firstChild);
- }
+
+ fixture.innerHTML = '';
+ makeShadowTree(fixture.querySelector('div'));
+ var tree = axe.utils.getFlattenedTree(fixture.firstChild);
+ var el = axe.utils.querySelectorAll(tree, 'a')[0];
+ assert.equal(axe.commons.dom.findUp(el.actualNode, 'label'), fixture.firstChild);
+ });
+
+ (shadowSupport.v1 ? it : xit)('should work on shadow root children', function () {
+ fixture.innerHTML = '';
+ var shadow = fixture.querySelector('#something').attachShadow({ mode: 'open' });
+
+ shadow.innerHTML = '
item 1
';
+ var listItem = shadow.querySelector('[role=listitem]');
+
+ assert.equal(axe.commons.dom.findUp(listItem, '[role=list]'),
+ fixture.firstChild);
});
});
\ No newline at end of file