Playwright Cheatsheet
Debugging
Use this Playwright reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Playwright Inspector
npx playwright test --debug # pause before every test npx playwright test --debug tests/foo.spec.ts # specific file npx playwright test --debug -g "my test" # filter by name PWDEBUG=1 npx playwright test # env var equivalent
In the Inspector you can: - Step through actions one at a time - Hover to highlight elements in the browser - Use the Pick locator tool to generate selectors - See action log with timing
page.pause()
test('debug this', async ({ page }) => { await page.goto('/'); await page.pause(); // <-- execution stops here; Inspector opens await page.locator('button').click(); });
UI mode (interactive test runner)
npx playwright test --ui
- Watch mode — re-run tests on file save
- Timeline view of each action
- Live DOM snapshot viewer
- Network waterfall
- Filter tests by file, title, tag, status
- Pick locator tool built-in
Headed mode (visible browser)
npx playwright test --headed npx playwright test --headed --slowMo=500 # slow down actions by 500 ms
// In config / fixture const browser = await chromium.launch({ headless: false, slowMo: 100 });
Verbose logging
DEBUG=pw:api npx playwright test # Playwright API calls DEBUG=pw:browser npx playwright test # browser protocol messages DEBUG=pw:* npx playwright test # everything
console & page errors
// Capture browser console messages page.on('console', msg => { console.log(`[${msg.type()}] ${msg.text()}`); }); // Capture uncaught errors page.on('pageerror', err => { console.error('Page error:', err.message); }); // Fail test on console errors page.on('console', msg => { if (msg.type() === 'error') throw new Error(`Console error: ${msg.text()}`); });
Custom error messages in assertions
await expect(locator, 'Submit button should be visible after form loads') .toBeVisible({ timeout: 10_000 }); await expect(page, 'Should redirect to dashboard after login') .toHaveURL('/dashboard');
Taking screenshots on failure (manual)
test.afterEach(async ({ page }, testInfo) => { if (testInfo.status !== testInfo.expectedStatus) { const screenshotPath = testInfo.outputPath('screenshot.png'); await page.screenshot({ path: screenshotPath, fullPage: true }); await testInfo.attach('failure-screenshot', { path: screenshotPath, contentType: 'image/png', }); } });
Codegen — record tests from browser
npx playwright codegen https://example.com # opens browser + inspector npx playwright codegen --target=playwright-test # TypeScript output (default) npx playwright codegen --viewport-size=390,844 # mobile viewport npx playwright codegen --device="iPhone 13" npx playwright codegen --save-storage=auth.json # save cookies after recording npx playwright codegen --load-storage=auth.json # start authenticated
Codegen outputs to stdout; copy-paste or redirect:
npx playwright codegen https://example.com > tests/recorded.spec.ts
locator.highlight() — visual debug
// Highlight a locator in the browser for visual inspection await page.locator('.card').first().highlight();
page.locator.evaluate — inspect DOM state
const classes = await page.locator('#btn').evaluate(el => el.className); console.log(classes); const computed = await page.locator('h1').evaluate(el => getComputedStyle(el).color );
Tracing for post-mortem debugging
// playwright.config.ts — keep trace on failure use: { trace: 'retain-on-failure' } // View trace after a failed run: npx playwright show-trace test-results/my-test/trace.zip
The trace viewer shows: - Timeline — every action + duration - Before/after DOM snapshots — interactive clicking - Network — all HTTP requests - Console — log messages
Selectors — debugging strategies
// Count matching elements const count = await page.locator('.item').count(); console.log(count); // Check text content const texts = await page.locator('li').allTextContents(); console.log(texts); // Dump element handle properties const box = await page.locator('#btn').boundingBox(); console.log(box); // { x, y, width, height } or null if not visible // Check visibility manually const visible = await page.locator('#modal').isVisible();
Isolate a test run
npx playwright test tests/auth.spec.ts # single file npx playwright test -g "should login" # by title substring npx playwright test --project=chromium # single browser npx playwright test tests/auth.spec.ts:42 # line number
Test step annotations
test('checkout flow', async ({ page }) => { await test.step('navigate to cart', async () => { await page.goto('/cart'); }); await test.step('enter payment info', async () => { await page.locator('#card-number').fill('4242424242424242'); }); });
Steps appear in the HTML report and trace viewer with their own timing.
CLI flags reference
| Flag | Description |
|---|---|
--debug | Open Inspector before first action |
--ui | Interactive UI mode |
--headed | Run with visible browser |
--slowMo=N | Slow actions by N ms |
--timeout=N | Per-test timeout ms |
--retries=N | Number of retries |
--workers=N | Worker count |
--reporter=X | Reporter type |
--project=X | Run specific project |
-g "pattern" | Filter by test title |
--grep-invert "pat" | Exclude by title |
--list | List tests without running |
--update-snapshots | Update visual snapshots |
--forbid-only | Fail if test.only present |
--last-failed | Re-run only previously failed tests |
--pass-with-no-tests | Exit 0 even if no tests found |