【Next.js】テスト環境構築【Jest】【React Testing Library】

## パッケージのインストール
以下のコマンドを実行して必要なパッケージをインストールします。
```:ターミナル
$ npm install --save-dev jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom
```

## Jestの設定をする
`jest.config.js`を作成してJestの設定を行います。
```:jest.config.js 
const nextJest = require('next/jest')

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

const customJestConfig = {
  testEnvironment: 'jest-environment-jsdom',
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
  }
}

module.exports = createJestConfig(customJestConfig)
```

上記のように記述するとJestの設定は以下のようになります。

```
$ jest --showConfig
{
  "configs": [
    {
      "automock": false,
      "cache": true,
      "cacheDirectory": "/tmp/jest_rs",
      "clearMocks": false,
      "coveragePathIgnorePatterns": [
        "/node_modules/"
      ],
      "cwd": "/myapp/nextjs-testing",
      "detectLeaks": false,
      "detectOpenHandles": false,
      "errorOnDeprecated": false,
      "extensionsToTreatAsEsm": [],
      "fakeTimers": {
        "enableGlobally": false
      },
      "forceCoverageMatch": [],
      "globals": {},
      "haste": {
        "computeSha1": false,
        "enableSymlinks": false,
        "forceNodeFilesystemAPI": true,
        "throwOnModuleCollision": false
      },
      "id": "d07602bgs34e7dhs3aaeage69fags5fb",
      "injectGlobals": true,
      "moduleDirectories": [
        "node_modules"
      ],
      "moduleFileExtensions": [
        "js",
        "mjs",
        "cjs",
        "jsx",
        "ts",
        "tsx",
        "json",
        "node"
      ],
      "moduleNameMapper": [
        [
          "^@/(.*)$",
          "/myapp/nextjs-testing/src/$1"
        ],
        [
          "^.+\\.module\\.(css|sass|scss)$",
          "/myapp/nextjs-testing/.yarn/__virtual__/next-virtual-5ed7231e68/0/cache/next-npm-12.1.6-c0598c390e-670d544fd4.zip/node_modules/next/dist/build/jest/object-proxy.js"
        ],
        [
          "^.+\\.(css|sass|scss)$",
          "/myapp/nextjs-testing/.yarn/__virtual__/next-virtual-5ed7231e68/0/cache/next-npm-12.1.6-c0598c390e-670d544fd4.zip/node_modules/next/dist/build/jest/__mocks__/styleMock.js"
        ],
        [
          "^.+\\.(png|jpg|jpeg|gif|webp|avif|ico|bmp|svg)$",
          "/myapp/nextjs-testing/.yarn/__virtual__/next-virtual-5ed7231e68/0/cache/next-npm-12.1.6-c0598c390e-670d544fd4.zip/node_modules/next/dist/build/jest/__mocks__/fileMock.js"
        ]
      ],
      "modulePathIgnorePatterns": [],
      "prettierPath": "prettier",
      "resetMocks": false,
      "resetModules": false,
      "restoreMocks": false,
      "rootDir": "/myapp/nextjs-testing",
      "roots": [
        "/myapp/nextjs-testing"
      ],
      "runner": "/myapp/nextjs-testing/.yarn/cache/jest-runner-npm-28.1.1-709cf8e944-f265915434.zip/node_modules/jest-runner/build/index.js",
      "sandboxInjectedGlobals": [],
      "setupFiles": [],
      "setupFilesAfterEnv": [],
      "skipFilter": false,
      "slowTestThreshold": 5,
      "snapshotSerializers": [],
      "testEnvironment": "/myapp/nextjs-testing/.yarn/cache/jest-environment-jsdom-npm-28.1.1-dd6f755168-86db0304e1.zip/node_modules/jest-environment-jsdom/build/index.js",
      "testEnvironmentOptions": {},
      "testLocationInResults": false,
      "testMatch": [
        "**/__tests__/**/*.[jt]s?(x)",
        "**/?(*.)+(spec|test).[tj]s?(x)"
      ],
      "testPathIgnorePatterns": [
        "/node_modules/",
        "/.next/"
      ],
      "testRegex": [],
      "testRunner": "/myapp/nextjs-testing/.yarn/cache/jest-circus-npm-28.1.1-f9c8be5220-8fcca59012.zip/node_modules/jest-circus/runner.js",
      "transform": [
        [
          "^.+\\.(js|jsx|ts|tsx|mjs)$",
          "/myapp/nextjs-testing/.yarn/__virtual__/next-virtual-5ed7231e68/0/cache/next-npm-12.1.6-c0598c390e-670d544fd4.zip/node_modules/next/dist/build/swc/jest-transformer.js",
          {
            "nextConfig": {
              "env": {},
              "webpack": null,
              "webpackDevMiddleware": null,
              "eslint": {
                "ignoreDuringBuilds": false
              },
              "typescript": {
                "ignoreBuildErrors": false,
                "tsconfigPath": "tsconfig.json"
              },
              "distDir": ".next",
              "cleanDistDir": true,
              "assetPrefix": "",
              "configOrigin": "next.config.js",
              "useFileSystemPublicRoutes": true,
              "generateEtags": true,
              "pageExtensions": [
                "tsx",
                "ts",
                "jsx",
                "js"
              ],
              "target": "server",
              "poweredByHeader": true,
              "compress": true,
              "analyticsId": "",
              "images": {
                "deviceSizes": [
                  640,
                  750,
                  828,
                  1080,
                  1200,
                  1920,
                  2048,
                  3840
                ],
                "imageSizes": [
                  16,
                  32,
                  48,
                  64,
                  96,
                  128,
                  256,
                  384
                ],
                "path": "/_next/image",
                "loader": "default",
                "domains": [],
                "disableStaticImages": false,
                "minimumCacheTTL": 60,
                "formats": [
                  "image/webp"
                ],
                "dangerouslyAllowSVG": false,
                "contentSecurityPolicy": "script-src 'none'; frame-src 'none'; sandbox;"
              },
              "devIndicators": {
                "buildActivity": true,
                "buildActivityPosition": "bottom-right"
              },
              "onDemandEntries": {
                "maxInactiveAge": 15000,
                "pagesBufferLength": 2
              },
              "amp": {
                "canonicalBase": ""
              },
              "basePath": "",
              "sassOptions": {},
              "trailingSlash": false,
              "i18n": null,
              "productionBrowserSourceMaps": false,
              "optimizeFonts": true,
              "excludeDefaultMomentLocales": true,
              "serverRuntimeConfig": {},
              "publicRuntimeConfig": {},
              "reactStrictMode": true,
              "httpAgentOptions": {
                "keepAlive": true
              },
              "outputFileTracing": true,
              "staticPageGenerationTimeout": 60,
              "swcMinify": false,
              "experimental": {
                "newNextLinkBehavior": false,
                "cpus": 3,
                "sharedPool": true,
                "plugins": false,
                "profiling": false,
                "isrFlushToDisk": true,
                "workerThreads": false,
                "pageEnv": false,
                "optimizeCss": false,
                "nextScriptWorkers": false,
                "scrollRestoration": false,
                "externalDir": false,
                "reactRoot": false,
                "disableOptimizedLoading": false,
                "gzipSize": true,
                "swcFileReading": true,
                "craCompat": false,
                "esmExternals": true,
                "rootDir": false,
                "isrMemoryCacheSize": 52428800,
                "serverComponents": false,
                "fullySpecified": false,
                "outputFileTracingRoot": "",
                "outputStandalone": false,
                "images": {
                  "layoutRaw": false
                }
              },
              "configFile": "/myapp/nextjs-testing/next.config.js",
              "configFileName": "next.config.js"
            },
            "jsConfig": {
              "compilerOptions": {
                "target": 8,
                "lib": [
                  "lib.dom.d.ts",
                  "lib.dom.iterable.d.ts",
                  "lib.esnext.d.ts"
                ],
                "allowJs": true,
                "skipLibCheck": true,
                "strict": true,
                "forceConsistentCasingInFileNames": true,
                "noEmit": true,
                "esModuleInterop": true,
                "module": 99,
                "moduleResolution": 2,
                "resolveJsonModule": true,
                "isolatedModules": true,
                "jsx": 1,
                "incremental": true,
                "baseUrl": "/myapp/nextjs-testing",
                "paths": {
                  "@/*": [
                    "./src/*"
                  ]
                },
                "pathsBasePath": "/myapp/nextjs-testing"
              }
            },
            "resolvedBaseUrl": "/myapp/nextjs-testing",
            "isEsmProject": false,
            "pagesDir": "/myapp/nextjs-testing/src/pages"
          }
        ]
      ],
      "transformIgnorePatterns": [
        "/node_modules/",
        "^.+\\.module\\.(css|sass|scss)$"
      ],
      "watchPathIgnorePatterns": [
        "/.next/"
      ]
    }
  ],
  "globalConfig": {
    "bail": 0,
    "changedFilesWithAncestor": false,
    "ci": false,
    "collectCoverage": false,
    "collectCoverageFrom": [],
    "coverageDirectory": "/myapp/nextjs-testing/coverage",
    "coverageProvider": "babel",
    "coverageReporters": [
      "json",
      "text",
      "lcov",
      "clover"
    ],
    "detectLeaks": false,
    "detectOpenHandles": false,
    "errorOnDeprecated": false,
    "expand": false,
    "findRelatedTests": false,
    "forceExit": false,
    "json": false,
    "lastCommit": false,
    "listTests": false,
    "logHeapUsage": false,
    "maxConcurrency": 5,
    "maxWorkers": 3,
    "noStackTrace": false,
    "nonFlagArgs": [],
    "notify": false,
    "notifyMode": "failure-change",
    "onlyChanged": false,
    "onlyFailures": false,
    "passWithNoTests": false,
    "projects": [],
    "rootDir": "/myapp/nextjs-testing",
    "runTestsByPath": false,
    "skipFilter": false,
    "testFailureExitCode": 1,
    "testPathPattern": "",
    "testSequencer": "/myapp/nextjs-testing/.yarn/cache/@jest-test-sequencer-npm-28.1.1-d7bbefa803-acfa3b7ff1.zip/node_modules/@jest/test-sequencer/build/index.js",
    "updateSnapshot": "new",
    "useStderr": false,
    "watch": false,
    "watchAll": false,
    "watchman": true
  },
  "version": "28.1.1"
}

```

## package.jsonを編集する
`package.json`の`scripts`に以下を追記します。

```package.json
{
  "scripts": {

    "test": "jest --watch",

  }
}
```