Skip to content
Skillpedia
Testing280k · #114

react-testing

Lets your agent write tests for React components. It uses tools to check if everything works correctly, including accessibility.

What it does

Helps test software components built with React. It ensures they work as expected for the end-user by checking what's displayed on the screen and how the user interacts with them.

When to use it

  • ✓When creating new React components.
  • ✓When fixing issues in existing components.
  • ✓To ensure components don't break after changes.

Example of what to ask your AI

“Test the login component to ensure the user can type email and password and click the submit button.”

Want more? Open the sections below.

How to use

The easiest way: copy the message below and paste it into Claude, ChatGPT, Cursor or any AI. It reads the skill and follows the instructions.

Skill link

https://github.com/affaan-m/ECC/blob/main/pi/core/skills/react-testing/SKILL.md

Ready-to-paste message

Use this skill to help me: https://github.com/affaan-m/ECC/blob/main/pi/core/skills/react-testing/SKILL.md Read the SKILL.md file at that link and follow its instructions for my task.
How it works

It uses tools that simulate a browser to render your components and interact with them, as if a real user were using it. This helps find errors before users see them.

Installation

Easiest way: copy the skill link and paste it into Claude, ChatGPT or Cursor asking it to follow the instructions.

In the terminal (Claude Code, Codex, Cursor), in your project folder:

npx skills add affaan-m/ECC --skill react-testing

Or download just the file:

curl -L https://raw.githubusercontent.com/affaan-m/ECC/main/pi/core/skills/react-testing/SKILL.md -o SKILL.md
Technical content (original SKILL.md)

Original text by the author, straight from GitHub.

React Testing

Comprehensive React testing patterns for behavior-focused component tests, custom hook tests, accessibility assertions, and network-level mocking.

When to Activate

  • Writing tests for React components, custom hooks, or pages
  • Adding test coverage to legacy untested components
  • Migrating from Enzyme or class-component-era patterns to React Testing Library
  • Setting up Vitest or Jest for a new React project
  • Mocking HTTP requests in tests
  • Asserting accessibility violations
  • Deciding which tests belong in RTL vs Playwright Component Testing vs full E2E

Core Principle

Test what the user sees and does, not implementation details.

A test should:

  • Render the component with the same providers it has in production
  • Interact with it via accessible queries (role, label) and userEvent
  • Assert visible output and observable side effects (callback fired, request sent)

A test should NOT:

  • Inspect component state, props passed to children, or which hooks were called
  • Mock React itself or framework hooks
  • Assert on the number of renders or DOM structure beyond what affects users

Library Choice

Runner When Note
Vitest Vite, Remix, modern setups Faster, native ESM, Jest-compatible API
Jest Next.js, CRA, established repos Default for many React projects
Playwright Component Testing Real browser engine needed Use when JSDOM lacks the required feature
Cypress Component Testing Real browser, Cypress already in use Alternative to Playwright CT

Pick one. Do not run RTL + Vitest AND Playwright CT in the same repo unless you have a clear lane separation.

Query Priority

React Testing Library exposes queries in three tiers — use top-down:

  1. Accessible to everyone: getByRole, getByLabelText, getByPlaceholderText, getByText, getByDisplayValue
  2. Semantic: getByAltText, getByTitle
  3. Test IDs (escape hatch): getByTestId
// Best
screen.getByRole("button", { name: /save/i });

// OK for inputs
screen.getByLabelText("Email");

// Last resort
screen.getByTestId("save-btn");

Variants:

  • getBy* — throws if no match
  • queryBy* — returns null (use for "assert absence")
  • findBy* — async, returns a Promise (use for elements that appear after async work)

User Interaction with userEvent

import userEvent from "@testing-library/user-event";

test("submits the form", async () => {
  const user = userEvent.setup();
  const onSubmit = vi.fn();
  render(<UserForm onSubmit={onSubmit} />);

  await user.type(screen.getByLabelText("Email"), "user@example.com");
  await user.click(screen.getByRole("button", { name: /save/i }));

  expect(onSubmit).toHaveBeenCalledWith({ email: "user@example.com" });
});
  • Always await userEvent calls
  • Call userEvent.setup() once per test, reuse the returned user
  • userEvent simulates a real browser sequence; fireEvent dispatches a single synthetic event — prefer userEvent

Async Patterns

// Element that appears after async work
expect(await screen.findByText("Loaded")).toBeInTheDocument();

// Side effect assertion
await waitFor(() => expect(saveSpy).toHaveBeenCalled());

// Element that should disappear
await waitForElementToBeRemoved(() => screen.queryByText("Loading"));

Never setTimeout + assertion — flaky. Use the matchers above.

Network Mocking with MSW

Mock Service Worker mocks at the network layer. The component, hooks, and fetch library all behave exactly as in production.

Setup

// test/setup.ts
import { setupServer } from "msw/node";
import { http, HttpResponse } from "msw";

export const handlers = [
  http.get("/api/users/:id", ({ params }) =>
    HttpResponse.json({ id: params.id, name: "Alice" }),
  ),
  http.post("/api/users", async ({ request }) => {
    const body = await request.json();
    return HttpResponse.json({ id: "new-id", ...body }, { status: 201 });
  }),
];

export const server = setupServer(...handlers);

beforeAll(() => server.listen({ onUnhandledRequest: "error" }));
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

Configure onUnhandledRequest: "error" so any unmocked request fails the test loudly — silent passes are worse than red.

Per-test override

test("renders error on 500", async () => {
  server.use(
    http.get("/api/users/:id", () => new HttpResponse(null, { status: 500 })),
  );
  render(<UserPage id="1" />);

…
FAQ

What are component tests?

These are automatic checks that simulate the use of a small part of your software (a component) to see if it behaves correctly.

Why test what the user sees and does?

Testing the user experience ensures the software is useful and easy to use, rather than focusing on internal details that might change.

What does 'mocking' a network request mean?

It means simulating a response to an internet call. This allows testing how your component reacts to different responses (success, error) without needing a real connection.

Details

Original description by the author

React component testing with React Testing Library, Vitest/Jest, MSW for network mocking, accessibility assertions with axe, and the decision boundary between component tests and Playwright/Cypress end-to-end runs. Use when writing or fixing tests for React components, hooks, or pages.

repo: affaan-m/ECC

Popularity

GitHub stars
280k
Ranking position
#114
License
MIT
Updated
10/15/2026

Is this skill useful?

0

Sign in to vote.

Comments

  • …

More skills from this repository

Similar skills