- 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')
+ describe('visibility scenarios', () => {
+ describe('html and body overrides', () => {
+ beforeEach(() => {
+ cy.visit('/fixtures/empty.html')
})
- 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
+ describe('when display none', () => {
+ beforeEach(() => {
+ cy.get('html').then(($el) => {
+ $el.css('display', 'none')
+ })
- cy.wrap(this.$visHidden).should('be.hidden')
- cy.wrap(this.$visHidden).should('not.be.visible')
- })
+ cy.get('body').then(($el) => {
+ $el.css('display', 'none')
+ })
+ })
- 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
+ it('is always visible', () => {
+ expect(cy.$$('html').is(':hidden')).to.be.false
+ expect(cy.$$('html').is(':visible')).to.be.true
- expect(this.$parentVisHidden.find('button')).to.be.hidden
- expect(this.$parentVisHidden.find('button')).to.not.be.visible
+ expect(cy.$$('html')).not.to.be.hidden
+ expect(cy.$$('html')).to.be.visible
- cy.wrap(this.$parentVisHidden).find('button').should('be.hidden')
- cy.wrap(this.$parentVisHidden).find('button').should('not.be.visible')
- })
+ cy.wrap(cy.$$('html')).should('not.be.hidden')
+ cy.wrap(cy.$$('html')).should('be.visible')
+ expect(cy.$$('body').is(':hidden')).to.be.false
+ expect(cy.$$('body').is(':visible')).to.be.true
- 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(cy.$$('body')).not.to.be.hidden
+ expect(cy.$$('body')).to.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
+ cy.wrap(cy.$$('body')).should('not.be.hidden')
+ cy.wrap(cy.$$('body')).should('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
+ describe('when not display none', () => {
+ it('is visible', () => {
+ expect(cy.$$('html').is(':hidden')).to.be.false
+ expect(cy.$$('html').is(':visible')).to.be.true
- expect(this.$tableVisCollapse.find('#collapse-span')).to.be.hidden
- expect(this.$tableVisCollapse.find('#collapse-span')).to.not.be.visible
- })
+ expect(cy.$$('html')).not.to.be.hidden
+ expect(cy.$$('html')).to.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
+ cy.wrap(cy.$$('html')).should('not.be.hidden')
+ cy.wrap(cy.$$('html')).should('be.visible')
+ expect(cy.$$('body').is(':hidden')).to.be.false
+ expect(cy.$$('body').is(':visible')).to.be.true
- expect(this.$inputHidden).to.be.hidden
- expect(this.$inputHidden).to.not.be.visible
+ expect(cy.$$('body')).not.to.be.hidden
+ expect(cy.$$('body')).to.be.visible
- cy.wrap(this.$inputHidden).should('be.hidden')
- cy.wrap(this.$inputHidden).should('not.be.visible')
+ cy.wrap(cy.$$('body')).should('not.be.hidden')
+ cy.wrap(cy.$$('body')).should('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')
+ describe('basic CSS properties', () => {
+ beforeEach(() => {
+ cy.visit('/fixtures/visibility/basic-css-properties.html')
})
- 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', { browser: '!webkit' }, 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')
- })
+ assertVisibilityForSections([
+ 'visibility-property',
+ 'display-property',
+ 'opacity-property',
+ 'input-elements',
+ 'table-elements',
+ 'box-interactions',
+ ])
})
- 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')
+ describe('form elements', () => {
+ beforeEach(() => {
+ cy.visit('/fixtures/visibility/form-elements.html')
})
- 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')
- })
+ assertVisibilityForSections([
+ 'select-and-option-elements',
+ 'optgroup-elements',
+ 'options-outside-select',
+ 'hidden-options-within-visible-select',
+ 'input-elements',
+ ])
})
- describe('width and height', () => {
- it('is visible when el.textContent, even if offsetWidth is 0', function () {
- this.$divNoWidthTextContent = add('
width: 0
')
-
- 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('
height: 0
')
-
- 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('
\n \t
')
-
- 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
-
- 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 hidden if ancestor has overflow:hidden and no width', function () {
- expect(this.$ancestorNoWidth.find('span')).to.be.hidden
- expect(this.$ancestorNoWidth.find('span')).to.not.be.visible
- })
-
- it('is hidden if ancestor has overflow:hidden and no height', function () {
- expect(this.$ancestorNoHeight.find('span')).to.be.hidden
- expect(this.$ancestorNoHeight.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
- })
-
- it('is visible when ancestor has positive dimensions even with overflow hidden', function () {
- expect(this.$ancestorWithWidthHeightNoOverflow.find('span')).to.be.visible
- expect(this.$ancestorWithWidthHeightNoOverflow.find('span')).to.not.be.hidden
- })
+ describe('overflow', () => {
+ beforeEach(() => {
+ cy.visit('/fixtures/visibility/overflow.html')
+ })
+
+ assertVisibilityForSections([
+ 'zero-dimensions-with-overflow-hidden',
+ 'text-content-with-zero-dimensions',
+ 'positive-dimensions-with-overflow-hidden',
+ 'overflow-auto-with-zero-dimensions',
+ 'mixed-dimension-scenarios',
+ 'overflow-hidden',
+ 'overflow-y-hidden',
+ 'overflow-x-hidden',
+ 'overflow-auto-scenarios',
+ 'overflow-scroll-scenarios',
+ 'overflow-relative-positioning',
+ 'overflow-flex-container',
+ 'overflow-complex-scenarios',
+ 'clip-path-scenarios',
+ ])
})
- 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
+ describe('positioning', () => {
+ beforeEach(() => {
+ cy.visit('/fixtures/visibility/positioning.html')
})
- 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 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 () {
- 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#elOutOfParentBoundsAbove')).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 hidden when parent overflow clip and height is 0', function () {
- cy.$$('body').empty()
-
- const el = add('
I am not visible
')
-
- expect(el.find('#hidden')).to.be.hidden
- reasonIs(el.find('#hidden'), 'This element `
` 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`')
- })
-
- it('is visible when parent overflow clip and height is non-0', function () {
- cy.$$('body').empty()
-
- const el = add('
I am visible
')
-
- expect(el.find('#visible')).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
- })
-
- it('is visible when element is statically positioned and parent element is absolutely positioned and ancestor has overflow hidden', function () {
- cy.$$('body').empty()
-
- const el = add(`
-
-
-
-
-
-
-
- `)
-
- expect(el.find('#visible-button')).to.be.visible
- })
-
- it('is visible when element is relatively positioned and parent element is absolutely positioned and ancestor has overflow auto', function () {
- cy.$$('body').empty()
-
- const el = add(`
-
-
-
-
-
Example
-
-
-
-
-
-
-
- `)
-
- expect(el.find('#visible-button')).to.be.visible
- })
-
- it('is hidden when parent element is absolutely position and offset parent is a decendent of the ancestor', function () {
- cy.$$('body').empty()
-
- add(`
-
- `)
-
- cy.contains('test-2').should('not.be.visible')
- cy.contains('test-1').should('be.visible')
- })
-
- it('is hidden when element is an option and the parent has overflow clip', function () {
- cy.$$('body').empty()
-
- add(`
-