@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,731 @@
1
+ # Configuration
2
+
3
+ > **When to use**: Setting up a new Playwright project, adjusting timeouts, adding browser targets, configuring CI behavior, or connecting environment-specific settings.
4
+
5
+ ## Quick Reference
6
+
7
+ ```
8
+ npx playwright init # scaffold config + first test
9
+ npx playwright test --config=custom.config.ts # use non-default config
10
+ npx playwright test --project=chromium # run single project
11
+ npx playwright test --reporter=html # override reporter
12
+ npx playwright show-report # open last HTML report
13
+ DEBUG=pw:api npx playwright test # verbose Playwright logging
14
+ ```
15
+
16
+ ## Production-Ready Config (Copy-Paste Starter)
17
+
18
+ ### TypeScript
19
+
20
+ ```ts
21
+ // playwright.config.ts
22
+ import { defineConfig, devices } from '@playwright/test';
23
+ import dotenv from 'dotenv';
24
+ import path from 'path';
25
+
26
+ // Load environment variables from .env file
27
+ dotenv.config({ path: path.resolve(__dirname, '.env') });
28
+
29
+ export default defineConfig({
30
+ // ── Test discovery ──────────────────────────────────────────────
31
+ testDir: './tests',
32
+ testMatch: '**/*.spec.ts',
33
+
34
+ // ── Execution ───────────────────────────────────────────────────
35
+ fullyParallel: true,
36
+ forbidOnly: !!process.env.CI, // fail CI if test.only left in
37
+ retries: process.env.CI ? 2 : 0, // retry flakes in CI only
38
+ workers: process.env.CI ? '50%' : undefined, // half CPU in CI, auto locally
39
+
40
+ // ── Reporting ───────────────────────────────────────────────────
41
+ reporter: process.env.CI
42
+ ? [['html', { open: 'never' }], ['github']]
43
+ : [['html', { open: 'on-failure' }]],
44
+
45
+ // ── Timeouts ────────────────────────────────────────────────────
46
+ timeout: 30_000, // per-test timeout
47
+ expect: {
48
+ timeout: 5_000, // per-assertion retry timeout
49
+ },
50
+
51
+ // ── Shared browser context options ──────────────────────────────
52
+ use: {
53
+ baseURL: process.env.BASE_URL || 'http://localhost:3000',
54
+ actionTimeout: 10_000, // click, fill, etc.
55
+ navigationTimeout: 15_000, // goto, waitForURL, etc.
56
+
57
+ // Artifact collection
58
+ trace: 'on-first-retry', // full trace on first retry only
59
+ screenshot: 'only-on-failure', // screenshot on failure
60
+ video: 'retain-on-failure', // video only kept for failures
61
+ // 1.61+ adds video modes matching trace: 'on-all-retries',
62
+ // 'retain-on-first-failure', 'retain-on-failure-and-retries'
63
+
64
+ // Sensible defaults
65
+ locale: 'en-US',
66
+ timezoneId: 'America/New_York',
67
+ extraHTTPHeaders: {
68
+ 'x-test-automation': 'playwright',
69
+ },
70
+ },
71
+
72
+ // ── Projects (browser targets) ─────────────────────────────────
73
+ projects: [
74
+ {
75
+ name: 'chromium',
76
+ use: { ...devices['Desktop Chrome'] },
77
+ },
78
+ {
79
+ name: 'firefox',
80
+ use: { ...devices['Desktop Firefox'] },
81
+ },
82
+ {
83
+ name: 'webkit',
84
+ use: { ...devices['Desktop Safari'] },
85
+ },
86
+ {
87
+ name: 'mobile-chrome',
88
+ use: { ...devices['Pixel 7'] },
89
+ },
90
+ {
91
+ name: 'mobile-safari',
92
+ use: { ...devices['iPhone 14'] },
93
+ },
94
+ ],
95
+
96
+ // ── Dev server ──────────────────────────────────────────────────
97
+ webServer: {
98
+ command: 'npm run dev',
99
+ url: 'http://localhost:3000',
100
+ reuseExistingServer: !process.env.CI,
101
+ timeout: 120_000, // 2 min for cold builds
102
+ stdout: 'pipe',
103
+ stderr: 'pipe',
104
+ },
105
+ });
106
+ ```
107
+
108
+ ### JavaScript
109
+
110
+ ```js
111
+ // playwright.config.js
112
+ const { defineConfig, devices } = require('@playwright/test');
113
+ const dotenv = require('dotenv');
114
+ const path = require('path');
115
+
116
+ dotenv.config({ path: path.resolve(__dirname, '.env') });
117
+
118
+ module.exports = defineConfig({
119
+ testDir: './tests',
120
+ testMatch: '**/*.spec.js',
121
+
122
+ fullyParallel: true,
123
+ forbidOnly: !!process.env.CI,
124
+ retries: process.env.CI ? 2 : 0,
125
+ workers: process.env.CI ? '50%' : undefined,
126
+
127
+ reporter: process.env.CI
128
+ ? [['html', { open: 'never' }], ['github']]
129
+ : [['html', { open: 'on-failure' }]],
130
+
131
+ timeout: 30_000,
132
+ expect: {
133
+ timeout: 5_000,
134
+ },
135
+
136
+ use: {
137
+ baseURL: process.env.BASE_URL || 'http://localhost:3000',
138
+ actionTimeout: 10_000,
139
+ navigationTimeout: 15_000,
140
+
141
+ trace: 'on-first-retry',
142
+ screenshot: 'only-on-failure',
143
+ video: 'retain-on-failure',
144
+
145
+ locale: 'en-US',
146
+ timezoneId: 'America/New_York',
147
+ extraHTTPHeaders: {
148
+ 'x-test-automation': 'playwright',
149
+ },
150
+ },
151
+
152
+ projects: [
153
+ {
154
+ name: 'chromium',
155
+ use: { ...devices['Desktop Chrome'] },
156
+ },
157
+ {
158
+ name: 'firefox',
159
+ use: { ...devices['Desktop Firefox'] },
160
+ },
161
+ {
162
+ name: 'webkit',
163
+ use: { ...devices['Desktop Safari'] },
164
+ },
165
+ {
166
+ name: 'mobile-chrome',
167
+ use: { ...devices['Pixel 7'] },
168
+ },
169
+ {
170
+ name: 'mobile-safari',
171
+ use: { ...devices['iPhone 14'] },
172
+ },
173
+ ],
174
+
175
+ webServer: {
176
+ command: 'npm run dev',
177
+ url: 'http://localhost:3000',
178
+ reuseExistingServer: !process.env.CI,
179
+ timeout: 120_000,
180
+ stdout: 'pipe',
181
+ stderr: 'pipe',
182
+ },
183
+ });
184
+ ```
185
+
186
+ ## Patterns
187
+
188
+ ### Pattern 1: Environment-Specific Configuration
189
+
190
+ **Use when**: Tests run against dev, staging, and production environments.
191
+ **Avoid when**: Single-environment local-only projects.
192
+
193
+ #### TypeScript
194
+
195
+ ```ts
196
+ // playwright.config.ts
197
+ import { defineConfig } from '@playwright/test';
198
+ import dotenv from 'dotenv';
199
+ import path from 'path';
200
+
201
+ // Load environment-specific .env file: .env.staging, .env.production, etc.
202
+ const ENV = process.env.TEST_ENV || 'local';
203
+ dotenv.config({ path: path.resolve(__dirname, `.env.${ENV}`) });
204
+
205
+ const envConfig: Record<string, { baseURL: string; retries: number }> = {
206
+ local: { baseURL: 'http://localhost:3000', retries: 0 },
207
+ staging: { baseURL: 'https://staging.example.com', retries: 2 },
208
+ production: { baseURL: 'https://www.example.com', retries: 2 },
209
+ };
210
+
211
+ const env = envConfig[ENV];
212
+
213
+ export default defineConfig({
214
+ testDir: './tests',
215
+ testMatch: '**/*.spec.ts',
216
+ retries: env.retries,
217
+ use: {
218
+ baseURL: env.baseURL,
219
+ },
220
+ });
221
+ ```
222
+
223
+ ```bash
224
+ # Run against staging
225
+ TEST_ENV=staging npx playwright test
226
+
227
+ # Run against production (subset of smoke tests)
228
+ TEST_ENV=production npx playwright test --grep @smoke
229
+ ```
230
+
231
+ #### JavaScript
232
+
233
+ ```js
234
+ // playwright.config.js
235
+ const { defineConfig } = require('@playwright/test');
236
+ const dotenv = require('dotenv');
237
+ const path = require('path');
238
+
239
+ const ENV = process.env.TEST_ENV || 'local';
240
+ dotenv.config({ path: path.resolve(__dirname, `.env.${ENV}`) });
241
+
242
+ const envConfig = {
243
+ local: { baseURL: 'http://localhost:3000', retries: 0 },
244
+ staging: { baseURL: 'https://staging.example.com', retries: 2 },
245
+ production: { baseURL: 'https://www.example.com', retries: 2 },
246
+ };
247
+
248
+ const env = envConfig[ENV];
249
+
250
+ module.exports = defineConfig({
251
+ testDir: './tests',
252
+ testMatch: '**/*.spec.js',
253
+ retries: env.retries,
254
+ use: {
255
+ baseURL: env.baseURL,
256
+ },
257
+ });
258
+ ```
259
+
260
+ ### Pattern 2: Multi-Project with Setup Dependencies
261
+
262
+ **Use when**: Tests need shared authentication state or database seeding before running.
263
+ **Avoid when**: Tests are fully independent with no shared setup phase.
264
+
265
+ #### TypeScript
266
+
267
+ ```ts
268
+ // playwright.config.ts
269
+ import { defineConfig, devices } from '@playwright/test';
270
+
271
+ export default defineConfig({
272
+ testDir: './tests',
273
+ testMatch: '**/*.spec.ts',
274
+
275
+ projects: [
276
+ // Setup project runs first, saves auth state
277
+ {
278
+ name: 'setup',
279
+ testMatch: /global\.setup\.ts/,
280
+ },
281
+
282
+ // Browser projects depend on setup
283
+ {
284
+ name: 'chromium',
285
+ use: {
286
+ ...devices['Desktop Chrome'],
287
+ storageState: 'playwright/.auth/user.json',
288
+ },
289
+ dependencies: ['setup'],
290
+ },
291
+ {
292
+ name: 'firefox',
293
+ use: {
294
+ ...devices['Desktop Firefox'],
295
+ storageState: 'playwright/.auth/user.json',
296
+ },
297
+ dependencies: ['setup'],
298
+ },
299
+ ],
300
+ });
301
+ ```
302
+
303
+ ```ts
304
+ // tests/global.setup.ts
305
+ import { test as setup, expect } from '@playwright/test';
306
+
307
+ const authFile = 'playwright/.auth/user.json';
308
+
309
+ setup('authenticate', async ({ page }) => {
310
+ await page.goto('/login');
311
+ await page.getByLabel('Email').fill('user@example.com');
312
+ await page.getByLabel('Password').fill(process.env.TEST_PASSWORD!);
313
+ await page.getByRole('button', { name: 'Sign in' }).click();
314
+ await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
315
+ await page.context().storageState({ path: authFile });
316
+ });
317
+ ```
318
+
319
+ #### JavaScript
320
+
321
+ ```js
322
+ // playwright.config.js
323
+ const { defineConfig, devices } = require('@playwright/test');
324
+
325
+ module.exports = defineConfig({
326
+ testDir: './tests',
327
+ testMatch: '**/*.spec.js',
328
+
329
+ projects: [
330
+ {
331
+ name: 'setup',
332
+ testMatch: /global\.setup\.js/,
333
+ },
334
+ {
335
+ name: 'chromium',
336
+ use: {
337
+ ...devices['Desktop Chrome'],
338
+ storageState: 'playwright/.auth/user.json',
339
+ },
340
+ dependencies: ['setup'],
341
+ },
342
+ {
343
+ name: 'firefox',
344
+ use: {
345
+ ...devices['Desktop Firefox'],
346
+ storageState: 'playwright/.auth/user.json',
347
+ },
348
+ dependencies: ['setup'],
349
+ },
350
+ ],
351
+ });
352
+ ```
353
+
354
+ ```js
355
+ // tests/global.setup.js
356
+ const { test: setup, expect } = require('@playwright/test');
357
+
358
+ const authFile = 'playwright/.auth/user.json';
359
+
360
+ setup('authenticate', async ({ page }) => {
361
+ await page.goto('/login');
362
+ await page.getByLabel('Email').fill('user@example.com');
363
+ await page.getByLabel('Password').fill(process.env.TEST_PASSWORD);
364
+ await page.getByRole('button', { name: 'Sign in' }).click();
365
+ await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
366
+ await page.context().storageState({ path: authFile });
367
+ });
368
+ ```
369
+
370
+ ### Pattern 3: `webServer` with Build Step
371
+
372
+ **Use when**: Tests need a running application server. Let Playwright manage the server lifecycle.
373
+ **Avoid when**: Testing against an already-deployed environment (staging/prod).
374
+
375
+ #### TypeScript
376
+
377
+ ```ts
378
+ // playwright.config.ts
379
+ import { defineConfig } from '@playwright/test';
380
+
381
+ export default defineConfig({
382
+ testDir: './tests',
383
+ testMatch: '**/*.spec.ts',
384
+ use: {
385
+ baseURL: 'http://localhost:3000',
386
+ },
387
+ webServer: {
388
+ command: process.env.CI
389
+ ? 'npm run build && npm run start' // production build in CI
390
+ : 'npm run dev', // dev server locally
391
+ url: 'http://localhost:3000',
392
+ reuseExistingServer: !process.env.CI,
393
+ timeout: 120_000,
394
+ stdout: 'pipe',
395
+ stderr: 'pipe',
396
+ env: {
397
+ NODE_ENV: 'test',
398
+ DATABASE_URL: process.env.DATABASE_URL || 'postgresql://localhost:5432/test',
399
+ },
400
+ },
401
+ });
402
+ ```
403
+
404
+ #### JavaScript
405
+
406
+ ```js
407
+ // playwright.config.js
408
+ const { defineConfig } = require('@playwright/test');
409
+
410
+ module.exports = defineConfig({
411
+ testDir: './tests',
412
+ testMatch: '**/*.spec.js',
413
+ use: {
414
+ baseURL: 'http://localhost:3000',
415
+ },
416
+ webServer: {
417
+ command: process.env.CI
418
+ ? 'npm run build && npm run start'
419
+ : 'npm run dev',
420
+ url: 'http://localhost:3000',
421
+ reuseExistingServer: !process.env.CI,
422
+ timeout: 120_000,
423
+ stdout: 'pipe',
424
+ stderr: 'pipe',
425
+ env: {
426
+ NODE_ENV: 'test',
427
+ DATABASE_URL: process.env.DATABASE_URL || 'postgresql://localhost:5432/test',
428
+ },
429
+ },
430
+ });
431
+ ```
432
+
433
+ ### Pattern 4: `globalSetup` / `globalTeardown`
434
+
435
+ **Use when**: One-time non-browser work: seeding a database, starting a service, setting env vars. Runs once per `npx playwright test` invocation.
436
+ **Avoid when**: You need browser context (use a setup project instead) or per-test isolation (use fixtures).
437
+
438
+ #### TypeScript
439
+
440
+ ```ts
441
+ // playwright.config.ts
442
+ import { defineConfig } from '@playwright/test';
443
+
444
+ export default defineConfig({
445
+ testDir: './tests',
446
+ testMatch: '**/*.spec.ts',
447
+ globalSetup: './tests/global-setup.ts',
448
+ globalTeardown: './tests/global-teardown.ts',
449
+ });
450
+ ```
451
+
452
+ ```ts
453
+ // tests/global-setup.ts
454
+ import { FullConfig } from '@playwright/test';
455
+
456
+ async function globalSetup(config: FullConfig) {
457
+ // Seed test database
458
+ const { execSync } = await import('child_process');
459
+ execSync('npx prisma db seed', { stdio: 'inherit' });
460
+
461
+ // Store data for tests to use via environment variables
462
+ process.env.TEST_RUN_ID = `run-${Date.now()}`;
463
+ }
464
+
465
+ export default globalSetup;
466
+ ```
467
+
468
+ ```ts
469
+ // tests/global-teardown.ts
470
+ import { FullConfig } from '@playwright/test';
471
+
472
+ async function globalTeardown(config: FullConfig) {
473
+ const { execSync } = await import('child_process');
474
+ execSync('npx prisma db push --force-reset', { stdio: 'inherit' });
475
+ }
476
+
477
+ export default globalTeardown;
478
+ ```
479
+
480
+ #### JavaScript
481
+
482
+ ```js
483
+ // playwright.config.js
484
+ const { defineConfig } = require('@playwright/test');
485
+
486
+ module.exports = defineConfig({
487
+ testDir: './tests',
488
+ testMatch: '**/*.spec.js',
489
+ globalSetup: './tests/global-setup.js',
490
+ globalTeardown: './tests/global-teardown.js',
491
+ });
492
+ ```
493
+
494
+ ```js
495
+ // tests/global-setup.js
496
+ const { execSync } = require('child_process');
497
+
498
+ async function globalSetup(config) {
499
+ execSync('npx prisma db seed', { stdio: 'inherit' });
500
+ process.env.TEST_RUN_ID = `run-${Date.now()}`;
501
+ }
502
+
503
+ module.exports = globalSetup;
504
+ ```
505
+
506
+ ```js
507
+ // tests/global-teardown.js
508
+ const { execSync } = require('child_process');
509
+
510
+ async function globalTeardown(config) {
511
+ execSync('npx prisma db push --force-reset', { stdio: 'inherit' });
512
+ }
513
+
514
+ module.exports = globalTeardown;
515
+ ```
516
+
517
+ ### Pattern 5: `.env` File Setup
518
+
519
+ **Use when**: Managing secrets, URLs, or feature flags without hardcoding.
520
+ **Avoid when**: Never commit `.env` files with real secrets. Provide `.env.example` instead.
521
+
522
+ ```bash
523
+ # .env.example (commit this)
524
+ BASE_URL=http://localhost:3000
525
+ TEST_PASSWORD=
526
+ API_KEY=
527
+
528
+ # .env.local (gitignored)
529
+ BASE_URL=http://localhost:3000
530
+ TEST_PASSWORD=s3cret
531
+ API_KEY=test-key-abc123
532
+
533
+ # .env.staging (gitignored)
534
+ BASE_URL=https://staging.example.com
535
+ TEST_PASSWORD=staging-password
536
+ API_KEY=staging-key-xyz789
537
+ ```
538
+
539
+ ```bash
540
+ # .gitignore
541
+ .env
542
+ .env.local
543
+ .env.staging
544
+ .env.production
545
+ playwright/.auth/
546
+ ```
547
+
548
+ Install dotenv:
549
+
550
+ ```bash
551
+ npm install -D dotenv
552
+ ```
553
+
554
+ ### Pattern 6: Trace, Screenshot, and Video Settings
555
+
556
+ **Use when**: Deciding artifact collection strategy for local development vs CI.
557
+
558
+ | Setting | Local | CI | Why |
559
+ |---|---|---|---|
560
+ | `trace` | `'off'` or `'on-first-retry'` | `'on-first-retry'` | Traces are large; only collect on failure |
561
+ | `screenshot` | `'off'` | `'only-on-failure'` | Useful for CI debugging only |
562
+ | `video` | `'off'` | `'retain-on-failure'` | Video is slow to record; keep only failures |
563
+
564
+ #### TypeScript
565
+
566
+ ```ts
567
+ // playwright.config.ts
568
+ import { defineConfig } from '@playwright/test';
569
+
570
+ export default defineConfig({
571
+ testDir: './tests',
572
+ testMatch: '**/*.spec.ts',
573
+ use: {
574
+ // CI: capture everything on failure; Local: minimal overhead
575
+ trace: process.env.CI ? 'on-first-retry' : 'off',
576
+ screenshot: process.env.CI ? 'only-on-failure' : 'off',
577
+ video: process.env.CI ? 'retain-on-failure' : 'off',
578
+ },
579
+ });
580
+ ```
581
+
582
+ #### JavaScript
583
+
584
+ ```js
585
+ // playwright.config.js
586
+ const { defineConfig } = require('@playwright/test');
587
+
588
+ module.exports = defineConfig({
589
+ testDir: './tests',
590
+ testMatch: '**/*.spec.js',
591
+ use: {
592
+ trace: process.env.CI ? 'on-first-retry' : 'off',
593
+ screenshot: process.env.CI ? 'only-on-failure' : 'off',
594
+ video: process.env.CI ? 'retain-on-failure' : 'off',
595
+ },
596
+ });
597
+ ```
598
+
599
+ ## Decision Guide
600
+
601
+ ### Which Timeout to Adjust
602
+
603
+ | Symptom | Timeout to Change | Default | Recommended Range |
604
+ |---|---|---|---|
605
+ | Test takes too long overall | `timeout` | 30s | 30-60s (never above 120s) |
606
+ | Assertion `expect()` keeps retrying too long or not long enough | `expect.timeout` | 5s | 5-10s |
607
+ | `page.goto()` or `waitForURL()` times out | `navigationTimeout` | 30s | 10-30s |
608
+ | `click()`, `fill()`, `check()` time out | `actionTimeout` | 0 (no limit) | 10-15s |
609
+ | Dev server slow to start | `webServer.timeout` | 60s | 60-180s |
610
+
611
+ ### Server Management
612
+
613
+ | Scenario | Approach | Why |
614
+ |---|---|---|
615
+ | Local dev + CI, app in same repo | `webServer` with `reuseExistingServer: !process.env.CI` | Playwright manages server; reuses yours locally |
616
+ | Separate frontend/backend repos | Manual start or Docker Compose | `webServer` can only run one command |
617
+ | Testing deployed staging/production | No `webServer`; set `baseURL` via env var | Server already running remotely |
618
+ | Multiple services needed (API + frontend) | Array of `webServer` entries | Each gets its own command and URL health check |
619
+
620
+ ### Single vs Multi-Project Config
621
+
622
+ | Scenario | Approach | Why |
623
+ |---|---|---|
624
+ | Starting out, early development | Single project (chromium only) | Faster feedback, simpler config |
625
+ | Pre-release cross-browser validation | Multi-project: chromium + firefox + webkit | Catch rendering/API differences |
626
+ | Mobile-responsive app | Add mobile projects alongside desktop | Viewport + touch differences matter |
627
+ | Authenticated + unauthenticated tests | Setup project + dependent projects | Share auth state without re-login per test |
628
+ | CI pipeline with tight time budget | Chromium in PR checks; all browsers on merge to main | Balance speed vs coverage |
629
+
630
+ ### globalSetup vs Setup Projects vs Fixtures
631
+
632
+ | Need | Use | Why |
633
+ |---|---|---|
634
+ | One-time DB seed or external service prep | `globalSetup` | Runs once, no browser needed |
635
+ | Shared browser auth (login once, reuse cookies) | Setup project with `dependencies` | Needs browser context; `globalSetup` has none |
636
+ | Per-test isolated state (unique user, fresh data) | Custom fixture via `test.extend()` | Each test gets its own instance with teardown |
637
+ | Cleanup after all tests | `globalTeardown` | Runs once at the end regardless of pass/fail |
638
+
639
+ ## Anti-Patterns
640
+
641
+ | Don't Do This | Problem | Do This Instead |
642
+ |---|---|---|
643
+ | `timeout: 300_000` globally | Masks flaky tests; CI runs take forever | Fix the root cause; keep timeout at 30s; raise `navigationTimeout` only if warranted |
644
+ | Hardcoded URLs in tests: `page.goto('http://localhost:3000/login')` | Breaks in every non-local environment | Use `baseURL` in config, then `page.goto('/login')` |
645
+ | Running chromium + firefox + webkit on every PR | 3x CI time for marginal benefit on most PRs | Chromium on PRs; all browsers on main branch merges |
646
+ | `trace: 'on'` always in CI | Huge artifacts, slow uploads, disk full | `trace: 'on-first-retry'` -- only captures when a test fails and retries |
647
+ | `video: 'on'` always in CI | Massive CI storage; recording slows tests | `video: 'retain-on-failure'` -- records all but only keeps failures |
648
+ | Config values inline in test files: `test.use({ viewport: { width: 1280, height: 720 } })` in every file | Scattered, hard to maintain, inconsistent | Define once in project config; override per-file only when genuinely needed |
649
+ | `retries: 3` locally | Hides flakiness during development | `retries: 0` locally, `retries: 2` in CI |
650
+ | No `forbidOnly` in CI | Accidentally committed `test.only` runs a single test, everything else silently skipped | `forbidOnly: !!process.env.CI` |
651
+ | `globalSetup` for browser auth | No browser context available; complex workarounds needed | Use a setup project with `dependencies` |
652
+ | Committing `.env` files with real credentials | Security risk | Commit `.env.example` only; gitignore real `.env` files |
653
+
654
+ ## Troubleshooting
655
+
656
+ ### "baseURL" not working -- tests navigate to full URL
657
+
658
+ **Cause**: Using `page.goto('http://localhost:3000/path')` instead of `page.goto('/path')`. When `goto` receives an absolute URL, it ignores `baseURL`.
659
+
660
+ **Fix**: Always pass relative paths to `page.goto()`:
661
+
662
+ ```ts
663
+ // Wrong -- ignores baseURL
664
+ await page.goto('http://localhost:3000/dashboard');
665
+
666
+ // Correct -- uses baseURL from config
667
+ await page.goto('/dashboard');
668
+ ```
669
+
670
+ ### webServer starts but tests still fail with connection refused
671
+
672
+ **Cause**: The `url` in `webServer` does not match what the server actually serves, or the health check endpoint returns non-200.
673
+
674
+ **Fix**: Ensure `webServer.url` matches the actual server address. Add a health check route if needed:
675
+
676
+ ```ts
677
+ // playwright.config.ts
678
+ import { defineConfig } from '@playwright/test';
679
+
680
+ export default defineConfig({
681
+ testDir: './tests',
682
+ testMatch: '**/*.spec.ts',
683
+ webServer: {
684
+ command: 'npm run dev',
685
+ url: 'http://localhost:3000/api/health', // use a real endpoint
686
+ reuseExistingServer: !process.env.CI,
687
+ timeout: 120_000,
688
+ },
689
+ });
690
+ ```
691
+
692
+ ### Tests pass locally but timeout in CI
693
+
694
+ **Cause**: CI machines are slower. Default timeouts too tight for CI hardware.
695
+
696
+ **Fix**: Increase `navigationTimeout` for CI, reduce `workers` to avoid resource contention:
697
+
698
+ ```ts
699
+ // playwright.config.ts
700
+ import { defineConfig } from '@playwright/test';
701
+
702
+ export default defineConfig({
703
+ testDir: './tests',
704
+ testMatch: '**/*.spec.ts',
705
+ workers: process.env.CI ? '50%' : undefined,
706
+ use: {
707
+ navigationTimeout: process.env.CI ? 30_000 : 15_000,
708
+ actionTimeout: process.env.CI ? 15_000 : 10_000,
709
+ },
710
+ });
711
+ ```
712
+
713
+ ### "Error: page.goto: Target page, context or browser has been closed"
714
+
715
+ **Cause**: Test exceeded its `timeout` and Playwright tore down the browser while an action was still running.
716
+
717
+ **Fix**: Do not increase the global timeout. Instead, find the slow step using `--trace on` and fix it. Common causes: waiting for a slow API, unresolved network request, or missing `await`.
718
+
719
+ ```bash
720
+ # Record a trace for debugging
721
+ npx playwright test --trace on
722
+ npx playwright show-report
723
+ ```
724
+
725
+ ## Related
726
+
727
+ - [core/fixtures-and-hooks.md](fixtures-and-hooks.md) -- custom fixtures that replace `globalSetup` for per-test state
728
+ - [core/test-organization.md](test-organization.md) -- file structure, naming conventions, test grouping
729
+ - [core/authentication.md](authentication.md) -- setup projects for shared auth state
730
+ - [ci/ci-github-actions.md](../ci/ci-github-actions.md) -- CI-specific config and caching
731
+ - [ci/projects-and-dependencies.md](../ci/projects-and-dependencies.md) -- advanced multi-project patterns