Playwright Component Testing: E2E Tests for React Components
Playwright isn't just for full-page E2E tests anymore. Learn how to use Playwright's component testing to test React components in a real browser with real rendering — no jsdom required.
Unit testing React components with Jest and Testing Library has been the standard for years. But there's always been a gap: jsdom isn't a real browser. CSS doesn't render. Intersection observers don't exist. Viewport-dependent logic doesn't work. Playwright Component Testing closes that gap by mounting your components in an actual browser engine, giving you the confidence of E2E tests with the speed and isolation of unit tests.
Why Component Testing in a Real Browser?
The jsdom simulation handles most cases, but it fails silently on others. Components that depend on CSS layout, scroll position, resize observers, or browser-specific APIs produce false positives in jsdom — tests pass, but the component is broken in production. Playwright runs in Chromium, Firefox, or WebKit, so what you test is what your users see.
Setting Up Playwright Component Testing
Install the experimental component testing package alongside Playwright:
npm install -D @playwright/experimental-ct-react playwright
# Create the config
npx playwright init --ct
# playwright-ct.config.ts is generated with:
# - ctPort: dev server port for component mounting
# - ctViteConfig: Vite config for bundling components
Playwright uses Vite under the hood to bundle your components for testing. This means hot module replacement works during development, and the bundling is fast regardless of your production build tool.
Writing Your First Component Test
Component tests look remarkably similar to Playwright E2E tests, but instead of navigating to a URL, you mount a component directly:
// src/components/SearchInput.spec.tsx
import { test, expect } from "@playwright/experimental-ct-react";
import { SearchInput } from "./SearchInput";
test("renders placeholder and handles input", async ({ mount }) => {
let searchValue = "";
const component = await mount(
<SearchInput
placeholder="Search articles..."
onSearch={(value) => { searchValue = value; }}
/>
);
// Real browser rendering — CSS, focus states, animations all work
await expect(component.getByPlaceholder("Search articles...")).toBeVisible();
await component.getByRole("textbox").fill("React Server Components");
await component.getByRole("textbox").press("Enter");
expect(searchValue).toBe("React Server Components");
});
test("shows clear button only when input has value", async ({ mount }) => {
const component = await mount(<SearchInput placeholder="Search..." />);
// Clear button should be hidden initially
await expect(component.getByRole("button", { name: "Clear" })).toBeHidden();
// Type something
await component.getByRole("textbox").fill("test");
// Clear button should now be visible — this tests real CSS visibility
await expect(component.getByRole("button", { name: "Clear" })).toBeVisible();
});
Notice that you're testing real CSS visibility, not just DOM presence. The toBeVisible() assertion checks actual computed styles, layout, and opacity — something jsdom simply cannot do.
Testing Responsive Behavior
One of the strongest use cases is testing responsive components. You can set the viewport size per test, something impossible with jsdom. Test that your navigation collapses into a hamburger menu at 768px, or that your grid layout switches from 3 columns to 1 on mobile viewports.
Trade-offs vs. Testing Library
Playwright component tests are slower than jsdom-based tests — roughly 100-500ms per test versus 10-50ms. For a component library with 500 tests, that difference adds up. The pragmatic approach: use Testing Library for logic-heavy components where browser rendering doesn't matter, and Playwright for components where visual behavior, CSS, or browser APIs are critical.
Integration With CI
Playwright component tests run in CI exactly like E2E tests. The browser binaries are cached, and parallelization is built in. For GitHub Actions, the official playwright-github-action handles browser installation and caching automatically.
Component testing in Playwright is still marked as experimental, but the API has been stable for over a year and major teams are using it in production. If you've ever been burned by a jsdom false positive, give it a try on your most visually complex components. The confidence boost is immediate.
Admin
Cal.com
Open source scheduling — tự host booking system, thay thế Calendly. Free & privacy-first.
Bình luận (0)
Đăng nhập để bình luận
Chưa có bình luận nào. Hãy là người đầu tiên!