Why can't one Cypress test drive two browsers at once for a two-user flow?
answer
- one browser per spec, always
- a permanent trade-off, not a gap
- the plugin gives tabs, not browsers
- drive the other party from Node
- cy.request or cy.task as the door out
basics
~20 sCypress does not support controlling more than one open browser at a time; the spec runs inside the single browser it launched, and no command attaches to another. Cover a two-party flow by driving the second participant from Node with cy.request or cy.task.
solid answer
~40 sControlling more than one open browser at a time is a permanent Cypress trade-off, not a missing feature: a spec is launched into one browser and every `cy` command addresses that browser. The `@cypress/puppeteer` plugin does not change this — it connects to the browser Cypress already launched, so it buys another tab in the same browser, not a second isolated session. The way to cover a two-party flow is to drive the other participant from outside the browser. `cy.request()` acts as the back-office operator against your API, and `cy.task()` reaches anything that is not plain HTTP. A statements spec then reads: visit as the customer, `cy.request()` the operator's release endpoint, assert the customer's page now shows the statement. One browser, two participants, and one source of flakiness instead of two.
go deeper
Know that a Cypress spec runs in exactly one browser and that no command opens or attaches to a second one. Say so plainly rather than guessing at an API.
Explain the difference between another tab in the same browser and a genuinely separate session, and show how cy.request drives the second participant from Node.
Talk about determinism: a spec driving one browser and one API caller fails for one reason, while two live browsers fail for the union of both. Say which guarantees you deliberately move elsewhere.
Own where multi-session guarantees live in the overall test strategy, and be able to defend not recreating a second live client just because a feature involves two people.
## The ceiling, stated exactly Cypress does not support controlling more than **one open browser at a time**. This sits in the Cypress documentation under *permanent* trade-offs, alongside the fact that a test is bound to a single superdomain — it is a property of the design, not a missing feature. A spec is launched into one browser, and every `cy` command in that spec addresses that browser. There is no second `cy` namespace, no browser handle, and no configuration key that starts a second instance for the same spec. That matters most for **collaboration flows**: a bank statement app where a back-office operator releases a statement and the customer's open session is supposed to show it, or a shared-account view where one holder's action must appear to another. ## A second tab is not a second browser Candidates often reach for the `@cypress/puppeteer` plugin here and overstate what it does. The plugin connects a Node-side handler to the **browser Cypress already launched**, so it can find and drive another page in that same browser. That is a second tab, not a second browser, and it does not give you two independent, isolated sessions — the tabs share the browser's cookie jar and storage unless you have gone out of your way to separate them. So the honest position is: - **Two browsers in one spec:** not possible, by design. - **Two tabs in one browser:** possible through the plugin, on Chromium-family browsers, with the automation code living in Node. - **Two genuinely isolated user sessions in one spec:** not what either mechanism gives you. ## Covering a two-party flow from one browser The productive move is to stop trying to *render* the second participant and start **driving** them from outside the browser. Cypress gives you two doors out of the browser for exactly this: 1. **`cy.request()`** issues an HTTP request from Cypress's Node process, outside the browser's page context. The operator's release action becomes a call against your API, made as the operator, in the middle of the customer's browser test. 2. **`cy.task()`** runs a function you registered in `setupNodeEvents`, which is the door for anything that is not a plain HTTP call — a database write, a message on a queue, a helper process you control. A spec then reads: visit the statements page as the customer, `cy.request()` the operator's release endpoint, and assert that the customer's page shows the released statement. One browser, two participants, no tab juggling. The same shape covers real-time features. Cypress does not intercept WebSocket frames, so the way to make "the other side" say something is to have your server say it — drive a helper process or an API endpoint from the spec and let the real socket deliver the message into the browser you are watching. ## What you can and cannot prove this way | you want to prove | one-browser approach | honest verdict | |---|---|---| | the customer's page reacts to another party's action | drive that party with `cy.request()` or `cy.task()` | fully covered | | the released statement is visible to the right account | assert in the customer's browser after the request | fully covered | | two people's browsers stay in sync in real time | server-driven message plus an assertion in one browser | covered for the receiving side only | | two independent browser sessions cannot see each other's data | not reachable in one spec | needs a different layer of testing | The last row is the one to say out loud in an interview. Some multi-session guarantees are genuinely outside a single-browser runner, and the mature answer is to place them somewhere else rather than to fake them. ## Why this ceiling is usually fine Two things make it far less painful than it sounds: - Most "two-user" scenarios are really **one user reacting to a state change**. The second user is a state producer, and producing state through the API is faster and far more deterministic than driving a second UI. - A spec that drives the second participant through the API fails for one reason at a time. A spec that drives two live browsers fails for the union of both browsers' flakiness, and you get to debug which half broke. The trap is the workaround that does not exist: there is no Cypress command that launches, attaches to, or switches between browsers, and claiming one is a fast way to lose an interview.
- Does Cypress let you stub individual WebSocket frames to simulate the other participant?No. WebSocket connections work normally during a Cypress test, but Cypress does not intercept them, so individual frames are not stubbable. The documented approach is to make the real server send the message — drive an API endpoint or a helper process from the spec — and assert what arrives in the browser you are watching.
- What guarantee about two users genuinely cannot be tested in one Cypress browser?Anything that depends on two independent browser sessions existing at the same time — cross-session isolation, per-session storage separation, or a race between two live clients. A single spec has one browser and one storage partition, so those belong to a different layer of testing rather than to a workaround.
saying these in an interview costs you the question
- Claims Cypress can launch a second browser mid-spec
- Says the puppeteer plugin starts an independent browser
- Treats two tabs as two isolated user sessions
- Proposes a second cy namespace for the other user
- Assumes cy.intercept can stub WebSocket frames