From 3967b4801ae57e3dba4641df2fa26d98ead06008 Mon Sep 17 00:00:00 2001 From: Carolina Urrea <73137943+canourrea23@users.noreply.github.com> Date: Tue, 31 Oct 2023 11:39:29 -0700 Subject: [PATCH] fix: update visibility check with overflow: hidden and element on the edge (#27586) Co-authored-by: Chris Breiding Co-authored-by: Matt Schile Co-authored-by: Jennifer Shehane Co-authored-by: Emily Rohrbough Co-authored-by: Emily Rohrbough --- cli/CHANGELOG.md | 8 +++++++ .../driver/cypress/e2e/dom/visibility.cy.ts | 17 +++++++------- .../e2e/dom/visibility_shadow_dom.cy.ts | 8 +++---- packages/driver/src/dom/elements/find.ts | 8 ++++++- packages/driver/src/dom/visibility.ts | 23 +++++++++++++------ 5 files changed, 43 insertions(+), 21 deletions(-) diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index eabda4019d..4cb0cd8cf5 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -1,4 +1,12 @@ +## 13.4.1 + +_Released 11/7/2023 (PENDING)_ + +**Bugfixes:** + +- Fixed an issue determining visibility when an element is hidden by an ancestor with a shared edge. Fixes [#27514](https://github.com/cypress-io/cypress/issues/27514). + ## 13.4.0 _Released 10/30/2023_ diff --git a/packages/driver/cypress/e2e/dom/visibility.cy.ts b/packages/driver/cypress/e2e/dom/visibility.cy.ts index adaa51f99b..5dc7495afc 100644 --- a/packages/driver/cypress/e2e/dom/visibility.cy.ts +++ b/packages/driver/cypress/e2e/dom/visibility.cy.ts @@ -356,25 +356,25 @@ describe('src/cypress/dom/visibility', () => { this.$elOutOfParentBoundsToLeft = add(`\
- position: absolute, out of bounds left + position: absolute, out of bounds left
\ `) this.$elOutOfParentBoundsToRight = add(`\
- position: absolute, out of bounds right + position: absolute, out of bounds right
\ `) this.$elOutOfParentBoundsAbove = add(`\
- position: absolute, out of bounds above + position: absolute, out of bounds above
\ `) this.$elOutOfParentBoundsBelow = add(`\
- position: absolute, out of bounds below + position: absolute, out of bounds below
\ `) @@ -819,10 +819,9 @@ describe('src/cypress/dom/visibility', () => { }) describe('css overflow', () => { - it('is visible when parent doesnt have overflow hidden', function () { - expect(this.$parentNoWidthHeightOverflowAuto.find('span')).to.be.visible - - expect(this.$parentNoWidthHeightOverflowAuto.find('span')).to.not.be.hidden + it('is hidden when parent overflow auto and no width/height', function () { + expect(this.$parentNoWidthHeightOverflowAuto.find('span')).to.not.be.visible + expect(this.$parentNoWidthHeightOverflowAuto.find('span')).to.be.hidden }) it('is hidden when parent overflow hidden and out of bounds to left', function () { @@ -897,7 +896,7 @@ describe('src/cypress/dom/visibility', () => { }) describe('css clip-path', () => { - // TODO: why is this skipped? + // TODO: handle clip path 'hidden' equivalents it.skip('is hidden when outside of parents clip-path', function () { expect(this.$parentWithClipPathAbsolutePositionElOutsideClipPath.find('span')).to.be.hidden }) diff --git a/packages/driver/cypress/e2e/dom/visibility_shadow_dom.cy.ts b/packages/driver/cypress/e2e/dom/visibility_shadow_dom.cy.ts index f34df529e9..5d1b6779e4 100644 --- a/packages/driver/cypress/e2e/dom/visibility_shadow_dom.cy.ts +++ b/packages/driver/cypress/e2e/dom/visibility_shadow_dom.cy.ts @@ -303,7 +303,7 @@ describe('src/cypress/dom/visibility - shadow dom', () => { `
`, - `position: absolute, out of bounds left`, + `position: absolute, out of bounds left`, '#el-out-of-parent-bounds-to-left', ) @@ -316,7 +316,7 @@ describe('src/cypress/dom/visibility - shadow dom', () => { `
`, - `position: absolute, out of bounds right`, + `position: absolute, out of bounds right`, '#el-out-of-parent-bounds-to-right', ) @@ -329,7 +329,7 @@ describe('src/cypress/dom/visibility - shadow dom', () => { `
`, - `position: absolute, out of bounds above`, + `position: absolute, out of bounds above`, '#el-out-of-parent-bounds-above', ) @@ -342,7 +342,7 @@ describe('src/cypress/dom/visibility - shadow dom', () => { `
`, - `position: absolute, out of bounds below`, + `position: absolute, out of bounds below`, '#el-out-of-parent-bounds-below', ) diff --git a/packages/driver/src/dom/elements/find.ts b/packages/driver/src/dom/elements/find.ts index 9e657450ea..16f95fa201 100644 --- a/packages/driver/src/dom/elements/find.ts +++ b/packages/driver/src/dom/elements/find.ts @@ -176,7 +176,13 @@ export const isAncestor = ($el, $maybeAncestor) => { } export const isChild = ($el, $maybeChild) => { - return $el.children().index($maybeChild) >= 0 + let children = $el.children() + + if (children.length && children[0].nodeName === 'SHADOW-ROOT') { + return isDescendent($el, $maybeChild) + } + + return children.index($maybeChild) >= 0 } export const isDescendent = ($el1, $el2) => { diff --git a/packages/driver/src/dom/visibility.ts b/packages/driver/src/dom/visibility.ts index 9a1be1ac7f..2a92fae2b9 100644 --- a/packages/driver/src/dom/visibility.ts +++ b/packages/driver/src/dom/visibility.ts @@ -316,24 +316,27 @@ const elIsOutOfBoundsOfAncestorsOverflow = function ($el, $ancestor = getParent( return false } - const elProps = $coordinates.getElementPositioning($el) - if (canClipContent($el, $ancestor)) { + const elProps = $coordinates.getElementPositioning($el) const ancestorProps = $coordinates.getElementPositioning($ancestor) + if (elHasPositionAbsolute($el) && (ancestorProps.width === 0 || ancestorProps.height === 0)) { + return elIsOutOfBoundsOfAncestorsOverflow($el, getParent($ancestor)) + } + // target el is out of bounds if ( // target el is to the right of the ancestor's visible area - (elProps.fromElWindow.left > (ancestorProps.width + ancestorProps.fromElWindow.left)) || + (elProps.fromElWindow.left >= (ancestorProps.width + ancestorProps.fromElWindow.left)) || // target el is to the left of the ancestor's visible area - ((elProps.fromElWindow.left + elProps.width) < ancestorProps.fromElWindow.left) || + ((elProps.fromElWindow.left + elProps.width) <= ancestorProps.fromElWindow.left) || // target el is under the ancestor's visible area - (elProps.fromElWindow.top > (ancestorProps.height + ancestorProps.fromElWindow.top)) || + (elProps.fromElWindow.top >= (ancestorProps.height + ancestorProps.fromElWindow.top)) || // target el is above the ancestor's visible area - ((elProps.fromElWindow.top + elProps.height) < ancestorProps.fromElWindow.top) + ((elProps.fromElWindow.top + elProps.height) <= ancestorProps.fromElWindow.top) ) { return true } @@ -555,5 +558,11 @@ export const getReasonIsHidden = function ($el, options = { checkOpacity: true } /* eslint-enable no-cond-assign */ export default { - isVisible, isHidden, isStrictlyHidden, isHiddenByAncestors, getReasonIsHidden, isW3CFocusable, isW3CRendered, + isVisible, + isHidden, + isStrictlyHidden, + isHiddenByAncestors, + getReasonIsHidden, + isW3CFocusable, + isW3CRendered, }