Skip to content

Commit 0811921

Browse files
authored
fix: visibility issue when parent element is clipping (#30934)
1 parent 1548047 commit 0811921

File tree

5 files changed

+235
-39
lines changed

5 files changed

+235
-39
lines changed

.circleci/workflows.yml

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ mainBuildFilters: &mainBuildFilters
3030
- /^release\/\d+\.\d+\.\d+$/
3131
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
3232
- 'update-v8-snapshot-cache-on-develop'
33-
- 'chore/update_vue_test_utils'
34-
- 'publish-binary'
35-
- 'chore/fix_windows_kitchensink'
33+
- 'mschile/issue-30922'
3634

3735
# usually we don't build Mac app - it takes a long time
3836
# but sometimes we want to really confirm we are doing the right thing
@@ -43,8 +41,7 @@ macWorkflowFilters: &darwin-workflow-filters
4341
- equal: [ develop, << pipeline.git.branch >> ]
4442
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
4543
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
46-
- equal: [ 'chore/update_vue_test_utils', << pipeline.git.branch >> ]
47-
- equal: [ 'cacie/fix-hook-test-stack-analysis', << pipeline.git.branch >> ]
44+
- equal: [ 'mschile/issue-30922', << pipeline.git.branch >> ]
4845
- matches:
4946
pattern: /^release\/\d+\.\d+\.\d+$/
5047
value: << pipeline.git.branch >>
@@ -55,8 +52,7 @@ linuxArm64WorkflowFilters: &linux-arm64-workflow-filters
5552
- equal: [ develop, << pipeline.git.branch >> ]
5653
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
5754
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
58-
- equal: [ 'chore/update_binary_branch', << pipeline.git.branch >> ]
59-
- equal: [ 'cacie/fix-hook-test-stack-analysis', << pipeline.git.branch >> ]
55+
- equal: [ 'mschile/issue-30922', << pipeline.git.branch >> ]
6056
- matches:
6157
pattern: /^release\/\d+\.\d+\.\d+$/
6258
value: << pipeline.git.branch >>
@@ -79,8 +75,7 @@ windowsWorkflowFilters: &windows-workflow-filters
7975
- equal: [ develop, << pipeline.git.branch >> ]
8076
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
8177
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
82-
- equal: [ 'ryanm/chore/electron-33-upgrade', << pipeline.git.branch >> ]
83-
- equal: [ 'chore/fix_windows_kitchensink', << pipeline.git.branch >> ]
78+
- equal: [ 'mschile/issue-30922', << pipeline.git.branch >> ]
8479
- matches:
8580
pattern: /^release\/\d+\.\d+\.\d+$/
8681
value: << pipeline.git.branch >>
@@ -156,7 +151,7 @@ commands:
156151
name: Set environment variable to determine whether or not to persist artifacts
157152
command: |
158153
echo "Setting SHOULD_PERSIST_ARTIFACTS variable"
159-
echo 'if ! [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "chore/update_vue_test_utils" && "$CIRCLE_BRANCH" != chore/fix_windows_kitchensink ]]; then
154+
echo 'if ! [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "mschile/issue-30922" ]]; then
160155
export SHOULD_PERSIST_ARTIFACTS=true
161156
fi' >> "$BASH_ENV"
162157
# You must run `setup_should_persist_artifacts` command and be using bash before running this command

cli/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ _Released 1/28/2025 (PENDING)_
66
**Bugfixes:**
77

88
- Fixed an issue where Cypress would incorrectly navigate to `about:blank` when test isolation was disabled and the last test would fail and then retry. Fixes [#28527](https://github.com/cypress-io/cypress/issues/28527).
9+
- Fixed a regression introduced in [`14.0.0`](https://docs.cypress.io/guides/references/changelog#14-0-0) where an element would not return the correct visibility if its offset parent was within the clipping element. Fixes [#30922](https://github.com/cypress-io/cypress/issues/30922).
10+
- Fixed a regression introduced in [`14.0.0`](https://docs.cypress.io/guides/references/changelog#14-0-0) where the incorrect visiblity would be returned when either `overflow-x` or `overflow-y` was visible but the other one was clipping. Fixed in [#30934](https://github.com/cypress-io/cypress/pull/30934).
11+
- Fixed an issue where an `option` element would not return the correct visibility if its parent element has a clipping overflow. Fixed in [#30934](https://github.com/cypress-io/cypress/pull/30934).
912
- Fixed an issue where non-HTMLElement(s) may fail during assertions. Fixes [#30944](https://github.com/cypress-io/cypress/issues/30944)
1013

1114
**Misc:**

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

Lines changed: 180 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ describe('src/cypress/dom/visibility', () => {
66
return $(el).appendTo(cy.$$('body'))
77
}
88

9-
const reasonIs = ($el, str) => {
9+
const reasonIs = ($el: JQuery, str: string) => {
1010
expect(dom.getReasonIsHidden($el)).to.eq(str)
1111
}
1212

@@ -995,10 +995,6 @@ describe('src/cypress/dom/visibility', () => {
995995
})
996996

997997
it('is visible when element is statically positioned and parent element is absolutely positioned and ancestor has overflow hidden', function () {
998-
const add = (el) => {
999-
return $(el).appendTo(cy.$$('body'))
1000-
}
1001-
1002998
cy.$$('body').empty()
1003999

10041000
const el = add(`
@@ -1015,10 +1011,6 @@ describe('src/cypress/dom/visibility', () => {
10151011
})
10161012

10171013
it('is visible when element is relatively positioned and parent element is absolutely positioned and ancestor has overflow auto', function () {
1018-
const add = (el) => {
1019-
return $(el).appendTo(cy.$$('body'))
1020-
}
1021-
10221014
cy.$$('body').empty()
10231015

10241016
const el = add(`
@@ -1043,6 +1035,185 @@ describe('src/cypress/dom/visibility', () => {
10431035

10441036
expect(el.find('#visible-button')).to.be.visible
10451037
})
1038+
1039+
it('is hidden when parent element is absolutely position and offset parent is a decendent of the ancestor', function () {
1040+
cy.$$('body').empty()
1041+
1042+
add(`
1043+
<div style="display: grid; grid-template-columns: 332px 1fr; grid-template-rows: 62px 1fr;">
1044+
<div style="overflow-y: auto;">
1045+
<div style="height: 297px; position: relative;">
1046+
<div style="height: 96px; position: absolute; left: 0; top: 0;">
1047+
<a href="">test test-1</a>
1048+
</div>
1049+
<div style="height: 36px; position: absolute; left: 0; top: 96px; background-color: red;">
1050+
<a href="">test test-2</a>
1051+
</div>
1052+
</div>
1053+
</div>
1054+
</div>
1055+
`)
1056+
1057+
cy.contains('test-2').should('not.be.visible')
1058+
cy.contains('test-1').should('be.visible')
1059+
})
1060+
1061+
it('is hidden when element is an option and the parent has overflow clip', function () {
1062+
cy.$$('body').empty()
1063+
1064+
add(`
1065+
<div style="width: 150px; height: 20px; overflow: clip;">
1066+
<div style="width: 150px; height: 25px;"></div>
1067+
<select>
1068+
<optgroup label='Shinobi'>
1069+
<option>Naruto</option>
1070+
</optgroup>
1071+
</select>
1072+
</div>
1073+
`)
1074+
1075+
cy.get('option').should('not.be.visible').then(($el) => {
1076+
reasonIs($el, 'This element `<option>` is not visible because its content is being clipped by one of its parent elements, which has a CSS property of overflow: `hidden`, `clip`, `scroll` or `auto`')
1077+
})
1078+
1079+
cy.get('optgroup').should('not.be.visible').then(($el) => {
1080+
reasonIs($el, 'This element `<optgroup>` is not visible because its content is being clipped by one of its parent elements, which has a CSS property of overflow: `hidden`, `clip`, `scroll` or `auto`')
1081+
})
1082+
1083+
cy.get('select').should('not.be.visible').then(($el) => {
1084+
reasonIs($el, 'This element `<select>` is not visible because its content is being clipped by one of its parent elements, which has a CSS property of overflow: `hidden`, `clip`, `scroll` or `auto`')
1085+
})
1086+
})
1087+
1088+
it('is visible when element is an option and the parent has overflow clip but is within the bounds', function () {
1089+
cy.$$('body').empty()
1090+
1091+
add(`
1092+
<div style="width: 150px; height: 20px; overflow: clip;">
1093+
<select>
1094+
<optgroup label='Shinobi'>
1095+
<option>Naruto</option>
1096+
</optgroup>
1097+
</select>
1098+
</div>
1099+
`)
1100+
1101+
cy.get('option').should('be.visible')
1102+
cy.get('optgroup').should('be.visible')
1103+
cy.get('select').should('be.visible')
1104+
})
1105+
1106+
it('is visible when x direction is clip but element is visible in y direction', () => {
1107+
cy.$$('body').empty()
1108+
1109+
add(`
1110+
<div style="overflow-x: clip">
1111+
<div style="height: 100px; width: 500px;">
1112+
<div style="height: 100px; width: 500px;"></div>
1113+
<input type="radio"/>
1114+
<label>Visible</label>
1115+
</div>
1116+
</div>
1117+
`)
1118+
1119+
cy.get('label').should('be.visible')
1120+
})
1121+
1122+
it('is hidden when x direction is hidden and y direction is coerced by browser to auto', () => {
1123+
cy.$$('body').empty()
1124+
1125+
add(`
1126+
<div style="overflow-x: hidden">
1127+
<div style="height: 100px; width: 500px;">
1128+
<div style="height: 100px; width: 500px;"></div>
1129+
<input type="radio"/>
1130+
<label>Hidden</label>
1131+
</div>
1132+
</div>
1133+
`)
1134+
1135+
cy.get('label').should('not.be.visible')
1136+
})
1137+
1138+
it('is hidden when x direction is auto and y direction is coerced by browser to auto', () => {
1139+
cy.$$('body').empty()
1140+
1141+
add(`
1142+
<div style="overflow-x: auto">
1143+
<div style="height: 100px; width: 500px;">
1144+
<div style="height: 100px; width: 500px;"></div>
1145+
<input type="radio"/>
1146+
<label>Hidden</label>
1147+
</div>
1148+
</div>
1149+
`)
1150+
1151+
cy.get('label').should('not.be.visible')
1152+
})
1153+
1154+
it('is hidden when y direction is hidden and x direction is set to clip but coerced by browser to hidden', () => {
1155+
cy.$$('body').empty()
1156+
1157+
add(`
1158+
<div style="overflow-x: clip; overflow-y: hidden">
1159+
<div style="height: 100px; width: 500px;">
1160+
<div style="height: 100px; width: 500px;"></div>
1161+
<input type="radio"/>
1162+
<label>Hidden</label>
1163+
</div>
1164+
</div>
1165+
`)
1166+
1167+
cy.get('label').should('not.be.visible')
1168+
})
1169+
1170+
it('is hidden when y direction is auto and x direction is set to clip but coerced by browser to hidden', () => {
1171+
cy.$$('body').empty()
1172+
1173+
add(`
1174+
<div style="overflow-x: clip; overflow-y: auto">
1175+
<div style="height: 100px; width: 500px;">
1176+
<div style="height: 100px; width: 500px;"></div>
1177+
<input type="radio"/>
1178+
<label>Hidden</label>
1179+
</div>
1180+
</div>
1181+
`)
1182+
1183+
cy.get('label').should('not.be.visible')
1184+
})
1185+
1186+
it('is visible when x direction is clip and y direction is visible', () => {
1187+
cy.$$('body').empty()
1188+
1189+
add(`
1190+
<div style="overflow-x: clip; overflow-y: visible">
1191+
<div style="height: 100px; width: 500px;">
1192+
<div style="height: 100px; width: 500px;"></div>
1193+
<input type="radio"/>
1194+
<label>Visible</label>
1195+
</div>
1196+
</div>
1197+
`)
1198+
1199+
cy.get('label').should('be.visible')
1200+
})
1201+
1202+
it('is hidden when y direction is overriden by setting overflow to clip', () => {
1203+
cy.$$('body').empty()
1204+
1205+
add(`
1206+
<div style="overflow-y: visible; overflow: clip;">
1207+
<div style="height: 100px; width: 500px;">
1208+
<div style="height: 100px; width: 500px;"></div>
1209+
<input type="radio"/>
1210+
<label>Hidden</label>
1211+
</div>
1212+
</div>
1213+
`)
1214+
1215+
cy.get('label').should('not.be.visible')
1216+
})
10461217
})
10471218

10481219
describe('css clip-path', () => {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export const findParent = (el, condition) => {
6161
return collectParent(el)
6262
}
6363

64-
export const getFirstParentWithTagName = ($el, tagName) => {
64+
export const getFirstParentWithTagName = ($el: JQuery, tagName: string) => {
6565
if (isUndefinedOrHTMLBodyDoc($el) || !tagName) {
6666
return null
6767
}

0 commit comments

Comments
 (0)