ScreenshotNeo

BlogHow-to

Cypress Test Isolation: Why It Matters and How to Use It

Learn what Cypress resets between end-to-end tests, how to reuse login state with cy.session(), and when disabling isolation is appropriate.

By the ScreenshotNeo team4 October 20267 min read

Cypress end-to-end test isolation starts each test in a clean browser context by default. That helps a test pass both on its own and after other tests. For repeatable authentication, use cy.session() to restore cookies and web storage, then visit the application. Disable isolation only for a narrowly scoped suite whose tests do not need a fresh page, and verify each test passes alone.

What Cypress test isolation resets

With end-to-end testIsolation: true, Cypress resets the browser context before each test. It visits about:blank and clears cookies, localStorage, and sessionStorage across all domains. Cypress also resets test state such as aliases, clock mocks, intercepts, spies, stubs, and viewport changes.

This does not mean every browser storage mechanism is cleared. IndexedDB and other storage mechanisms are not cleared by test isolation. If your application uses them, arrange cleanup or deterministic setup for the relevant tests.

The purpose is independence: one test should not silently supply a page, login, or data state that a later test needs. A hidden dependency can make a test pass in a full run but fail alone, or make its outcome depend on execution order.

Configure isolation for end-to-end tests

Isolation is enabled by default. The project-level setting belongs in your Cypress configuration file. For example, in cypress.config.js:

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  e2e: {
    testIsolation: true,
    baseUrl: 'http://localhost:3000',
  },
})

For an ES module config, use the same option with your project’s module syntax:

import { defineConfig } from 'cypress'

export default defineConfig({
  e2e: {
    testIsolation: true,
    baseUrl: 'http://localhost:3000',
  },
})

Usually, leave the default enabled. If one end-to-end suite has a specific reason to preserve browser context, override it at the describe or context level:

describe('a flow that intentionally shares browser context', {
  testIsolation: false,
}, () => {
  it('performs the first step', () => {
    cy.visit('/flow/start')
    cy.get('[data-cy=continue]').click()
  })

  it('performs the next step', () => {
    // The page and browser context can carry over from the previous test.
    cy.get('[data-cy=confirm]').click()
    cy.contains('Complete').should('be.visible')
  })
})

In this mode Cypress does not alter the browser context before each test, so page state, cookies, and storage may remain available. That makes ordering significant: the second example above is not self-contained unless it creates its own prerequisites. Keep this override limited to the suite that needs it and confirm tests also pass independently before depending on the behavior.

Reuse login state with cy.session()

For most authenticated tests, keep isolation enabled and cache the authentication state instead of carrying a page from one test to another. cy.session() saves and restores cookies, localStorage, and sessionStorage created during setup. A reusable login command keeps this setup in one place.

// cypress/support/commands.js
Cypress.Commands.add('login', (username, password) => {
  cy.session([username], () => {
    cy.visit('/login')
    cy.get('[name=email]').type(username)
    cy.get('[name=password]').type(password, { log: false })
    cy.get('form').submit()
    cy.url().should('include', '/dashboard')
  })
})

Use the command in a test and visit the page under test afterward:

describe('account page', () => {
  beforeEach(() => {
    cy.login(Cypress.env('TEST_USER'), Cypress.env('TEST_PASSWORD'))
    cy.visit('/account')
  })

  it('shows the account heading', () => {
    cy.contains('h1', 'Account').should('be.visible')
  })
})

With isolation enabled, Cypress clears the page during session setup or restoration. Restoring the session does not leave your application page ready for assertions, so call cy.visit() afterward. Session data is cleared before the setup callback regardless of the isolation setting.

Choose a session ID that represents the identity and any meaningful state that changes the resulting login. If permissions or tenant selection alter the session, include those inputs in the ID so distinct states do not reuse the wrong credentials. Keep assertions in setup that establish whether authentication succeeded; a cached but invalid login state otherwise causes confusing downstream failures.

Decide between isolation and shared state

