Skip to content

Commit 0f98481

Browse files
authored
fix: Let findUp work on shadow root children (#447)
* fix: Let findUp work on shadow root children * fix: Solve a few tests # Conflicts: # test/testutils.js * Fix: Properly disable of shadow DOM checks * test: Use findUp on host element
1 parent 2c0b075 commit 0f98481

File tree

11 files changed

+70
-62
lines changed

11 files changed

+70
-62
lines changed

lib/checks/label/explicit.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
if (node.getAttribute('id')) {
2+
const root = axe.commons.dom.getRootNode(node);
23
const id = axe.commons.utils.escapeSelector(node.getAttribute('id'));
3-
const label = document.querySelector(`label[for="${id}"]`);
4+
const label = root.querySelector(`label[for="${id}"]`);
45

56
if (label) {
67
return !!axe.commons.text.accessibleText(label);

lib/commons/dom/find-up.js

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,24 @@
99
* @return {HTMLElement|null} Either the matching HTMLElement or `null` if there was no match
1010
*/
1111
dom.findUp = function (element, target) {
12-
'use strict';
13-
/*jslint browser:true*/
12+
let doc, matches,
13+
parent = element;
1414

15-
var parent,
16-
doc = axe.commons.dom.getRootNode(element),
17-
matches;
18-
19-
matches = doc.querySelectorAll(target);
20-
matches = axe.utils.toArray(matches);
21-
if (doc === document && !matches.length) {
22-
return null;
23-
}
24-
25-
// recursively walk up the DOM, checking each parent node
26-
parent = dom.getComposedParent(element);
27-
while (parent && matches.indexOf(parent) === -1) {
28-
parent = (parent.assignedSlot) ? parent.assignedSlot : parent.parentNode;
15+
do {// recursively walk up the DOM, checking each parent node
16+
parent = (parent.assignedSlot ? parent.assignedSlot : parent.parentNode);
2917
if (parent && parent.nodeType === 11) {
18+
matches = null;
3019
parent = parent.host;
20+
}
21+
if (!matches) {
3122
doc = axe.commons.dom.getRootNode(parent);
3223
matches = doc.querySelectorAll(target);
3324
matches = axe.utils.toArray(matches);
3425
if (doc === document && !matches.length) {
3526
return null;
3627
}
3728
}
38-
}
29+
} while (parent && !matches.includes(parent));
3930

4031
return parent;
4132
};

test/checks/lists/dlitem.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe('dlitem', function () {
2121
assert.isFalse(checks.dlitem.evaluate.apply(null, checkArgs));
2222
});
2323

24-
(shadowSupport ? it : xit)('should return true in a shadow DOM pass', function () {
24+
(shadowSupport.v1 ? it : xit)('should return true in a shadow DOM pass', function () {
2525
var node = document.createElement('div');
2626
node.innerHTML = '<dt>My list item </dt>';
2727
var shadow = node.attachShadow({ mode: 'open' });
@@ -31,7 +31,7 @@ describe('dlitem', function () {
3131
assert.isTrue(checks.dlitem.evaluate.apply(null, checkArgs));
3232
});
3333

34-
(shadowSupport ? it : xit)('should return false in a shadow DOM fail', function () {
34+
(shadowSupport.v1 ? it : xit)('should return false in a shadow DOM fail', function () {
3535
var node = document.createElement('div');
3636
node.innerHTML = '<dt>My list item </dt>';
3737
var shadow = node.attachShadow({ mode: 'open' });

test/checks/lists/has-listitem.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ describe('has-listitem', function () {
3333
assert.isFalse(checks['has-listitem'].evaluate.apply(null, checkArgs));
3434
});
3535

36-
(shadowSupport ? it : xit)('should return true in a shadow DOM pass', function () {
36+
(shadowSupport.v1 ? it : xit)('should return true in a shadow DOM pass', function () {
3737
var node = document.createElement('div');
3838
node.innerHTML = '<li>My list item </li>';
3939
var shadow = node.attachShadow({ mode: 'open' });
@@ -43,7 +43,7 @@ describe('has-listitem', function () {
4343
assert.isFalse(checks['has-listitem'].evaluate.apply(null, checkArgs));
4444
});
4545

46-
(shadowSupport ? it : xit)('should return false in a shadow DOM fail', function () {
46+
(shadowSupport.v1 ? it : xit)('should return false in a shadow DOM fail', function () {
4747
var node = document.createElement('div');
4848
node.innerHTML = '<p>Not a list</p>';
4949
var shadow = node.attachShadow({ mode: 'open' });

test/checks/lists/listitem.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ describe('listitem', function () {
3333
assert.isFalse(checks.listitem.evaluate.apply(null, checkArgs));
3434
});
3535

36-
(shadowSupport ? it : xit)('should return true in a shadow DOM pass', function () {
36+
(shadowSupport.v1 ? it : xit)('should return true in a shadow DOM pass', function () {
3737
var node = document.createElement('div');
3838
node.innerHTML = '<li>My list item </li>';
3939
var shadow = node.attachShadow({ mode: 'open' });
@@ -43,7 +43,7 @@ describe('listitem', function () {
4343
assert.isTrue(checks.listitem.evaluate.apply(null, checkArgs));
4444
});
4545

46-
(shadowSupport ? it : xit)('should return false in a shadow DOM fail', function () {
46+
(shadowSupport.v1 ? it : xit)('should return false in a shadow DOM fail', function () {
4747
var node = document.createElement('div');
4848
node.innerHTML = '<li>My list item </li>';
4949
var shadow = node.attachShadow({ mode: 'open' });

test/checks/lists/only-dlitems.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ describe('only-dlitems', function () {
104104
assert.isFalse(checks['only-dlitems'].evaluate.apply(checkContext, checkArgs));
105105
});
106106

107-
(shadowSupport ? it : xit)('should return false in a shadow DOM pass', function () {
107+
(shadowSupport.v1 ? it : xit)('should return false in a shadow DOM pass', function () {
108108
var node = document.createElement('div');
109109
node.innerHTML = '<dt>My list item </dt>';
110110
var shadow = node.attachShadow({ mode: 'open' });
@@ -114,7 +114,7 @@ describe('only-dlitems', function () {
114114
assert.isFalse(checks['only-dlitems'].evaluate.apply(checkContext, checkArgs));
115115
});
116116

117-
(shadowSupport ? it : xit)('should return true in a shadow DOM fail', function () {
117+
(shadowSupport.v1 ? it : xit)('should return true in a shadow DOM fail', function () {
118118
var node = document.createElement('div');
119119
node.innerHTML = '<p>Not a list</p>';
120120
var shadow = node.attachShadow({ mode: 'open' });

test/checks/lists/only-listitems.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ describe('only-listitems', function () {
9797
assert.isFalse(checks['only-listitems'].evaluate.apply(checkContext, checkArgs));
9898
});
9999

100-
(shadowSupport ? it : xit)('should return false in a shadow DOM pass', function () {
100+
(shadowSupport.v1 ? it : xit)('should return false in a shadow DOM pass', function () {
101101
var node = document.createElement('div');
102102
node.innerHTML = '<li>My list item </li>';
103103
var shadow = node.attachShadow({ mode: 'open' });
@@ -107,7 +107,7 @@ describe('only-listitems', function () {
107107
assert.isFalse(checks['only-listitems'].evaluate.apply(checkContext, checkArgs));
108108
});
109109

110-
(shadowSupport ? it : xit)('should return true in a shadow DOM fail', function () {
110+
(shadowSupport.v1 ? it : xit)('should return true in a shadow DOM fail', function () {
111111
var node = document.createElement('div');
112112
node.innerHTML = '<p>Not a list item</p>';
113113
var shadow = node.attachShadow({ mode: 'open' });

test/checks/lists/structured-dlitems.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ describe('structured-dlitems', function () {
4949
assert.isFalse(checks['structured-dlitems'].evaluate.apply(null, checkArgs));
5050
});
5151

52-
(shadowSupport ? it : xit)('should return false in a shadow DOM pass', function () {
52+
(shadowSupport.v1 ? it : xit)('should return false in a shadow DOM pass', function () {
5353
var node = document.createElement('div');
5454
node.innerHTML = '<dt>Grayhound bus</dt><dd>at dawn</dd>';
5555
var shadow = node.attachShadow({ mode: 'open' });
@@ -59,7 +59,7 @@ describe('structured-dlitems', function () {
5959
assert.isFalse(checks['structured-dlitems'].evaluate.apply(null, checkArgs));
6060
});
6161

62-
(shadowSupport ? it : xit)('should return true in a shadow DOM fail', function () {
62+
(shadowSupport.v1 ? it : xit)('should return true in a shadow DOM fail', function () {
6363
var node = document.createElement('div');
6464
node.innerHTML = '<dd>Galileo</dd><dt>Figaro</dt>';
6565
var shadow = node.attachShadow({ mode: 'open' });

test/checks/navigation/landmark.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ describe('landmark', function () {
2424
assert.isFalse(checks.landmark.evaluate.apply(null, checkArgs));
2525
});
2626

27-
(shadowSupport ? it : xit)('should not automatically pass if there is a shadow tree', function () {
27+
(shadowSupport.v1 ? it : xit)('should not automatically pass if there is a shadow tree', function () {
2828
var node = document.createElement('div');
2929
var shadow = node.attachShadow({ mode: 'open' });
3030
shadow.innerHTML = '<div></div>';
@@ -33,7 +33,7 @@ describe('landmark', function () {
3333
assert.isFalse(checks.landmark.evaluate.apply(null, checkArgs));
3434
});
3535

36-
(shadowSupport ? it : xit)('should find elements inside shadow trees', function () {
36+
(shadowSupport.v1 ? it : xit)('should find elements inside shadow trees', function () {
3737
var node = document.createElement('div');
3838
var shadow = node.attachShadow({ mode: 'open' });
3939
shadow.innerHTML = '<main></main>';
@@ -42,7 +42,7 @@ describe('landmark', function () {
4242
assert.isTrue(checks.landmark.evaluate.apply(null, checkArgs));
4343
});
4444

45-
(shadowSupport ? it : xit)('should find elements slotted in shadow trees', function () {
45+
(shadowSupport.v1 ? it : xit)('should find elements slotted in shadow trees', function () {
4646
var node = document.createElement('div');
4747
node.innerHTML = '<main></main>';
4848
var shadow = node.attachShadow({ mode: 'open' });

test/checks/shared/button-has-visible-text.js

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ describe('button-has-visible-text', function () {
22
'use strict';
33

44
var fixture = document.getElementById('fixture');
5-
5+
var checkSetup = axe.testUtils.checkSetup;
66
var checkContext = {
77
_data: null,
88
data: function (d) {
@@ -16,32 +16,28 @@ describe('button-has-visible-text', function () {
1616
});
1717

1818
it('should return false if button element is empty', function () {
19-
fixture.innerHTML = '<button></button>';
19+
var checkArgs = checkSetup('<button></button>', 'button');
2020

21-
var node = fixture.querySelector('button');
22-
assert.isFalse(checks['button-has-visible-text'].evaluate.call(checkContext, node));
21+
assert.isFalse(checks['button-has-visible-text'].evaluate.apply(checkContext, checkArgs));
2322
});
2423

2524
it('should return true if a button element has text', function () {
26-
fixture.innerHTML = '<button>Name</button>';
25+
var checkArgs = checkSetup('<button>Name</button>', 'button');
2726

28-
var node = fixture.querySelector('button');
29-
assert.isTrue(checks['button-has-visible-text'].evaluate.call(checkContext, node));
27+
assert.isTrue(checks['button-has-visible-text'].evaluate.apply(checkContext, checkArgs));
3028
assert.deepEqual(checkContext._data, 'Name');
3129
});
3230

3331
it('should return true if ARIA button has text', function () {
34-
fixture.innerHTML = '<div role="button">Text</div>';
32+
var checkArgs = checkSetup('<div role="button">Text</div>>', '[role=button]');
3533

36-
var node = fixture.querySelector('div');
37-
assert.isTrue(checks['button-has-visible-text'].evaluate.call(checkContext, node));
34+
assert.isTrue(checks['button-has-visible-text'].evaluate.apply(checkContext, checkArgs));
3835
assert.deepEqual(checkContext._data, 'Text');
3936
});
4037

4138
it('should return false if ARIA button has no text', function () {
42-
fixture.innerHTML = '<div role="button"></div>';
39+
var checkArgs = checkSetup('<div role="button"></div>>', '[role=button]');
4340

44-
var node = fixture.querySelector('div');
45-
assert.isFalse(checks['button-has-visible-text'].evaluate.call(checkContext, node));
41+
assert.isFalse(checks['button-has-visible-text'].evaluate.apply(checkContext, checkArgs));
4642
});
4743
});

0 commit comments

Comments
 (0)