skip to content

Choosing and Moving

Where a browser-resident runner belongs, what its placement costs a team, and what survives a port in either direction. Interviewers probe judgement here, not command recall.

on this pageshow

explore

questions

17

Which projects is Cypress a strong fit for, and which are the classic misfits?

level: juniorimportance: must knowfreq 74%

answer

  1. Start from whose application it is
  2. Count the origins one journey crosses
  3. One browser at a time, always
  4. Which browsers can it actually launch
  5. Docs call it a specialized tool

basics

~20 s

Cypress fits an application your own team owns: JavaScript or TypeScript, one superdomain per test, Chrome-family or Firefox. The classic misfits are third-party sites, two-browser or second-tab flows, a real Safari or mobile-device sign-off, and spidering or performance work.

solid answer

~40 s

Cypress's sweet spot, in its own documentation, is **testing an application your team owns**: a JavaScript or TypeScript codebase, served from one superdomain per test, exercised in a Chrome-family browser or Firefox, with `cypress open` running beside the app you are editing. The misfits are equally specific. Cypress is not a general-purpose automation tool - the docs name indexing the web, spidering links, performance testing and scripting third-party sites as somebody else's job. It drives **one browser at a time**, so a two-user collaboration test is out, and a second tab needs the `@cypress/puppeteer` plugin. It launches Chrome-family, Firefox and experimental WebKit - never Safari itself, and no mobile device. Name the misfit that applies to the app in front of you, then say what you would do about it.

go deeper

for a junior

Be ready to say in one sentence what Cypress is for: testing an application your own team owns, written in JavaScript or TypeScript. Then name one thing it cannot do.

for a middle

Explain why each limit exists rather than listing it. One browser at a time, one superdomain per test and JavaScript-only specs all follow from test code running inside the browser.

for a senior

Show that you check fit against the specific app in front of you: its origins, its browser sign-off list, whether your team deploys it. Name the misfit before anyone asks.

for a principal

Own the framing that a tool's boundaries are a design position, not a defect. Be ready to say which boundaries you would accept for a whole organisation and which would rule the tool out.

