@assertrx/dino 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +293 -0
  2. package/extensions/dino.ts +70 -0
  3. package/extensions/mabl-mcp.ts +306 -0
  4. package/extensions/playwright-mcp.ts +142 -0
  5. package/package.json +47 -0
  6. package/prompts/create-pr.md +110 -0
  7. package/prompts/generate-bdd-from-url.md +65 -0
  8. package/prompts/generate-pom-from-url-cli.md +48 -0
  9. package/prompts/generate-pom-from-url.md +45 -0
  10. package/prompts/generate-spec-from-feature.md +64 -0
  11. package/prompts/heal-playwright-failures.md +106 -0
  12. package/prompts/setup-playwright.md +81 -0
  13. package/scripts/start-dino.cmd +8 -0
  14. package/scripts/start-dino.mjs +226 -0
  15. package/scripts/start-dino.ps1 +9 -0
  16. package/scripts/start-dino.sh +10 -0
  17. package/skills/acli/SKILL.md +292 -0
  18. package/skills/bdd-gherkin/SKILL.md +552 -0
  19. package/skills/build-review-interface/SKILL.md +96 -0
  20. package/skills/error-analysis/SKILL.md +164 -0
  21. package/skills/eval-audit/SKILL.md +183 -0
  22. package/skills/evaluate-rag/SKILL.md +177 -0
  23. package/skills/generate-synthetic-data/SKILL.md +131 -0
  24. package/skills/mabl-mcp/SKILL.md +79 -0
  25. package/skills/playwright-cli/SKILL.md +246 -0
  26. package/skills/playwright-cli/advanced-workflows.md +679 -0
  27. package/skills/playwright-cli/core-commands.md +375 -0
  28. package/skills/playwright-cli/device-emulation.md +475 -0
  29. package/skills/playwright-cli/request-mocking.md +373 -0
  30. package/skills/playwright-cli/running-custom-code.md +553 -0
  31. package/skills/playwright-cli/screenshots-and-media.md +457 -0
  32. package/skills/playwright-cli/session-management.md +425 -0
  33. package/skills/playwright-cli/storage-and-auth.md +487 -0
  34. package/skills/playwright-cli/test-generation.md +336 -0
  35. package/skills/playwright-cli/tracing-and-debugging.md +501 -0
  36. package/skills/playwright-core/SKILL.md +101 -0
  37. package/skills/playwright-core/accessibility.md +1517 -0
  38. package/skills/playwright-core/angular.md +1086 -0
  39. package/skills/playwright-core/api-testing.md +1623 -0
  40. package/skills/playwright-core/assertions-and-waiting.md +703 -0
  41. package/skills/playwright-core/auth-flows.md +1081 -0
  42. package/skills/playwright-core/authentication.md +1409 -0
  43. package/skills/playwright-core/browser-apis.md +673 -0
  44. package/skills/playwright-core/browser-extensions.md +319 -0
  45. package/skills/playwright-core/canvas-and-webgl.md +494 -0
  46. package/skills/playwright-core/clock-and-time-mocking.md +427 -0
  47. package/skills/playwright-core/common-pitfalls.md +1318 -0
  48. package/skills/playwright-core/component-testing.md +1179 -0
  49. package/skills/playwright-core/configuration.md +731 -0
  50. package/skills/playwright-core/crud-testing.md +945 -0
  51. package/skills/playwright-core/debugging.md +827 -0
  52. package/skills/playwright-core/drag-and-drop.md +992 -0
  53. package/skills/playwright-core/electron-testing.md +622 -0
  54. package/skills/playwright-core/error-and-edge-cases.md +1181 -0
  55. package/skills/playwright-core/error-index.md +1903 -0
  56. package/skills/playwright-core/file-operations.md +749 -0
  57. package/skills/playwright-core/file-upload-download.md +1012 -0
  58. package/skills/playwright-core/fixtures-and-hooks.md +1072 -0
  59. package/skills/playwright-core/flaky-tests.md +883 -0
  60. package/skills/playwright-core/forms-and-validation.md +1056 -0
  61. package/skills/playwright-core/i18n-and-localization.md +622 -0
  62. package/skills/playwright-core/iframes-and-shadow-dom.md +488 -0
  63. package/skills/playwright-core/locator-strategy.md +588 -0
  64. package/skills/playwright-core/locators.md +743 -0
  65. package/skills/playwright-core/mobile-and-responsive.md +1669 -0
  66. package/skills/playwright-core/multi-context-and-popups.md +581 -0
  67. package/skills/playwright-core/multi-user-and-collaboration.md +477 -0
  68. package/skills/playwright-core/network-mocking.md +1395 -0
  69. package/skills/playwright-core/nextjs.md +1013 -0
  70. package/skills/playwright-core/performance-testing.md +608 -0
  71. package/skills/playwright-core/react.md +1082 -0
  72. package/skills/playwright-core/search-and-filter.md +1366 -0
  73. package/skills/playwright-core/security-testing.md +624 -0
  74. package/skills/playwright-core/service-workers-and-pwa.md +524 -0
  75. package/skills/playwright-core/test-architecture.md +569 -0
  76. package/skills/playwright-core/test-data-management.md +1209 -0
  77. package/skills/playwright-core/test-organization.md +947 -0
  78. package/skills/playwright-core/third-party-integrations.md +754 -0
  79. package/skills/playwright-core/trace-analysis.md +161 -0
  80. package/skills/playwright-core/visual-regression.md +1027 -0
  81. package/skills/playwright-core/vue.md +1162 -0
  82. package/skills/playwright-core/websockets-and-realtime.md +623 -0
  83. package/skills/playwright-core/when-to-mock.md +827 -0
  84. package/skills/playwright-pom/SKILL.md +94 -0
  85. package/skills/playwright-pom/page-object-model.md +921 -0
  86. package/skills/playwright-pom/pom-vs-fixtures-vs-helpers.md +937 -0
  87. package/skills/validate-evaluator/SKILL.md +215 -0
  88. package/skills/write-judge-prompt/SKILL.md +144 -0
  89. package/themes/dino.json +66 -0
