🎭 Playwright Component Test Setup
Your Stage Crew for Testing UI Pieces
🎪 The Big Picture: What’s This All About?
Imagine you’re building a LEGO castle. You have many pieces—walls, towers, doors, windows. Before putting everything together, wouldn’t it be smart to test each piece separately?
That’s exactly what Component Testing does!
Instead of testing your whole app (the entire castle), you test one piece at a time (just the door, just the window). This way, if something breaks, you know exactly which piece is the problem!
🧩 Component Testing: Test One Piece at a Time
What Is a Component?
Think of a component like a LEGO brick. It’s a small, reusable piece of your app.
🧱 Examples of Components:
• A "Like" button
• A search bar
• A user profile card
• A dropdown menu
Why Test Components Alone?
| Testing the Whole App | Testing Components |
|---|---|
| 🐢 Slow | ⚡ Super Fast |
| 🔍 Hard to find bugs | 🎯 Easy to spot issues |
| 📦 Need everything running | 🧩 Just the piece you want |
Real Example:
// This is a simple React button component
function LikeButton({ onClick }) {
return (
<button onClick={onClick}>
❤️ Like
</button>
);
}
With component testing, you can test JUST this button—does it show the heart? Does clicking it work?
🎬 Mounting Components: Putting Your Piece on Stage
The Theatre Analogy 🎭
Imagine a theatre stage. Before an actor performs, they need to:
- Walk onto the stage (mount)
- Perform their scene (interact)
- Walk off the stage (unmount)
Mounting = Putting your component on a “mini stage” so you can test it!
How Mounting Works
graph TD A["Your Component Code"] --> B["Mount Function"] B --> C["Mini Browser Stage"] C --> D["Ready to Test! ✅"]
Simple Mounting Example
// playwright-ct.config.ts
import { defineConfig } from '@playwright/experimental-ct-react';
export default defineConfig({
testDir: './tests',
use: {
ctPort: 3100,
},
});
// tests/LikeButton.spec.tsx
import { test, expect } from '@playwright/experimental-ct-react';
import { LikeButton } from '../src/LikeButton';
test('button shows heart', async ({ mount }) => {
// Put the button on our mini stage
const component = await mount(<LikeButton />);
// Check if we can see the heart
await expect(component).toContainText('❤️');
});
What mount() Actually Does
1. Creates a tiny webpage
2. Puts your component inside it
3. Gives you a handle to interact with it
Think of it like putting a toy on a test table. Now you can poke it, press it, and see what happens!
🌐 Web Server Configuration: The Behind-the-Scenes Crew
Why Do We Need a Web Server?
Your component needs a home to live in while being tested. A web server is like a temporary house that holds your component.
graph TD A["Your Component"] --> B["Web Server"] B --> C["Test Browser"] C --> D["Playwright Tests"]
The Restaurant Kitchen Analogy 🍳
Think of testing like ordering food:
- Your component = The dish being prepared
- Web server = The kitchen where it’s cooked
- Browser = The plate it’s served on
- Your test = The taste tester!
Without a kitchen (web server), there’s nowhere to prepare the food (component)!
⚙️ webServer in Config: Your Automatic Kitchen Starter
The Magic Button 🔘
The webServer option in your config is like having a magic button that:
- Starts your kitchen (server) automatically
- Waits until it’s ready
- Runs your tests
- Shuts everything down when done
Basic webServer Setup
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
webServer: {
command: 'npm run dev',
port: 3000,
reuseExistingServer: true,
},
});
What Each Part Means
| Option | What It Does | Analogy |
|---|---|---|
command |
Starts your server | “Turn on the stove” |
port |
Which door to use | “Kitchen window #3000” |
reuseExistingServer |
Use existing if running | “Don’t start a new kitchen if one exists” |
Full Configuration Example
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests',
webServer: {
command: 'npm run dev',
port: 3000,
timeout: 120000,
reuseExistingServer: !process.env.CI,
},
use: {
baseURL: 'http://localhost:3000',
},
});
Multiple Servers? No Problem!
Sometimes you need more than one server (like a kitchen AND a bakery):
// playwright.config.ts
export default defineConfig({
webServer: [
{
command: 'npm run start:api',
port: 4000,
},
{
command: 'npm run start:web',
port: 3000,
},
],
});
🎯 Putting It All Together
Complete Component Test Setup
// playwright-ct.config.ts
import { defineConfig, devices } from '@playwright/experimental-ct-react';
export default defineConfig({
testDir: './tests/components',
// Timeout for each test
timeout: 10000,
// Run tests in parallel
fullyParallel: true,
// Fail the build on CI if you accidentally left test.only in the source code
forbidOnly: !!process.env.CI,
use: {
ctPort: 3100,
ctViteConfig: {
// Your Vite config here
},
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
});
Your First Complete Test
// tests/Counter.spec.tsx
import { test, expect } from '@playwright/experimental-ct-react';
import { Counter } from '../src/Counter';
test('counter starts at zero', async ({ mount }) => {
const component = await mount(<Counter />);
await expect(component).toContainText('Count: 0');
});
test('clicking increases count', async ({ mount }) => {
const component = await mount(<Counter />);
await component.getByRole('button').click();
await expect(component).toContainText('Count: 1');
});
🎊 You Did It!
You now understand:
✅ Component Testing - Testing one piece at a time ✅ Mounting Components - Putting pieces on a test stage ✅ Web Server Configuration - Setting up the behind-the-scenes magic ✅ webServer in Config - Auto-starting your test environment
graph TD A["Write Component"] --> B["Configure webServer"] B --> C["Mount Component"] C --> D["Run Tests"] D --> E["Happy Developer! 🎉"]
💡 Quick Tips
🚀 Pro Tip: Use
reuseExistingServer: trueduring development. It saves time by not restarting the server every time!
🧠 Remember: Component tests run in a real browser, so they catch real bugs!
⚡ Speed Hack: Component tests are much faster than full end-to-end tests. Use them for quick feedback!
Now go test those components like a pro! 🎭✨
