The application
Imagine a very simple application:
- you click a button
- the application does something while showing the text "Loading"
- the application shows the success message "Loaded"
Simple. If everything goes well, the end-to-end test can be
1 | cy.contains('button', 'load') |
🎁 You can find the example application and the tests in my collection of Cypress examples.
Everything goes well. We do not know when the "loading..." message switches to "Loaded", but the test relies on Cypress retry-ability to keep checking the page until it find the text "Loaded"
1 | // even if it takes 3.9 seconds |
If the application might take 10 seconds to show the "Loaded" message, we can increase the retry-ability timeout:
1 | // keep trying to find the text "Loaded" on the page |
The most common situation for adding a timeout
parameter to a Cypress command like cy.contains
is to increase the time limit. But there are cases when we want to shrink the timeout period to zero or just a few milliseconds instead.
Unexpected elements
Imagine that our application instead of successfully loading the data, for some reason shows an unexpected warning message, and then completes successfully.
Hmm, notice the test still passed. We do not care about the unexpected "Something went wrong" message, we are looking for the "Loaded" text, and it eventually appear. How do we "catch" the expected elements? We cannot use negative assertions because A) we do not know all possible unexpected elements and B) we cannot control the timing when these elements appear to know when to check. Here is an updated test that still does not "notice" the warning:
1 | // 🚨 DOES NOT WORK |
We need something better. We need to really "shrink" the time between the "Loading..." element going away and the "Loaded" text appearing. Then any other element trying to sneak in will be caught.
Shrink the time gap using the timeout option
Here is what we can do. We can confirm when the "Loading..." text goes away.
1 | cy.contains('button', 'load') |
Note: despite having "not.exist", cy.contains('button', 'Loading...').should('not.exist')
is an example of a positive assertion. We check that something happens in response to an action.
Ok, so we know the "Loading..." text is gone. Now we are looking to see the "Loaded" text there immediately.
1 | // the "Loading..." element goes away |
Beautiful - if there are no extra elements, the test passes. Now let's see what happens when a warning message does "insert" itself.
By setting the timeout: 0
we tell Cypress to really shrink the retries limit to make sure no unexpected element can sneak in.
Video
You can watch this blog post explained in the video below