skip to content

Hard Ceilings

What a browser-resident runner structurally cannot do: leave its origin, drive a second tab, or cover every engine. Interviewers ask here to see whether you know where the tool stops.

on this pageshow

explore

questions

16

Which browsers can Cypress 16 launch, and how do you pick one for a run?

level: juniorimportance: must knowfreq 76%

answer

  1. Three engine families, not four
  2. One of them is only an experiment
  3. One of them is on its way out
  4. A CLI flag picks the browser per run
  5. defaultBrowser fills in when the flag is absent

basics

~20 s

Cypress 16 launches Chrome-family browsers - Chrome, Chrome for Testing, Chromium and Edge - plus Firefox, experimental WebKit, and the deprecated bundled Electron. Choose one per run with the --browser flag, or set defaultBrowser in the Cypress config.

solid answer

~40 s

As of Cypress 16, three engine families are drivable. The **Chromium** family covers Chrome, Chrome Beta, Chrome Canary, Chrome for Testing, Chromium itself and Microsoft Edge in stable, beta, dev and canary channels. The **Firefox** family covers Firefox, Firefox Developer Edition and Firefox Nightly, but only version 140 or newer. **WebKit**, Safari's engine, exists only as an experiment behind `experimentalWebKitSupport`. The bundled **Electron** browser still runs but is deprecated in Cypress 16 and will be removed. Cypress officially supports the latest three majors of Chrome, Firefox and Edge. Select one with `cypress run --browser edge`, add a release channel with a colon (`chrome:canary`), or pass a filesystem path for a build Cypress did not auto-detect. With no flag, Cypress uses `defaultBrowser`, and falls back to Electron when that is unset.

code

bash · 10 lines
bash
# what did Cypress detect on this machine?
npx cypress info

# pick a browser explicitly, per run
npx cypress run --browser chrome --spec cypress/e2e/statement-list.cy.js
npx cypress run --browser firefox --spec cypress/e2e/statement-list.cy.js
npx cypress run --browser edge:dev --spec cypress/e2e/statement-list.cy.js

# a build Cypress did not auto-detect, launched by path
npx cypress run --browser /usr/bin/chromium --headed

go deeper

for a junior

Be ready to name the browser families Cypress can launch and to select one from the command line. Interviewers use this as a warm-up before anything harder about the runner.

for a middle

Explain how Cypress detects browsers on the machine, what a channel suffix such as chrome:canary selects, and which setting decides the browser when no flag is passed.

for a senior

Show how you make the browser explicit in CI so a run never depends on whatever the image happens to contain, and how you spot a browser that is present but outside the supported window.

for a principal

Own the team-wide default: which browser a run uses when nobody passes a flag, where that default is written down, and who is accountable when a browser drifts out of support.

