skip to content

With Cypress testIsolation on, what is reset between tests and what survives?

level: middleimportance: must knowfreq 64%

answer

  1. Three storage mechanisms, not all of them
  2. The page itself goes somewhere blank
  3. One popular offline store is untouched
  4. Component testing cannot configure this
  5. Clearing it yourself needs a window first

basics

~20 s

Cypress clears the page by visiting about:blank and clears cookies, localStorage and sessionStorage in all domains. Everything else, IndexedDB above all, survives untouched, so a test that needs an empty IndexedDB must clear it itself.

solid answer

~50 s

As of Cypress 16, `testIsolation` defaults to `true` for end-to-end tests. Before each test Cypress navigates the app frame to `about:blank` and clears cookies, `localStorage` and `sessionStorage` across all domains, so every test has to `cy.visit()` again. Separately, and regardless of the setting, it resets its own per-test state: aliases, `cy.clock()`, `cy.intercept()` routes, spies, stubs and viewport changes. What it does **not** clear is every other browser storage mechanism, and the one that matters in practice is **IndexedDB** — an offline catalogue cache or client-side database is still fully populated in the next test. Clear it yourself in a `beforeEach`, after `cy.visit()`, via `cy.window()` and the browser's `indexedDB.deleteDatabase()`. The reset is also a browser-side operation only: records the suite created on the server are untouched by it, and nothing is cleared after the final test, so the app is left where the run stopped.

code

javascript · 15 lines
javascript
beforeEach(() => {
  cy.visit('/catalogue')

  cy.window().then((win) => {
    return new Cypress.Promise((resolve) => {
      const request = win.indexedDB.deleteDatabase('offline-catalogue')

      // resolve on every outcome so a missing or blocked
      // database cannot hang the test
      request.onsuccess = resolve
      request.onerror = resolve
      request.onblocked = resolve
    })
  })
})

go deeper

for a junior

Know that Cypress starts each test on a blank page and with cookies and web storage cleared, and that this is why nearly every spec opens with a visit.

for a middle

Be able to list the four things the browser-context reset does and separate them from the per-test slate Cypress applies regardless, then name IndexedDB as the storage that is left alone.

for a senior

Show that you have hit the gap in practice: a spec that passes alone and fails in order because an offline cache persisted, and the beforeEach that deletes the database after a visit so a window exists.

for a principal

Own the standard: which storage the application is allowed to depend on in tests, who writes the reset for the ones the runner will not clear, and how that decision is documented so a new spec inherits it.

## What `testIsolation` is `testIsolation` is a Cypress configuration option, **`true` by default**, that decides whether the runner puts the browser back into a clean context before each test. As of Cypress 16 it applies to end-to-end testing only: component testing always resets and rejects the option outright. It is the switch that turns "each test starts from nothing" from a discipline you have to enforce into something the runner does for you. It is worth separating two resets that people blur together. - **The always-on slate.** Regardless of `testIsolation`, Cypress restores and clears its own per-test state before every test: aliases, `cy.clock()` mocks, `cy.intercept()` routes, `cy.spy()` and `cy.stub()` doubles, and any `cy.viewport()` change. - **The browser context**, which is what `testIsolation` governs. ## What the browser-context reset clears With `testIsolation: true`, before each test Cypress: - clears the DOM by navigating the application frame to **`about:blank`**; - clears **cookies** in all domains; - clears **`localStorage`** in all domains; - clears **`sessionStorage`** in all domains. The practical consequence is that each test must call `cy.visit()` again and re-establish whatever the catalogue page needs. A borrow flow cannot be spread over three `it()` blocks that each pick up where the last one stopped, because the page is gone by the time the second one starts. ## What survives — and the one to remember Cookies, `localStorage` and `sessionStorage` are the **only** storage mechanisms Cypress clears. Everything else in the browser persists for the life of the browser, whether isolation is on or off, and in both testing types. The one that bites is **IndexedDB**. A catalogue app that keeps an offline copy of search results, a borrowing basket, or a client-side database still has all of it in the next test. Libraries that use IndexedDB under the hood — offline caches, sync engines, client-side stores — leak silently, because nothing in the Command Log says so. The same limit applies to a cached session: a session saves and restores cookies and web storage only, so IndexedDB is neither captured with one nor cleared when one is restored. | | `testIsolation: true` (default) | `testIsolation: false` | |---|---|---| | Page | navigated to `about:blank` | left exactly as the last test left it | | Cookies, `localStorage`, `sessionStorage` | cleared in all domains | not touched | | IndexedDB and other storage | **not cleared** | **not cleared** | | Aliases, clock, intercepts, spies, stubs, viewport | reset | reset | | Where you may set it | root config or a `describe` block | a `describe` block | ## Clearing what Cypress will not If a test depends on IndexedDB being empty, empty it yourself, in a `beforeEach` and after a `cy.visit()` so a `window` exists: 1. Get the application window with `cy.window()`. 2. Call the browser's `indexedDB.deleteDatabase()` for each database your app uses. 3. Wrap the request in a `Cypress.Promise` and resolve on `onsuccess`, `onerror` **and** `onblocked`, so a missing or blocked database cannot hang the test. If you do not know the names ahead of time you can enumerate them with the browser's `indexedDB.databases()` in Chromium-based browsers and WebKit; Firefox does not implement it, so name each database explicitly if you run there. ## What isolation costs, and why it is still the default Re-visiting and re-seeding per test is real time, and that cost is the whole argument people make for switching isolation off. The counter-argument is that the alternative is a suite whose tests only pass in one order — reorder them, run one alone, or let a retry re-enter the block, and the result changes. Cypress ships the reset on by default precisely so that a green test means the same thing whether it ran first or fourteenth. The cheap ways to pay less without giving up the reset are: - seed catalogue data programmatically in a `before` or `beforeEach` — an API call or a `cy.task()` is far cheaper than driving the UI to build state; - re-set a known cookie you control with `cy.setCookie()` in `beforeEach` rather than clicking through a banner in every test; - restore an expensive authenticated context from a cached session instead of repeating a sign-in. Two details are worth carrying into an interview because they are where the model breaks down in practice. First, the reset is **per test, not per spec**: the last test of a run is left standing so you can keep using the catalogue app where it stopped, which is why open mode does not blank the page after the final test. Second, the reset is a **browser** operation and knows nothing about your server — records the suite created through the API are exactly where the previous test left them, and no `testIsolation` setting will undo them.

  • Why must a Cypress test call cy.visit() again even though the previous test already loaded the page?
    Because the browser-context reset navigates the application frame to `about:blank` before each test. The previous page, its DOM and its in-memory JavaScript state are gone, so the test starts against a blank frame. That is deliberate: it removes the possibility of a test passing only because an earlier one left the right screen open.
  • Does Cypress reset intercepts and stubs even when testIsolation is disabled?
    Yes. Restoring aliases, clock mocks, intercepts, spies, stubs and viewport changes is a separate, always-on slate that Cypress applies before every test. `testIsolation` governs only the browser context — the page, cookies and web storage. Turning it off does not give you a route stub that carries into the next test.

Test isolation is the librarian who resets the reading room between visitors: the desk is cleared and the day pass is taken back, but whatever a reader left in a locker is still there for whoever comes next.

saying these in an interview costs you the question

  • Says testIsolation clears every kind of browser storage
  • Thinks IndexedDB is wiped between tests
  • Assumes the page survives when isolation is enabled
  • Believes disabling it also keeps stubs and intercepts