Reputation: 3451
Is it possible to wait until an element is visible?
cy.get('[data-test=submitIsVisible]').should('be.visible');
This should error if the submit button is not visible. I want to wait until the submit button is visible.
The primary use case is visual testing, i.e. taking a screenshot of the page.
Upvotes: 53
Views: 178279
Reputation: 6312
You can wait for the element to be visible like so:
// Give this element 10 seconds to appear
cy.get('[data-test=submitIsVisible]', { timeout: 10000 }).should('be.visible');
According to Cypress's Documentation:
DOM
based commands will automatically retry and wait for their corresponding elements to exist before failing.
Cypress offers you many robust ways to query the DOM
, all wrapped with retry-and-timeout logic.
Another way to wait for an element’s presence in the DOM
is through timeouts
. Cypress commands have a default timeout
of 4 seconds, however, most Cypress commands have customizable timeout
options. Timeouts can be configured globally or on a per-command basis. Check the customizable timeout
options list here.
In some cases, your DOM
element will not be actionable. Cypress gives you a powerful {force:true}
option you can pass to most action commands.
Caveat:
As Anthony Cregan pointed out, the .should('be.visible')
assertion checks whether an element is visible on the page, not necessarily in the viewport. This means that this assertion will return true even if the element is not within the visible area of the screen when the test is run.
Further recommended readings:
Upvotes: 114
Reputation: 4966
If you want to see exactly how Cypress waits for something to become visible, follow this example.
Using this code, you can check out how the delay
and the timeout
can affect the passing or failing of the .should('be.visible')
assertion.
Add a simple page to a VSCode project containing Cypress v12.1.0
Call it index.html
<html>
<body>
<h2>API fetched data</h2>
<span>will become visible here</span>
</body>
<script>
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then(response => response.json())
.then(data => document.querySelector('span').innerText = data.title )
</script>
</html>
Right-click index.html
and choose "Open with Live Server" to activate the page.
Add this test to see how Cypress waits for the API data
describe('test the waiting of API data', () => {
const timings = [
{ delay: 0, timeout: 4000 }, // default, passes
{ delay: 2000, timeout: 4000 }, // passes
{ delay: 4000, timeout: 4000 }, // flaky
{ delay: 5000, timeout: 4000 }, // fails
{ delay: 5000, timeout: 10000 }, // passes
]
timings.forEach(timing => {
const {delay, timeout} = timing;
it(`delayed API by ${delay} ms, command timout is ${timeout} ms`, () => {
cy.intercept('https://jsonplaceholder.typicode.com/posts/1', (req) => {
req.continue((res) => res.setDelay(delay))
})
cy.visit('http://127.0.0.1:5500/index.html')
cy.contains('sunt aut facere', {timeout})
.should('be.visible')
})
})
})
This shows that the longer the delay in receiving the data, the bigger the timeout needed on the visibility assertion.
Upvotes: 113
Reputation: 654
you can also do it by passing below script into your cypress.config.js files
e2e: {
defaultCommandTimeout: 25000,
}
pass defaultCommandTimeout
as per your requirement.
Upvotes: 3