Open2

Next.js + Storybook + Playwrightでスナップショットテストを導入する

おとのおとの

作成したページのスナップショットテストを実行する

  1. 下記コマンドを実行し、@playwright/testをプロジェクトにインストールする
npm i -D @playwright/test
  1. プロジェクトのルートディレクトリにplaywright.config.tsを追加する
playwright.config.ts
import { devices, PlaywrightTestConfig } from "@playwright/test";

const config: PlaywrightTestConfig = {
  use: {
    baseURL: "http://127.0.0.1:8080",
  },
  outputDir: "playwright/out/images",
  reporter: [
    // スナップショットテストのレポートを生成する
    ["html", { open: "never", outputFolder: "playwright/out/report" }],
  ],
  webServer: {
    // 開発サーバーだとfirefoxのキャプチャーが撮れないことがあるので本番サーバーを起動
    command: "npm run start",
    url: "http://127.0.0.1:8080",
  },
  projects: [
    // 各端末のスナップショットテストを実行する
    {
      name: "chromium",
      use: { ...devices["Desktop Chrome"] },
    },
    {
      name: "firefox",
      use: { ...devices["Desktop Firefox"] },
    },
    {
      name: "safari",
      use: { ...devices["Desktop Safari"] },
    },
    {
      name: "iPhone 13",
      use: { ...devices["iPhone 13"] },
    },
    {
      name: "iPhone SE",
      use: { ...devices["iPhone SE"] },
    },
    {
      name: "iPad Mini",
      use: { ...devices["iPad Mini"] },
    },
    {
      name: "iPad Mini landscape",
      use: { ...devices["iPad Mini landscape"] },
    },
    {
      name: "Pixel 5",
      use: { ...devices["Pixel 5"] },
    },
  ],
};
export default config;
  1. playwrightディレクトリを作成し、page-snapshot.spec.tsを作成する
playwrightpage-snapshot.spec.ts
import { expect, test } from "@playwright/test";

const pagePath = [
  // ここに各ページの情報を追加
  {
    name: "top",
    path: "/",
  },
];

test.describe.parallel("Visual regression testing of page", () => {
  pagePath.map((item) => {
    test(`snapshot test ${item.name}`, async ({ page }) => {
      await page.goto(item.path);
      expect(await page.screenshot({ fullPage: true })).toMatchSnapshot([
        item.name,
        `${item.name}.png`,
      ]);
    });
  });
});
  1. package.jsonに以下記述を追加する
package.json

  <上記略>

  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
+   "snapshots:page": "npm run build && playwright test playwright/page-snapshot.spec",
+   "snapshots-update:page": "npm run build && playwright test playwright/page-snapshot.spec --update-snapshots",
  },

  <下記略>
  1. npm run snapshots:pageを実行

ここまで完了すると(pagePathに追加したページの)テストが実行されるはずです。最初の1回目は比較するスクリーンショットが無いことから実行途中でエラーが発生しますが、スクリーンショットの保存には成功するため、2回目以降から正しくスナップショットテストが稼働します。

スナップショットを更新したい場合はnpm run snapshots-update:pageを実行してください。

実際の差分が無いにも関わらず記録されるスクリーンショットの画像サイズが異なるために差分として検知されるなど、safariやfirefox、スマホ端末でのスナップショットは若干不安定なので注意。

githubのissueでも最新バージョンで改善が期待されていました。
https://github.com/microsoft/playwright/issues/15802

おとのおとの

Storybookに登録したコンポーネントのスナップショットテストを実行する

  1. 下記コマンドを実行し、start-server-and-testhttp-serverをインストールする
npm i -D start-server-and-test http-server
  1. 上記で作成したplaywrightディレクトリにstorybook-snapshot.spec.tsを作成する
/playwright/storybook-snapshot.spec.ts
import { readFileSync } from "node:fs";
import { resolve } from "node:path";

import { expect, test } from "@playwright/test";
import { StoryIndex } from "@storybook/store";

const storybookDir = resolve(__dirname, "..", "storybook-static");
const data: StoryIndex = JSON.parse(
  readFileSync(resolve(storybookDir, "stories.json")).toString()
);
test.describe.parallel("visual regression testing of storybook", () => {
  Object.values(data.stories).forEach((story) => {
    test(`snapshot test ${story.title}: ${story.name}`, async ({ page }) => {
      await page.goto(`http://localhost:8081/iframe.html?id=${story.id}`, {
        waitUntil: "networkidle",
      });
      expect(await page.screenshot({ fullPage: true })).toMatchSnapshot([
        story.title,
        `${story.id}.png`,
      ]);
    });
  });
});
  1. storybook/main.jsに以下記述を追加する
.storybook/main.js
module.exports = {
  
    <中略>
  
+  features: {
+    buildStoriesJson: true,
+  },
};
  1. package.jsonに以下記述を追加する
package.json
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "snapshots:page": "npm run build && playwright test playwright/page-snapshot.spec",
    "snapshots-update:page": "npm run build && playwright test playwright/page-snapshot.spec --update-snapshots",
+   "preview-storybook": "build-storybook && http-server storybook-static/ -p 8081",
+   "snapshots:storybook": "start-server-and-test preview-storybook http://127.0.0.1:8081 'playwright test playwright/storybook-snapshot.spec.ts'",
+   "snapshots-update:storybook": "start-server-and-test preview-storybook http://127.0.0.1:8081 'playwright test playwright/storybook-snapshot.spec.ts --update-snapshots'",
  },
  1. npm run snapshots:storybookを実行する。

そうすると、storybookに登録したコンポーネントのスナップショットテストが実行されるはずです(ページのテストと同様、初回は実行中にエラーが発生します)

スナップショットを更新したい場合はnpm run snapshots-update:storybookを実行してください。