In Cypress, what does `cy.wait(['@getStations', '@getAlerts'])` resolve on and yield?
answer
- One command, several route aliases
- All of them, not the first one
- Order comes from your array
- Same request and response budgets apply
- spread unpacks the yielded array
basics
~20 sIt blocks until every listed route alias has completed a request-response cycle, each within the usual requestTimeout and responseTimeout budgets, then yields an array of interceptions ordered by the aliases as you passed them, not by arrival.
solid answer
~50 sPassing an array makes one `cy.wait()` block on all of the listed route aliases. Each alias gets the same `requestTimeout` and `responseTimeout` budgets a single wait uses, and those clocks run concurrently. The yielded subject is an **array of interception objects in the order you listed the aliases**, not the order the responses came back: `interceptions[0]` is always `@getStations` above, even if the alerts feed answered first. `.spread((stations, alerts) => …)` unpacks that array into named arguments and reads better than indexing. Each entry consumes one recorded request for its own alias, exactly as a single wait would, so a later `cy.wait('@getStations')` is asking for the station route's *second* request. If one alias never sees a request the whole command fails, naming the alias and the phase that stalled — the array never partially resolves.
code
javascript · 13 linesit('renders the dashboard once both feeds land', () => {
cy.intercept('GET', '/api/stations').as('getStations')
cy.intercept('GET', '/api/alerts').as('getAlerts')
cy.visit('/dashboard')
cy.wait(['@getStations', '@getAlerts']).spread((stations, alerts) => {
expect(stations.response.statusCode).to.equal(200)
expect(alerts.response.body).to.have.length(2)
})
cy.get('[data-testid="alert-banner"]').should('be.visible')
})go deeper
Know that one cy.wait can take a list of route aliases and waits for all of them, and that what comes back is an array with one interception per alias.
Explain that the array order follows your alias list rather than response arrival, that .spread names the entries, and that the command fails as a unit when one alias never fires.
Discuss when grouping concurrent page-load calls into one wait gives a clearer failure than a run of separate waits, and how the overlapping request budgets change how fast a broken page fails.
Be ready to set a house convention for how page-load traffic is synchronised across a large suite, and what that convention costs when the app's call graph changes.
## One command, several routes `cy.wait()` accepts an array of route aliases as well as a single one. Given `cy.wait(['@getStations', '@getAlerts'])`, Cypress blocks the command queue until **both** routes have completed a request-response cycle, and then releases with an array of interception objects — one per alias — as the subject. This is the natural shape for a dashboard that fires several independent calls on load. A weather dashboard that fetches its station list and its active alerts at the same time has two requests in flight concurrently, and no reason to care which answers first. ## The yielded array is in *your* order The single most testable fact here: the array is ordered by the aliases **as you listed them**, not by the order the responses arrived. `interceptions[0]` is always `@getStations` in the example above, even when the alerts feed answered first. That is what makes positional access safe. - `.then((interceptions) => …)` gives you the array and you index into it. - `.spread((stations, alerts) => …)` unpacks the array into named arguments, which reads better and removes the chance of an index typo. - Each entry is an ordinary interception, so `stations.response.statusCode` and `alerts.request.url` work exactly as they do after a single-alias wait. ## Budgets and failure Each alias in the array gets the same two-phase treatment a single wait gets, and those clocks run concurrently rather than one after another: | Phase | Governed by | Default | |---|---|---| | A matching request leaves the browser | `requestTimeout` | `5000` ms | | The server or stub answers it | `responseTimeout` | `30000` ms | The command is **all or nothing**. If `/api/alerts` is never requested, the whole `cy.wait()` fails and the error names the alias and the phase that stalled — you do not get a partial array with a hole in it, and the `@getStations` interception that did arrive is not handed to you as a consolation prize. ## Array wait versus back-to-back waits | | `cy.wait(['@a', '@b'])` | `cy.wait('@a')` then `cy.wait('@b')` | |---|---|---| | Requires both routes to complete | Yes | Yes | | Tolerates either arrival order | Yes | Yes | | Timeout clocks | Run concurrently | Run one after the other | | Failure report | One command, names the stalled alias | Two commands, the second one fails | | Yields | An array, in your alias order | Two separate interceptions | Back-to-back waits tolerate either arrival order too, because Cypress records an interception the moment the cycle completes — by the time the second wait runs, the request it wants may already be sitting in the recording. The real differences are the concurrent budgets and how the failure reads. **Counters still apply per alias.** An array wait consumes one recorded request **per alias**, exactly as a single wait would. So after `cy.wait(['@getStations', '@getAlerts'])`, a later `cy.wait('@getStations')` is asking for the station route's *second* request, not its first. Mixing the two forms in one test is fine, as long as you count deliberately. ```javascript cy.intercept('GET', '/api/stations').as('getStations') cy.intercept('GET', '/api/alerts').as('getAlerts') cy.visit('/dashboard') cy.wait(['@getStations', '@getAlerts']).spread((stations, alerts) => { expect(stations.response.statusCode).to.equal(200) expect(alerts.response.body).to.have.length(2) }) ``` Two things make this preferable to two separate waits here: the failure message points at the alias that never happened rather than at whichever wait ran second, and the per-alias request budgets overlap instead of stacking. ## When an array wait is the wrong shape The array form says "all of these happen, in no particular order". Reach for something else when that is not what you mean: - **The calls are genuinely sequential.** If the alerts request is only issued once the station list has come back, two separate waits describe the app honestly and fail closer to the real cause. - **One of the routes is conditional.** A route that fires only for some fixtures will stall the whole array wait, and the failure will read as a missing request rather than as a branch not taken. - **You need the interceptions apart.** Where each cycle drives a long block of assertions, two named waits read better than a `.spread()` callback that has to hold both. - **A route is hit more than once.** The array consumes one request per alias; if the dashboard calls the station list twice on load, the second cycle is still sitting unconsumed in the recording. ## Common mistakes 1. **Assuming arrival order.** Writing `.spread((alerts, stations) => …)` because the alerts feed is usually faster produces a test that passes for the wrong reason and then flips. 2. **Expecting partial resolution.** There is no "two of three arrived" state; the command either satisfies every alias or fails. 3. **Passing several string arguments.** `cy.wait('@getStations', '@getAlerts')` is an error — Cypress reports that you cannot pass multiple strings and to use an array instead. 4. **Forgetting the per-alias counter.** A later single wait on an alias already consumed by the array is asking for that route's next request.
- In Cypress, is `cy.wait(['@a', '@b'])` different from two consecutive `cy.wait()` calls?Both require every listed route to complete, and both tolerate either arrival order, because Cypress records an interception the moment the cycle finishes. The array form differs in two ways: the per-alias timeout clocks run concurrently rather than back to back, and a failure comes back as one command naming the alias that stalled.
- What happens if you write `cy.wait('@getStations', '@getAlerts')` with two string arguments in Cypress?It is rejected. Cypress reports that `cy.wait()` was passed invalid arguments and that you cannot pass multiple strings, pointing you at the array form. The second positional argument is reserved for the options object, which is where `timeout`, `requestTimeout` and `responseTimeout` go.
saying these in an interview costs you the question
- Thinks the array yields interceptions in arrival order
- Expects a partial result when one alias never fires
- Believes the array form waits for any one alias
- Guesses indexes in .then instead of using .spread
- Assumes an array wait resets each alias counter