Skip to content
Latchkey

Jest "ReferenceError: X is not defined" - jsdom Globals in CI

Code under test referenced a browser or Node global that does not exist in the Jest environment. Either the test environment is node when it should be jsdom, or jsdom simply does not implement that API.

What this error means

A test throws ReferenceError: document is not defined (DOM code under the node environment) or ReferenceError: TextEncoder is not defined (a Web API jsdom does not provide). The same code runs fine in a real browser.

Jest output
ReferenceError: TextEncoder is not defined

   6 | import { encode } from './codec';
   7 |
 > 8 | const enc = new TextEncoder();
     |             ^

Common causes

Wrong testEnvironment for DOM code

Jest’s default environment in recent versions is node, which has no window/document. DOM-touching tests need the jsdom environment.

jsdom does not implement the API

jsdom omits some Web APIs (TextEncoder, crypto.subtle, ResizeObserver, fetch on older setups). Referencing them throws unless you polyfill in setup.

How to fix it

Select the jsdom environment

Set it globally, or per-file with a docblock for just the DOM tests.

jest.config.js
// jest.config.js
module.exports = { testEnvironment: 'jsdom' };

// or per file:
/**
 * @jest-environment jsdom
 */

Polyfill the missing global in setup

Provide the API in a setup file referenced by setupFiles.

jest.setup.js
// jest.setup.js
import { TextEncoder, TextDecoder } from 'util';
global.TextEncoder = TextEncoder;
global.TextDecoder = TextDecoder;

How to prevent it

  • Pick jsdom for component/DOM suites and node for pure-logic suites.
  • Keep polyfills in a shared setupFiles module.
  • Pin jest-environment-jsdom, which is a separate package since Jest 28.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →