できない.dev

Jest で「ReferenceError: document is not defined」が解決できない

Jest 27 以降は既定の testEnvironment が node で DOM が無い。
ブラウザ向けテストは testEnvironment を jsdom にし、Jest 28 以降は jest-environment-jsdom を別途インストールする。

公開: 更新:

実行例あり(2026-10-02 に実環境で検証)

要約

Jest 27 以降、既定の testEnvironment は "node" になり、document や window が存在しない。

React コンポーネントや DOM 操作のテストで document を触ると「ReferenceError: document is not defined」になる。

解決は testEnvironment を jsdom に切り替えること。
さらに Jest 28 以降は jsdom 環境が本体から分離されたため、jest-environment-jsdom を別途インストールする必要がある。

実行例

Jest 30.5.2 では、設定なしで document を触るテストが ReferenceError: document is not defined で失敗し、終了コードは 1 だった。jest-environment-jsdom を入れないまま testEnvironment に jsdom だけ指定すると、環境が見つからない Validation Error で止まる。
パッケージを入れると終了コード 0 で通り、設定を外してテストファイル先頭の docblock で指定する方法でも同じテストが通っている。

$ npx jest --version
30.5.2
$ npx jest
FAIL ./dom.test.js
  ✕ renders (2 ms)
 
  ● renders
 
    The error below may be caused by using the wrong test environment, see https://jestjs.io/docs/configuration#testenvironment-string.
    Consider using the "jsdom" test environment.
 
    ReferenceError: document is not defined
 
      1 | test('renders', () => {
    > 2 |   document.body.innerHTML = '<div id="app"></div>';
        |   ^
      3 |   expect(document.getElementById('app')).not.toBeNull();
      4 | });
      5 |
 
      at Object.document (dom.test.js:2:3)
 
Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        0.227 s
Ran all test suites.
$ echo $?
1
$ npx jest
● Validation Error:
 
  Test environment jest-environment-jsdom cannot be found. Make sure the testEnvironment configuration option points to an existing node module.
 
  Configuration Documentation:
  https://jestjs.io/docs/configuration
 
As of Jest 28 "jest-environment-jsdom" is no longer shipped by default, make sure to install it separately.
$ echo $?
1
$ npm i -D jest-environment-jsdom --no-audit --no-fund
npm warn deprecated whatwg-encoding@3.1.1: Use @exodus/bytes instead for a more spec-conformant and faster implementation
 
added 43 packages in 2s
$ npx jest
PASS ./dom.test.js
  ✓ renders (16 ms)
 
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.447 s
Ran all test suites.
$ echo $?
0
$ npx jest
PASS ./dom.test.js
  ✓ renders (6 ms)
 
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.401 s, estimated 1 s
Ran all test suites.
$ echo $?
0

— 2026-10-02 時点の出力

検証環境

検証日
実行環境
node:20 Debian GNU/Linux 12 (bookworm)
バージョン
  • Node.js 20.20.2
  • npm 10.8.2
  • Python 3.11.2
  • Git 2.39.5

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

よくある原因

  1. 既定が node 環境: Jest 27 で既定が jsdom から node へ変わった。
  2. jsdom パッケージ未導入: Jest 28 で jsdom 環境は別パッケージに分離された。
  3. ファイル単位の指定漏れ: 一部のテストだけ DOM が要るのにグローバル設定していない。

解決策

1. グローバルに jsdom を使う

npm i -D jest-environment-jsdom
// jest.config.js
module.exports = {
  testEnvironment: 'jsdom',
};

2. ファイル単位で環境を指定する

テストファイル先頭の docblock で切り替えられる。
DOM が要るテストだけ jsdom にできる。

/**
 * @jest-environment jsdom
 */
test('renders', () => {
  document.body.innerHTML = '<div id="app"></div>';
  expect(document.getElementById('app')).not.toBeNull();
});

指定できる値と挙動は 公式の testEnvironment 設定(新しいタブで開く) を参照する。
DOM 不要なテストは node のままにしておくと起動が速い。

この記事は役立ちましたか?