🐥

Next.jsとFirebaseとTypsScriptで構成されたリポジトリにJestを導入した記録

2024/10/17に公開

概要

Next.js(App Router)、Firebase、TypsScriptという組み合わせの環境でJestを導入した内容を忘れないようにメモしました。
Next.js公式の手順をベースにenvファイルの値を読み込めない事象に対応しています。

開発環境など

  • Next.js(App Router) v14.2.7
  • TypeScript
  • Firebase Auth
  • Cloud Firestore
  • Node.js v20.15.0

追加したnpmパッケージ

  • @testing-library/jest-dom ^6.5.0
  • @testing-library/react ^16.0.1
  • @types/jest ^29.5.13
  • jest ^29.7.0
  • jest-environment-jsdom ^29.7.0
  • ts-jest ^29.2.5
  • ts-node ^10.9.2
npm install --save-dev @testing-library/jest-dom @testing-library/react @types/jest jest jest-environment-jsdom ts-jest ts-node

追加した設定ファイルなど

  • jest.config.ts
  • jest.setup.ts
  • .env.test.local
  • setupEnv.ts(src/app/__tests__/に配置)

jest.config.ts

下記コマンドを実行すると対話インターフェースが起動します。質問に答えるとjest.config.tsを作成してれます。(参照:https://nextjs.org/docs/app/building-your-application/testing/jest)

npm init jest@latest
//jest.config.ts
import type { Config } from 'jest';
import nextJest from 'next/jest.js';

const createJestConfig = nextJest({
  dir: './',
});

const config: Config = {

  // test用の環境変数を設定する
  globalSetup: '<rootDir>/src/app/__tests__/setupEnv.ts',

  // テストを除外するファイルを指定する
  testPathIgnorePatterns: [
    '/src/app/__tests__/setupEnv.ts'
  ],

  // 各テストの前にモックの呼び出し、インスタンス、コンテキスト、および結果を自動的にクリアする
  clearMocks: true,

  // テストの実行中にカバレッジ情報を収集するかどうかを示す
  collectCoverage: true,

  // Jestがカバレッジファイルを出力するディレクトリ
  coverageDirectory: "coverage",

  // カバレッジの計測に使用するプロバイダーを指定
  coverageProvider: "v8",

  // 正規表現からモジュール名またはモジュール名の配列へのマップ。単一のモジュールでリソースをスタブアウトすることを可能にします。
  moduleNameMapper: {
    '@/(.*)$': '<rootDir>/src/$1',
  },

  // テストに使用されるテスト環境
  testEnvironment: "jsdom",

  // 各テストを実行する前に、さらに設定オプションを追加する
  setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],

};

export default createJestConfig(config)

jest.setup.ts

以下を記述。

import '@testing-library/jest-dom'

jest.config.js の setupFilesAfterEnv にこのファイルのパスを指定すると
テストファイルごとにセットアップファイルのコードが1回実行されるようになります。

.env.test.local

私の開発環境ではenvファイルに設定したFirebaseの設定値が読み込めず、テストを実行するとエラーとなりました。

// next.config.mjs
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: process.env.FIREBASE_IMG_HOSTNAME, //エラー発生
        port: '',
      },
    ],
  },
};

対応するための事前準備として.env.test.localを作成し、下記を記載しました。

# .env.test.local
FIREBASE_IMG_HOSTNAME=※※※※※(←プロジェクト固有の値)

この値をsetupEnv.tsで読み込むようにする、という仕掛けのようです。

setupEnv.ts

setupEnv.tsを設置し、以下を記述。

// setupEnv.ts
import { loadEnvConfig } from '@next/env'

const setupTestEnvironment = async (): Promise<void> => {
  const projectDir = process.cwd()
  loadEnvConfig(projectDir)
}

export default setupTestEnvironment

事前にjest.config.jsに記述しておいた
globalSetup: '<rootDir>/src/app/__tests__/setupEnv.ts',により、
setupEnv.tsが機能してエラーが解消されました。

参考記事

余談

JestとVtestどちらにするか迷いましたが、初心者なのでまずは伝統的なJest覚えてみようかなと。急がば回れ。

Discussion