Cypress Handling Waits
Web pages often load content at different speeds due to network conditions or server delays. Cypress handles most of this delay automatically, but some situations still need explicit waiting strategies. This topic explains how waiting works in Cypress.
Built-In Automatic Waiting
Cypress automatically waits for elements to appear before interacting with them. A click command waits for the target element to exist and become visible first.
cy.get('#submit-button').click()This single line already includes built-in retry logic behind the scenes, checking repeatedly until the button appears or a timeout occurs.
A Simple Way to Picture It
Think of Cypress as a patient guest waiting at a restaurant door. The guest does not walk in immediately at the scheduled time if the door is still locked. The guest checks the door repeatedly for a short while before giving up and reporting a problem.
Why Fixed Waits Cause Problems
Some testers add a fixed wait time, pausing the test for an exact number of seconds regardless of actual page state.
cy.wait(5000)This approach wastes time when the page loads faster than expected. It also fails unpredictably when the page loads slower than the fixed wait duration.
Waiting Approaches Comparison
Fixed Wait (cy.wait(5000)) - Always pauses for the full duration - Wastes time or fails unpredictably Automatic Retry (cy.get, should) - Checks repeatedly until ready - Stops early once the condition is met
Waiting for a Specific Condition
Instead of a fixed pause, attach an assertion that Cypress retries automatically until it passes.
cy.get('.loading-spinner').should('not.exist')
cy.get('.results').should('be.visible')This pattern waits exactly as long as needed, no more and no less.
Waiting for Network Requests
Network-dependent pages benefit from waiting on a specific request instead of guessing a timing value.
cy.intercept('GET', '/api/products').as('getProducts')
cy.visit('/shop')
cy.wait('@getProducts')This wait pauses the test only until the aliased network request actually completes.
Adjusting Timeout Values
Some elements take longer than the default timeout to appear, such as content behind a slow API call. Cypress allows extending the timeout for a specific command.
cy.get('.report-data', { timeout: 10000 }).should('be.visible')This line waits up to ten seconds instead of the default four seconds for this specific check.
Waiting for Animations to Finish
Cypress waits for elements to stop animating before certain interactions, avoiding clicks during a sliding or fading transition. This built-in behavior reduces flaky test failures caused by animation timing.
Debugging Timeout Failures
A timeout failure usually points to one of three causes: a missing element, a slow-loading page, or an incorrect selector. Checking the command log inside the Test Runner often reveals which cause applies to a specific failure.
Waiting Diagram
Page Action Triggered
|
v
Cypress checks condition
|
v
Condition met? --- No ---> wait a short interval, check again
|
Yes
|
v
Continue to next command
Best Practices for Waiting
Avoid fixed wait times whenever possible, since they slow down tests and hide real timing problems. Prefer assertions and network aliases that wait based on actual conditions. Reserve fixed waits only for rare edge cases without a reliable condition to check.
Key Points
- Cypress automatically retries most commands until a condition succeeds.
- Fixed waits using cy.wait with a number often waste time or cause failures.
- Assertions and network aliases provide reliable, condition-based waiting.
- Timeout values can be extended for specific slow-loading elements.
- Timeout failures usually point to missing elements, slow pages, or wrong selectors.
