पाठ 23 / 25

Testing Components

Test what users see and do.

Behaviour, not implementation

Good component tests render the component, interact as a user would (click, type), and assert on visible output and accessibility attributes, not on internal state. React Testing Library with Vitest or Jest is the common setup, using jsdom as a fake browser; act() ensures updates are applied before assertions. End-to-end tools such as Playwright cover full flows in real browsers. Test reducers and pure helpers directly as plain functions.

Build with confidence

Test behaviour, organise code for growth, and review with a checklist.

Three ideas: testing, project structure, checklist.
Figure 8.1 — Testing, structure and checklist.

Testing a stepper's behaviour, run

I ran this with React 19.3 and react-dom 19.3 on Node.js 22, compiling JSX with esbuild 0.28. Browser-style examples use jsdom 29 as a fake DOM (imported from a small setup-dom.mjs file) and act() to apply updates. The test renders a stepper, clicks "increase" five times, and asserts that the value stops at the maximum of 3, the increase button is disabled and decrease is enabled; all assertions pass. Real projects would use React Testing Library queries such as getByRole for the same checks.

import "./setup-dom.mjs";   // test setup: jsdom provides a browser-like DOM in Node
import { useState, act } from "react";
import { createRoot } from "react-dom/client";
import assert from "node:assert/strict";

function Stepper({ min = 0, max = 3 }) {
  const [n, setN] = useState(min);
  return <>
    <button aria-label="decrease" disabled={n <= min} onClick={() => setN(n - 1)}>-</button>
    <output>{n}</output>
    <button aria-label="increase" disabled={n >= max} onClick={() => setN(n + 1)}>+</button>
  </>;
}
const root = createRoot(document.getElementById("root"));
await act(() => root.render(<Stepper />));
const inc = document.querySelector('[aria-label="increase"]');
for (let i = 0; i < 5; i++) await act(() => inc.click());
assert.equal(document.querySelector("output").textContent, "3");      // clamps at max
assert.equal(inc.disabled, true);
assert.equal(document.querySelector('[aria-label="decrease"]').disabled, false);
console.log("all assertions passed");

Output:

all assertions passed

Query by role and label

Selecting elements by role and accessible name makes tests resilient and nudges you towards accessible markup.

त्वरित जाँच: What should component tests focus on?

  • What users see and can do
  • Internal state variable names
  • The number of hooks
  • CSS class order
Answer

What users see and can do — Behavioural tests survive refactors.