mcpField
F
frontend-testing

frontend-testing

github.com/exceptionlessテスト・品質2.5k42 回インストール1 日前に更新
リポジトリ

frontend-testing について

Vitestと@testing-library/svelteを使うチーム向けのフロントエンドテストガイドです。テスト配置、TDDとAAAの実践、アクセシブルなクエリの優先順位、モジュールのモック例を示します。

主な機能

  1. 01VitestとTesting Libraryの構成
  2. 02テストファイルの配置規約
  3. 03TDDとArrange-Act-Assertのパターン
  4. 04アクセシブルなクエリの選択順
  5. 05モジュールモックの例

活用シーン

  1. 01Svelteコンポーネントのテスト作成
  2. 02バグ修正時のテスト追加
  3. 03アクセシブルなテストクエリの選択

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/exceptionless/exceptionless --skill frontend-testing

インストール後、Claude Code で/frontend-testingを入力して読み込まれたか確認します。

詳細

フロントエンドのテスト

ドキュメント: vitest.dev | testing-library.com

フレームワークと配置場所

  • フレームワーク:Vitest + @testing-library/svelte
  • 配置場所:コードと同じ場所に .test.ts または .spec.ts として配置します
  • TDD ワークフロー:バグ修正や機能追加の際は、まず失敗するテストを書きます

AAA パターン

Arrange、Act、Assert の領域を明示します。

import { describe, expect, it } from "vitest";

describe("Calculator", () => {
    it("should add two numbers correctly", () => {
        // Arrange
        const a = 5;
        const b = 3;

        // Act
        const result = add(a, b);

        // Assert
        expect(result).toBe(8);
    });
});

スパイを使ったテスト

import { beforeEach, describe, expect, it, vi } from "vitest";
import { CachedPersistedState } from "./cached-persisted-state.svelte";

describe("CachedPersistedState", () => {
    beforeEach(() => {
        vi.clearAllMocks();
    });

    it("should return cached value without reading storage repeatedly", () => {
        // Arrange
        const getItemSpy = vi.spyOn(Storage.prototype, "getItem");
        localStorage.setItem("test-key", "value1");
        const state = new CachedPersistedState("test-key", "default");
        getItemSpy.mockClear();

        // Act
        const val1 = state.current;
        const val2 = state.current;

        // Assert
        expect(val1).toBe("value1");
        expect(val2).toBe("value1");
        expect(getItemSpy).not.toHaveBeenCalled();
    });
});

クエリ選択の優先順位

実装の詳細ではなく、アクセシブルなクエリを使用します。

  1. screen.getByRole("button", { name: /submit/i }) — ロールベース(推奨)
  2. screen.getByLabelText("Email address") — ラベルベース
  3. screen.getByText("Welcome back") — テキストベース
  4. screen.getByTestId("complex-chart") — テスト ID(代替手段)
  5. ❌ screen.getByClassName("btn-primary") — 実装の詳細は使用しないでください

モジュールのモック

import { vi, describe, it, beforeEach, expect } from "vitest";
import { render, screen } from "@testing-library/svelte";

vi.mock("$lib/api/organizations", () => ({
    getOrganizations: vi.fn(),
}));

import { getOrganizations } from "$lib/api/organizations";
import OrganizationList from "./organization-list.svelte";

describe("OrganizationList", () => {
    beforeEach(() => {
        vi.clearAllMocks();
    });

    it("displays organizations from API", async () => {
        // Arrange
        vi.mocked(getOrganizations).mockResolvedValue([{ id: "1", name: "Org One" }]);

        // Act
        render(OrganizationList);

        // Assert
        expect(await screen.findByText("Org One")).toBeInTheDocument();
    });
});

コメント