👮

Next.js 12+Storybook(CSF3.0) でStoryShotsを実現する

2022/10/08に公開

StoryShotsの概要

StoryShotsとは、コンポーネントの自動スナップショットテストを実現するツールで、Storybookに登録されているコンポーネントのUIが予期せず変更されていないかを確認することができます。

StoryShotsのセットアップ

Next.jsのアプリケーションにStorybookが導入されていることを前提で進めます。
まだ導入されていない方は、以下参考にしてください。
https://zenn.dev/toono_f/articles/3aa990971975cb

  1. package.jsonに以下記述を追加する
package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build && next export",
    "start": "next start",
    "storybook": "start-storybook -p 6006",
    "build-storybook": "build-storybook",
+   "storyshots": "jest --config ./jest.config.storyshots.js",
  },
+  "resolutions": {
+   "react-test-renderer": "18.1.0"
+ },
}

※ 2022年10月現在、React 18を利用したアプリケーションでStoryShotsを実行するとTypeError: Cannot read properties of undefined (reading 'current')というエラーが発生したので、依存関係のreact-test-rendererのバージョンを指定することで解決しました。yarnを使っていない場合はnpm-force-resolutionsプラグインを使えば依存関係を固定することができます。

  1. 以下コマンドを実行し、必要なプラグインをインストールする
yarn add -D @storybook/addon-storyshots @testing-library/react @testing-library/jest-dom jest-environment-jsdom @storybook/testing-react
  1. jest.config.storyshots.jsを作成する
jest.config.storyshots.js
const nextJest = require("next/jest");

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

const customJestConfig = {
  displayName: "storyshots",
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/$1", // tsconfig.jsonのcompilerOptions>pathsの定義に合わせてください
  },
  testEnvironment: "jest-environment-jsdom",
  testMatch: ["<rootDir>/src/tests/jest.storyshots.ts"],
};

module.exports = createJestConfig(customJestConfig);
  1. jest.storyshots.tsを作成する(配置先は上記にあるtestMatchの設定に合わせる)
src/tests/jest.storyshots.ts
import initStoryshots, { multiSnapshotWithOptions } from "@storybook/addon-storyshots";

initStoryshots({
  test: multiSnapshotWithOptions(),
});

multiSnapshotWithOptionsを設定すると、各コンポーネントごとにスナップショットファイルを生成できます。

StoryShotsを実行する

セットアップが完了したら、以下コマンドでStoryShotsを実行できます。

yarn storyshots

このようなログが表示されたら実行成功です✨

差分が発生している場合は、以下のようなログが表示されます。

意図的な差分の場合、下記コマンドを実行することでスナップショットを更新できます。

yarn storyshots -u

コンポーネント内でuseRouterをimportしている場合

StoryShotsを実行するコンポーネント内にuseRouterが利用されている場合、実行時に下記のエラーが発生することがあります。

TypeError: Cannot read properties of null (reading 'pathname')

その場合、.storybook/preview.jsに以下記述を追加することで、useRouterのモックデータが設定され、本エラーを解決することができます。

.storybook/preview.js
+ import * as nextRouter from "next/router";

~中略~

+ nextRouter.useRouter = () => ({
+   route: "",
+   pathname: "",
+   query: { query: "" },
+   asPath: "",
+   basePath: "",
+ });

コンポーネント内でfetchを利用している場合

  1. jest-fetch-mockをインストールする
yarn add -D jest-fetch-mock
  1. jest.setup.jsを作成する
jest.setup.js
require("jest-fetch-mock").enableMocks();
  1. jest.config.storyshots.jsに以下記述を加える
jest.config.storyshots.js
const nextJest = require("next/jest");

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

const customJestConfig = {
  displayName: "storyshots",
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/$1",
  },
  testEnvironment: "jest-environment-jsdom",
+ setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
  testMatch: ["<rootDir>/src/tests/jest.storyshots.ts"],
};

module.exports = createJestConfig(customJestConfig);

続きはこちら・・・
https://zenn.dev/toono_f/articles/7cb6e94d05932f

LCL Engineers

Discussion