かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Jest import 文が SyntaxError: Unexpected identifier になるにハマる

create-react-app を使わずに自分で独自に作成していたプロジェクトにテストとして Jest を導入したけど、テストコマンドを走らせると SyntaxError: Unexpected identifier が出てハマってしまったのでメモ。

構成
|- /tests
|     |- setup.enzyme.js
|     |- App.test.js
|- /src
|- jest.config.js

jest.config.js

module.exports = {
  moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node'],
  roots: ['<rootDir>/tests/'],
  setupFilesAfterEnv: ['<rootDir>/tests/setup.enzyme.js'],
  transformIgnorePatterns: [
    "/node_modules/.+.(js|jsx|ts|tsx)$",
  ],
}

この状態でテストを実行すると次のようなエラーが表示されました。

$ yarn jest 
    /Users/.../MyAPP/tests/setup.enzyme.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import Enzyme from 'enzyme';
                                                                                                    ^^^^^^
    SyntaxError: Unexpected identifier

import Enzyme from 'enzyme; でエラーが出ているもよう。なんもわからん…

Jest はデフォルトでは import が使えない?

JavaScript のモジュール周りは CommonJS (CJS) と ESModule (ESM) があり、node.js 上ではまだ ESM の import が上手く使えなず、それが原因で Jest でもデフォルトの設定では import 文が上手く扱えないっぽい。 (雰囲気理解なので間違えていたらスミマセン。)

babel を使って ESM の import を CJS に変換できれば良さそう。
検索すると "transform-es2015-modules-commonjs@babel/plugin-transform-modules-commonjs プラグインを使う方法も出てきたのですが、一旦は Jest のドキュメントにある babel の導入を参考にすることにしました。

babel パッケージのインストールと設定ファイルの作成

パッケージをインストールします。 babel-jest を使って変換するのですが、babel-jest は Jest インストール時に付いてきていて babel の設定があれば自動的に babel-jest で変換してくれるようなので、corepreset-env だけインストールすれば良さそう。

$ yarn add -D @babel/core @babel/preset-env

次に babel の 設定ファイルを作成します。

$ touch babel.config.js

babel.config.js

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          node: 'current'
        },
      }
    ],
  ],
};

これでテストを走らせます

$ yarn test
PASS  tests/App.test.js
...
✨  Done in 4.46s.

問題なく test ができるようになりました! ₍ᐢ •̥ ̫ •̥ ᐢ₎‪ やったねグーン✨

JSX がエラーになる

テストの中身を書いていくと、今度は JSX でエラーが表示されてしまいました。

$ yarn test
    Jest encountered an unexpected token
    ...
    SyntaxError: /Users/.../MyApp/tests/App.test.js: Unexpected token (12:14)
    ...
    > 12 |       return (<div>{value}</div>);

React のテストを行うには @babel/preset-react が必要

Create React Appを使わないセットアップ
既存のアプリケーションがある場合は、いくつかのパッケージをインストールしてうまく機能するようにする必要があります。 babel-jest パッケージと react の babel preset をテスト環境内のコードを変換するのに利用しています。
cf Create React Appを使わないセットアップ Testing React Apps | JEST

JSX だけなら @babel/preset-react を snapshot テストも行うなら react-test-renderer をインストールします。

$ yarn add -D @babel/preset-react

babel.config.js に設定を追加します。

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      '@babel/preset-react', // <- 追加
      {
        targets: {
          node: 'current'
        },
      }
    ],
  ],
};

これで JSX のあるテストも通るようになりました!

$ yarn test
PASS  tests/App.test.js
...
✨  Done in 4.46s.

✌️₍ ᐢ. ̫ .ᐢ ₎✌️ イェイイェイイェイ!!!

所感

Jest の導入で今までハマったことがなかったので、あれ?こんなに大変だったかな???ってなりました。
英語のドキュメントがサクッと読める英語力を付けることが問題解決のスピードアップに繋がると痛感しました。学んでいこう!
そして、CJS と ESM まわり理解が足りてないので、実験してちゃんと理解しておこうと、やることタスクをそっと心に積んだのでした。。。


[参考]

推し武道マジいいからみんな見て…