skip to content

In Cypress, what happens to screenshots when the app opens a second tab?

level: seniorimportance: nice to knowfreq 20%

answer

  1. the tab opens, Cypress cannot use it
  2. backgrounded renderers stop painting
  3. a capture needs a painted frame
  4. the extension does it quietly
  5. forcing the tab steals focus

basics

~20 s

Chromium pauses the renderer of a backgrounded tab, so the Cypress tab cannot paint a frame to capture. Cypress therefore activates its own tab before screenshotting, using its browser extension when enabled and force-fronting the tab otherwise, which steals focus in open mode.

solid answer

~50 s

Cypress cannot address a second tab, but the browser still opens one, brings it to the front, and pushes the Cypress tab into the background. Chromium will not capture a screenshot while the renderer process for the Cypress tab is paused, which is exactly what a backgrounded tab risks — and the documented common cause is a click on an anchor with `target="_blank"`. So before capturing, Cypress activates its own tab: first through the Cypress browser extension, and if that is disabled, by forcing the main tab to the front. The forced path is what makes the browser visibly steal focus during `cypress open`. Headless `cypress run` has no window to steal focus from, so the symptom is local-only. The real fix is not to let the tab open: assert the link, or strip its `target` before clicking.

go deeper

for a junior

Know that clicking a target="_blank" link really does open a tab, and that Cypress keeps running in the original one rather than closing or following the new one.

for a middle

Explain why a backgrounded tab cannot be screenshotted: Chromium pauses its renderer, and a capture needs a painted frame from that renderer.

for a senior

Diagnose the symptom from the outside in — focus jumping during open mode, or capture failures that never reproduce in CI — and trace it back to a spec that opens a tab it should not.

for a principal

Set the expectation that suites do not leave stray tabs behind, and weigh a browser-extension dependency against the noise its absence creates for everyone running locally.

## The tab really opens It is worth being precise about what the one-tab ceiling does and does not mean. Cypress cannot *address* a second tab, but nothing stops the browser from *creating* one. Click the bank statement's `target="_blank"` link and Chromium opens the third-party PDF viewer in a new tab, brings it to the front, and leaves your Cypress tab in the background — where it stays until something puts it back. That background state is not neutral. Chromium throttles and can outright **pause the renderer process** of a backgrounded tab. A paused renderer has no compositor work scheduled, which means it cannot produce a frame. ## Why that breaks a screenshot specifically A screenshot is a request for a painted frame. `cy.screenshot()` and the automatic failure screenshot that `screenshotOnRunFailure` produces both need the Cypress tab to be able to paint. The Cypress documentation states the consequence directly: Chromium will not capture screenshots while the renderer process for the Cypress tab is paused, and the most common cause of that is a new tab opened by clicking an anchor with `target="_blank"`. So the symptom is not "the screenshot shows the wrong tab". It is that the capture cannot happen at all until the Cypress tab is active again. ## What Cypress does about it Cypress does not leave this to chance. When a screenshot is captured, it tries to activate its own tab first, along this path: 1. Ask the **Cypress browser extension** to bring the main tab to the front. This is the quiet path — the extension does it without disturbing the rest of the window. 2. If the extension is unavailable or disabled, **force** the main tab to the front directly. 3. Capture the frame now that the Cypress tab's renderer is live again. Step 2 is where the visible weirdness comes from. Forcing the tab forward makes the browser steal focus, which in `cypress open` is exactly the behaviour that has people filing bugs: the window jumps to the foreground mid-run and takes your keyboard with it. The Cypress docs' own advice is to make sure the extension is enabled so that step 2 is never reached. The same activation is built into the `@cypress/puppeteer` plugin: after each Node-side handler finishes on a headed Chromium browser, the plugin brings Cypress's tab back to the front through the extension, and errors with a message about not being able to communicate with the extension if it cannot. ## What you actually see, by mode | situation | what you observe | |---|---| | headed run, extension enabled | screenshots succeed; the Cypress tab quietly returns to the front | | headed run, extension disabled | screenshots succeed, but the browser visibly steals focus each time | | `cypress open` with a tab left open | the same focus theft, on every failure screenshot in the session | | headless `cypress run` | no window to steal focus from, so the whole problem is invisible in CI | That last row is the trap. A suite that leaves stray tabs open behaves perfectly in CI and irritates everyone locally, so the problem never gets prioritised and never gets fixed. ## The fix that removes the problem instead of managing it Two levels of response, in order of preference: - **Do not let the tab open.** Assert the link's `target` and `href`, or strip the attribute with `.invoke('removeAttr', 'target')` before clicking, or stub `window.open` in `cy.visit()`'s `onBeforeLoad` when JavaScript is what opens it. With no second tab, the Cypress tab is never backgrounded and none of this applies. - **If a tab must open,** keep the Cypress browser extension enabled so activation takes the quiet path, and close the extra tab as part of the test rather than leaving it for the next spec. Treat a run whose screenshots are unreliable, or whose window keeps grabbing focus, as a signal that a spec is opening a tab it should not have opened. It is nearly always cheaper to remove the tab than to work around what a backgrounded tab does to Chromium.

  • Why does this problem show up locally but never in the CI run?
    A headless `cypress run` has no window manager and no foreground to fight over, so activation costs nothing visible and focus theft has no meaning. In `cypress open` the same forced activation yanks the window forward and takes your keyboard, which is why the symptom looks like a local-only annoyance and rarely gets prioritised.
  • Is disabling failure screenshots a reasonable fix for the focus stealing?
    No — it trades away the evidence you most need when a test fails and leaves the stray tab in place for whatever runs next. Fix the cause: keep the browser extension enabled so activation is quiet, and change the spec so the extra tab never opens, by asserting the link instead of clicking through it.

saying these in an interview costs you the question

  • Says the screenshot captures the newly opened tab
  • Claims Cypress closes any tab the app opens
  • Thinks a second tab has no effect on the run at all
  • Blames flaky screenshots on the viewport or animations
  • Treats focus stealing as a bug with no known cause