## Why the fit list and the misfit list are the same list Cypress runs your test code **inside the browser**, in the same event loop as the application under test. Every entry on the fit list and every entry on the misfit list falls out of that single architectural decision, which is why the documented trade-offs read as a coherent set rather than a pile of missing features. The documentation says so directly: Cypress is a *specialized* tool, and its **sweet spot is testing your own application**. A candidate project is a strong fit when all of the following hold. - The team **owns and deploys the application**, so it can add stable test attributes, seed data, and stand up a staging environment on demand. - Each user journey stays inside **one superdomain**, or crosses a boundary rarely enough that `cy.origin()` is an occasional seam rather than a habit. - The engineers who will maintain the suite write **JavaScript or TypeScript**, the only languages a spec can be written in. - The browsers the release must be signed off in are **Chrome-family or Firefox**, both of which Cypress launches directly. - The team actually values the **fast local loop** - `cypress open` next to the running app, with the Command Log showing each command against the live DOM. ## The misfit list | Misfit | Why Cypress is the wrong answer | What it does offer instead | |---|---|---| | Scripting a site you do not own | A documented non-goal, alongside indexing the web and spidering links | Nothing; this is another tool's job | | Two users interacting in one test | Cypress does not control more than one open browser at a time | Stub the second participant, or drive that connection from outside the browser | | A flow that opens a second tab | Same one-browser constraint | `@cypress/puppeteer`, a first-party plugin in public beta, on Chromium-family browsers only | | A Safari or mobile-device sign-off | As of Cypress 16 it launches Chrome-family, Firefox and experimental WebKit | `experimentalWebKitSupport` runs Safari's *engine* through the `playwright-webkit` package - not Safari, and not a device | | Measuring performance | A documented non-goal | Nothing; use a tool built for it | | A team that writes no JavaScript | Test code is evaluated in the browser, so specs are JavaScript or TypeScript | `cy.task()` and `cy.request()` reach Node and your back end | Two rows deserve emphasis because candidates get them backwards. **WebKit is an engine, not Safari.** Turning on `experimentalWebKitSupport` and installing `playwright-webkit` gives you a WebKit build that is useful for catching engine-level layout and API differences from Linux or CI without a Mac, but it is experimental and has published gaps - `cy.origin()` is unsupported there, and so is Test Replay. If a compliance checklist says *Safari*, this does not close it. And **one browser at a time is permanent by design**, not a bug awaiting a fix: the documentation's advice for a collaboration feature is to simulate the other participant rather than to open a second browser. ## The misfits people invent Half of a fit conversation is refusing the objections that are not true. - *"Cypress cannot test cross-origin flows."* It can. Each test is bound to one superdomain, and `cy.origin()` is the command that lets a test drive another one. - *"Cypress cannot touch the database."* Specs cannot import a server-side module, but `cy.task()` runs Node code from `setupNodeEvents`, and `cy.request()` calls your API directly. - *"Cypress cannot see inside an iframe."* Same-origin iframes can be queried natively; what is missing is a *switch into this iframe* command, which is still an open proposal. - *"Cypress is not cross-browser."* It runs Chrome, Chromium, Chrome for Testing, Edge and Firefox. The real gap is Safari and real devices, not cross-browser as a category. ## How to answer this in an interview The question is a judgement question wearing a knowledge question's clothes, so answer it in this order. 1. State the sweet spot in one sentence: an application your team owns, JavaScript or TypeScript, mostly single-origin, Chrome-family or Firefox. 2. Name two or three misfits **unprompted** - the second browser, Safari and devices, third-party sites. An interviewer is listening for whether you know where your tool stops. 3. Say which misfit applies to the application they just described, if any. 4. Say what you would do about it: a first-party workaround, a different tool for that slice, or a different tool entirely. A candidate who can only sell the tool is more expensive to work with than one who can also say where it fails, because the second candidate will not spend a sprint discovering the limit in production code.

  • Is a marketing site your team does not own a fit for Cypress?
    No. Scripting third-party sites is a documented non-goal, and the practical problems follow: you cannot add test attributes, seed state, or pin a deploy, so every selector and every fixture is at the mercy of somebody else's release. Cypress's sweet spot is an application you control.
  • The app is single-origin except that sign-in redirects to an identity provider. Still a fit?
    Yes. A test is bound to one superdomain at a time, and `cy.origin()` exists precisely for the hop. The cost is that the callback is an isolated block with its own rules, so treat it as a seam you cross deliberately rather than a thing you sprinkle through the suite.

saying these in an interview costs you the question

  • Says Cypress cannot test cross-origin flows at all
  • Claims Cypress runs tests in real Safari
  • Treats a second browser tab as a config flag
  • Calls Cypress a general-purpose browser automation tool
  • Judges fit from the demo and never names a misfit
open as a page

What does it mean that Cypress runs your test code inside the browser?

level: juniorimportance: must knowfreq 82%

basics

~20 s

Cypress loads your spec into the browser alongside the application, so both run in the same run loop. Nothing is serialized between a command and an element: the test holds the real window, document and DOM nodes directly.

open as a page

In Cypress, which languages can specs be written in, and why is that permanent?

level: juniorimportance: must knowfreq 72%

basics

~20 s

JavaScript and TypeScript, and nothing else. Cypress evaluates spec code inside the browser alongside the application, so the only language it can ever run is the language of the web; the docs list this as a permanent trade-off.

open as a page

Which of a ported suite's waits vanish into Cypress retry-ability, and which do not?

level: middleimportance: must knowfreq 74%

basics

~20 s

Waits for an element to appear, become visible or change text vanish: cy.get() and .should() retry inside defaultCommandTimeout. Network waits become cy.intercept() plus cy.wait('@alias'). Waits on state outside the browser do not vanish at all.

open as a page

Porting a suite to Cypress, what replaces its XPath locators?

level: juniorimportance: should knowfreq 58%

basics

~10 s

Cypress has no first-class XPath support: cy.get() takes a CSS selector. Text-based XPath becomes cy.contains(), structural XPath becomes a CSS selector, and XPath axes become traversal commands such as .find(), .parent(), .next() and .eq().