Cypress launches and controls its own browser instance rather than attaching to one you already have open, so the list of browsers a suite can cover is fixed by what Cypress knows how to automate. As of **Cypress 16.0.0** that list is short and worth knowing exactly. ## The engine families Cypress 16 drives - **Chromium family** (`Cypress.browser.family === 'chromium'`) - Chrome, Chrome Beta, Chrome Canary, **Chrome for Testing**, Chromium, and Microsoft Edge in stable, beta, dev and canary channels. - **Firefox family** (`family === 'firefox'`) - Firefox, Firefox Developer Edition and Firefox Nightly. - **WebKit** (`family === 'webkit'`) - Safari's rendering engine, available only as an opt-in experiment via the `experimentalWebKitSupport` configuration option. - **Electron** - the Chromium build bundled inside Cypress itself. It reports `family: 'chromium'`, and Cypress 16 **deprecates it as a test browser**; it will be removed in a future major version. Cypress auto-detects what is installed on the machine, so a suite driving a bank statement app normally needs no browser paths configured at all: it walks the well-known binary names for each browser above, reads a version out of each one it finds, and offers the result. `cypress info` prints what was found on that machine, which is the fastest way to answer "why is Edge not in the list" on a CI agent you cannot see. ## Choosing one for a run | `--browser` value | Family | Status in Cypress 16 | | --- | --- | --- | | `chrome`, `chrome:beta`, `chrome:canary` | `chromium` | Supported | | `chrome-for-testing` | `chromium` | Supported, pinned build | | `chromium` | `chromium` | Supported | | `edge`, `edge:beta`, `edge:dev`, `edge:canary` | `chromium` | Supported | | `firefox`, `firefox:dev`, `firefox:nightly` | `firefox` | Supported, version 140+ only | | `webkit` | `webkit` | Experimental, opt-in | | `electron` | `chromium` | Deprecated, removal planned | Cypress resolves which browser to launch in a fixed order: 1. A `--browser` value on the command line wins - a name (`chrome`), a name plus release channel (`edge:dev`), or a filesystem path such as `/usr/bin/chromium`. 2. Otherwise the `defaultBrowser` configuration option, if the project sets one. 3. Otherwise the bundled Electron browser - which is exactly the fallback Cypress 16 wants you to stop relying on. In `cypress open` you pick from a dropdown near the top right instead, and the browser is always headed there so you can watch the run. During `cypress run` every browser starts **headless** by default - Electron through its own headless mode, Chrome, Chromium and Edge with `--headless=new`, Firefox with `-headless`, and WebKit headless through Playwright. `--headed` shows the browser, and `--headless` forces it back. That default is why `cypress run` works on a CI machine with no display attached. ## Which versions count as supported Cypress officially supports the **latest three major versions** of Chrome, Firefox and Edge. These browsers are evergreen and their automation interfaces move quickly, so the window is deliberately narrow. One hard stop sits inside it: Cypress cannot launch **Firefox older than 140** at all, and refuses with an error naming the version to install. The consequence for a CI image is that "we installed a browser once" is not a finished job. An evergreen browser moves under a suite, an old pinned one falls out of the window, and both show up as a Cypress problem long before anyone suspects the browser. Chrome for Testing exists as the deliberate answer to the first half of that, and `--browser chrome-for-testing` selects it. ## Reacting to the browser from inside a spec Sometimes a statement page genuinely renders differently per engine and one assertion has to bend: - `Cypress.browser` exposes `name`, `family`, `channel`, `version`, `majorVersion`, `displayName`, `path`, `isHeaded` and `isHeadless`. - `Cypress.isBrowser('firefox')` matches by name, `Cypress.isBrowser('!chrome')` inverts it, an array matches several, and an object filters on properties such as `{ family: 'chromium' }`. - Cypress's test configuration takes a `browser` option, so `describe('embedded PDF viewer', { browser: 'firefox' }, ...)` runs a suite only under Firefox. Reach for these sparingly. Branching a spec per browser is how a suite quietly stops asserting the same behaviour everywhere. ## What is not on the list - **Safari itself cannot be launched.** Experimental WebKit runs Safari's *engine*, obtained from Playwright's `playwright-webkit` package; it is not the Safari application, and it does not carry Safari's own UI behaviour. - **Internet Explorer and real mobile browsers are not options.** Cypress launches desktop browser binaries on the machine running the test. - **A browser Cypress cannot detect is not automatically excluded.** You can pass its path to `--browser`, or add an entry to the `browsers` array returned from `setupNodeEvents` so it appears in the open-mode dropdown; filtering that array is also how you *remove* browsers a team should not use. The practical takeaway for a suite covering a bank statement app: Chromium browsers and Firefox are first-class, WebKit is a partial preview of Safari, and Electron is a fallback you should be actively leaving.

  • How do you launch a Chromium build that Cypress does not auto-detect?
    Pass a filesystem path to `--browser` instead of a name, for example `cypress run --browser /usr/bin/chromium`. Cypress inspects the binary, works out which browser it is, and launches it. To have it listed in `cypress open` as well, append an entry to the `browsers` array returned from `setupNodeEvents` with `name`, `family`, `channel`, `displayName`, `version`, `majorVersion` and `path`.
  • How do you run one Cypress suite only in Firefox?
    Use Cypress's test configuration `browser` option on the suite or test: `describe('statement viewer', { browser: 'firefox' }, ...)` runs it only under Firefox, and `{ browser: '!firefox' }` runs it everywhere else. Inside a test, `Cypress.isBrowser('firefox')` and `Cypress.browser.family` let you branch. A suite excluded this way simply does not run in the other browsers.

saying these in an interview costs you the question

  • Claims Cypress can launch Safari itself on macOS
  • Thinks WebKit is available by default in Cypress
  • Says Cypress drives any browser with a WebDriver server
  • Believes Electron is the recommended browser for CI
open as a page

Why do Cypress commands fail after the app navigates to another origin?

