Skip to content

Commit 3967b48

Browse files
canourrea23chrisbreidingmschilejennifer-shehaneemilyrohrbough
authored
fix: update visibility check with overflow: hidden and element on the edge (#27586)
Co-authored-by: Chris Breiding <[email protected]> Co-authored-by: Matt Schile <[email protected]> Co-authored-by: Jennifer Shehane <[email protected]> Co-authored-by: Emily Rohrbough <[email protected]> Co-authored-by: Emily Rohrbough <[email protected]>
1 parent 6aafb52 commit 3967b48

File tree

5 files changed

+43
-21
lines changed

5 files changed

+43
-21
lines changed

cli/CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
<!-- See the ../guides/writing-the-cypress-changelog.md for details on writing the changelog. -->
2+
## 13.4.1
3+
4+
_Released 11/7/2023 (PENDING)_
5+
6+
**Bugfixes:**
7+
8+
- 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).
9+
210
## 13.4.0
311

412
_Released 10/30/2023_

packages/driver/cypress/e2e/dom/visibility.cy.ts

+8-9
Original file line numberDiff line numberDiff line change
@@ -356,25 +356,25 @@ describe('src/cypress/dom/visibility', () => {
356356

357357
this.$elOutOfParentBoundsToLeft = add(`\
358358
<div style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
359-
<span style='position: absolute; left: -400px; top: 0px;'>position: absolute, out of bounds left</span>
359+
<span style='position: absolute; width: 100px; height: 100px; left: -100px; top: 0px;'>position: absolute, out of bounds left</span>
360360
</div>\
361361
`)
362362

363363
this.$elOutOfParentBoundsToRight = add(`\
364364
<div id="elOutOfParentBoundsToRight" style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
365-
<span style='position: absolute; left: 200px; top: 0px;'>position: absolute, out of bounds right</span>
365+
<span style='position: absolute; width: 100px; height: 100px; right: -100px; top: 0px;'>position: absolute, out of bounds right</span>
366366
</div>\
367367
`)
368368

369369
this.$elOutOfParentBoundsAbove = add(`\
370370
<div style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
371-
<span style='position: absolute; left: 0px; top: -100px;'>position: absolute, out of bounds above</span>
371+
<span style='position: absolute; width: 100px; height: 100px; left: 0px; top: -100px;'>position: absolute, out of bounds above</span>
372372
</div>\
373373
`)
374374

375375
this.$elOutOfParentBoundsBelow = add(`\
376376
<div id="elOutOfParentBoundsBelow" style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
377-
<span style='position: absolute; left: 0px; top: 200px;'>position: absolute, out of bounds below</span>
377+
<span style='position: absolute; width: 100px; height: 100px; left: 0px; bottom: -100px;'>position: absolute, out of bounds below</span>
378378
</div>\
379379
`)
380380

@@ -819,10 +819,9 @@ describe('src/cypress/dom/visibility', () => {
819819
})
820820

821821
describe('css overflow', () => {
822-
it('is visible when parent doesnt have overflow hidden', function () {
823-
expect(this.$parentNoWidthHeightOverflowAuto.find('span')).to.be.visible
824-
825-
expect(this.$parentNoWidthHeightOverflowAuto.find('span')).to.not.be.hidden
822+
it('is hidden when parent overflow auto and no width/height', function () {
823+
expect(this.$parentNoWidthHeightOverflowAuto.find('span')).to.not.be.visible
824+
expect(this.$parentNoWidthHeightOverflowAuto.find('span')).to.be.hidden
826825
})
827826

828827
it('is hidden when parent overflow hidden and out of bounds to left', function () {
@@ -897,7 +896,7 @@ describe('src/cypress/dom/visibility', () => {
897896
})
898897

899898
describe('css clip-path', () => {
900-
// TODO: why is this skipped?
899+
// TODO: handle clip path 'hidden' equivalents
901900
it.skip('is hidden when outside of parents clip-path', function () {
902901
expect(this.$parentWithClipPathAbsolutePositionElOutsideClipPath.find('span')).to.be.hidden
903902
})

packages/driver/cypress/e2e/dom/visibility_shadow_dom.cy.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ describe('src/cypress/dom/visibility - shadow dom', () => {
303303
`<div style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
304304
<shadow-root id="el-out-of-parent-bounds-to-left"></shadow-root>
305305
</div>`,
306-
`<span style='position: absolute; left: -400px; top: 0;'>position: absolute, out of bounds left</span>`,
306+
`<span style='position: absolute; width: 100px; height: 100px; left: -100px; top: 0;'>position: absolute, out of bounds left</span>`,
307307
'#el-out-of-parent-bounds-to-left',
308308
)
309309

@@ -316,7 +316,7 @@ describe('src/cypress/dom/visibility - shadow dom', () => {
316316
`<div style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
317317
<shadow-root id="el-out-of-parent-bounds-to-right"></shadow-root>
318318
</div>`,
319-
`<span style='position: absolute; left: 200px; top: 0;'>position: absolute, out of bounds right</span>`,
319+
`<span style='position: absolute; width: 100px; height: 100px; right: -100px; top: 0;'>position: absolute, out of bounds right</span>`,
320320
'#el-out-of-parent-bounds-to-right',
321321
)
322322

@@ -329,7 +329,7 @@ describe('src/cypress/dom/visibility - shadow dom', () => {
329329
`<div style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
330330
<shadow-root id="el-out-of-parent-bounds-above"></shadow-root>
331331
</div>`,
332-
`<span style='position: absolute; top: -100px; left: 0;'>position: absolute, out of bounds above</span>`,
332+
`<span style='position: absolute; width: 100px; height: 100px; top: -100px; left: 0;'>position: absolute, out of bounds above</span>`,
333333
'#el-out-of-parent-bounds-above',
334334
)
335335

@@ -342,7 +342,7 @@ describe('src/cypress/dom/visibility - shadow dom', () => {
342342
`<div style='width: 100px; height: 100px; overflow: hidden; position: relative;'>
343343
<shadow-root id="el-out-of-parent-bounds-below"></shadow-root>
344344
</div>`,
345-
`<span style='position: absolute; top: 200px; left: 0;'>position: absolute, out of bounds below</span>`,
345+
`<span style='position: absolute; width: 100px; height: 100px; bottom: -100px; left: 0;'>position: absolute, out of bounds below</span>`,
346346
'#el-out-of-parent-bounds-below',
347347
)
348348

packages/driver/src/dom/elements/find.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,13 @@ export const isAncestor = ($el, $maybeAncestor) => {
176176
}
177177

178178
export const isChild = ($el, $maybeChild) => {
179-
return $el.children().index($maybeChild) >= 0
179+
let children = $el.children()
180+
181+
if (children.length && children[0].nodeName === 'SHADOW-ROOT') {
182+
return isDescendent($el, $maybeChild)
183+
}
184+
185+
return children.index($maybeChild) >= 0
180186
}
181187

182188
export const isDescendent = ($el1, $el2) => {

packages/driver/src/dom/visibility.ts

+16-7
Original file line numberDiff line numberDiff line change
@@ -316,24 +316,27 @@ const elIsOutOfBoundsOfAncestorsOverflow = function ($el, $ancestor = getParent(
316316
return false
317317
}
318318

319-
const elProps = $coordinates.getElementPositioning($el)
320-
321319
if (canClipContent($el, $ancestor)) {
320+
const elProps = $coordinates.getElementPositioning($el)
322321
const ancestorProps = $coordinates.getElementPositioning($ancestor)
323322

323+
if (elHasPositionAbsolute($el) && (ancestorProps.width === 0 || ancestorProps.height === 0)) {
324+
return elIsOutOfBoundsOfAncestorsOverflow($el, getParent($ancestor))
325+
}
326+
324327
// target el is out of bounds
325328
if (
326329
// target el is to the right of the ancestor's visible area
327-
(elProps.fromElWindow.left > (ancestorProps.width + ancestorProps.fromElWindow.left)) ||
330+
(elProps.fromElWindow.left >= (ancestorProps.width + ancestorProps.fromElWindow.left)) ||
328331

329332
// target el is to the left of the ancestor's visible area
330-
((elProps.fromElWindow.left + elProps.width) < ancestorProps.fromElWindow.left) ||
333+
((elProps.fromElWindow.left + elProps.width) <= ancestorProps.fromElWindow.left) ||
331334

332335
// target el is under the ancestor's visible area
333-
(elProps.fromElWindow.top > (ancestorProps.height + ancestorProps.fromElWindow.top)) ||
336+
(elProps.fromElWindow.top >= (ancestorProps.height + ancestorProps.fromElWindow.top)) ||
334337

335338
// target el is above the ancestor's visible area
336-
((elProps.fromElWindow.top + elProps.height) < ancestorProps.fromElWindow.top)
339+
((elProps.fromElWindow.top + elProps.height) <= ancestorProps.fromElWindow.top)
337340
) {
338341
return true
339342
}
@@ -555,5 +558,11 @@ export const getReasonIsHidden = function ($el, options = { checkOpacity: true }
555558
/* eslint-enable no-cond-assign */
556559

557560
export default {
558-
isVisible, isHidden, isStrictlyHidden, isHiddenByAncestors, getReasonIsHidden, isW3CFocusable, isW3CRendered,
561+
isVisible,
562+
isHidden,
563+
isStrictlyHidden,
564+
isHiddenByAncestors,
565+
getReasonIsHidden,
566+
isW3CFocusable,
567+
isW3CRendered,
559568
}

0 commit comments

Comments
 (0)