Skip to content

Jest Test Environment

Jest runs your tests inside a simulated JavaScript environment, and you can choose which kind. This lesson explains the difference between the jsdom (browser-like) and node environments and when to use each.

jsdom vs. node Environments

The jsdom environment simulates a browser using the jsdom library, giving your tests access to document, window, and other DOM APIs even though there's no real browser running. This is required for testing frontend code that touches the DOM, such as React components.

The node environment runs tests in a plain Node.js context with no DOM globals at all. It starts faster and is the correct choice for backend code: Express routes, database logic, and utility functions that never touch the browser.

// jest.config.js
module.exports = {
  testEnvironment: 'jsdom', // for frontend/DOM code
  // testEnvironment: 'node', // for backend/Node.js code
};

As of Jest 28+, you must install jest-environment-jsdom separately, since node became the new default environment.

Setting the Environment Per File

/**
 * @jest-environment jsdom
 */
test('renders in a simulated browser', () => {
  document.body.innerHTML = '<div id="app"></div>';
  expect(document.getElementById('app')).not.toBeNull();
});
  • A docblock comment at the top of a file overrides the project-wide testEnvironment setting.
  • Useful in a mostly-backend project that has a few DOM-touching test files, or vice versa.
  • Install jest-environment-jsdom as a dev dependency to use the jsdom environment.
  • The node environment has no document/window; using them there throws a ReferenceError.

Test Environment Cheat Sheet

Choosing the right Jest test environment.

Environment Provides Use For
node Plain Node.js globals only Backend logic, utilities, Express routes
jsdom Simulated document, window, DOM APIs React/Vue components, DOM manipulation
Per-file override /** @jest-environment jsdom */ Mixed backend/frontend projects
Package needed for jsdom jest-environment-jsdom Required since Jest 28

Why node Became the Default

Earlier Jest versions defaulted to jsdom for every project, even pure backend ones, adding unnecessary overhead and a large dependency. Starting with Jest 28, node is the default, and projects that need DOM simulation must explicitly set testEnvironment: 'jsdom' and install jest-environment-jsdom.

  • Faster test startup for backend-only projects (no DOM simulation cost).
  • Smaller default dependency footprint.
  • Frontend projects (Create React App, Vite + RTL templates) configure jsdom explicitly.

Mixed Frontend/Backend Projects

In a monorepo or full-stack project with both an Express API and a React frontend tested by the same Jest config, set the project-wide default to whichever is more common, and override the exception files with the docblock comment shown above.

// Project default: node (most tests are backend)
// jest.config.js
module.exports = { testEnvironment: 'node' };

// One frontend test file overrides it:
/**
 * @jest-environment jsdom
 */
test('Button renders label text', () => { /* ... */ });

Common Mistakes

  • Getting a document is not defined error because the project uses node but the test needs jsdom.
  • Forgetting to install jest-environment-jsdom after upgrading to Jest 28+.
  • Setting jsdom project-wide for a backend-only project, slowing down every test unnecessarily.
  • Assuming jsdom behaves identically to a real browser for every API (some browser features are not implemented).

Key Takeaways

  • node is the default environment since Jest 28 and suits backend-only code.
  • jsdom simulates a browser DOM and is required for most frontend component tests.
  • A per-file docblock comment can override the project's default environment.
  • jest-environment-jsdom must be installed separately to use the jsdom environment.

Pro Tip

If you see ReferenceError: document is not defined, check your testEnvironment setting before debugging anything else — it's the single most common cause of that error in Jest.