React: From Components to Production · Testing and Accessibility

End-to-End Tests with Playwright

Verify critical journeys in real browsers.

Playwright runs tests in Chromium, Firefox and WebKit with auto-waiting, role-based locators, network interception, and traces for debugging. Cover a few critical journeys (sign in, checkout), use isolated test accounts and seeded data, authenticate once and reuse storage state, and run them in CI against a preview deployment. Add @axe-core/playwright for automated accessibility checks.

import { test, expect } from "@playwright/test";
import AxeBuilder from "@axe-core/playwright";

test("user can add a product to the cart", async ({ page }) => {
  await page.goto("/products/42");
  await page.getByRole("button", { name: "Add to cart" }).click();
  await expect(page.getByRole("status")).toHaveText(/added to cart/i);
  await page.getByRole("link", { name: /cart \(1\)/i }).click();
  await expect(page).toHaveURL(/\/cart$/);
});

test("cart page has no detectable a11y violations", async ({ page }) => {
  await page.goto("/cart");
  const results = await new AxeBuilder({ page }).analyze();
  expect(results.violations).toEqual([]);
});

Common pitfalls

  • Fixed waitForTimeout sleeps instead of web-first assertions.
  • Tests depending on each other's data.
  • Too many E2E tests duplicating unit-level checks.

Key points

  • Few, critical journeys
  • Role locators and auto-waiting
  • Traces for debugging; axe for a11y

Further reading: Playwright documentation

Practice questions

What makes Playwright tests less flaky than older tools?

Answer

Auto-waiting locators and web-first assertions (toHaveText, toBeVisible) retry until conditions are met, instead of relying on fixed sleeps.

Which flows deserve E2E tests?

Answer

Business-critical journeys where integration failures are costly: signup/login, checkout/payment, and core create/edit flows.

Open in the app to mark lessons complete, take notes and track your progress.