3.8 KiB
3.8 KiB
Debugging Guide
Playwright Inspector
# Run in debug mode
npx playwright test --debug
# Debug specific test
npx playwright test my-test.spec.ts --debug
# Headed mode (see browser)
npx playwright test --headed
// Pause in test
await page.pause();
Trace Viewer
# Record trace
npx playwright test --trace on
# View trace file
npx playwright show-trace trace.zip
// Config for traces
use: {
trace: 'on-first-retry', // Only on failures
trace: 'retain-on-failure', // Keep failed traces
}
Common Errors
Element Not Found
Error: Timeout 30000ms exceeded waiting for selector
Causes:
- Element doesn't exist in DOM
- Element is inside iframe
- Element is in shadow DOM
- Page hasn't loaded
Fixes:
// Wait for element
await page.waitForSelector('.element');
// Check frame context
const frame = page.frameLocator('iframe');
await frame.locator('.element').click();
// Increase timeout
await page.click('.element', { timeout: 60000 });
Flaky Click
Error: Element is not visible
Error: Element is outside viewport
Fixes:
// Ensure visible
await page.locator('.btn').waitFor({ state: 'visible' });
await page.locator('.btn').click();
// Scroll into view
await page.locator('.btn').scrollIntoViewIfNeeded();
// Force click (bypass checks)
await page.locator('.btn').click({ force: true });
Timeout in CI
Causes:
- Slower CI environment
- Network latency
- Resource constraints
Fixes:
// Increase global timeout
export default defineConfig({
timeout: 60000,
expect: { timeout: 10000 },
});
// Use polling assertions
await expect.poll(async () => {
return await page.locator('.items').count();
}, { timeout: 30000 }).toBeGreaterThan(5);
Stale Element
Error: Element is no longer attached to DOM
Fix:
// Don't store element references
const button = page.locator('.submit'); // This is fine (locator)
// Re-query when needed
await button.click(); // Playwright re-queries automatically
Network Issues
// Log all requests
page.on('request', request => {
console.log('>>', request.method(), request.url());
});
page.on('response', response => {
console.log('<<', response.status(), response.url());
});
// Wait for specific request
const responsePromise = page.waitForResponse('**/api/data');
await page.click('.load-data');
const response = await responsePromise;
Screenshot Debugging
// Take screenshot on failure
test.afterEach(async ({ page }, testInfo) => {
if (testInfo.status !== 'passed') {
await page.screenshot({
path: `screenshots/${testInfo.title}.png`,
fullPage: true,
});
}
});
Console Logs
// Capture console messages
page.on('console', msg => {
console.log('PAGE LOG:', msg.text());
});
page.on('pageerror', error => {
console.log('PAGE ERROR:', error.message);
});
Slow Motion
// playwright.config.ts
use: {
launchOptions: {
slowMo: 500, // 500ms delay between actions
},
}
Compare Local vs CI
| Check | Command |
|---|---|
| Viewport | await page.viewportSize() |
| User agent | await page.evaluate(() => navigator.userAgent) |
| Timezone | await page.evaluate(() => Intl.DateTimeFormat().resolvedOptions().timeZone) |
| Network | page.on('request', ...) to log all requests |
Debugging Checklist
- Run with
--debugor--headed - Add
await page.pause()before failure point - Check for iframes/shadow DOM
- Verify element exists with
page.locator().count() - Review trace file in Trace Viewer
- Compare screenshots between local and CI
- Check console for JS errors
- Verify network requests completed