@@ -0,0 +1,827 @@
1
+ # Debugging Playwright Tests
2
+
3
+ > **When to use**: A test is failing and you need to understand why — wrong selectors, timing issues, network failures, or unexpected application state.
4
+
5
+ ## Quick Reference
6
+
7
+ | Tool | Command | Best For |
8
+ |---|---|---|
9
+ | UI Mode | `npx playwright test --ui` | Interactive exploration, visual timeline, re-running tests |
10
+ | Playwright Inspector | `PWDEBUG=1 npx playwright test` | Step-through debugging, selector playground |
11
+ | Trace Viewer | `npx playwright show-trace trace.zip` | Post-mortem CI failure analysis |
12
+ | CLI debugger | `npx playwright test --debug=cli` | Agent workflows, SSH sessions, terminal-first debugging |
13
+ | Headed mode | `npx playwright test --headed` | Watching the browser during test execution |
14
+ | Slow motion | `npx playwright test --headed --slow-mo=500` | Visually following fast interactions |
15
+ | `page.pause()` | Insert in test code | Pausing at an exact point to inspect state |
16
+ | Verbose API logs | `DEBUG=pw:api npx playwright test` | Seeing every Playwright API call with timing |
17
+ | VS Code extension | Playwright Test for VS Code | Breakpoints, step-through, pick locator |
18
+
19
+ ## Systematic Debugging Workflow
20
+
21
+ Follow this order. Do not skip to step 5 — most issues resolve by step 2.
22
+
23
+ ```
24
+ 1. Read the full error message
25
+ └─ Check troubleshooting/error-index.md for known patterns
26
+ 2. Run with --ui to see what happened visually
27
+ └─ Timeline shows every action, screenshot at failure point
28
+ 3. Enable tracing if not already on
29
+ └─ use: { trace: 'on' } temporarily in config
30
+ 4. Check the network tab in trace for API failures
31
+ └─ Missing responses, 4xx/5xx, CORS errors
32
+ 5. Insert page.pause() at the failure point
33
+ └─ Inspect live DOM, try selectors in console
34
+ 6. Check browser console for JavaScript errors
35
+ └─ page.on('console') or console tab in trace
36
+ ```
37
+
38
+ ## Patterns
39
+
40
+ ### Pattern 1: UI Mode for Interactive Debugging
41
+
42
+ **Use when**: Developing new tests, investigating failures locally, exploring application behavior.
43
+ **Avoid when**: CI environments (use traces instead).
44
+
45
+ UI Mode provides a visual timeline, DOM snapshots at each step, network waterfall, and the ability to re-run individual tests.
46
+
47
+ **TypeScript**
48
+ ```typescript
49
+ // Launch UI Mode from terminal:
50
+ // npx playwright test --ui
51
+
52
+ // Run a specific test file in UI Mode:
53
+ // npx playwright test tests/checkout.spec.ts --ui
54
+
55
+ // playwright.config.ts — configure for UI Mode convenience
56
+ import { defineConfig } from '@playwright/test';
57
+
58
+ export default defineConfig({
59
+ use: {
60
+ // Traces are always available in UI Mode regardless of this setting,
61
+ // but this ensures traces are captured for CI failures too
62
+ trace: 'on-first-retry',
63
+ },
64
+ });
65
+ ```
66
+
67
+ For flaky tests on Playwright 1.59+, consider `trace: 'retain-on-failure-and-retries'` so you can compare the failing attempt with any passing retries instead of keeping only one trace artifact.
68
+
69
+ **JavaScript**
70
+ ```javascript
71
+ // Launch UI Mode from terminal:
72
+ // npx playwright test --ui
73
+
74
+ // Run a specific test file in UI Mode:
75
+ // npx playwright test tests/checkout.spec.js --ui
76
+
77
+ // playwright.config.js
78
+ const { defineConfig } = require('@playwright/test');
79
+
80
+ module.exports = defineConfig({
81
+ use: {
82
+ trace: 'on-first-retry',
83
+ },
84
+ });
85
+ ```
86
+
87
+ ### Pattern 2: Playwright Inspector with PWDEBUG
88
+
89
+ **Use when**: You need to step through actions one at a time, test selectors interactively, or see the exact state before and after each action.
90
+ **Avoid when**: The failure is visible from the error message or trace alone.
91
+
92
+ **TypeScript**
93
+ ```typescript
94
+ // Launch Inspector from terminal:
95
+ // PWDEBUG=1 npx playwright test tests/login.spec.ts
96
+
97
+ // On Windows PowerShell:
98
+ // $env:PWDEBUG=1; npx playwright test tests/login.spec.ts
99
+
100
+ // On Windows CMD:
101
+ // set PWDEBUG=1 && npx playwright test tests/login.spec.ts
102
+
103
+ // Inspector opens automatically. Use these controls:
104
+ // - "Step over" button: execute one action at a time
105
+ // - "Pick locator" button: hover elements to see the best locator
106
+ // - "Resume" button: run to the next page.pause() or end
107
+
108
+ import { test, expect } from '@playwright/test';
109
+
110
+ test('debug login flow', async ({ page }) => {
111
+ await page.goto('/login');
112
+
113
+ // Inspector pauses before each action when PWDEBUG=1
114
+ await page.getByLabel('Email').fill('user@example.com');
115
+ await page.getByLabel('Password').fill('password123');
116
+ await page.getByRole('button', { name: 'Sign in' }).click();
117
+
118
+ await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
119
+ });
120
+ ```
121
+
122
+ **JavaScript**
123
+ ```javascript
124
+ // Launch Inspector from terminal:
125
+ // PWDEBUG=1 npx playwright test tests/login.spec.js
126
+
127
+ const { test, expect } = require('@playwright/test');
128
+
129
+ test('debug login flow', async ({ page }) => {
130
+ await page.goto('/login');
131
+
132
+ await page.getByLabel('Email').fill('user@example.com');
133
+ await page.getByLabel('Password').fill('password123');
134
+ await page.getByRole('button', { name: 'Sign in' }).click();
135
+
136
+ await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
137
+ });
138
+ ```
139
+
140
+ ### Pattern 3: Trace Viewer for CI Failure Analysis
141
+
142
+ **Use when**: A test fails in CI and you need to understand what happened without re-running locally.
143
+ **Avoid when**: You can reproduce the failure locally (use UI Mode or Inspector instead).
144
+
145
+ **TypeScript**
146
+ ```typescript
147
+ // playwright.config.ts — trace configuration
148
+ import { defineConfig } from '@playwright/test';
149
+
150
+ export default defineConfig({
151
+ retries: process.env.CI ? 2 : 0,
152
+ use: {
153
+ // 'on-first-retry' — captures trace on first retry only (recommended for CI)
154
+ // 'on' — captures every run (use temporarily for stubborn failures)
155
+ // 'retain-on-failure' — captures every run, keeps only failures
156
+ trace: 'on-first-retry',
157
+ },
158
+ });
159
+
160
+ // After CI failure, download the trace artifact and open it:
161
+ // npx playwright show-trace test-results/tests-login-Login-test-chromium/trace.zip
162
+
163
+ // Or open from URL:
164
+ // npx playwright show-trace https://ci.example.com/artifacts/trace.zip
165
+
166
+ // Or use trace.playwright.dev to view traces in the browser — drag and drop the zip file
167
+ ```
168
+
169
+ **JavaScript**
170
+ ```javascript
171
+ // playwright.config.js
172
+ const { defineConfig } = require('@playwright/test');
173
+
174
+ module.exports = defineConfig({
175
+ retries: process.env.CI ? 2 : 0,
176
+ use: {
177
+ trace: 'on-first-retry',
178
+ },
179
+ });
180
+
181
+ // After CI failure, download the trace artifact and open it:
182
+ // npx playwright show-trace test-results/tests-login-Login-test-chromium/trace.zip
183
+ ```
184
+
185
+ **Reading a trace — what to check in order:**
186
+
187
+ 1. **Actions tab** — see every Playwright action with before/after screenshots
188
+ 2. **Console tab** — browser console output (errors, warnings, logs)
189
+ 3. **Network tab** — every HTTP request with status, timing, request/response bodies
190
+ 4. **Source tab** — test source code highlighting the failing line
191
+ 5. **Call tab** — exact arguments and return values of each Playwright call
192
+
193
+ ### Pattern 3b: CLI Debugger for Agent Workflows
194
+
195
+ **Use when**: You are debugging from a terminal, remote machine, or coding-agent workflow where opening the full inspector is awkward.
196
+ **Avoid when**: You want the richest interactive UI locally; use UI Mode or Inspector for that.
197
+
198
+ ```bash
199
+ # Start a paused debugging session
200
+ npx playwright test --debug=cli
201
+
202
+ # Attach from another terminal using the session id printed by Playwright
203
+ playwright-cli attach tw-87b59e
204
+ playwright-cli --session=tw-87b59e snapshot
205
+ playwright-cli --session=tw-87b59e step-over
206
+ playwright-cli --session=tw-87b59e console error
207
+ ```
208
+
209
+ This flow is ideal when an agent or teammate needs to inspect the live browser state without leaving the command line.
210
+
211
+ ### Pattern 3c: Terminal Trace Analysis
212
+
213
+ **Use when**: You have a trace archive but need fast answers from a shell, CI worker, or remote box.
214
+ **Avoid when**: You need the full visual timeline; use Trace Viewer for that.
215
+
216
+ ```bash
217
+ npx playwright trace open test-results/checkout-chromium/trace.zip
218
+ npx playwright trace actions --grep="expect"
219
+ npx playwright trace action 9
220
+ npx playwright trace snapshot 9 --name after
221
+ npx playwright trace close
222
+ ```
223
+
224
+ This is especially helpful for agentic repair loops and flaky-test triage, where opening a GUI trace viewer adds friction.
225
+
226
+ ### Pattern 4: Headed Mode with Slow Motion
227
+
228
+ **Use when**: You want to watch the browser during execution without the full Inspector overhead.
229
+ **Avoid when**: The test runs too fast to follow even with slow-mo (use Inspector instead).
230
+
231
+ **TypeScript**
232
+ ```typescript
233
+ // From terminal — quick visual debugging:
234
+ // npx playwright test tests/checkout.spec.ts --headed --slow-mo=500
235
+
236
+ // playwright.config.ts — configure headed mode for local development
237
+ import { defineConfig } from '@playwright/test';
238
+
239
+ export default defineConfig({
240
+ use: {
241
+ // Do NOT commit these — use CLI flags or environment checks instead
242
+ headless: !process.env.HEADED,
243
+ launchOptions: {
244
+ slowMo: process.env.SLOW_MO ? parseInt(process.env.SLOW_MO) : 0,
245
+ },
246
+ },
247
+ });
248
+
249
+ // Then run:
250
+ // HEADED=1 SLOW_MO=500 npx playwright test tests/checkout.spec.ts
251
+ ```
252
+
253
+ **JavaScript**
254
+ ```javascript
255
+ // From terminal:
256
+ // npx playwright test tests/checkout.spec.js --headed --slow-mo=500
257
+
258
+ // playwright.config.js
259
+ const { defineConfig } = require('@playwright/test');
260
+
261
+ module.exports = defineConfig({
262
+ use: {
263
+ headless: !process.env.HEADED,
264
+ launchOptions: {
265
+ slowMo: process.env.SLOW_MO ? parseInt(process.env.SLOW_MO) : 0,
266
+ },
267
+ },
268
+ });
269
+ ```
270
+
271
+ ### Pattern 5: VS Code Integration
272
+
273
+ **Use when**: You prefer IDE-based debugging with breakpoints, variable inspection, and integrated test running.
274
+ **Avoid when**: You are debugging CI-only failures that do not reproduce locally.
275
+
276
+ Install the **Playwright Test for VS Code** extension (`ms-playwright.playwright`).
277
+
278
+ **Key capabilities:**
279
+ - **Run/debug individual tests** — click the green play button in the gutter next to any `test()`
280
+ - **Set breakpoints** — click the gutter to set breakpoints; tests pause at them automatically
281
+ - **Pick locator** — use the "Pick locator" command to hover over elements and get the best selector
282
+ - **Show browser** — check "Show Browser" in the testing sidebar to see the browser during execution
283
+ - **Watch mode** — enable to re-run tests on file save
284
+
285
+ **TypeScript**
286
+ ```typescript
287
+ // When debugging in VS Code, use test.only() to focus on one test
288
+ // instead of running the entire suite through the debugger
289
+ import { test, expect } from '@playwright/test';
290
+
291
+ test.only('debug this specific test', async ({ page }) => {
292
+ await page.goto('/products');
293
+
294
+ // Set a VS Code breakpoint on this line, then inspect `page` in the debug panel
295
+ const productCard = page.getByRole('listitem').filter({ hasText: 'Widget' });
296
+ await expect(productCard).toBeVisible();
297
+
298
+ await productCard.getByRole('button', { name: 'Add to cart' }).click();
299
+ await expect(page.getByTestId('cart-count')).toHaveText('1');
300
+ });
301
+ ```
302
+
303
+ **JavaScript**
304
+ ```javascript
305
+ const { test, expect } = require('@playwright/test');
306
+
307
+ test.only('debug this specific test', async ({ page }) => {
308
+ await page.goto('/products');
309
+
310
+ const productCard = page.getByRole('listitem').filter({ hasText: 'Widget' });
311
+ await expect(productCard).toBeVisible();
312
+
313
+ await productCard.getByRole('button', { name: 'Add to cart' }).click();
314
+ await expect(page.getByTestId('cart-count')).toHaveText('1');
315
+ });
316
+ ```
317
+
318
+ ### Pattern 6: Capturing Browser Console Logs
319
+
320
+ **Use when**: Suspecting JavaScript errors, failed client-side API calls, or application-level logging that explains the failure.
321
+ **Avoid when**: The issue is clearly a selector or timing problem visible in the trace.
322
+
323
+ **TypeScript**
324
+ ```typescript
325
+ import { test, expect } from '@playwright/test';
326
+
327
+ test('capture console output', async ({ page }) => {
328
+ // Collect all console messages
329
+ const consoleLogs: string[] = [];
330
+ page.on('console', (msg) => {
331
+ consoleLogs.push(`[${msg.type()}] ${msg.text()}`);
332
+ });
333
+
334
+ // Capture uncaught exceptions
335
+ page.on('pageerror', (error) => {
336
+ console.error('Page error:', error.message);
337
+ });
338
+
339
+ await page.goto('/dashboard');
340
+ await page.getByRole('button', { name: 'Load data' }).click();
341
+ await expect(page.getByRole('table')).toBeVisible();
342
+
343
+ // Print collected logs on failure for debugging context
344
+ console.log('Browser console output:', consoleLogs);
345
+ });
346
+
347
+ // Reusable fixture for console logging across all tests
348
+ import { test as base } from '@playwright/test';
349
+
350
+ type ConsoleFixtures = {
351
+ consoleMessages: string[];
352
+ };
353
+
354
+ export const test = base.extend<ConsoleFixtures>({
355
+ consoleMessages: async ({ page }, use) => {
356
+ const messages: string[] = [];
357
+ page.on('console', (msg) => messages.push(`[${msg.type()}] ${msg.text()}`));
358
+ page.on('pageerror', (err) => messages.push(`[pageerror] ${err.message}`));
359
+ await use(messages);
360
+ },
361
+ });
362
+ ```
363
+
364
+ **JavaScript**
365
+ ```javascript
366
+ const { test, expect } = require('@playwright/test');
367
+
368
+ test('capture console output', async ({ page }) => {
369
+ const consoleLogs = [];
370
+ page.on('console', (msg) => {
371
+ consoleLogs.push(`[${msg.type()}] ${msg.text()}`);
372
+ });
373
+
374
+ page.on('pageerror', (error) => {
375
+ console.error('Page error:', error.message);
376
+ });
377
+
378
+ await page.goto('/dashboard');
379
+ await page.getByRole('button', { name: 'Load data' }).click();
380
+ await expect(page.getByRole('table')).toBeVisible();
381
+
382
+ console.log('Browser console output:', consoleLogs);
383
+ });
384
+
385
+ // Reusable fixture for console logging
386
+ const { test: base } = require('@playwright/test');
387
+
388
+ const test = base.extend({
389
+ consoleMessages: async ({ page }, use) => {
390
+ const messages = [];
391
+ page.on('console', (msg) => messages.push(`[${msg.type()}] ${msg.text()}`));
392
+ page.on('pageerror', (err) => messages.push(`[pageerror] ${err.message}`));
393
+ await use(messages);
394
+ },
395
+ });
396
+
397
+ module.exports = { test };
398
+ ```
399
+
400
+ #### Pinpointing Uncaught Errors With `webError.location()` (Playwright 1.60+)
401
+
402
+ `page.on('pageerror')` gives you the error, but not *where* it came from. Playwright 1.60 adds `webError.location()` (on the `context`-level `weberror` event), mirroring `consoleMessage.location()` — so you get the URL, line, and column of an uncaught exception.
403
+
404
+ **TypeScript**
405
+ ```typescript
406
+ import { test, expect } from '@playwright/test';
407
+
408
+ test('capture uncaught errors with their source location', async ({ context, page }) => {
409
+ context.on('weberror', (webError) => {
410
+ const loc = webError.location(); // { url, line, column } — 0-based
411
+ console.error(
412
+ `Uncaught: ${webError.error().message} @ ${loc.url}:${loc.line}:${loc.column}`
413
+ );
414
+ });
415
+
416
+ await page.goto('/dashboard');
417
+ await page.getByRole('button', { name: 'Load data' }).click();
418
+ await expect(page.getByRole('table')).toBeVisible();
419
+ });
420
+ ```
421
+
422
+ The location makes it far quicker to map a browser-side exception back to the exact source file and line, especially with source maps enabled.
423
+
424
+ ### Pattern 7: Screenshots on Failure
425
+
426
+ **Use when**: You need a visual snapshot at the exact moment of failure.
427
+ **Avoid when**: Traces are enabled (they already include screenshots at every step).
428
+
429
+ **TypeScript**
430
+ ```typescript
431
+ // playwright.config.ts — automatic screenshots on failure
432
+ import { defineConfig } from '@playwright/test';
433
+
434
+ export default defineConfig({
435
+ use: {
436
+ // 'off' — no screenshots (default)
437
+ // 'on' — screenshot after every test
438
+ // 'only-on-failure' — screenshot only when test fails (recommended)
439
+ screenshot: 'only-on-failure',
440
+ },
441
+ });
442
+ ```
443
+
444
+ ```typescript
445
+ // Manual screenshot at a specific point
446
+ import { test, expect } from '@playwright/test';
447
+
448
+ test('debug visual state', async ({ page }) => {
449
+ await page.goto('/checkout');
450
+ await page.getByLabel('Promo code').fill('SAVE20');
451
+ await page.getByRole('button', { name: 'Apply' }).click();
452
+
453
+ // Capture screenshot before assertion for debugging
454
+ await page.screenshot({ path: 'test-results/before-discount.png', fullPage: true });
455
+
456
+ await expect(page.getByTestId('discount-amount')).toHaveText('-$20.00');
457
+ });
458
+ ```
459
+
460
+ **JavaScript**
461
+ ```javascript
462
+ // playwright.config.js
463
+ const { defineConfig } = require('@playwright/test');
464
+
465
+ module.exports = defineConfig({
466
+ use: {
467
+ screenshot: 'only-on-failure',
468
+ },
469
+ });
470
+ ```
471
+
472
+ ```javascript
473
+ // Manual screenshot
474
+ const { test, expect } = require('@playwright/test');
475
+
476
+ test('debug visual state', async ({ page }) => {
477
+ await page.goto('/checkout');
478
+ await page.getByLabel('Promo code').fill('SAVE20');
479
+ await page.getByRole('button', { name: 'Apply' }).click();
480
+
481
+ await page.screenshot({ path: 'test-results/before-discount.png', fullPage: true });
482
+
483
+ await expect(page.getByTestId('discount-amount')).toHaveText('-$20.00');
484
+ });
485
+ ```
486
+
487
+ ### Pattern 8: Network Debugging
488
+
489
+ **Use when**: Suspecting API failures, wrong request payloads, missing auth headers, or slow responses causing timeouts.
490
+ **Avoid when**: The trace network tab already shows the problem.
491
+
492
+ **TypeScript**
493
+ ```typescript
494
+ import { test, expect } from '@playwright/test';
495
+
496
+ test('debug network requests', async ({ page }) => {
497
+ // Log all requests
498
+ page.on('request', (request) => {
499
+ console.log(`>> ${request.method()} ${request.url()}`);
500
+ });
501
+
502
+ // Log all responses with status
503
+ page.on('response', (response) => {
504
+ console.log(`<< ${response.status()} ${response.url()}`);
505
+ });
506
+
507
+ // Log failed requests (network errors, not HTTP errors)
508
+ page.on('requestfailed', (request) => {
509
+ console.log(`FAILED: ${request.url()} ${request.failure()?.errorText}`);
510
+ });
511
+
512
+ await page.goto('/dashboard');
513
+ await page.getByRole('button', { name: 'Refresh' }).click();
514
+ await expect(page.getByRole('table')).toBeVisible();
515
+ });
516
+
517
+ // Wait for a specific API response and inspect it
518
+ test('inspect API response', async ({ page }) => {
519
+ await page.goto('/products');
520
+
521
+ const responsePromise = page.waitForResponse(
522
+ (resp) => resp.url().includes('/api/products') && resp.status() === 200
523
+ );
524
+
525
+ await page.getByRole('button', { name: 'Load products' }).click();
526
+
527
+ const response = await responsePromise;
528
+ const body = await response.json();
529
+ console.log('API response:', JSON.stringify(body, null, 2));
530
+
531
+ await expect(page.getByRole('listitem')).toHaveCount(body.products.length);
532
+ });
533
+ ```
534
+
535
+ **JavaScript**
536
+ ```javascript
537
+ const { test, expect } = require('@playwright/test');
538
+
539
+ test('debug network requests', async ({ page }) => {
540
+ page.on('request', (request) => {
541
+ console.log(`>> ${request.method()} ${request.url()}`);
542
+ });
543
+
544
+ page.on('response', (response) => {
545
+ console.log(`<< ${response.status()} ${response.url()}`);
546
+ });
547
+
548
+ page.on('requestfailed', (request) => {
549
+ console.log(`FAILED: ${request.url()} ${request.failure()?.errorText}`);
550
+ });
551
+
552
+ await page.goto('/dashboard');
553
+ await page.getByRole('button', { name: 'Refresh' }).click();
554
+ await expect(page.getByRole('table')).toBeVisible();
555
+ });
556
+
557
+ test('inspect API response', async ({ page }) => {
558
+ await page.goto('/products');
559
+
560
+ const responsePromise = page.waitForResponse(
561
+ (resp) => resp.url().includes('/api/products') && resp.status() === 200
562
+ );
563
+
564
+ await page.getByRole('button', { name: 'Load products' }).click();
565
+
566
+ const response = await responsePromise;
567
+ const body = await response.json();
568
+ console.log('API response:', JSON.stringify(body, null, 2));
569
+
570
+ await expect(page.getByRole('listitem')).toHaveCount(body.products.length);
571
+ });
572
+ ```
573
+
574
+ ### Pattern 9: Verbose API Logs
575
+
576
+ **Use when**: You need to see every single Playwright API call with timing to identify where the test is spending time or getting stuck.
577
+ **Avoid when**: You already know which action is failing (use Inspector or `page.pause()` instead).
578
+
579
+ ```bash
580
+ # See all Playwright API calls with timestamps
581
+ DEBUG=pw:api npx playwright test tests/slow-test.spec.ts
582
+
583
+ # See browser protocol messages (very verbose — use sparingly)
584
+ DEBUG=pw:protocol npx playwright test tests/slow-test.spec.ts
585
+
586
+ # Combine multiple debug channels
587
+ DEBUG=pw:api,pw:browser npx playwright test tests/slow-test.spec.ts
588
+
589
+ # Windows PowerShell
590
+ $env:DEBUG="pw:api"; npx playwright test tests/slow-test.spec.ts
591
+
592
+ # Windows CMD
593
+ set DEBUG=pw:api && npx playwright test tests/slow-test.spec.ts
594
+ ```
595
+
596
+ ### Pattern 10: `page.pause()` — Inline Breakpoints
597
+
598
+ **Use when**: You need to pause execution at a precise point to inspect the live DOM, try locators, or check application state.
599
+ **Avoid when**: You can use `PWDEBUG=1` which pauses at every step automatically.
600
+
601
+ **TypeScript**
602
+ ```typescript
603
+ import { test, expect } from '@playwright/test';
604
+
605
+ test('debug with pause', async ({ page }) => {
606
+ await page.goto('/checkout');
607
+ await page.getByLabel('Email').fill('user@example.com');
608
+
609
+ // Execution pauses here — Inspector opens with:
610
+ // - Live DOM inspection
611
+ // - Selector playground (try locators in the console)
612
+ // - Step through remaining actions
613
+ await page.pause();
614
+
615
+ // These actions wait until you click "Resume" in the Inspector
616
+ await page.getByRole('button', { name: 'Continue' }).click();
617
+ await expect(page.getByText('Order confirmed')).toBeVisible();
618
+ });
619
+ ```
620
+
621
+ **JavaScript**
622
+ ```javascript
623
+ const { test, expect } = require('@playwright/test');
624
+
625
+ test('debug with pause', async ({ page }) => {
626
+ await page.goto('/checkout');
627
+ await page.getByLabel('Email').fill('user@example.com');
628
+
629
+ // Execution pauses here — Inspector opens
630
+ await page.pause();
631
+
632
+ await page.getByRole('button', { name: 'Continue' }).click();
633
+ await expect(page.getByText('Order confirmed')).toBeVisible();
634
+ });
635
+ ```
636
+
637
+ **Important**: Remove `page.pause()` before committing. It will hang indefinitely in CI. Use this lint rule or CI check:
638
+
639
+ ```bash
640
+ # Add to your pre-commit hook or CI pipeline
641
+ grep -r "page.pause()" tests/ && echo "ERROR: Remove page.pause() before committing" && exit 1
642
+ ```
643
+
644
+ ### Pattern 11: Styled Highlights and `errorContext` (Playwright 1.60+)
645
+
646
+ **Use when**: You're visually debugging which element a locator resolves to (especially in headed mode or while recording a video), or you want richer diagnostics attached to assertion failures.
647
+ **Avoid when**: A trace already answers the question — it shows the resolved element per step.
648
+
649
+ Playwright 1.60 adds a `style` option to `locator.highlight()` (custom inline CSS on the highlight box) plus `page.hideHighlight()` to clear it. It also surfaces `testInfoError.errorContext`, which carries extra diagnostics — such as the aria snapshot of the element when an `expect()` matcher failed.
650
+
651
+ **TypeScript**
652
+ ```typescript
653
+ import { test, expect } from '@playwright/test';
654
+
655
+ test('highlight an element while debugging headed', async ({ page }) => {
656
+ await page.goto('/dashboard');
657
+
658
+ const cta = page.getByRole('button', { name: 'Upgrade' });
659
+ await cta.highlight({ style: 'outline: 3px solid magenta; background: rgba(255,0,255,.15)' });
660
+
661
+ // ... inspect visually / take a screenshot ...
662
+ await page.hideHighlight();
663
+ });
664
+
665
+ test.afterEach(async ({}, testInfo) => {
666
+ // On failure, surface the diagnostic context Playwright captured
667
+ for (const err of testInfo.errors) {
668
+ if (err.errorContext) {
669
+ console.log('Failure context:\n', err.errorContext);
670
+ }
671
+ }
672
+ });
673
+ ```
674
+
675
+ **JavaScript**
676
+ ```javascript
677
+ const { test, expect } = require('@playwright/test');
678
+
679
+ test('highlight an element while debugging headed', async ({ page }) => {
680
+ await page.goto('/dashboard');
681
+
682
+ const cta = page.getByRole('button', { name: 'Upgrade' });
683
+ await cta.highlight({ style: 'outline: 3px solid magenta' });
684
+
685
+ await page.hideHighlight();
686
+ });
687
+ ```
688
+
689
+ `errorContext` is most useful in custom reporters and `afterEach` hooks where you want to log *why* a matcher failed beyond the bare message.
690
+
691
+ ## Decision Guide
692
+
693
+ Use this table to pick the right tool based on the failure type.
694
+
695
+ | Failure Type | First Tool | Why |
696
+ |---|---|---|
697
+ | **Element not found** (selector wrong) | UI Mode (`--ui`) | See the DOM at the moment of failure, try selectors in Pick Locator |
698
+ | **Element not found** (timing issue) | Trace Viewer — Actions tab | Compare before/after screenshots to see if element appeared after timeout |
699
+ | **Wrong text / value** | Trace Viewer — Actions tab | Inspect the actual DOM content at each action step |
700
+ | **Test hangs / times out** | `DEBUG=pw:api` | See which API call is waiting and never resolving |
701
+ | **Network / API failure** | Trace Viewer — Network tab | See request/response status codes, payloads, timing |
702
+ | **Auth / session issues** | Network debugging (`page.on('response')`) | Check for 401/403 responses, missing cookies/tokens |
703
+ | **Visual rendering wrong** | `--headed --slow-mo=500` | Watch the actual rendering in the browser |
704
+ | **JavaScript error in app** | Console logging (`page.on('console')`) | Catch uncaught exceptions and error logs |
705
+ | **CI-only failure** | Trace Viewer (from CI artifact) | Reproduce the exact CI state without running locally |
706
+ | **Flaky / intermittent** | Trace on every run (`trace: 'on'`) + retries | Compare passing and failing traces side by side |
707
+ | **State pollution** | Run single test with `test.only()` | Isolate from other tests; if it passes alone, state leaks from another test |
708
+
709
+ ## Anti-Patterns
710
+
711
+ ### Adding `waitForTimeout` to fix timing issues
712
+
713
+ ```typescript
714
+ // WRONG — arbitrary delays mask the real problem and make tests slow and flaky
715
+ await page.getByRole('button', { name: 'Submit' }).click();
716
+ await page.waitForTimeout(3000); // "It works with this delay"
717
+ await expect(page.getByText('Success')).toBeVisible();
718
+
719
+ // RIGHT — wait for the actual condition
720
+ await page.getByRole('button', { name: 'Submit' }).click();
721
+ await expect(page.getByText('Success')).toBeVisible(); // Auto-retries for up to 5s
722
+ ```
723
+
724
+ If the default timeout is insufficient, investigate *why* the operation is slow, then either:
725
+ - Fix the application performance
726
+ - Increase the specific assertion timeout: `await expect(locator).toBeVisible({ timeout: 15000 })`
727
+ - Wait for a prerequisite: `await page.waitForResponse('**/api/submit')`
728
+
729
+ ### Commenting out tests to isolate a failure
730
+
731
+ ```typescript
732
+ // WRONG — commenting out tests to find which one causes the failure
733
+ // test('test A', ...);
734
+ // test('test B', ...);
735
+ test('test C — this one fails', async ({ page }) => { /* ... */ });
736
+
737
+ // RIGHT — use .only to run a single test
738
+ test.only('test C — this one fails', async ({ page }) => { /* ... */ });
739
+
740
+ // RIGHT — use grep to run tests matching a pattern
741
+ // npx playwright test --grep "test C"
742
+ ```
743
+
744
+ ### Not reading the full error message
745
+
746
+ Playwright error messages include:
747
+ - The **expected** vs **actual** value
748
+ - The **locator** that was used
749
+ - A **call log** showing what Playwright tried before timing out
750
+ - The **line number** in your test
751
+
752
+ Read all of it. The call log alone often shows exactly what went wrong (e.g., "waiting for selector to be visible" when the element exists but is hidden).
753
+
754
+ ### Debugging in CI without traces
755
+
756
+ ```typescript
757
+ // WRONG — no traces in CI, no way to debug failures
758
+ export default defineConfig({
759
+ use: {
760
+ trace: 'off',
761
+ },
762
+ });
763
+
764
+ // RIGHT — always capture traces on failure in CI
765
+ export default defineConfig({
766
+ retries: process.env.CI ? 2 : 0,
767
+ use: {
768
+ trace: 'on-first-retry',
769
+ },
770
+ });
771
+ ```
772
+
773
+ ### Using `console.log` instead of proper debugging tools
774
+
775
+ ```typescript
776
+ // WRONG — sprinkling console.log everywhere
777
+ test('debug with logs', async ({ page }) => {
778
+ await page.goto('/dashboard');
779
+ console.log('page loaded');
780
+ const el = page.getByRole('button', { name: 'Save' });
781
+ console.log('button found:', await el.isVisible());
782
+ console.log('button text:', await el.textContent());
783
+ // ...20 more console.log calls
784
+
785
+ // RIGHT — use page.pause() at the point of interest
786
+ await page.goto('/dashboard');
787
+ await page.pause(); // Inspect everything interactively
788
+ });
789
+ ```
790
+
791
+ ### Leaving `page.pause()` or `test.only()` in committed code
792
+
793
+ ```typescript
794
+ // WRONG — these should never reach CI
795
+ test.only('focused test', async ({ page }) => { // Skips all other tests
796
+ await page.goto('/');
797
+ await page.pause(); // Hangs forever in CI
798
+ });
799
+
800
+ // Add a CI guard if needed during development
801
+ if (!process.env.CI) {
802
+ await page.pause();
803
+ }
804
+ ```
805
+
806
+ ## Troubleshooting
807
+
808
+ | Symptom | Likely Cause | Fix |
809
+ |---|---|---|
810
+ | Inspector does not open with `PWDEBUG=1` | Running in headless mode or workers > 1 | Run with `--headed` and `--workers=1` |
811
+ | Trace is empty or missing | `trace: 'off'` in config, or test did not retry | Set `trace: 'on'` temporarily, or `trace: 'retain-on-failure'` |
812
+ | UI Mode shows stale test results | File watcher did not pick up changes | Stop UI Mode, clear `test-results/`, restart |
813
+ | `page.pause()` does nothing | `PWDEBUG` is not set and running headless | Run with `--headed` or set `PWDEBUG=1` |
814
+ | Screenshots are blank or wrong size | Viewport not set or test runs on wrong project | Set `viewport` in config; check which browser project ran |
815
+ | Verbose logs are overwhelming | Using `DEBUG=pw:protocol` | Use `DEBUG=pw:api` for a manageable level of detail |
816
+ | Trace file is too large | `trace: 'on'` for all tests, including passing | Switch to `trace: 'on-first-retry'` or `trace: 'retain-on-failure'` |
817
+ | VS Code does not detect tests | Wrong `testDir` or `testMatch` config | Ensure config paths match and extension settings point to your `playwright.config` |
818
+ | Network events not firing | Request was made before listener was attached | Attach `page.on('request')` and `page.on('response')` before `page.goto()` |
819
+
820
+ ## Related
821
+
822
+ - [core/error-index.md](error-index.md) — look up specific error messages
823
+ - [core/flaky-tests.md](flaky-tests.md) — intermittent failure patterns and fixes
824
+ - [core/common-pitfalls.md](common-pitfalls.md) — common beginner mistakes
825
+ - [core/assertions-and-waiting.md](assertions-and-waiting.md) — web-first assertions and auto-waiting
826
+ - [core/configuration.md](configuration.md) — trace, screenshot, and retry configuration
827
+ - [ci/reporting-and-artifacts.md](../ci/reporting-and-artifacts.md) — CI artifact collection for traces and screenshots