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 从公开仓库中收录这些内容。

举报或申请下架