zudo-test-wisdom

Type to search...

to open search from anywhere

レベル2: DOMベースのコンポーネントテスト

jsdom または happy-dom と Testing Library を使ったコンポーネントテスト。

レベル2がテストするもの

レベル2のテストは、シミュレートされたDOM環境でのコンポーネントの動作を検証します。実際のブラウザなしで、コンポーネントが正しい要素をレンダリングし、ユーザーイベントに応答し、状態を正しく更新することを確認できます。

典型的な対象:

  • コンポーネントのレンダリング(正しい要素を出力するか?)
  • 条件付き表示(propsや状態に基づいて表示/非表示するか?)
  • イベントハンドラー(クリックで正しい動作がトリガーされるか?)
  • propsに基づく動作
  • コンポーネント間の連携(親子コンポーネントの通信)

ツール

ツール役割
vitestテストランナー
jsdom または happy-domシミュレートされたブラウザDOM環境
@testing-library/reactDOMクエリとユーザーイベントシミュレーション
@testing-library/preactPreactプロジェクト向け

セットアップ

DOM環境を使用するようvitestを設定します:

// vitest.config.ts
import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    environment: "jsdom", // or "happy-dom"
  },
});

💡 Tip

happy-dom はほとんどのケースで jsdom より高速です。より広いブラウザAPI互換性が必要な場合は jsdom を使用してください。

// components/Toggle.tsx
import { useState } from "react";

export function Toggle({ label }: { label: string }) {
  const [on, setOn] = useState(false);
  return (
    <button onClick={() => setOn(!on)}>
      {label}: {on ? "ON" : "OFF"}
    </button>
  );
}
// components/Toggle.test.tsx
import { describe, it, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { Toggle } from "./Toggle";

describe("Toggle", () => {
  it("renders with OFF state", () => {
    render(<Toggle label="Sound" />);
    expect(screen.getByText("Sound: OFF")).toBeTruthy();
  });

  it("toggles to ON on click", async () => {
    render(<Toggle label="Sound" />);
    await userEvent.click(screen.getByRole("button"));
    expect(screen.getByText("Sound: ON")).toBeTruthy();
  });
});

ブラインドスポット

⚠️ Warning

レベル2のテストは実際のブラウザではなくシミュレートされたDOMを使用します。以下を検出できません:

  • CSSの効果(DOMにはCSSエンジンがない)
  • 視覚的レイアウト(CSSによりDOMに存在しても非表示の要素)
  • ブラウザ固有のレンダリング
  • スクロール動作
  • アニメーションとトランジションの状態
  • 算出スタイル

重要なギャップ:jsdomのツリーに要素が存在していても(レベル2はパス)、CSSにより画面上では完全に非表示になっている場合があります(レベル5ならこれをキャッチ)。

レベル2を使用するタイミング

シナリオレベル2は適切か?
コンポーネントが誤ったテキストをレンダリングはい
propsが正しく渡されないはい
クリックハンドラーが状態を更新しないはい
要素が存在するが表示されないいいえ — レベル5を使用
CSSレイアウトが壊れているいいえ — レベル5を使用
複数ページのナビゲーションフローいいえ — レベル4を使用

Revision History