21-Day Playwright Challenge — Day 1: Installation, First Test, and How Playwright Works
This is Day 1 of the 21-Day Playwright with TypeScript Challenge. One lesson per day. Zero to production-ready in 3 weeks.
🎭 Want to master this with real projects? Join the Playwright Automation Mastery course at The Testing Academy.
Playwright communicates directly with browsers via Chrome DevTools Protocol (CDP) — no driver middleman like Selenium. This makes it faster, more reliable, and eliminates driver version headaches. Today you install it, write your first test, and understand what happens under the hood.
Contents
Installation
# Create new project
npm init playwright@latest
# What this does:
# 1. Creates package.json with @playwright/test
# 2. Creates playwright.config.ts
# 3. Creates tests/ directory with example test
# 4. Downloads Chromium, Firefox, WebKit browsers
# 5. Optionally adds GitHub Actions workflow
Your First Test
// tests/example.spec.ts
import { test, expect } from '@playwright/test';
test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');
await expect(page).toHaveTitle(/Playwright/);
});
test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');
await page.getByRole('link', { name: 'Get started' }).click();
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});
Running Tests
# Run all tests (headless)
npx playwright test
# Run with browser visible
npx playwright test --headed
# Run specific test file
npx playwright test tests/example.spec.ts
# Run with UI Mode (interactive)
npx playwright test --ui
# Run in debug mode
npx playwright test --debug
🚀 Level Up Your Playwright
From locators to CI pipelines — build a production-grade Playwright + TypeScript framework step by step.
How Playwright Works Under the Hood
Your Test Code (TypeScript)
|
v
Playwright API (page.goto, locator, click, expect)
|
v
CDP / BiDi Protocol (WebSocket - direct connection!)
|
v
Browser (Chromium, Firefox, WebKit)
Key difference from Selenium:
- No HTTP-based driver middleman
- WebSocket = persistent connection = faster
- Browser bundled with package = no version mismatch
Understanding playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests', // Where tests live
fullyParallel: true, // Run tests in parallel
retries: process.env.CI ? 2 : 0, // Retry on CI only
workers: process.env.CI ? 1 : undefined,
reporter: 'html', // HTML report
use: {
baseURL: 'http://localhost:3000', // Base URL for relative paths
trace: 'on-first-retry', // Record trace on retry
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
],
});
Key Concepts You Just Learned
- test() — defines a test case with a name and async function
- page — represents a browser tab (injected via fixture)
- expect() — auto-retrying assertion (waits until condition met or timeout)
- getByRole() — finds elements by accessibility role (preferred locator)
- goto() — navigates to a URL
Tomorrow (Day 2): Locator strategies — why getByRole wins and XPath loses.
🎓 Master Playwright End to End
Join hundreds of SDETs building real automation frameworks. Lifetime access, hands-on projects, and a job-ready portfolio.
