Ivaan Information Technology
Testing React Apps: What to Test and What to Skip
← Back to Blog
Tech Insights

Testing React Apps: What to Test and What to Skip

✍By Khushal Chugh
πŸ—“Sep 25, 2026
⏱5 min read

Teams often swing between two extremes: no tests, or hundreds of brittle tests that break on every refactor. Good testing sits between them. It protects the behavior users rely on and stays out of the way of change. Here is a practical approach for React applications.

Test behavior, not implementation

A user clicks a button and sees a message. They do not care whether you used useState or a reducer. Tests that check internal state, component method names or exact markup fail when you refactor even though nothing visible changed. Write tests from the user's point of view: what they see, click and type.

The testing pyramid, adjusted for the front end

  • Unit tests: pure functions such as price calculations, formatters and validators. Fast and numerous.
  • Component tests: a component rendered with Testing Library, driven by simulated user events.
  • End-to-end tests: a few critical journeys in a real browser with Playwright or Cypress, such as sign-up, checkout and contact form.

Put most effort into the first two, and keep end-to-end tests few and stable.

What is worth testing

  1. Business logic: totals, discounts, permissions and date handling.
  2. Forms: validation messages, required fields, submit success and failure.
  3. Conditional UI: loading, empty, error and success states.
  4. Custom hooks that contain real logic, tested directly or through a component.
  5. Critical paths where a bug costs money or trust.

What you can skip

  • Purely presentational components with no logic.
  • Third-party library behavior, which its authors already test.
  • Exact CSS values and class names.
  • Snapshot tests of large trees, which people approve without reading.
  • Implementation details such as how many times a state setter was called.

Write queries the way users find things

Testing Library encourages queries by role and label, which doubles as an accessibility check:

  • Prefer getByRole("button", { name: "Send" }) and getByLabelText.
  • Use getByTestId only when nothing else fits.
  • Use findBy queries for content that appears after async work, rather than fixed timeouts.

If a test cannot find an element by role, a screen reader user probably cannot either. That is a real bug. See our article on accessible web applications.

Mock the network, not your own code

Use Mock Service Worker to intercept HTTP requests and return fixed responses. Your components and data-fetching code run for real, and you test both success and failure. Avoid mocking internal modules, because that hides integration bugs.

Keep tests fast and reliable

  • Use Vitest or Jest with a jsdom environment for component tests.
  • Never rely on real time or randomness. Use fake timers and fixed seeds.
  • Isolate each test so order does not matter.
  • Fix or delete flaky tests immediately. A test nobody trusts is worse than none.

Cover the journeys that matter end to end

Pick three to five flows: a visitor submits the contact form, a user signs in and a customer completes checkout. Run them in CI against a preview deployment. Record traces on failure so a broken run is easy to debug.

Run tests where they cannot be forgotten

  1. Run unit and component tests on every pull request.
  2. Run end-to-end tests before merging to the main branch.
  3. Block merges when they fail.
  4. Add a failing test first when you fix a bug, then fix it.

A realistic target

Aim for strong coverage of logic and critical paths, not a coverage percentage. Eighty percent coverage of trivial code protects less than twenty percent aimed well.

A small example: testing an invoice form

Consider a form where a user picks a customer, adds line items and sees a live total. Good tests render the form, type a quantity and price, and check that the total text updates. They also submit with a missing customer and expect a clear error message, and they mock a failed network call to confirm a retry message appears. They do not check how many times a state setter ran. Three or four tests like these protect the form for years and survive a rewrite of its internals.

A starter list for a business app

  1. Calculation helpers for tax, discount and totals, with edge cases such as zero and rounding.
  2. Role-based screens: a viewer must not see the delete button.
  3. The main forms: create invoice, add product, record payment.
  4. One end-to-end test per money flow.

How this applies to what we ship

In products such as our Lena Dena business platform, with invoicing, inventory, multi-language screens and different permissions per role, tests keep each of those promises. Switching the interface from English to Hindi should not break a form, and a sales user should never gain access to accountant-only pages. The same discipline applies to messaging flows. Our WhatsApp automation is covered by tests that feed in sample messages, including messy ones, and check the extracted fields. Realistic samples catch more bugs than clean ones.

Our team builds React and Next.js products with testing in the pipeline. See our development services and projects, or contact us to discuss your app.

Explore Our Services

Need help putting this into practice? See our web, mobile and AI development services, browse projects we have delivered, read the FAQs, or contact our team.