Frontend Testing Best Practices

sergiodxa/agent-skills/skills/frontend-testing-best-practices

作者 sergiodxa40e21b46189d無授權條款90 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫8 個月前更新

Testing best practices for the frontend. Emphasizes E2E tests over unit tests, minimal mocking, and testing behavior over implementation details. Use when writing tests or reviewing test code.

AI 產生的概覽

面向前端測試的規範,主張優先採用端對端測試、減少模擬,並聚焦行為而非實作。

功能
此技能提供六條撰寫與審查前端測試的規則。它建議優先採用端對端測試而非單元測試,避免直接測試 React 元件,盡量減少模擬,並使用可存取的選擇器。它也說明了端對端測試與單元測試的檔案結構與放置位置。
適用情境
適用於決定要撰寫哪一種測試、撰寫新的端對端或單元測試、審查測試程式碼,或重構現有測試時。
執行需求
不需要任何指令碼或工具,僅為說明性內容。範例中提及 Playwright、Vitest 與 MSW,但此技能本身除了代理程式外不需要其他相依項目。

Testing Best Practices

Guidelines for writing effective, maintainable tests that provide real confidence. Contains 6 rules focused on preferring E2E tests, minimizing mocking, and testing behavior over implementation.

Core Philosophy

  1. Prefer E2E tests over unit tests - Test the whole system, not isolated pieces
  2. Minimize mocking - If you need complex mocks, write an E2E test instead
  3. Test behavior, not implementation - Test what users see and do
  4. Avoid testing React components directly - Test them through E2E

When to Apply

Reference these guidelines when:

  • Deciding what type of test to write
  • Writing new E2E or unit tests
  • Reviewing test code
  • Refactoring tests

Rules Summary

Testing Strategy (CRITICAL)

prefer-e2e-tests - @rules/prefer-e2e-tests.md

Default to E2E tests. Only write unit tests for pure functions.

typescript
// E2E test (PREFERRED) - tests real user flowtest("user can place an order", async ({ page }) => {  await createTestingAccount(page, { account_status: "active" });  await page.goto("/catalog");  await page.getByRole("heading", { name: "Example Item" }).click();  await page.getByRole("link", { name: "Buy" }).click();  // ... complete flow  await expect(page.getByAltText("Thank you")).toBeVisible();});
// Unit test - ONLY for pure functionstest("formatCurrency formats with two decimals", () => {  expect(formatCurrency(1234.5)).toBe("$1,234.50");});
avoid-component-tests - @rules/avoid-component-tests.md

Don't unit test React components. Test them through E2E or not at all.

typescript
// BAD: Component unit testdescribe("OrderCard", () => {  test("renders amount", () => {    render(<OrderCard amount={100} />);    expect(screen.getByText("$100")).toBeInTheDocument();  });});
// GOOD: E2E test covers the component naturallytest("order history shows orders", async ({ page }) => {  await page.goto("/orders");  await expect(page.getByText("$100")).toBeVisible();});
minimize-mocking - @rules/minimize-mocking.md

Keep mocks simple. If you need 3+ mocks, write an E2E test instead.

typescript
// BAD: Too many mocks = write E2E testvi.mock("~/lib/auth");vi.mock("~/lib/transactions");vi.mock("~/hooks/useAccount");
// GOOD: Simple MSW mock for loader testmockServer.use(  http.get("/api/user", () => HttpResponse.json({ name: "John" })),);

E2E Tests (HIGH)

e2e-test-structure - @rules/e2e-test-structure.md

E2E tests go in e2e/tests/, not frontend/.

typescript
// e2e/tests/order.spec.tsimport { test, expect } from "@playwright/test";import { addAccountBalance, createTestingAccount } from "./utils";
test.describe("Orders", () => {  test.beforeEach(async ({ page, context }) => {    await createTestingAccount(page, { account_status: "active" });    let cookies = await context.cookies();    let account_id = cookies.find((c) => c.name === "account_id").value;    await addAccountBalance({ account_id, amount: 10000, replaceBalance: true });  });
  test("place order with default values", async ({ page }) => {    await page.goto("/catalog");    // ... user flow  });});
e2e-selectors - @rules/e2e-selectors.md

Use accessible selectors: role > label > text > testid.

typescript
// GOOD: Role-based (preferred)await page.getByRole("button", { name: "Submit" }).click();await page.getByRole("heading", { name: "Dashboard" });
// GOOD: Label-basedawait page.getByLabel("Email").fill("[email protected]");
// OK: Test ID when no accessible selector existsawait expect(page.getByTestId("balance")).toHaveText("$1,234");
// BAD: CSS selectorsawait page.locator(".btn-primary").click();

Unit Tests (MEDIUM)

unit-test-structure - @rules/unit-test-structure.md

Unit tests for pure functions only. Co-locate with source files.

typescript
// app/utils/format.test.tsimport { describe, test, expect } from "vitest";import { formatCurrency } from "./format";
describe("formatCurrency", () => {  test("formats positive amounts", () => {    expect(formatCurrency(1234.5)).toBe("$1,234.50");  });
  test("handles zero", () => {    expect(formatCurrency(0)).toBe("$0.00");  });});

Key Files

  • e2e/tests/ - E2E tests (Playwright)
  • e2e/tests/utils.ts - E2E test utilities
  • vitest.config.ts - Unit test configuration
  • vitest.setup.ts - Global test setup with MSW
  • app/utils/test-utils.ts - Unit test utilities

來源與署名

來源:sergiodxa/agent-skills位於skills/frontend-testing-best-practices提交40e21b4

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架