📗

Next.jsでjestを使うときにつまったので対応内容の備忘

2024/11/21に公開

経緯

Next.JSでFullcalendarを使用していて、jestで単体テストを書いている中で
「SyntaxError: Unexpected token 'export'」というエラーが発生したのでその解消時の内容を備忘として残しておく。

事前準備

その前にjestの設定としてやったことも残しておく。
参考
https://nextjs.org/docs/app/building-your-application/testing/jest

インストールしたモジュール

jest
jest-environment-jsdom
@testing-library/react
@testing-library/jest-dom
@testing-library/dom

ts-jest
ts-node
@types/jest
@babel/core
@babel/plugin-transform-modules-commonjs
@babel/preset-env
@babel/preset-typescript
babel-jest

エラーの原因

今回使用しているモジュール(FullCalendar)がESModuleというのが原因とのこと。
エラーの原因をググると結構でてくるのでよくある事象っぽい
fullcakendarはESmと記載があった
https://fullcalendar.io/docs/initialize-browser-esm

※ここで出てきた疑問
Next.JSってmoduleもesnextだしESMじゃないの?。。
なんでESModuleで怒られるんだろう。。。

よくよく考えたら実行してるのはJestなのでそっちの確認が必要と気づいた。
調べて見ると、JestはCommonJS形式で動くのでESMを使用する場合は別途設定追加が必要とのこと

対処

jest.config.tsに追加したもの
せっかくの機会なのでどういったものなのかとかも調べておく

  preset: 'ts-jest/presets/default-esm',
  globals: {
    'ts-jest': {
      tsconfig: './tsconfig.test.json',
      useESM: true,
    },
  },
  transform: {
    '^.+\\.(js|jsx)$': 'babel-jest',
    '^.+\\.(ts|tsx)$': 'ts-jest',
  },
  transformIgnorePatterns: ['/node_modules/(?!@fullcalendar/*).+\\.[t|j]sx?$'],
  moduleNameMapper: {
    '^preact(/(.*)|$)': 'preact$1',
  },

priset

jestの設定のベースとなる項目でtypescriptでテストコード書く場合は「ts-jest」を設定する必要がある

globals

テスト環境で設定するグローバル変数の設定
ts-jestの設定に「tsconfig.test.json」を読み込ませるように記載
useESMをtrueにすることでESModuleを読み込めるように設定(デフォルトはfalseらしい)

transform

変換処理をかける対象のファイルを指定
ts,tsxにts-jestのオプションを指定しておく

transformIgnorePatterns

transformの対象にしないモジュールを指定する

moduleNameMapper

指定したモジュールをスタブ化する
今回は「preact」がエラーの原因になっていたので指定した

Babelの設定について

参考
https://jestjs.io/ja/docs/getting-started
https://babeljs.io/docs/babel-plugin-transform-modules-commonjs

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          node: 'current',
        },
      },
    ],
    '@babel/preset-typescript',
  ],
  plugins: ['@babel/plugin-transform-modules-commonjs'],
};

基本的に公式ドキュメントの設定どおりで下位互換をかけるバージョンを指定してtypescriptも使用しているのでその設定を追加する。
追加でECMAScriptのモジュールをCommonJSに変換してくれるプラグインを設定。

初期の設定を自分でやることは今までなかったのと、数年触れてなかったのもあったので改めてやると疑問点も出てきていい勉強になった。

Discussion