Approach Page and DOM between tests Cookies and web storage Best fit Main risk
Isolation enabled Reset to a clean context Cleared before each test Independent end-to-end tests More setup unless state is reused
Isolation enabled with cy.session() Page is cleared; visit the app after restore Can be restored for repeatable login Authenticated tests that should remain independent Incorrect session IDs or stale authentication
Isolation disabled for a suite Can remain available Can remain available A narrowly scoped flow that intentionally spans tests Order dependence and state leakage

Disabling isolation may improve end-to-end performance because Cypress does less reset work, but the documentation does not quantify the gain. Compare the saved setup time against the additional coupling and debugging cost for your suite; do not treat a faster run as evidence that tests remain reliable.

Component testing behaves differently

Cypress component testing has fixed reset behavior. Before each test, Cypress unmounts the rendered component and clears cookies, localStorage, and sessionStorage. The configurable end-to-end testIsolation option is not exposed for component testing. Build each component test around its own mount and required state.

Migration note for Cypress 12

Cypress 12 enforced a clean browser context for tests. If a suite was written to keep the application page between tests, review it for assumptions that the page persists. The migration guidance describes testIsolation: true and false; treat this as Cypress 12 migration context, not as a claim about every historical configuration detail. Recheck the current Cypress documentation when upgrading.

Common failures and fixes

Symptom Likely cause Fix
A test fails alone but passes after another test It depends on state created by an earlier test. Set up the required data and page state within the test or a shared hook. Keep isolation enabled and use cy.session() for login state.
Assertions run against a blank page after restoring a session Isolation cleared the page; session restoration restores browser storage, not the application page. Call cy.visit() after cy.session() before querying the page.
A test is logged out after a session restore The session setup did not establish valid authentication, or its ID represents the wrong user or permission state. Assert login success in the setup callback and use a session ID that includes the inputs that distinguish the state.
Data seems to survive a test reset IndexedDB or another storage mechanism is outside the storage Cypress test isolation clears. Clear that store through application-specific setup or reset the backing data deterministically.
A suite passes as a whole but fails with .only() With isolation disabled, the test may rely on browser state from an earlier test. Make the test establish its own prerequisites, or keep the shared flow explicitly scoped and avoid treating its tests as independently runnable.
Tests unexpectedly start on a different page Isolation visits about:blank before each end-to-end test. Visit the application in each test or a beforeEach hook after any session restoration.

Practical reliability and performance checklist

  • Keep end-to-end isolation enabled unless a concrete suite requirement justifies an override.
  • Make tests establish their own application and data prerequisites.
  • Use cy.session() to reuse authentication storage, then visit the page for each test.
  • Include identity and meaningful permission or tenant differences in session IDs.
  • Account explicitly for IndexedDB and any other storage that isolation leaves intact.
  • When isolation is disabled, scope it to the suite and run its tests individually with .only() to find hidden dependencies.
  • Measure suite runtime in your own CI before changing isolation for speed; Cypress publishes no quantified performance gain for disabling it.

Or skip the browser setup

If your test or documentation workflow needs a screenshot of a page, ScreenshotNeo provides a one-request screenshot API. Its API documentation covers the available options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie banners are accepted and removed before capture; known consent banners, newsletter popups, and chat widgets can be removed, with each step configurable.
  • Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Responses identify the page verdict and billing status in headers.
  • An MCP server gives AI agents tools to take screenshots, inspect page information, and capture PDFs.
  • The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Every feature is on every plan.

Learn about ScreenshotNeo, or sign up free for 1,000 screenshots a month with no card.

FAQ

Does isolation clear IndexedDB?

No. Plan explicit cleanup or deterministic setup for IndexedDB and other storage that Cypress does not clear.

Do I need to disable isolation to avoid logging in for every test?

No. Use cy.session() to restore authentication state while keeping tests independently runnable.

Can component tests use testIsolation: false?

No. Component testing uses its fixed reset behavior and does not expose the same configurable option.

Does disabling isolation make the suite faster?

It may reduce reset work, but Cypress does not provide a quantified gain. Measure your own suite and account for the reliability cost of shared state.

Sources