diff --git a/packages/driver/cypress/fixtures/shadow-dom.html b/packages/driver/cypress/fixtures/shadow-dom.html index c75e753632f8..c4c1f240542c 100644 --- a/packages/driver/cypress/fixtures/shadow-dom.html +++ b/packages/driver/cypress/fixtures/shadow-dom.html @@ -3,7 +3,7 @@ Shadow DOM Fixture - +
Non Shadow
diff --git a/packages/driver/cypress/integration/commands/traversals_shadow_dom_spec.js b/packages/driver/cypress/integration/commands/traversals_shadow_dom_spec.js index a8bfb9ca7397..d0e58307268a 100644 --- a/packages/driver/cypress/integration/commands/traversals_shadow_dom_spec.js +++ b/packages/driver/cypress/integration/commands/traversals_shadow_dom_spec.js @@ -266,15 +266,15 @@ describe('src/cy/commands/traversals - shadow dom', () => { .then(($parents) => { expect($parents.length).to.eq(10) expect($parents[0]).to.have.class('shadow-div') - expect($parents[1]).to.match('html') - expect($parents[2]).to.match('body') + expect($parents[1]).to.have.id('shadow-element-3') + expect($parents[2]).to.have.id('parent-of-shadow-container-1') expect($parents[3]).to.have.id('parent-of-shadow-container-0') - expect($parents[4]).to.have.id('parent-of-shadow-container-1') - expect($parents[5]).to.have.id('shadow-element-3') - expect($parents[6]).to.have.class('shadow-div') + expect($parents[4]).to.have.class('shadow-div') + expect($parents[5]).to.have.id('shadow-element-8') + expect($parents[6]).to.have.id('parent-of-shadow-container-3') expect($parents[7]).to.have.id('parent-of-shadow-container-2') - expect($parents[8]).to.have.id('parent-of-shadow-container-3') - expect($parents[9]).to.have.id('shadow-element-8') + expect($parents[8]).to.match('body') + expect($parents[9]).to.match('html') }) }) }) @@ -321,9 +321,10 @@ describe('src/cy/commands/traversals - shadow dom', () => { .find('p', { includeShadowDom: true }) .parents('.filter-me') .then(($parents) => { - expect($parents.length).to.eq(2) + expect($parents.length).to.eq(3) expect($parents[0]).to.have.id('parent-of-shadow-container-1') expect($parents[1]).to.have.id('parent-of-shadow-container-3') + expect($parents[2]).to.match('body') }) }) }) @@ -368,15 +369,15 @@ describe('src/cy/commands/traversals - shadow dom', () => { .then(($parents) => { expect($parents.length).to.eq(10) expect($parents[0]).to.have.class('shadow-div') - expect($parents[1]).to.match('html') - expect($parents[2]).to.match('body') + expect($parents[1]).to.have.id('shadow-element-3') + expect($parents[2]).to.have.id('parent-of-shadow-container-1') expect($parents[3]).to.have.id('parent-of-shadow-container-0') - expect($parents[4]).to.have.id('parent-of-shadow-container-1') - expect($parents[5]).to.have.id('shadow-element-3') - expect($parents[6]).to.have.class('shadow-div') + expect($parents[4]).to.have.class('shadow-div') + expect($parents[5]).to.have.id('shadow-element-8') + expect($parents[6]).to.have.id('parent-of-shadow-container-3') expect($parents[7]).to.have.id('parent-of-shadow-container-2') - expect($parents[8]).to.have.id('parent-of-shadow-container-3') - expect($parents[9]).to.have.id('shadow-element-8') + expect($parents[8]).to.match('body') + expect($parents[9]).to.match('html') }) }) }) @@ -426,13 +427,13 @@ describe('src/cy/commands/traversals - shadow dom', () => { .then(($parents) => { expect($parents.length).to.eq(8) expect($parents[0]).to.have.class('shadow-div') - expect($parents[1]).to.have.id('parent-of-shadow-container-0') + expect($parents[1]).to.have.id('shadow-element-3') expect($parents[2]).to.have.id('parent-of-shadow-container-1') - expect($parents[3]).to.have.id('shadow-element-3') + expect($parents[3]).to.have.id('parent-of-shadow-container-0') expect($parents[4]).to.have.class('shadow-div') - expect($parents[5]).to.have.id('parent-of-shadow-container-2') + expect($parents[5]).to.have.id('shadow-element-8') expect($parents[6]).to.have.id('parent-of-shadow-container-3') - expect($parents[7]).to.have.id('shadow-element-8') + expect($parents[7]).to.have.id('parent-of-shadow-container-2') }) }) }) @@ -455,9 +456,10 @@ describe('src/cy/commands/traversals - shadow dom', () => { .find('.shadow-8-nested-3', { includeShadowDom: true }) .parentsUntil('#parent-of-shadow-container-0', '.filter-me') .then(($parents) => { - expect($parents.length).to.eq(2) + expect($parents.length).to.eq(3) expect($parents[0]).to.have.class('shadow-8-nested-1') expect($parents[1]).to.have.id('parent-of-shadow-container-3') + expect($parents[2]).to.match('body') }) }) @@ -475,11 +477,12 @@ describe('src/cy/commands/traversals - shadow dom', () => { cy .get('#shadow-element-3, #shadow-element-8') .find('p', { includeShadowDom: true }) - .parentsUntil('body', '.filter-me') + .parentsUntil('html', '.filter-me') .then(($parents) => { - expect($parents.length).to.eq(2) + expect($parents.length).to.eq(3) expect($parents[0]).to.have.id('parent-of-shadow-container-1') expect($parents[1]).to.have.id('parent-of-shadow-container-3') + expect($parents[2]).to.match('body') }) }) }) @@ -536,17 +539,23 @@ describe('src/cy/commands/traversals - shadow dom', () => { it('handles multiple elements in subject', () => { cy - .get('#shadow-element-8') - .find('.shadow-div', { includeShadowDom: true }) + .get('html') .then(($untilEl) => { cy - .get('.shadow-8-nested-3, .shadow-8-nested-4', { includeShadowDom: true }) + .get('#shadow-element-3, #shadow-element-8') + .find('p', { includeShadowDom: true }) .parentsUntil($untilEl[0]) .then(($parents) => { - expect($parents.length).to.eq(3) - expect($parents[0]).to.have.class('shadow-content') - expect($parents[1]).to.have.class('shadow-8-nested-1') - expect($parents[2]).to.have.class('shadow-8-nested-2') + expect($parents.length).to.eq(9) + expect($parents[0]).to.have.class('shadow-div') + expect($parents[1]).to.have.id('shadow-element-3') + expect($parents[2]).to.have.id('parent-of-shadow-container-1') + expect($parents[3]).to.have.id('parent-of-shadow-container-0') + expect($parents[4]).to.have.class('shadow-div') + expect($parents[5]).to.have.id('shadow-element-8') + expect($parents[6]).to.have.id('parent-of-shadow-container-3') + expect($parents[7]).to.have.id('parent-of-shadow-container-2') + expect($parents[8]).to.match('body') }) }) }) @@ -578,9 +587,10 @@ describe('src/cy/commands/traversals - shadow dom', () => { .find('.shadow-8-nested-3', { includeShadowDom: true }) .parentsUntil($untilEl[0], '.filter-me') .then(($parents) => { - expect($parents.length).to.eq(2) + expect($parents.length).to.eq(3) expect($parents[0]).to.have.class('shadow-8-nested-1') expect($parents[1]).to.have.id('parent-of-shadow-container-3') + expect($parents[2]).to.match('body') }) }) }) @@ -601,15 +611,17 @@ describe('src/cy/commands/traversals - shadow dom', () => { it('handles multiple elements in subject', () => { cy - .get('#shadow-element-8') - .find('.shadow-div', { includeShadowDom: true }) + .get('html') .then(($untilEl) => { cy - .get('.shadow-8-nested-3, .shadow-8-nested-4', { includeShadowDom: true }) + .get('#shadow-element-3, #shadow-element-8') + .find('p', { includeShadowDom: true }) .parentsUntil($untilEl[0], '.filter-me') .then(($parents) => { - expect($parents.length).to.eq(1) - expect($parents[0]).to.have.class('shadow-8-nested-1') + expect($parents.length).to.eq(3) + expect($parents[0]).to.have.id('parent-of-shadow-container-1') + expect($parents[1]).to.have.id('parent-of-shadow-container-3') + expect($parents[2]).to.match('body') }) }) }) @@ -667,17 +679,23 @@ describe('src/cy/commands/traversals - shadow dom', () => { it('handles multiple elements in subject', () => { cy - .get('#shadow-element-8') - .find('.shadow-div', { includeShadowDom: true }) + .get('html') .then(($untilEl) => { cy - .get('.shadow-8-nested-3, .shadow-8-nested-4', { includeShadowDom: true }) + .get('#shadow-element-3, #shadow-element-8') + .find('p', { includeShadowDom: true }) .parentsUntil($untilEl) .then(($parents) => { - expect($parents.length).to.eq(3) - expect($parents[0]).to.have.class('shadow-content') - expect($parents[1]).to.have.class('shadow-8-nested-1') - expect($parents[2]).to.have.class('shadow-8-nested-2') + expect($parents.length).to.eq(9) + expect($parents[0]).to.have.class('shadow-div') + expect($parents[1]).to.have.id('shadow-element-3') + expect($parents[2]).to.have.id('parent-of-shadow-container-1') + expect($parents[3]).to.have.id('parent-of-shadow-container-0') + expect($parents[4]).to.have.class('shadow-div') + expect($parents[5]).to.have.id('shadow-element-8') + expect($parents[6]).to.have.id('parent-of-shadow-container-3') + expect($parents[7]).to.have.id('parent-of-shadow-container-2') + expect($parents[8]).to.match('body') }) }) }) @@ -709,9 +727,10 @@ describe('src/cy/commands/traversals - shadow dom', () => { .find('.shadow-8-nested-3', { includeShadowDom: true }) .parentsUntil($untilEl, '.filter-me') .then(($parents) => { - expect($parents.length).to.eq(2) + expect($parents.length).to.eq(3) expect($parents[0]).to.have.class('shadow-8-nested-1') expect($parents[1]).to.have.id('parent-of-shadow-container-3') + expect($parents[2]).to.match('body') }) }) }) @@ -732,15 +751,17 @@ describe('src/cy/commands/traversals - shadow dom', () => { it('handles multiple elements in subject', () => { cy - .get('#shadow-element-8') - .find('.shadow-div', { includeShadowDom: true }) + .get('html') .then(($untilEl) => { cy - .get('.shadow-8-nested-3, .shadow-8-nested-4', { includeShadowDom: true }) + .get('#shadow-element-3, #shadow-element-8') + .find('p', { includeShadowDom: true }) .parentsUntil($untilEl, '.filter-me') .then(($parents) => { - expect($parents.length).to.eq(1) - expect($parents[0]).to.have.class('shadow-8-nested-1') + expect($parents.length).to.eq(3) + expect($parents[0]).to.have.id('parent-of-shadow-container-1') + expect($parents[1]).to.have.id('parent-of-shadow-container-3') + expect($parents[2]).to.match('body') }) }) }) diff --git a/packages/driver/src/cy/commands/traversals.js b/packages/driver/src/cy/commands/traversals.js index cdbe60396b7a..82e7145d4085 100644 --- a/packages/driver/src/cy/commands/traversals.js +++ b/packages/driver/src/cy/commands/traversals.js @@ -1,4 +1,3 @@ -const $ = require('jquery') const _ = require('lodash') const $dom = require('../../dom') @@ -20,6 +19,14 @@ const optInShadowTraversals = { }, } +const sortedUnique = (cy, $el) => { + // we want _.uniq() to keep the elements with higher indexes instead of lower + // so we reverse, uniq, then reverse again + // so [div1, body, html, div2, body, html] + // becomes [div1, div2, body, html] and not [div1, body, html, div2] + return cy.$$(_($el).reverse().uniq().reverse().value()) +} + const autoShadowTraversals = { closest: (cy, $el, selector) => { const nodes = _.reduce($el, (nodes, el) => { @@ -38,14 +45,14 @@ const autoShadowTraversals = { return getClosest(el) }, []) - return $.uniqueSort(nodes) + return sortedUnique(cy, nodes) }, parent: (cy, $el) => { const parents = $el.map((i, el) => { return $elements.getParent(el) }) - return $.uniqueSort(parents) + return sortedUnique(cy, parents) }, parents: (cy, $el, selector) => { let $parents = $el.map((i, el) => { @@ -53,7 +60,7 @@ const autoShadowTraversals = { }) if ($el.length > 1) { - $parents = $.uniqueSort($parents) + $parents = sortedUnique(cy, $parents) } if (!selector) { @@ -68,7 +75,7 @@ const autoShadowTraversals = { }) if ($el.length > 1) { - $parents = $.uniqueSort($parents) + $parents = sortedUnique(cy, $parents) } if (!filter) {