')
const win = cy.state('window')
const fn = () => {
return dom.isScrollable(win)
}
expect(fn()).to.be.false
})
it('returns false el is not scrollable', function () {
const noScroll = this.add(`\
No Scroll
\
`)
const fn = () => {
return dom.isScrollable(noScroll)
}
expect(fn()).to.be.false
})
it('returns false el has no overflow', function () {
const noOverflow = this.add(`\
No Overflow Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean lacinia bibendum nulla sed consectetur. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod.
out of ancestor's bounds due to ancestor translate
in ancestor's bounds due to ancestor translate
\
`)
// scroll the 2nd element into view so that
// there is always a scrollTop so we ensure
// its factored in (window vs viewport) calculations
scrollThisIntoView.get(1).scrollIntoView()
})
describe('html or body', () => {
it('is visible if html', () => {
expect(cy.$$('html').is(':hidden')).to.be.false
expect(cy.$$('html').is(':visible')).to.be.true
expect(cy.$$('html')).not.to.be.hidden
expect(cy.$$('html')).to.be.visible
cy.wrap(cy.$$('html')).should('not.be.hidden')
cy.wrap(cy.$$('html')).should('be.visible')
})
it('is visible if body', () => {
expect(cy.$$('body').is(':hidden')).to.be.false
expect(cy.$$('body').is(':visible')).to.be.true
expect(cy.$$('body')).not.to.be.hidden
expect(cy.$$('body')).to.be.visible
cy.wrap(cy.$$('body')).should('not.be.hidden')
cy.wrap(cy.$$('body')).should('be.visible')
})
it('is visible if display none on body or html', () => {
cy.$$('html').css('display', 'none')
cy.$$('body').css('display', 'none')
expect(cy.$$('html')).not.to.be.hidden
expect(cy.$$('html')).to.be.visible
expect(cy.$$('body')).not.to.be.hidden
expect(cy.$$('body')).to.be.visible
})
})
describe('css visibility', () => {
it('is hidden if .css(visibility) is hidden', function () {
expect(this.$visHidden.is(':hidden')).to.be.true
expect(this.$visHidden.is(':visible')).to.be.false
expect(this.$visHidden).to.be.hidden
expect(this.$visHidden).to.not.be.visible
cy.wrap(this.$visHidden).should('be.hidden')
cy.wrap(this.$visHidden).should('not.be.visible')
})
it('is hidden if parents have .css(visibility) hidden', function () {
expect(this.$parentVisHidden.find('button').is(':hidden')).to.be.true
expect(this.$parentVisHidden.find('button').is(':visible')).to.be.false
expect(this.$parentVisHidden.find('button')).to.be.hidden
expect(this.$parentVisHidden.find('button')).to.not.be.visible
cy.wrap(this.$parentVisHidden).find('button').should('be.hidden')
cy.wrap(this.$parentVisHidden).find('button').should('not.be.visible')
})
it('is hidden if visibility collapse', function () {
expect(this.$tableVisCollapse.find('td.collapse')).to.be.hidden
expect(this.$tableVisCollapse.find('td.collapse')).to.not.be.visible
expect(this.$tableVisCollapse.find('tr.collapse')).to.be.hidden
expect(this.$tableVisCollapse.find('tr.collapse')).to.not.be.visible
expect(this.$tableVisCollapse.find('tr.collapse td')).to.be.hidden
expect(this.$tableVisCollapse.find('tr.collapse td')).to.not.be.visible
})
it('is hidden if parent has visibility collapse', function () {
expect(this.$tableVisCollapse.find('tr.collapse td')).to.be.hidden
expect(this.$tableVisCollapse.find('tr.collapse td')).to.not.be.visible
expect(this.$tableVisCollapse.find('#collapse-span')).to.be.hidden
expect(this.$tableVisCollapse.find('#collapse-span')).to.not.be.visible
})
it('is hidden if input type hidden', function () {
expect(this.$inputHidden.is(':hidden')).to.be.true
expect(this.$inputHidden.is(':visible')).to.be.false
expect(this.$inputHidden).to.be.hidden
expect(this.$inputHidden).to.not.be.visible
cy.wrap(this.$inputHidden).should('be.hidden')
cy.wrap(this.$inputHidden).should('not.be.visible')
})
})
describe('option and optgroup', () => {
it('is visible if option in visible select', function () {
expect(this.$optionInSelect.find('option').is(':hidden')).to.be.false
expect(this.$optionInSelect.find('option').is(':visible')).to.be.true
expect(this.$optionInSelect.find('option')).not.to.be.hidden
expect(this.$optionInSelect.find('option')).to.be.visible
cy.wrap(this.$optionInSelect.find('option')).should('not.be.hidden')
cy.wrap(this.$optionInSelect.find('option')).should('be.visible')
})
it('is visible if optgroup in visible select', function () {
expect(this.$optgroupInSelect.find('optgroup').is(':hidden')).to.be.false
expect(this.$optgroupInSelect.find('optgroup').is(':visible')).to.be.true
expect(this.$optgroupInSelect.find('optgroup')).not.to.be.hidden
expect(this.$optgroupInSelect.find('optgroup')).to.be.visible
cy.wrap(this.$optgroupInSelect.find('optgroup')).should('not.be.hidden')
cy.wrap(this.$optgroupInSelect.find('optgroup')).should('be.visible')
})
it('is hidden if option in hidden select', function () {
expect(this.$optionInHiddenSelect.find('option').is(':hidden')).to.be.true
expect(this.$optionInHiddenSelect.find('option').is(':visible')).to.be.false
expect(this.$optionInHiddenSelect.find('option')).to.be.hidden
expect(this.$optionInHiddenSelect.find('option')).not.to.be.visible
cy.wrap(this.$optionInHiddenSelect.find('option')).should('be.hidden')
cy.wrap(this.$optionInHiddenSelect.find('option')).should('not.be.visible')
})
it('is hidden if option is display none', function () {
expect(this.$optionHiddenInSelect.find('#hidden-opt').is(':hidden')).to.be.true
expect(this.$optionHiddenInSelect.find('#hidden-opt').is(':visible')).to.be.false
expect(this.$optionHiddenInSelect.find('#hidden-opt')).to.be.hidden
expect(this.$optionHiddenInSelect.find('#hidden-opt')).not.to.be.visible
cy.wrap(this.$optionHiddenInSelect.find('#hidden-opt')).should('be.hidden')
cy.wrap(this.$optionHiddenInSelect.find('#hidden-opt')).should('not.be.visible')
})
it('follows regular visibility logic if option outside of select', function () {
expect(this.$optionOutsideSelect.find('#option-hidden').is(':hidden')).to.be.true
expect(this.$optionOutsideSelect.find('#option-hidden')).to.be.hidden
cy.wrap(this.$optionOutsideSelect.find('#option-hidden')).should('be.hidden')
expect(this.$optionOutsideSelect.find('#option-visible').is(':visible')).to.be.true
expect(this.$optionOutsideSelect.find('#option-visible')).to.be.visible
cy.wrap(this.$optionOutsideSelect.find('#option-visible')).should('be.visible')
})
})
describe('css opacity', () => {
it('is hidden if opacity is 0', function () {
expect(this.$btnOpacityZero.is(':hidden')).to.be.true
expect(this.$btnOpacityZero.is(':visible')).to.be.false
expect(this.$btnOpacityZero).to.be.hidden
expect(this.$btnOpacityZero).not.to.be.visible
cy.wrap(this.$btnOpacityZero).should('be.hidden')
cy.wrap(this.$btnOpacityZero).should('not.be.visible')
})
it('is hidden if parent has `opacity: 0`', function () {
expect(this.$parentOpacityZero.find('button').is(':hidden')).to.be.true
expect(this.$parentOpacityZero.find('button').is(':visible')).to.be.false
expect(this.$parentOpacityZero.find('button')).to.be.hidden
expect(this.$parentOpacityZero.find('button')).not.to.be.visible
cy.wrap(this.$parentOpacityZero.find('button')).should('be.hidden')
cy.wrap(this.$parentOpacityZero.find('button')).should('not.be.visible')
})
it('is visible if opacity is greater than 0 but less than 1', function () {
expect(this.$btnOpacityHalf.is(':visible')).to.be.true
expect(this.$btnOpacityHalf.is(':hidden')).to.be.false
expect(this.$btnOpacityHalf).to.be.visible
expect(this.$btnOpacityHalf).not.to.be.hidden
cy.wrap(this.$btnOpacityHalf).should('be.visible')
cy.wrap(this.$btnOpacityHalf).should('not.be.hidden')
})
})
describe('width and height', () => {
it('is hidden if offsetWidth is 0', function () {
expect(this.$divNoWidth.is(':hidden')).to.be.true
expect(this.$divNoWidth.is(':visible')).to.be.false
expect(this.$divNoWidth).to.be.hidden
expect(this.$divNoWidth).to.not.be.visible
cy.wrap(this.$divNoWidth).should('be.hidden')
cy.wrap(this.$divNoWidth).should('not.be.visible')
})
it('is hidden if parent has overflow: hidden and no width', function () {
expect(this.$parentNoWidth.find('span')).to.be.hidden
expect(this.$parentNoWidth.find('span')).to.not.be.visible
})
it('is hidden if parent has overflow: hidden and no height', function () {
expect(this.$parentNoHeight.find('span')).to.be.hidden
expect(this.$parentNoHeight.find('span')).to.not.be.visible
})
it('is visible when parent has positive dimensions even with overflow hidden', function () {
expect(this.$parentWithWidthHeightNoOverflow.find('span')).to.be.visible
expect(this.$parentWithWidthHeightNoOverflow.find('span')).to.not.be.hidden
})
})
describe('css position', () => {
it('is visible if child has position: absolute', function () {
expect(this.$childPosAbs.find('span')).to.be.visible
expect(this.$childPosAbs.find('span')).not.be.hidden
})
it('is visible if child has position: fixed', function () {
expect(this.$childPosFixed.find('button')).to.be.visible
expect(this.$childPosFixed.find('button')).not.to.be.hidden
})
it('is visible if descendent from parent has position: fixed', function () {
expect(this.$descendentPosFixed.find('button')).to.be.visible
expect(this.$descendentPosFixed.find('button')).not.to.be.hidden
})
it('is visible if has position: fixed and descendent is found', function () {
expect(this.$descendantInPosFixed.find('#descendantInPosFixed')).to.be.visible
expect(this.$descendantInPosFixed.find('#descendantInPosFixed')).not.to.be.hidden
})
it('is hidden if position: fixed and covered up', function () {
expect(this.$coveredUpPosFixed.find('#coveredUpPosFixed')).to.be.hidden
expect(this.$coveredUpPosFixed.find('#coveredUpPosFixed')).not.to.be.visible
})
it('is hidden if position: fixed and off screen', function () {
expect(this.$offScreenPosFixed).to.be.hidden
expect(this.$offScreenPosFixed).not.to.be.visible
})
it('is visible if descendent from parent has position: absolute', function () {
expect(this.$descendentPosAbs.find('span')).to.be.visible
expect(this.$descendentPosAbs.find('span')).to.not.be.hidden
})
it('is hidden if only the parent has position absolute', function () {
expect(this.$parentPosAbs.find('span')).to.be.hidden
expect(this.$parentPosAbs.find('span')).to.not.be.visible
})
it('is visible if position: fixed and parent has pointer-events: none', function () {
expect(this.$parentPointerEventsNone.find('span')).to.be.visible
expect(this.$parentPointerEventsNone.find('span')).to.not.be.hidden
})
it('is not visible if covered when position: fixed and parent has pointer-events: none', function () {
expect(this.$parentPointerEventsNoneCovered.find('span')).to.be.hidden
expect(this.$parentPointerEventsNoneCovered.find('span')).to.not.be.visible
})
it('is visible if pointer-events: none and parent has position: fixed', function () {
expect(this.$childPointerEventsNone.find('span')).to.be.visible
expect(this.$childPointerEventsNone.find('span')).to.not.be.hidden
})
it('is visible when position: sticky', () => {
cy.visit('fixtures/sticky.html')
cy.get('#button').should('be.visible')
})
})
describe('css display', function () {
// https://github.com/cypress-io/cypress/issues/6183
it('parent is visible if display inline and child has display block', function () {
expect(this.$parentDisplayInlineChildDisplayBlock.find('span')).to.be.visible
expect(this.$parentDisplayInlineChildDisplayBlock.find('span')).to.not.be.hidden
})
})
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 hidden and out of bounds to left', function () {
expect(this.$elOutOfParentBoundsToLeft.find('span')).to.be.hidden
})
it('is hidden when parent overflow hidden and out of bounds to right', function () {
expect(this.$elOutOfParentBoundsToRight.find('span')).to.be.hidden
})
it('is hidden when parent overflow hidden and out of bounds above', function () {
expect(this.$elOutOfParentBoundsAbove.find('span')).to.be.hidden
})
it('is hidden when parent overflow hidden and out of bounds below', function () {
expect(this.$elOutOfParentBoundsBelow.find('span')).to.be.hidden
})
it('is hidden when parent overflow-y hidden and out of bounds', function () {
expect(this.$elOutOfParentWithOverflowYHiddenBounds.find('span')).to.be.hidden
})
it('is hidden when parent overflow-x hidden and out of bounds', function () {
expect(this.$elOutOfParentWithOverflowXHiddenBounds.find('span')).to.be.hidden
})
it('is visible when parent overflow hidden but el in a closer parent with position absolute', function () {
expect(this.$elOutOfParentWithOverflowHiddenBoundsButCloserPositionAbsoluteParent.find('span')).to.be.visible
})
it('is hidden when parent flex and overflow hidden and el out of bounds', function () {
expect(this.$elOutOfParentWithFlexAndOverflowHiddenBounds.find('#red')).to.be.visible
expect(this.$elOutOfParentWithFlexAndOverflowHiddenBounds.find('#green')).to.be.visible
expect(this.$elOutOfParentWithFlexAndOverflowHiddenBounds.find('#blue')).to.be.hidden
})
it('is hidden when parent is wide and ancestor is overflow auto', function () {
expect(this.$elOutOfAncestorOverflowAutoBounds.find('span')).to.be.hidden
})
it('is hidden when parent overflow scroll and out of bounds', function () {
expect(this.$elOutOfScrollingParentBounds.find('span')).to.be.hidden
})
it('is hidden when parent absolutely positioned and overflow hidden and out of bounds', function () {
expect(this.$elOutOfPosAbsParentsBounds.find('span')).to.be.hidden
})
it('is visible when parent absolutely positioned and overflow hidden and not out of bounds', function () {
expect(this.$elInPosAbsParentsBounds.find('span')).to.be.visible
})
it('is visible when parent overflow hidden and not out of bounds', function () {
expect(this.$elInParentBounds.find('span')).to.be.visible
})
it('is visible when ancestor is overflow hidden but more distant ancestor is the offset parent', function () {
expect(this.$elIsOutOfBoundsOfAncestorsOverflowButWithinRelativeAncestor.find('span')).to.be.visible
})
it('is hidden when relatively positioned outside ancestor with overflow hidden', function () {
expect(this.$elIsRelativeAndOutOfBoundsOfAncestorOverflow.find('span')).to.be.hidden
})
it('is visible when el is relatively positioned outside ancestor that does not hide overflow', function () {
expect(this.$elIsRelativeAndOutOfBoundsOfAncestorButAncestorShowsOverflow.find('span')).to.be.visible
})
it('is visible when parent is relatively positioned out of bounds but el is relatively positioned back in bounds', function () {
expect(this.$parentOutOfBoundsButElInBounds.find('span')).to.be.visible
})
})
describe('css clip-path', () => {
// TODO: why is this skipped?
it.skip('is hidden when outside of parents clip-path', function () {
expect(this.$parentWithClipPathAbsolutePositionElOutsideClipPath.find('span')).to.be.hidden
})
it('is visible when inside of parents clip-path', function () {
expect(this.$parentWithClipPathAbsolutePositionElInsideClipPath.find('span')).to.be.visible
})
})
describe('css transform', () => {
const add = (el) => {
return $(el).appendTo(cy.$$('body'))
}
describe('element visibility by css transform', () => {
it('is visible when an element is translated a bit', () => {
const el = add(`
Translated
`)
expect(el).to.be.visible
})
it('is visible when an element is only skewed', () => {
const el = add(`
Skewed
`)
expect(el).to.be.visible
})
it('is visible when an element is only rotated', () => {
const el = add(`
Rotated
`)
expect(el).to.be.visible
})
it('is visible when an element is scaled by non-zero', () => {
const el = add(`
Scaled
`)
expect(el).to.be.visible
})
it('is visible when an element is transformed in multiple ways but not scaled to zero', () => {
const el = add(`
Multiple transform
`)
expect(el).to.be.visible
})
it('is visible when an element is rotateZ(90deg)', () => {
const el = add(`
rotateZ(90deg)
`)
expect(el).to.be.visible
})
// https://github.com/cypress-io/cypress/issues/6745
it('is visible even if there is a dangling element in the tree', () => {
cy.visit('/fixtures/dangling-element.html')
cy.get('.hello')
})
it('is hidden when an element is scaled to X axis in 0', () => {
const el = add(`
ScaleX(0)
`)
expect(el).to.be.hidden
})
it('is hidden when an element is scaled to Y axis in 0', () => {
const el = add(`
ScaleY(0)
`)
expect(el).to.be.hidden
})
it('is hidden when an element is scaled to Z axis in 0', () => {
const el = add(`
ScaleZ(0)
`)
expect(el).to.be.hidden
})
it('is hidden when an element is transformed in multiple ways but scaled to 0 in one axis', () => {
const el = add(`
Multiple 2
`)
expect(el).to.be.hidden
})
it('is hidden when an element is rotateX(90deg)', () => {
const el = add(`
rotateX(90deg)
`)
expect(el).to.be.hidden
})
it('is hidden when an element is rotateY(90deg)', () => {
const el = add(`
rotateY(90deg)
`)
expect(el).to.be.hidden
})
it('is hidden when an element is rotateX(90deg) rotateY(90deg)', () => {
const el = add(`
rotateX(90deg)
`)
expect(el).to.be.hidden
})
it('is hidden when an element is transformed in multiple ways but rotated to 90 deg in X or Y axis', () => {
const el = add(`
rotateX(90deg)
`)
expect(el).to.be.hidden
const el2 = add(`
rotateX(90deg)
`)
expect(el2).to.be.hidden
const el3 = add(`
rotateX(90deg)
`)
expect(el3).to.be.hidden
})
})
describe('when height/width is set', () => {
it('is visible when transform is not 0, but height is 0', () => {
const el = add('
Text
')
expect(el).to.be.visible
})
it('is visible when transform is not 0, but width is 0', () => {
const el = add('
Text
')
expect(el).to.be.visible
})
it('is visible when parent transform is not 0, but height is 0', () => {
const el = add('
Text
')
expect(el.find('#tr-p-0')).to.be.visible
})
it('is visible when parent transform is not 0, but width is 0', () => {
const el = add('
Test
')
expect(el.find('#tr-p-1')).to.be.visible
})
it('is invisible when parent transform is 0, but height is not 0', () => {
const el = add('
')
expect(el.find('#h0th')).to.be.hidden
})
})
})
it('is hidden when outside parents transform scale', function () {
expect(this.$parentWithTransformScaleElOutsideScale.find('span')).to.be.hidden
})
it('is visible when inside of parents transform scale', function () {
expect(this.$parentWithTransformScaleElInsideScale.find('span')).to.be.visible
})
it('is hidden when out of ancestor\'s bounds due to ancestor\'s transform', function () {
expect(this.$ancestorTransformMakesElOutOfBoundsOfAncestor.find('span')).to.be.hidden
})
it('is visible when in ancestor\'s bounds due to ancestor\'s transform', function () {
expect(this.$ancestorTransformMakesElInBoundsOfAncestor.find('#inbounds')).to.be.visible
})
})
describe('#getReasonIsHidden', () => {
beforeEach(function () {
this.reasonIs = ($el, str) => {
expect(dom.getReasonIsHidden($el)).to.eq(str)
}
})
it('has `display: none`', function () {
this.reasonIs(this.$displayNone, 'This element `