TypeScript: JestでES Modulesは問題なくテストできるのか?
TypeScript + Node.js + ESM + Jestの組み合わせを調査する。
調査すること
- ES Modulesをts-jestで問題なく実行できるか?
実験コード
実験のために書いたコードはGitHubに置いてある
package.jsonの設定
まず、Node.jsにパッケージがESMであると認識してもらうために、package.jsonのtype
を"module"
にする。
{
"name": "typescript-nodejs-esm-jest",
"version": "1.0.0",
"private": true,
"license": "MIT",
+ "type": "module",
...
}
TypeScriptをts-jestで実行するための環境構築
これはESM関係なくTypeScriptのコンパイル手順なしにテストコードを実行するために必要。
pnpm add -D typescript jest @types/jest ts-jest
ts-jestでESMを使えるようにする設定
公式ドキュメント: ESM Support | ts-jest
package.jsonに次の設定を加える
{
...
+ "jest": {
+ "globals": {
+ "ts-jest": {
+ "useESM": true
+ }
+ },
+ "preset": "ts-jest/presets/default-esm"
+ },
...
}
tsconfig.jsonの設定
tsc -init
で生成したtsconfig.jsonはmodule
がcommonjs
になっているはずなので、そこをes2020
に変えてコンパイル後のJavaScriptコードがESMになるようにする:
{
"compilerOptions": {
"target": "es2020",
+ "module": "es2020",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true
}
}
ESMのテスト対象をJestでテストする
ESMのテスト対象として次のファイルを作った:
export default "TypeScript default value";
export const typescriptNamedValue: string = "TypeScript named value";
これをテストするテストコードを作った:
import typescriptDefaultValue, { typescriptNamedValue } from "./typescript";
test("typescript.ts", () => {
expect(typescriptDefaultValue).toMatchInlineSnapshot(
`"TypeScript default value"`
);
expect(typescriptNamedValue).toMatchInlineSnapshot(
`"TypeScript named value"`
);
});
Jestを動かす:
npx jest
実行結果:
TypeScriptのテストコードでJavaScriptのESMをテストできるのか?
TypeScriptのテストコードでTypeScriptのESMはテストできることが分かった。
では、TypeScriptのテストコードでJavaScriptのESMはテストできるのだろうか?
JavaScriptのESMを用意する:
export default "JavaScript default value";
export const javascriptNamedValue = "JavaScript named value";
これをTypeScriptからテストするコードを書く:
import javascriptDefaultValue, { javascriptNamedValue } from "./javascript";
test("javascript.js", () => {
expect(javascriptDefaultValue).toMatchInlineSnapshot(
`"JavaScript default value"`
);
expect(javascriptNamedValue).toMatchInlineSnapshot(
`"JavaScript named value"`
);
});
tsconfig.jsonの設定変更も忘れずに:
{
"compilerOptions": {
"target": "es2020",
"module": "es2020",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true,
+ "allowJs": true
}
}
実行する:
npx jest
結果: 「Jest encountered an unexpected token」というエラーが発生してFAILとなった
TypeScriptのテストコードでJavaScriptのESMをテストする設定
TypeScriptのテストコードでJavascriptのESMをテストするには、ts-jestの設定を変える必要があるようだ。presetをts-jest/presets/js-with-ts-esmにすればいい。
{
...
"jest": {
"globals": {
"ts-jest": {
"useESM": true
}
},
- "preset": "ts-jest/presets/default-esm"
+ "preset": "ts-jest/presets/js-with-ts-esm"
},
...
}
この設定で実行してみる:
npx jest
実行結果: 上手くテストできている