level: juniorimportance: must knowfreq 70%

basics

~20 s

Cypress runs inside the browser and obeys the same-origin policy, so a test is bound to one origin and cannot touch a document from a different one. Wrap the commands for the new origin in a cy.origin() block.

open as a page

Which browser does `cypress run` launch in Cypress 16 without --browser?

level: middleimportance: must knowfreq 60%

basics

~20 s

The bundled Electron browser, unless the project sets defaultBrowser. Electron is deprecated as a test browser in Cypress 16 and will be removed in a future major, so set defaultBrowser or pass --browser to point runs at an installed browser.

open as a page

Why can't a Cypress cy.origin() callback see variables declared outside it?

level: middleimportance: must knowfreq 62%

basics

~20 s

The callback is not a closure. Cypress stringifies it, ships it to a second instance of itself running in the other origin and evaluates it there, so the surrounding scope is gone. Data reaches it only through the args option.

open as a page

In Cypress, what happens when you call cy.hover(), and what do you use instead?

level: middleimportance: must knowfreq 70%

basics

~20 s

Cypress has no hover command. Calling cy.hover() fails with an error saying it is not implemented and links to the workarounds page. Use .trigger('mouseover'), .invoke('show'), a forced action, or the cypress-real-events plugin's realHover for genuine pointer input.

open as a page

Why is WebKit missing from Cypress 16's browser list despite experimentalWebKitSupport?

level: middleimportance: should knowfreq 37%

basics

~20 s

Because the configuration flag is only half of the opt-in. Cypress finds WebKit by resolving Playwright's playwright-webkit package from the project directory, so with the flag set but that package missing there is no WebKit build to list.

open as a page

Why can't one Cypress test drive two browsers at once for a two-user flow?

level: middleimportance: should knowfreq 48%

basics

~20 s

Cypress 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.

open as a page

Why does Cypress 16 refuse to launch Firefox 128 in a pinned CI image?

level: seniorimportance: should knowfreq 33%

basics

~20 s

Cypress automates Firefox through WebDriver BiDi, and Firefox builds below 140 implement it incompletely. Cypress 16 marks such a build unsupported and refuses to launch it, naming the version to install. The fix is to update the pinned image or ESR build.

open as a page

Why does a Cypress cy.origin() callback error when it calls cy.intercept() or cy.session()?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Those commands are not supported inside the callback, because the block runs in a second Cypress instance in the other origin. Declare them outside the block instead: the interception before the navigation, and cy.session() wrapping the whole flow.

open as a page

Why does cy.origin() not help a Cypress test reach into a cross-origin iframe?

level: seniorimportance: should knowfreq 46%

basics

~20 s

cy.origin() handles top-level navigation to another origin, not embedded frames. A cross-origin iframe's contentDocument reads as null under the same-origin policy, so no Cypress command can get a handle on its DOM. Same-origin iframes can be queried.

open as a page

In Cypress, how does the @cypress/puppeteer plugin reach a tab the test opened?

level: seniorimportance: should knowfreq 35%

basics

~20 s

The plugin registers named Node-side handlers in your Cypress config and adds a cy.puppeteer() command that calls one by name. The handler receives a Puppeteer browser connected to the browser Cypress launched, so it can find and drive the extra page.

open as a page

In a Cypress suite, how far should you go to cover a flow that opens a new tab?

level: principalimportance: should knowfreq 40%

basics

~20 s

Decide by what the second tab would prove. Assert the handoff and request the URL when the destination is not yours; reach for the puppeteer plugin only when real value lives on the other side and no cheaper seam reaches it.

open as a page

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

level: seniorimportance: nice to knowfreq 20%

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.

open as a page

In Cypress CI, should you pin Chrome for Testing or use the installed Chrome?

level: principalimportance: nice to knowfreq 27%

basics

~20 s

Pin Chrome for Testing where a red run must mean a real regression, and keep a separate evergreen job so browser changes still reach you. A pin buys reproducibility, not immunity from the next Chrome release, and it needs a bump schedule.

open as a page

How would you decide whether a Cypress suite sets injectDocumentDomain to true?

level: principalimportance: nice to knowfreq 33%

basics

~20 s

Treat it as a dated migration budget, not a setting. It buys time for specs that cross subdomains after Cypress 14 made every origin change need cy.origin(), but it is deprecated, breaks some identity providers, and will be removed.

open as a page