SolidJSのユニットテスト環境構築

目次

はじめに

SolidJSのプロジェクトでユニットテストを書くための環境構築を行ったのでメモ

適当なディレクトリで↓を実行してプロジェクト作成

npm init solid@latest

モジュールのインストール

npm i -D @solidjs/testing-library  @testing-library/jest-dom @types/testing-library__jest-dom @vitest/coverage-c8 @vitest/ui jsdom vitest

コンフィグファイルの追加修正

package.json

testスクリプトを追加する

"scripts": {
    "dev": "solid-start dev",
    "build": "solid-start build",
    "start": "solid-start start",
    "test": "vitest" // 追加
  }

vitest.config.js

以下の内容のファイルを作成する

import solid from "solid-start/vite";
import { defineConfig } from "vitest/config";

export default defineConfig({
  plugins: [solid()],
  test: {
    deps: {
      registerNodeLoader: true,
      inline: [/solid-js/],
    },
    environment: "jsdom",
    globals: true,
    setupFiles: [
      "node_modules/@testing-library/jest-dom/extend-expect",
      "./setupVitest.js",
    ],
    transformMode: { web: [/\.[jt]sx?$/] },
  },
  resolve: {
    conditions: ["development", "browser"],
  },
});

setupVitest.js

以下の内容のファイルを作成する

import "@testing-library/jest-dom";

tsconfig.json

compilerOptions.types@testing-library/jest-domを追加する

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "node",
    "jsxImportSource": "solid-js",
    "jsx": "preserve",
    "strict": true,
    "types": [
      "solid-start/env",
      "@testing-library/jest-dom" // 追加
    ],
    "baseUrl": "./",
    "paths": {
      "~/*": [
        "./src/*"
      ]
    },
  }
}

ユニットテストを書く

テスト対象コンポーネント(Counter.tsx)

import { createSignal } from "solid-js";

export default function Counter() {
  const [count, setCount] = createSignal(0);
  return (
    <button class="increment" onClick={() => setCount(count() + 1)}>
      Clicks: {count()}
    </button>
  );
}

ユニットテスト(Counter.test.tsx)

import { fireEvent, render } from "@solidjs/testing-library";
import Counter from "./Counter";

describe("<Counter />", () => {
  it("increments value", async () => {
    // ボタンを押したときの挙動をチェック
    const { queryByRole, unmount } = render(() => <Counter />);
    const button = (await queryByRole("button")) as HTMLButtonElement;
    expect(button).toBeInTheDocument();
    expect(button).toHaveTextContent(/Clicks: 0/);
    fireEvent.click(button);
    expect(button).toHaveTextContent(/Clicks: 1/);
    unmount();
  });

  it("renders 1", () => {
    // スナップショットと一致するかチェック
    const { container, unmount } = render(() => <Counter />);
    expect(container).toMatchSnapshot();
    unmount();
  });
});

ユニットテスト実行

コマンド

npm test

スナップショット

テスト実行後、snapshots以下にスナップショットファイルが作成される

スナップショットが存在する際にtoMatchSnapshot()を呼び出すと、レンダリングされたコンポーネントとスナップショットとを比較して一致するかチェックする
※存在しない場合はスナップショットを新規作成するだけ

コンポーネントを変更してテストを実行すると、スナップショットとの差分が発生するのでテストには失敗する
↓ではボタンのテキストをClicksからクリックに変えて実行した

スナップショットファイルの更新

vitestのCLIでも言われている通りuキーを押せばスナップショットは更新される

また、vitestコマンドに-uオプションを追加することでも更新可能
※npm scripts実行時は↓

npm test -- -u

参考

github.com