テスト環境でのSyntaxError: Unexpected token '<'を実行環境と統一して解消する
この記事の内容
Next.js 12以降でSWCを利用している場合は、JestでもSWCを利用するようにしましょう。
Next.jsのデフォルトのコンパイラはSWCだが、Jestはbabel-jestを利用するので気をつけましょう。
SyntaxError: Unexpected token '<'
開発中のNext.jsのプロジェクトに、テストを追加したいなと思い、Jestを導入しました。
node_modules以下のデザインを読み込んだコンポーネントだけ、ブラウザ上ではデザインが反映されているが、テストではコンポーネントの描写に失敗する事象に遭遇しました。
原因は既に様々な記事で解説されています。
次の記事がとても理解の助けになりました。
ここで、上記の記事でも紹介されているように .babelrc ファイルを作成することでもテストを通すことができます。
しかし、私の環境では .babelrc ファイルを作成すると今度はブラウザでのレンダリングに失敗してしまいました。
これは上記の記事やnext.jsの公式ページにも記載がある通り .babelrc ファイルが存在する場合はNext.jsがそれを自動的に使用する=babelを利用してコンパイルを行うようになる という仕様のため、コンパイルの動作が変わってしまうからです。
JestでもSWCを利用してコンパイルする
そもそもNext.js側でSWCを利用しているのであれば、Jestでも同じコンパイラを使う方が良いのでは?ということで、JestにもSWCを利用してコンパイルを行うようにしてみます。
JestでSWCを利用する場合は、以下のように設定します。
moduleNameMapperや、transformIgnorePatternsの設定を利用することでnode_modules以下のファイルをコンパイルに含める必要があります。
(各環境に応じ適宜調整してください。)
import type { Config } from "jest";
const config: Config = {
moduleNameMapper: {
~コンパイルしたいnode_modules以下のファイルを設定~
},
transform: {
"^.+\.(t|j)sx?$": [
"@SWC/jest",
{
jsc: {
transform: {
react: {
runtime: "automatic",
},
},
},
},
],
},
extensionsToTreatAsEsm: [".ts", ".tsx"],
setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
testEnvironment: "jsdom",
verbose: true,
};
export default config;
SWCのリファレンスにも SWC/jestの利用パターンが公開されています。
JestのESMモジュールのサポートを有効にする
JestがESMモジュールを読み込めない場合は、テスト実行コマンドにオプションを付与することで対応可能です。
例えば、package.jsonに以下のようにスクリプトを設定します。
scripts :{
test: node --experimental-vm-modules node_modules/jest/bin/jest.js
}
無事、ESMモジュールを含んだコンポーネントのテストが成功するようになりました。
余談 (最初からこうしておけばよかった)
そもそも公式ドキュメントに載っているように、プロジェクト立ち上げの際に -with-jestオプションを使用すれば、jest側の設定がされた状態でプロジェクトが作成されるようです。
また、vitestも公式に載っているため、利用を検討しても良いかもしれないです。
vitestはESMをデフォルトでサポートしているようです。
今回は、私が既に作成したプロジェクトにJestによるテストを追加したことで手間取ってしまった ということのようでしたが、実行環境とテスト環境で同じコンパイラを利用することで、なんとなく気分も良くなりました。
めでたしめでたし。
Discussion