open as a page

Which Cypress limitations are permanent by design, and which have workarounds?

level: middleimportance: should knowfreq 58%

basics

~20 s

Cypress documents two lists. Permanent: it is a specialized tool, specs run inside the browser, it drives one browser at a time, and each test is bound to one superdomain. Temporary: no hover command, no native or mobile events, limited iframe switching.

open as a page

What can a Cypress test do to the app under test that an out-of-process runner cannot?

level: middleimportance: should knowfreq 58%

basics

~20 s

It can touch the application's live objects directly. cy.window() yields the app's real window, cy.stub() replaces its own functions, and cy.clock() takes over the page's timers -- no expression is shipped anywhere and no result is serialized back.

open as a page

In a Cypress proof-of-concept, which flows do you spike first to expose a misfit?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Spike the flows most likely to kill the decision, not the happy path: the journey that leaves your superdomain, the one that opens a second tab, the one your browser sign-off names, and the one that needs back-end seeding.

open as a page

In a Cypress migration, where does a Java suite's test-data helper code end up?

level: seniorimportance: should knowfreq 44%

basics

~20 s

Nowhere inside the spec. Browser-evaluated Cypress specs cannot import Java, so that logic is either rewritten in JavaScript, moved into Node behind a cy.task() handler, or exposed as an HTTP endpoint the spec calls with cy.request().

open as a page

A suite ported to Cypress kept its driver-shaped session helper. What does that cost?

level: seniorimportance: should knowfreq 46%

basics

~20 s

In Cypress there is no browser session object to wrap: Cypress launches and disposes of the browser itself. The wrapper's start and quit calls do nothing, anything it caches dies at the spec boundary, and its methods cannot return values.

open as a page

When is a second runner alongside Cypress better than working around a misfit?

level: principalimportance: should knowfreq 36%

basics

~20 s

When the misfit is a bounded, named set of flows with an owner, a second tool can be cheaper than a workaround nobody trusts. When most journeys hit the limit, the answer is not two suites but one different primary tool.

open as a page

How far should Cypress specs be allowed to reach into application internals?

level: principalimportance: should knowfreq 44%

basics

~20 s

Reach in while arranging state, assert on what the user would see. Setup through the application is cheap and safe; assertions on internals pass with the interface broken. Declare each reach-in once so a rename is one edit.

open as a page

How do you decide whether Cypress's JavaScript-only ceiling is acceptable for your team?

level: principalimportance: should knowfreq 38%

basics

~20 s

Decide by who will own the suite, not by what the team writes today. A Cypress spec is permanently JavaScript or TypeScript, so the ceiling is cheap when the maintainers already live there and expensive when it forces a second skill set.

open as a page

How far should a Cypress port raise defaultCommandTimeout to absorb old waits?

level: principalimportance: should knowfreq 36%

basics

~20 s

Barely at all. The 4000 ms default costs nothing on a passing run but is paid in full on every failure, so a global 30-second budget buys slow red builds and hidden regressions. Raise it per command instead.

open as a page

Why does a TypeScript Cypress project add its own cypress/tsconfig.json?

level: middleimportance: nice to knowfreq 28%

basics

~10 s

To scope TypeScript's global type definitions to Cypress. A tsconfig.json inside the cypress folder with types set to cypress and node stops Chai, jQuery and another runner's globals from colliding with Cypress's own declarations.

open as a page

Why does a long Cypress run accumulate browser memory a fresh tab would not?

level: seniorimportance: nice to knowfreq 32%

basics

~20 s

Everything runs in one browser tab: the spec, the runner and the application share a heap and a main thread. No process boundary disposes of anything between tests, so the application's leaked nodes, listeners and state survive from test to test.

open as a page

In Cypress, what replaces a ported suite's soft assertions that collected every failure?

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

Nothing does. Cypress bundles Chai and the test ends at the first failed assertion. Port a batch either into separate it blocks, one per behaviour, or into a single .should() callback whose expect calls are retried together.

open as a page