fix: update visibility check with overflow: hidden and element on the edge (#27586)

Co-authored-by: Chris Breiding <chrisbreiding@users.noreply.github.com>
Co-authored-by: Matt Schile <mschile@cypress.io>
Co-authored-by: Jennifer Shehane <jennifer@cypress.io>
Co-authored-by: Emily Rohrbough <emilyrohrbough@yahoo.com>
Co-authored-by: Emily Rohrbough <emilyrohrbough@users.noreply.github.com>
This commit is contained in:
Carolina Urrea
2023-10-31 11:39:29 -07:00
committed by GitHub
parent 6aafb528dd
commit 3967b4801a
5 changed files with 43 additions and 21 deletions

View File

@@ -1,4 +1,12 @@
<!-- See the ../guides/writing-the-cypress-changelog.md for details on writing the changelog. -->
## 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_

View File

@@ -356,25 +356,25 @@ describe('src/cypress/dom/visibility', () => {
this.$elOutOfParentBoundsToLeft = add(`\
<div style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
<span style='position: absolute; left: -400px; top: 0px;'>position: absolute, out of bounds left</span>
<span style='position: absolute; width: 100px; height: 100px; left: -100px; top: 0px;'>position: absolute, out of bounds left</span>
</div>\
`)
this.$elOutOfParentBoundsToRight = add(`\
<div id="elOutOfParentBoundsToRight" style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
<span style='position: absolute; left: 200px; top: 0px;'>position: absolute, out of bounds right</span>
<span style='position: absolute; width: 100px; height: 100px; right: -100px; top: 0px;'>position: absolute, out of bounds right</span>
</div>\
`)
this.$elOutOfParentBoundsAbove = add(`\
<div style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
<span style='position: absolute; left: 0px; top: -100px;'>position: absolute, out of bounds above</span>
<span style='position: absolute; width: 100px; height: 100px; left: 0px; top: -100px;'>position: absolute, out of bounds above</span>
</div>\
`)
this.$elOutOfParentBoundsBelow = add(`\
<div id="elOutOfParentBoundsBelow" style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
<span style='position: absolute; left: 0px; top: 200px;'>position: absolute, out of bounds below</span>
<span style='position: absolute; width: 100px; height: 100px; left: 0px; bottom: -100px;'>position: absolute, out of bounds below</span>
</div>\
`)
@@ -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
})

View File

@@ -303,7 +303,7 @@ describe('src/cypress/dom/visibility - shadow dom', () => {
`<div style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
<shadow-root id="el-out-of-parent-bounds-to-left"></shadow-root>
</div>`,
`<span style='position: absolute; left: -400px; top: 0;'>position: absolute, out of bounds left</span>`,
`<span style='position: absolute; width: 100px; height: 100px; left: -100px; top: 0;'>position: absolute, out of bounds left</span>`,
'#el-out-of-parent-bounds-to-left',
)
@@ -316,7 +316,7 @@ describe('src/cypress/dom/visibility - shadow dom', () => {
`<div style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
<shadow-root id="el-out-of-parent-bounds-to-right"></shadow-root>
</div>`,
`<span style='position: absolute; left: 200px; top: 0;'>position: absolute, out of bounds right</span>`,
`<span style='position: absolute; width: 100px; height: 100px; right: -100px; top: 0;'>position: absolute, out of bounds right</span>`,
'#el-out-of-parent-bounds-to-right',
)
@@ -329,7 +329,7 @@ describe('src/cypress/dom/visibility - shadow dom', () => {
`<div style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
<shadow-root id="el-out-of-parent-bounds-above"></shadow-root>
</div>`,
`<span style='position: absolute; top: -100px; left: 0;'>position: absolute, out of bounds above</span>`,
`<span style='position: absolute; width: 100px; height: 100px; top: -100px; left: 0;'>position: absolute, out of bounds above</span>`,
'#el-out-of-parent-bounds-above',
)
@@ -342,7 +342,7 @@ describe('src/cypress/dom/visibility - shadow dom', () => {
`<div style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
<shadow-root id="el-out-of-parent-bounds-below"></shadow-root>
</div>`,
`<span style='position: absolute; top: 200px; left: 0;'>position: absolute, out of bounds below</span>`,
`<span style='position: absolute; width: 100px; height: 100px; bottom: -100px; left: 0;'>position: absolute, out of bounds below</span>`,
'#el-out-of-parent-bounds-below',
)

View File

@@ -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) => {

View File

@@ -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,
}