Debug the Element Visibility Problems in Cypress

How to step through the visibility code to determine why Cypress thinks an element is invisible during the test

In GitHub issue #9378 the user submitted a reproducible example of a failing test. Cypress fails the test when the clearly visible "Cypress is amazing!" element is deemed NOT to be visible.

The test is failing because an element is deemed to be invisible

In the video below I show how to debug the visibility problem. This is a general approach anyone can take when encountering such error. Or you can continue reading this blog post.

Pause and debug

Cypress v6 uses the function Cypress.dom.isVisible to determine if an element is visible during the test. In order to hit this function so we can step through it we need to pause the test using cy.pause, open the DevTools, and tell the browser to break when the function is executed.

1
2
3
4
cy.wait(5000); // Just to make sure everything is loaded.
cy.pause();
cy.contains('Cypress is amazing!')
.should('be.visible');

Then open the DevTools console and enter

1
debug(Cypress.dom.isVisible)

Set the debug while the test is paused

Click the "Resume" button in Cypress and see how the debugger automatically breaks on Cypress.dom.isVisible execution.

The test stops at the function

Now you can use the DevTools debugger to step through the Cypress internal code to see where the visibility logic goes wrong (or not).

Tip: to stop debugging the visibility function execute undebug(Cypress.dom.isVisible) in the DevTools console.

Use any element

Another alternative is to let the test finish (and fail), then open the DevTools Elements panel, and find the element you want to check visibility for. In our case, it is this element, highlighted by the DevTools

The element we are investigating

Notice that right above that element is the <video> element that Cypress says covers our "Cypress is amazing!" element. When you hover over that <video> element it kind of looks like it does cover the entire viewport.

The video element that covers our element

We can pick an element and call Cypress.dom.isVisible(el) ourselves, right from the DevTools, outside the test. When you select an element in the Elements panel, the DevTools points at it using a special variable $0. Just call the visibility function and pass $0 as shown below.

Call isVisible and pass the selected element

Now click on the <video> element and inspect its properties. Maybe you can modify one of them and then run isVisible($0) again to see if it changes to true? For example, the display: none on the element itself is ignored by the browser because the more general CSS style has display: block !important set.

Video element CSS props

Is this intentional? Seems weird. Let's add the !important to the element itself to make sure its own display property is respected.

Enforce the display property on the dialog

As you can see, after we change the display property on the element itself, the text is now considered visible.

Tip: while we are changing the <video> element's properties it gets $0 variable. The previously selected element with "Cypress is amazing!" automatically gets the special $1 variable which we used above.

Finally, let's see if this is really the video element when it is visible that covers our text - even if the video is not playing. Let's change its height from 100% to 80% and check the visibility again.

Element is visible if the video element does not cover it

So it seems the <video> element is really considered to cover everything - but of course you need to actually step through the Cypress.dom.isVisible code to figure out the precise details.