skip to content

Which edits make a `cypress open` session rerun your Cypress spec?

level: middleimportance: should knowfreq 40%

answer

  1. Follow the spec's import graph
  2. Something else already watches the app
  3. Fixtures are not part of it
  4. One config key turns it off
  5. The batch mode has nothing to watch

basics

~20 s

Only edits inside the spec graph: the active spec file, the support file, and any module they import or require. Application source, node_modules and cypress/fixtures are deliberately not watched, and the whole watcher is governed by watchForFileChanges.

solid answer

~40 s

Cypress watches the project root for files matching `specPattern`. When one changes, it recompiles the **active spec, the support file, and everything they `import` or `require`** through the preprocessor, then reloads the browser and reruns the spec. Anything outside that graph is ignored — most importantly your application code, which is left out on purpose because a modern dev server's hot module replacement already watches it and Cypress does not duplicate that work. `node_modules` and `cypress/fixtures/` are not watched either. The `watchForFileChanges` configuration key controls the behaviour and defaults to `true` in open mode; set it to `false` when constant reruns get in your way. It has no effect during `cypress run`, where nothing is watched at all.

go deeper

for a junior

Know that saving a spec in open mode reruns it, and that editing the app you are testing does not. That single distinction explains most confusion about the feedback loop.

for a middle

Explain the scope precisely — spec, support file, and their imports, recompiled through the preprocessor — and name the config key that governs it plus its mode-dependent default.

for a senior

Be ready to diagnose a session that stopped rerunning: spec graph, specPattern membership, config overrides in the npm script, and whether the developer is even in open mode.

for a principal

Own how fast the local loop should be across a large repo, and where the boundary sits between the app's own reload machinery and the test runner's.

## What the watcher actually watches During `cypress open` Cypress watches your entire project root for spec files. Any file matching `specPattern`, wherever it lives in the project, is detected. When something changes, Cypress recompiles the **active spec file, the support file, and anything they `import` or `require`** through the preprocessor, and the browser reloads and reruns the spec. The practical consequence in a multi-package storefront monorepo is that the watcher follows the spec's own import graph, not the repo layout: - Saving `packages/checkout/cypress/e2e/place-order.cy.js` reruns it. - Saving a page-object or helper module that the spec imports reruns it, even if that module sits in a different workspace package. - Saving the support file reruns it, because the support file is loaded before every spec. ## What it deliberately does not watch Files outside the spec graph are ignored. That includes, but is not limited to: - **Your application code.** Editing the storefront's own components or routes does not rerun the spec. This is intentional: a modern JS stack already has hot module replacement watching application source, and Cypress does not duplicate that work. - **`node_modules`.** - **`cypress/fixtures/`.** Editing a fixture JSON file does not trigger a rerun; press the rerun control yourself. ## `watchForFileChanges` The behaviour is governed by the `watchForFileChanges` configuration key, which defaults to `true` during `cypress open`. Set it to `false` in `cypress.config.js` (or pass `--config watchForFileChanges=false`) when the reruns are getting in your way — for example while you edit a spec in several passes and only want to run it when you are ready. The key **has no effect during `cypress run`**: nothing is watched in a batch run at all, so setting it there changes nothing. Its default reflects that — `true` in open mode, `false` in run mode. The component responsible for the watching and rebundling is the default preprocessor, `@cypress/webpack-batteries-included-preprocessor`, which Cypress registers automatically when you have not supplied your own `file:preprocessor` handler. ## Diagnosing "my spec did not rerun" 1. **Did you edit something in the spec graph?** If you changed application source, that is expected — your dev server reloads the app, but the spec does not restart. 2. **Is the file inside `specPattern`?** A spec living outside the configured pattern is not part of the watched set and will not even appear in the spec list. 3. **Is `watchForFileChanges` still `true`?** It may be `false` in the project config, or set through `--config` in the npm script you actually ran. 4. **Are you in open mode at all?** In `cypress run` there is no watcher, so nothing about saving a file matters. ## Membership comes before watching A file has to match `specPattern` before any of this applies. Cypress watches the project root *for files matching that pattern*, wherever in the repo they live, so in a workspace layout the watcher does follow specs across packages — but a spec sitting outside the configured pattern is not merely unwatched, it never appears in the spec list to be run in the first place. When a teammate says "my new spec does nothing when I save it", check membership before you check the watcher: | Symptom | Likely cause | |---|---| | Spec is missing from the spec list | it does not match `specPattern` | | Spec runs, but never reruns on save | `watchForFileChanges` is `false` | | Only some edits rerun it | the others are outside the spec's import graph | | Nothing reruns, ever | you are in `cypress run`, not `cypress open` | ## Why this only exists on one side The two modes have different jobs. Open mode is a session a developer keeps alive; rerunning on save is the whole feedback loop, and the cost of rebundling is worth paying dozens of times an hour. A batch run is a job with a defined end: it enumerates the specs once, executes them, and exits. Watching would have nothing to do, because there will be no second pass. That asymmetry is worth stating out loud in an interview, because it explains a whole family of non-bugs. Nothing you set to make the local loop pleasant — the watcher, the retained snapshots, the visible browser — carries over to the batch run, and nothing you set to make the batch run cheap has any bearing on how fast your local loop feels.

  • Why does Cypress deliberately not watch the application's own source files?
    Because something else already does. A modern JS stack runs a dev server with hot module replacement that reloads the app on change, so a Cypress watcher over the same files would duplicate that work and rerun specs for edits that have nothing to do with the test. Cypress restricts itself to the spec graph.
  • When would you set `watchForFileChanges: false` in a Cypress project?
    In open mode, when the automatic rerun is a nuisance rather than a help — editing a long spec in several passes, or working on a suite whose rebundle is slow. It changes nothing under `cypress run`, so setting it for CI's benefit is pointless.

saying these in an interview costs you the question

  • Says editing application code reruns the spec automatically
  • Thinks fixtures are watched like spec files
  • Sets watchForFileChanges expecting it to affect cypress run
  • Believes only the spec file itself is watched, never its imports
  • Assumes the watcher restarts the whole suite on each save