Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: update visibility for elements with textContent but without width/height #29688

Merged
merged 48 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
3e25863
Parent with correctly visible
senpl Jun 17, 2024
6036095
cahngelog entry
senpl Jun 17, 2024
4a8a730
changelog update
senpl Jun 17, 2024
a2f67ad
Merge branch 'develop' into issue-29687
senpl Jun 17, 2024
9e0afe3
test cleanup
senpl Jun 17, 2024
f41e92f
Merge branch 'issue-29687' of https://github.com/senpl/cypress into i…
senpl Jun 17, 2024
0759e35
first working version
senpl Jul 1, 2024
35dd425
fix with cleaner code
senpl Jul 1, 2024
ea3dca2
Merge branch 'develop' into issue-29687
senpl Jul 1, 2024
57ec09d
changelog update for pipeline
senpl Jul 1, 2024
e33ee3c
error message fixes
senpl Jul 2, 2024
3657f21
Merge branch 'develop' into issue-29687
senpl Jul 3, 2024
20cabe3
changelog update
senpl Jul 3, 2024
86b21a7
Merge branch 'issue-29687' of https://github.com/senpl/cypress into i…
senpl Jul 3, 2024
a94f560
looks like it works in old form
senpl Jul 8, 2024
8f79ee7
Merge branch 'develop' into issue-29687
senpl Jul 8, 2024
62c341d
fix for display none
senpl Jul 8, 2024
83ffde7
Merge branch 'develop' into issue-29687
jennifer-shehane Jul 8, 2024
832f4e3
Merge branch 'develop' into issue-29687
senpl Jul 11, 2024
641cac9
Update cli/CHANGELOG.md
senpl Jul 11, 2024
2bfecbf
Merge branch 'develop' into issue-29687
senpl Jul 12, 2024
d2ec46b
Merge branch 'develop' into issue-29687
senpl Jul 13, 2024
dbd4533
Merge branch 'develop' into issue-29687
senpl Jul 25, 2024
9b2de0c
Update CHANGELOG.md
senpl Jul 25, 2024
6a44f5a
Merge branch 'develop' into issue-29687
senpl Jul 26, 2024
3a0309f
Merge branch 'develop' into issue-29687
senpl Aug 7, 2024
c127b36
Merge branch 'develop' into issue-29687
senpl Aug 8, 2024
599e3d7
Merge branch 'develop' into issue-29687
senpl Aug 12, 2024
411f60e
Merge branch 'develop' into issue-29687
senpl Aug 16, 2024
3de8716
Merge branch 'develop' into issue-29687
senpl Sep 30, 2024
012d49a
Merge branch 'release/14.0.0' into issue-29687
senpl Oct 1, 2024
cd94f78
Merge branch 'release/14.0.0' into issue-29687
senpl Oct 28, 2024
a561c06
Merge branch 'release/14.0.0' into issue-29687
jennifer-shehane Oct 29, 2024
80ad94c
Merge branch 'release/14.0.0' into issue-29687
senpl Oct 30, 2024
5e53747
changelog fixes
senpl Oct 30, 2024
ceb7148
Merge branch 'release/14.0.0' into issue-29687
jennifer-shehane Nov 6, 2024
c41f1c1
changelog update
jennifer-shehane Nov 6, 2024
9847e19
Rewrite some code / ensure tests cover new rules
jennifer-shehane Nov 6, 2024
1b6d74b
remove whitespace from textContent since that cannot be seen.
jennifer-shehane Nov 7, 2024
b229d5f
Merge branch 'release/14.0.0' into issue-29687
jennifer-shehane Nov 7, 2024
be5587c
add existential check to replace
jennifer-shehane Nov 8, 2024
17b5780
Merge branch 'release/14.0.0' into issue-29687
jennifer-shehane Nov 8, 2024
44d50a6
Merge branch 'release/14.0.0' into issue-29687
mschile Nov 19, 2024
8afed31
Merge branch 'release/14.0.0' into issue-29687
mschile Nov 26, 2024
0afd2c6
updates
mschile Nov 26, 2024
6ae90ee
update test
mschile Nov 26, 2024
7fe35e3
update changelog
mschile Nov 26, 2024
2cff37f
Merge branch 'release/14.0.0' into issue-29687
mschile Dec 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ in this [GitHub issue](https://github.com/cypress-io/cypress/issues/30447). Addr

- Elements with `display: contents` will no longer use box model calculations for visibility, and correctly show as visible when it is visible. Fixed in [#29680](https://github.com/cypress-io/cypress/pull/29680). Fixes [#29605](https://github.com/cypress-io/cypress/issues/29605).
- The CSS pseudo-class `:dir()` is now supported when testing in Electron. Addresses [#29766](https://github.com/cypress-io/cypress/issues/29766).
- Fixed a visibility issue for elements with `textContent` but without a width or height. Fixed in [#29688](https://github.com/cypress-io/cypress/pull/29688). Fixes [#29687](https://github.com/cypress-io/cypress/issues/29687).

**Dependency Updates:**

Expand Down
1 change: 0 additions & 1 deletion packages/driver/cypress/e2e/commands/actions/click.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -2190,7 +2190,6 @@ describe('src/cy/commands/actions/click', () => {

cy.click()
})
// Array(1).fill().map(()=>

it('throws when any member of the subject isnt visible', function (done) {
// sometimes the command will timeout early with
Expand Down
65 changes: 57 additions & 8 deletions packages/driver/cypress/e2e/dom/visibility.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,21 +161,21 @@ describe('src/cypress/dom/visibility', () => {
})
})

const add = (el) => {
return $(el).appendTo(cy.$$('body'))
}

context('hidden/visible overrides', () => {
beforeEach(function () {
const add = (el) => {
return $(el).appendTo(cy.$$('body'))
}

// ensure all tests run against a scrollable window
const scrollThisIntoView = add('<div style=`height: 1000px;`></div><div>Should be in view</div>')

this.$visHidden = add('<ul style="visibility: hidden;"></ul>')
this.$parentVisHidden = add('<div class="invis" style="visibility: hidden;"><button>parent visibility: hidden</button></div>')
this.$displayNone = add('<button style="display: none">display: none</button>')
this.$inputHidden = add('<input type="hidden" value="abcdef">')
this.$divNoWidth = add('<div style="width: 0; height: 100px;">width: 0</div>')
this.$divNoHeight = add('<div style="width: 50px; height: 0px;">height: 0</div>')
this.$divNoWidth = add('<div style="width: 0; height: 100px;"></div>')
this.$divNoHeight = add('<div style="width: 50px; height: 0px;"></div>')
this.$divDetached = $('<div>foo</div>')
this.$divVisible = add(`<div>visible</div>`)

Expand Down Expand Up @@ -687,7 +687,6 @@ describe('src/cypress/dom/visibility', () => {
cy.wrap(this.$optionHiddenInSelect.find('#hidden-opt')).should('not.be.visible')
})

// TODO(webkit): fix+unskip
it('follows regular visibility logic if option outside of select', { browser: '!webkit' }, function () {
expect(this.$optionOutsideSelect.find('#option-hidden').is(':hidden')).to.be.true
expect(this.$optionOutsideSelect.find('#option-hidden')).to.be.hidden
Expand Down Expand Up @@ -736,7 +735,57 @@ describe('src/cypress/dom/visibility', () => {
})

describe('width and height', () => {
it('is hidden if offsetWidth is 0', function () {
it('is visible when el.textContent, even if offsetWidth is 0', function () {
this.$divNoWidthTextContent = add('<div style="width: 0; height: 100px;">width: 0</div>')

expect(this.$divNoWidthTextContent.is(':hidden')).to.be.false
expect(this.$divNoWidthTextContent.is(':visible')).to.be.true

expect(this.$divNoWidthTextContent).to.not.be.hidden
expect(this.$divNoWidthTextContent).to.be.visible

cy.wrap(this.$divNoWidthTextContent).should('be.not.hidden')
cy.wrap(this.$divNoWidthTextContent).should('be.visible')
})

it('is visible when el.textContent, even if offsetHeight is 0', function () {
this.$divNoHeightTextContent = add('<div style="width: 50px; height: 0px;">height: 0</div>')

expect(this.$divNoHeightTextContent.is(':hidden')).to.be.false
expect(this.$divNoHeightTextContent.is(':visible')).to.be.true

expect(this.$divNoHeightTextContent).to.not.be.hidden
expect(this.$divNoHeightTextContent).to.be.visible

cy.wrap(this.$divNoHeightTextContent).should('be.not.hidden')
cy.wrap(this.$divNoHeightTextContent).should('be.visible')
})

it('is hidden when when el.textContent contains only whitespace and offsetWidth is 0', function () {
this.$divNoHeightBlankTextContent = add('<div style="width: 0px; height: 50px;"> \n \t </div>')

expect(this.$divNoHeightBlankTextContent.is(':hidden')).to.be.true
expect(this.$divNoHeightBlankTextContent.is(':visible')).to.be.false

expect(this.$divNoHeightBlankTextContent).to.be.hidden
expect(this.$divNoHeightBlankTextContent).to.not.be.visible

cy.wrap(this.$divNoHeightBlankTextContent).should('be.hidden')
cy.wrap(this.$divNoHeightBlankTextContent).should('not.be.visible')
})

it('is hidden when no el.textContent with offsetHeight is 0', function () {
expect(this.$divNoHeight.is(':hidden')).to.be.true
expect(this.$divNoHeight.is(':visible')).to.be.false

expect(this.$divNoHeight).to.be.hidden
expect(this.$divNoHeight).to.not.be.visible

cy.wrap(this.$divNoHeight).should('be.hidden')
cy.wrap(this.$divNoHeight).should('not.be.visible')
})

it('is hidden when no el.textContent with offsetWidth is 0', function () {
expect(this.$divNoWidth.is(':hidden')).to.be.true
expect(this.$divNoWidth.is(':visible')).to.be.false

Expand Down
17 changes: 8 additions & 9 deletions packages/driver/src/dom/visibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const ensureEl = (el, methodName) => {
}
}

const isStrictlyHidden = (el, methodName = 'isStrictlyHidden()', options = { checkOpacity: true }, recurse?) => {
const isStrictlyHidden = (el: HTMLElement, methodName = 'isStrictlyHidden()', options = { checkOpacity: true }, recurse?) => {
ensureEl(el, methodName)
const $el = $jquery.wrap(el)

Expand Down Expand Up @@ -117,7 +117,7 @@ const isHiddenByAncestors = (el, methodName = 'isHiddenByAncestors()', options =
return elIsOutOfBoundsOfAncestorsOverflow($el)
}

const elHasNoEffectiveWidthOrHeight = ($el) => {
const elHasNoEffectiveWidthOrHeight = ($el: JQuery) => {
// Is the element's CSS width OR height, including any borders,
// padding, and vertical scrollbars (if rendered) less than 0?
//
Expand All @@ -140,10 +140,12 @@ const elHasNoEffectiveWidthOrHeight = ($el) => {
transform = 'none'
}

const hasTextContent = !!el.textContent?.trim().length

const width = elClientWidth($el)
const height = elClientHeight($el)

return isZeroLengthAndTransformNone(width, height, transform) ||
return (isZeroLengthAndTransformNone(width, height, transform) && !hasTextContent) ||
isZeroLengthAndOverflowHidden(width, height, elHasOverflowHidden($el)) ||
(el.getClientRects().length <= 0)
}
Expand All @@ -153,21 +155,18 @@ const isZeroLengthAndTransformNone = (width, height, transform) => {
// we learned that when an element has non-'none' transform style value like "translate(0, 0)",
// it is visible even with `height: 0` or `width: 0`.
// That's why we're checking `transform === 'none'` together with elClientWidth/Height.

return (width <= 0 && transform === 'none') ||
(height <= 0 && transform === 'none')
return (width <= 0 && transform === 'none') || (height <= 0 && transform === 'none')
}

const isZeroLengthAndOverflowHidden = (width, height, overflowHidden) => {
return (width <= 0 && overflowHidden) ||
(height <= 0 && overflowHidden)
return (width <= 0 && overflowHidden) || (height <= 0 && overflowHidden)
}

const elHasNoClientWidthOrHeight = ($el) => {
return (elClientWidth($el) <= 0) || (elClientHeight($el) <= 0)
}

const elementBoundingRect = ($el) => $el[0].getBoundingClientRect()
const elementBoundingRect = ($el: JQuery) => $el[0].getBoundingClientRect()

const elClientHeight = ($el) => elementBoundingRect($el).height

Expand Down