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
waitForTimeoutsleeps 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.