All skills
sergiodxa avatar

/frontend-testing-best-practices

@4d1d816

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.

Use this Skill: https://skilld.dev/gh/sergiodxa/agent-skills/frontend-testing-best-practices

This session only. Nothing lands on disk.

rulesminimize-mocking.md

≈810 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Minimize Mocking

Keep mocks simple and minimal. If you need complex mocking, write an E2E test instead.

Why

  • Mocks can diverge from real implementations
  • Complex mocks are hard to maintain
  • Mocks test your mock, not your code
  • Over-mocking leads to false confidence

The Mock Smell Test

If your test setup looks like this, write an E2E test:

// BAD: Too many mocks = write an E2E test
vi.mock("~/lib/auth");
vi.mock("~/lib/transactions");
vi.mock("~/hooks/useUser");
vi.mock("~/hooks/useCart");
vi.mock("@remix-run/react", () => ({
  useNavigate: () => vi.fn(),
  useLoaderData: () => mockLoaderData,
}));

describe("CheckoutPage", () => {
  // This test provides false confidence
});

Acceptable Mocking

1. MSW for API Calls (Simple Cases)

import { mockServer, http, HttpResponse } from "~/lib/test-utils";

beforeEach(() => {
  mockServer.use(
    http.get("/api/user", () => HttpResponse.json({ id: 1, name: "John" })),
  );
});

test("loader returns user data", async () => {
  let response = await loader({ request, params: {}, context: {} });
  let data = await response.json();
  expect(data.user.name).toBe("John");
});

2. Fake Timers for Time-Based Logic

import { vi, beforeAll, afterAll } from "vitest";

beforeAll(() => {
  vi.useFakeTimers();
  vi.setSystemTime(new Date("2025-01-15"));
});

afterAll(() => {
  vi.useRealTimers();
});

test("isExpired returns true for past dates", () => {
  expect(isExpired(new Date("2025-01-01"))).toBe(true);
});

3. Environment Variables

test("uses production API in production", async () => {
  vi.stubEnv("NODE_ENV", "production");
  const { apiUrl } = await import("./config");
  expect(apiUrl).toBe("https://api.example.com");
  vi.unstubAllEnvs();
});

Unacceptable Mocking

Mocking React Hooks

// BAD: Mocking hooks
vi.mock("react", async () => ({
  ...(await vi.importActual("react")),
  useState: vi.fn(),
  useEffect: vi.fn(),
}));

Mocking Remix Functions

// BAD: Mocking Remix internals
vi.mock("@remix-run/react", () => ({
  useLoaderData: () => ({ user: { name: "John" } }),
  useActionData: () => null,
  useNavigation: () => ({ state: "idle" }),
}));

Mocking Multiple Services

// BAD: If you need all these mocks, write an E2E test
vi.mock("~/lib/auth");
vi.mock("~/lib/transactions");
vi.mock("~/lib/notifications");

Decision Tree

Can I test this with no mocks?
  → Yes: Do that
  → No: Continue...

Can I test this with just MSW (1-2 endpoints)?
  → Yes: Integration test with MSW
  → No: Continue...

Would I need to mock Remix, React, or 3+ services?
  → Yes: Write an E2E test instead

Rules

  1. Zero mocks is the ideal - test pure functions
  2. MSW is acceptable for simple API mocking (1-2 endpoints)
  3. Fake timers are acceptable for time-based logic
  4. Never mock React, Remix, or third-party UI libraries
  5. If you need 3+ mocks, write an E2E test
  6. Complex mock setup is a code smell - refactor or use E2E
  7. Mocks should be simple enough to verify correctness at a glance

Source: SKILL.md on GitHub

No alerts16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill provides a set of best practices and guidelines for frontend testing, focusing on E2E tests with Playwright and unit tests with Vitest. No security issues were detected.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer7mo

    7 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 4d1d816. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Dormantupdated 8 months ago
  • Testing
  • React
  • e2e-testing
  • playwright
  • vitest
  • behavior-testing
  • mocking
  • unit-tests
  • test-strategy

README badge

README badge for sergiodxa/agent-skills/frontend-testing-best-practices

Provides guidelines for frontend testing that prioritize end-to-end tests over unit tests, minimize mocking, and test user behavior rather than implementation details. Use when writing or reviewing test code for web applications built with Playwright and Vitest.

Generated from the current SKILL.md.

When should I write unit tests vs E2E tests?
Default to E2E tests for user workflows and features. Only write unit tests for pure functions. If you need 3 or more mocks for a unit test, write an E2E test instead.
Should I test React components directly?
No. Test components through E2E tests that exercise them in a real user flow, rather than isolated component unit tests.
What selectors should I use in E2E tests?
Prefer accessible selectors in this order: role-based (getByRole), label-based (getByLabel), text-based, then test IDs. Avoid CSS selectors.
What testing tools does this skill assume?
E2E tests use Playwright, unit tests use Vitest. MSW (Mock Service Worker) is used for simple API mocking.

Generated from the current SKILL.md. These answers refresh after source changes.