This guide shows you how to make Cypress wait until your application is fully loaded before running tests, preventing flaky failures caused by slow starts. You’ll learn several reliable strategies, from built-in retry logic to explicit waits, and how to choose the right one for your setup. No special tools are required beyond your existing Cypress installation.
What You’ll Need
- A Cypress test project (version 10 or later recommended)
- Your application’s local dev server or a running instance
- Basic familiarity with Cypress commands and test structure
Step-by-Step
- Use Cypress’s built-in retry logic. Cypress automatically retries commands like
cy.get()andcy.contains()until the element appears or the timeout expires. By default, the timeout is 4 seconds. Increase this for slower apps by settingdefaultCommandTimeoutin yourcypress.config.jsfile:module.exports = { e2e: { defaultCommandTimeout: 10000, // 10 seconds }, };This is the simplest and most robust way to handle most app-start delays.
- Wait for a specific element that only appears when the app is ready. Instead of a fixed wait, use
cy.get()on a known element that is rendered only after the app initializes (e.g., a header, a login button, or a loading spinner that disappears).cy.visit('/'); cy.get('[data-testid="app-ready"]', { timeout: 15000 }).should('be.visible');This ensures the app is actually interactive, not just that the page loaded.
- Use
cy.intercept()to wait for network requests. If your app fetches initial data, wait for that request to complete before proceeding. This is especially useful for SPAs that render after an API call.cy.intercept('GET', '/api/initial-data').as('getData'); cy.visit('/'); cy.wait('@getData', { timeout: 20000 });This works even if the response is not immediately used by the UI.
- Poll for a condition with
cy.waitUntil()(if using a plugin). For complex conditions (e.g., a global variable is set), you can use thecypress-wait-untilplugin. Install it withnpm install cypress-wait-until, then in your test:cy.waitUntil(() => cy.window().then(win => win.appReady), { timeout: 15000 });This polls the condition until it returns true.
- Set a global
baseUrland usecy.visit()with a long timeout. If your app takes a long time to respond to the initial page load, you can pass a timeout tocy.visit():cy.visit('/', { timeout: 30000 });This waits for the page’s
loadevent, but note it does not wait for JavaScript to finish executing. - Use
cy.clock()andcy.tick()for testing with fake timers. If your app usessetTimeoutto indicate readiness, you can control time in tests:cy.clock(); cy.visit('/'); cy.tick(5000); // advance 5 seconds cy.get('[data-testid="ready"]').should('be.visible');This is useful for deterministic tests, but be careful with real network requests.
Common Mistakes
- Using
cy.wait(5000)with a fixed time. This is brittle: if the app is slower on CI, the test fails; if faster, you waste time. Always prefer waiting for a condition. - Waiting for the
loadevent only. The page may load, but the JavaScript bundle may still be executing. Usecy.get()on a rendered element instead. - Setting timeouts too low. On slow CI machines, 4 seconds is often not enough. Increase to 10–15 seconds for initial loads.
- Ignoring network requests. If your app fetches data on startup, waiting for the DOM alone may not be sufficient; the data might not be displayed yet.
- Using
cy.wait()aftercy.visit()without a condition. This is just a fixed delay, which is unreliable.
Tips
- Add a data attribute to your app’s root component (e.g.,
data-testid="app-ready") that is set only after initialization. This makes tests more resilient to UI changes. - Use
beforeEach()to centralize the wait logic so every test starts from a ready state. - Run Cypress with
--browser chromefor faster startup compared to Electron in some cases. - Consider using
cy.session()to cache authentication state, which can reduce startup time for subsequent tests. - If your app uses WebSockets, wait for a connection message using
cy.intercept()on the WebSocket upgrade request.
Troubleshooting
If your tests still fail even after adding waits, try these steps:
- Check the Cypress command log. It shows how long each command took and when the timeout occurred. Look for the step that failed and see if the element was present but not visible.
- Increase the timeout further. Sometimes 10 seconds is not enough on heavily loaded CI machines. Try 20 seconds to see if the test passes; if it does, you can optimize later.
- Verify the selector is correct. Use
cy.get()with a unique attribute. Avoid class names that may change. - Check if the app is throwing console errors. Open the browser dev tools in Cypress (by clicking on the URL in the runner) and look for errors that prevent initialization.
- If using
cy.intercept(), ensure the request URL matches exactly. Usecy.intercept('**/api/data').as('data')to match any path. - Try a fresh Cypress run with
cypress open. Sometimes the headless runner behaves differently; compare results.
Frequently Asked Questions
Why does Cypress not wait for my app to start automatically?
Cypress waits for the page’s load event, but that fires before your JavaScript finishes running. You need to explicitly wait for a condition that indicates your app is ready.
What is the best way to wait for an app to start?
The best way is to wait for a specific element that is only rendered after initialization, using cy.get() with an appropriate timeout. This is both reliable and fast.
Can I use cy.wait() with a variable time?
No, cy.wait() requires a fixed number of milliseconds. For dynamic waits, use cy.get() with a timeout or the cypress-wait-until plugin.
How long should I set the timeout?
Start with 10 seconds. If your app is slow, increase to 20–30 seconds. A longer timeout only affects tests when the condition is not met, so it’s safe to be generous.
Does waiting for a network request guarantee the app is ready?
Not always. The request may complete, but the app might still be processing the response. It’s better to wait for the UI to reflect the data.
Can I wait for a global JavaScript variable?
Yes, you can use cy.window().its('appReady') with a timeout, or the cypress-wait-until plugin for more complex conditions.
Related
General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.
More in this bed
- Fix Mir4 Crashing on PC: 7 Working Solutions
- How to Use Multiple Stops in Google Maps
- How to Fix HDMI No Signal on a Mini PC
- How to Install a CPU on a Motherboard
- Snapchat How to Get More Views: 12 Proven Tips
- Edit PDFs in Windows 11: Built-In Ways