Skip to content

Commit bdd94a2

Browse files
committed
fix(get-ancestry): add nth-child selector for multiple siblings of shadow root (#4606)
Closes: #4563
1 parent 364eb72 commit bdd94a2

File tree

2 files changed

+43
-22
lines changed

2 files changed

+43
-22
lines changed

lib/core/utils/get-ancestry.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,24 @@ import getShadowSelector from './get-shadow-selector';
22

33
function generateAncestry(node) {
44
const nodeName = node.nodeName.toLowerCase();
5-
const parent = node.parentElement;
6-
if (!parent) {
7-
return nodeName;
8-
}
5+
const parentElement = node.parentElement;
6+
const parentNode = node.parentNode;
97

108
let nthChild = '';
119
if (
1210
nodeName !== 'head' &&
1311
nodeName !== 'body' &&
14-
parent.children.length > 1
12+
parentNode.children.length > 1
1513
) {
16-
const index = Array.prototype.indexOf.call(parent.children, node) + 1;
14+
const index = Array.prototype.indexOf.call(parentNode.children, node) + 1;
1715
nthChild = `:nth-child(${index})`;
1816
}
1917

20-
return generateAncestry(parent) + ' > ' + nodeName + nthChild;
18+
if (!parentElement) {
19+
return nodeName + nthChild;
20+
}
21+
22+
return generateAncestry(parentElement) + ' > ' + nodeName + nthChild;
2123
}
2224

2325
/**

test/core/utils/get-ancestry.js

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,69 @@
1-
describe('axe.utils.getAncestry', function () {
1+
describe('axe.utils.getAncestry', () => {
22
'use strict';
3-
var fixture = document.getElementById('fixture');
4-
var shadowTest = axe.testUtils.shadowSupport.v1 ? it : xit;
3+
const fixture = document.getElementById('fixture');
54

6-
afterEach(function () {
5+
afterEach(() => {
76
fixture.innerHTML = '';
87
});
98

10-
it('should be a function', function () {
9+
it('should be a function', () => {
1110
assert.isFunction(axe.utils.getAncestry);
1211
});
1312

14-
it('should generate an ancestry selector', function () {
13+
it('should generate an ancestry selector', () => {
1514
fixture.innerHTML = '<div>1</div> <p>2</p> <p>3</p>';
1615

17-
var sel1 = axe.utils.getAncestry(fixture.children[0]);
16+
const sel1 = axe.utils.getAncestry(fixture.children[0]);
1817
assert.equal(sel1, 'html > body > div:nth-child(1) > div:nth-child(1)');
1918
assert.isNotNull(document.querySelector(sel1));
2019

21-
var sel2 = axe.utils.getAncestry(fixture.children[1]);
20+
const sel2 = axe.utils.getAncestry(fixture.children[1]);
2221
assert.equal(sel2, 'html > body > div:nth-child(1) > p:nth-child(2)');
2322
assert.isNotNull(document.querySelector(sel1));
2423

25-
var sel3 = axe.utils.getAncestry(fixture.children[2]);
24+
const sel3 = axe.utils.getAncestry(fixture.children[2]);
2625
assert.equal(sel3, 'html > body > div:nth-child(1) > p:nth-child(3)');
2726
assert.isNotNull(document.querySelector(sel1));
2827
});
2928

30-
shadowTest('generates selectors of nested shadow trees', function () {
31-
var node = document.createElement('section');
29+
it('generates selectors of nested shadow trees', () => {
30+
const node = document.createElement('section');
3231
fixture.appendChild(node);
3332

34-
var shadowRoot1 = node.attachShadow({ mode: 'open' });
33+
const shadowRoot1 = node.attachShadow({ mode: 'open' });
3534
shadowRoot1.innerHTML = '<div><article><slot /></article</div>';
3635

37-
var shadowRoot2 = shadowRoot1
36+
const shadowRoot2 = shadowRoot1
3837
.querySelector('article')
3938
.attachShadow({ mode: 'open' });
4039
shadowRoot2.innerHTML = '<h1>Hello world</h1>';
4140

42-
var target = shadowRoot2.querySelector('h1');
43-
var sel = axe.utils.getAncestry(target);
41+
const target = shadowRoot2.querySelector('h1');
42+
const sel = axe.utils.getAncestry(target);
4443
assert.deepEqual(sel, [
4544
'html > body > div:nth-child(1) > section',
4645
'div > article',
4746
'h1'
4847
]);
4948
});
49+
50+
it('generates selectors of siblings in shadow tree', () => {
51+
const node = document.createElement('section');
52+
fixture.appendChild(node);
53+
54+
const shadowRoot = node.attachShadow({ mode: 'open' });
55+
shadowRoot.innerHTML = '<div>1</div> <div>2</div>';
56+
57+
const sel1 = axe.utils.getAncestry(shadowRoot.children[0]);
58+
assert.deepEqual(sel1, [
59+
'html > body > div:nth-child(1) > section',
60+
'div:nth-child(1)'
61+
]);
62+
63+
const sel2 = axe.utils.getAncestry(shadowRoot.children[1]);
64+
assert.deepEqual(sel2, [
65+
'html > body > div:nth-child(1) > section',
66+
'div:nth-child(2)'
67+
]);
68+
});
5069
});

0 commit comments

Comments
 (0)