Jest を使用した ECMAScript Modules (ESM) のテスト
はじめに
Jest を使用して ECMAScript Modules (ESM) をテストする際、次のエラーに遭遇するかもしれません。
SyntaxError: Cannot use import statement outside a module
この問題は、対象モジュールが import
キーワードを使用することで発生します。幸いなことに、Jest はこれらのエラーを解決するための実験的サポートを提供しています。
Jest ships with experimental support for ECMAScript Modules (ESM).
この投稿では、Jest を設定し、例として ESM パッケージを用いてこれらのエラーを解決する方法を説明します。
プロジェクトのセットアップ
ESM パッケージの作成
まず、次のコマンドで新しい ESM パッケージを作成します。
mkdir jest-esm && cd jest-esm
npm init -y
必要な開発依存関係をインストールします。
npm i -D typescript jest @types/jest ts-node ts-jest
package.json
は次のようになります。
{
"name": "jest-esm",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@types/jest": "^29.5.12",
"jest": "^29.7.0",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
}
}
package.json
に "type": "module"
を追加します。
@@ -3,6 +3,7 @@
"version": "1.0.0",
"description": "",
"main": "index.js",
+ "type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
TypeScript の設定
以下のコマンドで tsconfig.json
ファイルを生成します。
npx tsc --init
tsconfig.json
を次のように更新します。
@@ -14 +14 @@
- "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
+ "target": "es6", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
@@ -28 +28 @@
- "module": "commonjs", /* Specify what module code is generated. */
+ "module": "es6", /* Specify what module code is generated. */
@@ -30 +30 @@
- // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
+ "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
Jest の設定
以下のコマンドで Jest の設定を行います。
npm init jest@latest
以下のオプションを選択します。
オプション | 値 |
---|---|
Use Jest for the “test” script | Yes |
Use TypeScript for the configuration | Yes |
Test environment | jsdom |
Add coverage reports | No |
Provider for coverage | v8 |
Automatically clear mock calls… | No |
生成された jest.config.ts
を編集し、以下を追加します。
- // preset: undefined,
+ preset: 'ts-jest',
Jest での ESM サポート
Jest での ESM テストを有効にするには、次の手順に従います。
package.json
の修正
package.json
の test
スクリプトを Node の実験的 VM モジュールを有効にするよう更新します。
"scripts": {
- "test": "jest"
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
}
jest.config.ts
の更新
Jest にどのファイルタイプを ESM として扱うべきかを示すために extensionsToTreatAsEsm
を追加します。
+ extensionsToTreatAsEsm: ['.ts'],
ts-jest での ESM サポート
ts-jest
で ESM を設定するには、公式ドキュメントをご参照ください。
設定の変更
.js
拡張子を処理するために moduleNameMapper
を更新します。
- // moduleNameMapper: {},
+ moduleNameMapper: {
+ '^(\\.{1,2}/.*)\\.js$': '$1',
+ },
ESM をサポートするように transform
を設定します。
- // transform: undefined,
+ transform: {
+ '^.+\\.tsx?$': [
+ 'ts-jest',
+ {
+ useESM: true,
+ },
+ ],
+ },
ESM の作成
依存関係のインストール
デモ用に hast-util-from-html
パッケージをインストールします。
npm i hast-util-from-html
hast-util-from-html
モジュールは ECMAScript Module (ESM) であり、エクスポートに export
キーワードを使用しています。これは、node_modules/hast-util-from-html/index.js
にあるファイルを確認することで検証できます。以下に、モジュールのエクスポート構造の一部を示します。
/**
* @typedef {import('hast-util-from-parse5')} DoNotTouchItRegistersData
*
* @typedef {import('./lib/index.js').ErrorCode} ErrorCode
* @typedef {import('./lib/index.js').ErrorSeverity} ErrorSeverity
* @typedef {import('./lib/index.js').OnError} OnError
* @typedef {import('./lib/index.js').Options} Options
*/
export { fromHtml } from './lib/index.js';
モジュールの作成
index.ts
を作成します。
import { fromHtml } from 'hast-util-from-html';
export default function JestEsm(): void {
const root = fromHtml(
'<span><a href="https://github.com">GitHub</a></span>',
{ fragment: true }
);
console.info(root);
}
テストの作成
index.spec.ts
を作成します。
import JestEsm from './index';
test('case1', () => {
JestEsm();
});
ESM のテスト
テストを実行します。
npm run test
エラーが表示された場合:
● 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.
不足しているパッケージをインストールします。
npm i -D jest-environment-jsdom
再度テストを実行します。
npm run test
期待される出力:
PASS ./index.spec.ts
✓ case1 (20 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1 s
Ran all test suites.
まとめ
Jest を使用した ESM のテストは、実験的サポートのため慎重な設定が必要です。この投稿に従うことで、インポートエラーを解決し、ESM パッケージを効果的にテストできます。
詳細については、Jest ESM ドキュメントをご参照ください。
Happy Coding! 🚀