@desplega.ai/qa-use 2.8.6 → 2.9.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 (49) hide show
  1. package/README.md +21 -0
  2. package/dist/package.json +4 -2
  3. package/dist/src/cli/commands/api/index.d.ts +3 -0
  4. package/dist/src/cli/commands/api/index.d.ts.map +1 -0
  5. package/dist/src/cli/commands/api/index.js +6 -0
  6. package/dist/src/cli/commands/api/index.js.map +1 -0
  7. package/dist/src/cli/commands/api/lib/http.d.ts +18 -0
  8. package/dist/src/cli/commands/api/lib/http.d.ts.map +1 -0
  9. package/dist/src/cli/commands/api/lib/http.js +51 -0
  10. package/dist/src/cli/commands/api/lib/http.js.map +1 -0
  11. package/dist/src/cli/commands/api/lib/openapi-cache.d.ts +10 -0
  12. package/dist/src/cli/commands/api/lib/openapi-cache.d.ts.map +1 -0
  13. package/dist/src/cli/commands/api/lib/openapi-cache.js +41 -0
  14. package/dist/src/cli/commands/api/lib/openapi-cache.js.map +1 -0
  15. package/dist/src/cli/commands/api/lib/openapi-errors.d.ts +8 -0
  16. package/dist/src/cli/commands/api/lib/openapi-errors.d.ts.map +1 -0
  17. package/dist/src/cli/commands/api/lib/openapi-errors.js +20 -0
  18. package/dist/src/cli/commands/api/lib/openapi-errors.js.map +1 -0
  19. package/dist/src/cli/commands/api/lib/openapi-spec.d.ts +62 -0
  20. package/dist/src/cli/commands/api/lib/openapi-spec.d.ts.map +1 -0
  21. package/dist/src/cli/commands/api/lib/openapi-spec.js +166 -0
  22. package/dist/src/cli/commands/api/lib/openapi-spec.js.map +1 -0
  23. package/dist/src/cli/commands/api/lib/output.d.ts +8 -0
  24. package/dist/src/cli/commands/api/lib/output.d.ts.map +1 -0
  25. package/dist/src/cli/commands/api/lib/output.js +31 -0
  26. package/dist/src/cli/commands/api/lib/output.js.map +1 -0
  27. package/dist/src/cli/commands/api/ls.d.ts +3 -0
  28. package/dist/src/cli/commands/api/ls.d.ts.map +1 -0
  29. package/dist/src/cli/commands/api/ls.js +76 -0
  30. package/dist/src/cli/commands/api/ls.js.map +1 -0
  31. package/dist/src/cli/commands/api/request.d.ts +11 -0
  32. package/dist/src/cli/commands/api/request.d.ts.map +1 -0
  33. package/dist/src/cli/commands/api/request.js +225 -0
  34. package/dist/src/cli/commands/api/request.js.map +1 -0
  35. package/dist/src/cli/commands/docs.d.ts +6 -0
  36. package/dist/src/cli/commands/docs.d.ts.map +1 -0
  37. package/dist/src/cli/commands/docs.js +71 -0
  38. package/dist/src/cli/commands/docs.js.map +1 -0
  39. package/dist/src/cli/commands/setup.d.ts +1 -1
  40. package/dist/src/cli/commands/setup.d.ts.map +1 -1
  41. package/dist/src/cli/commands/setup.js +100 -34
  42. package/dist/src/cli/commands/setup.js.map +1 -1
  43. package/dist/src/cli/generated/docs-content.d.ts +15 -0
  44. package/dist/src/cli/generated/docs-content.d.ts.map +1 -0
  45. package/dist/src/cli/generated/docs-content.js +2420 -0
  46. package/dist/src/cli/generated/docs-content.js.map +1 -0
  47. package/dist/src/cli/index.js +50 -3
  48. package/dist/src/cli/index.js.map +1 -1
  49. package/package.json +4 -2
@@ -0,0 +1,2420 @@
1
+ /**
2
+ * Auto-generated documentation content for the docs command.
3
+ * DO NOT EDIT MANUALLY — Generated from plugins/qa-use/skills/qa-use/
4
+ * Run 'bun run generate:docs' to regenerate.
5
+ */
6
+ export const MAIN_DOC = `---
7
+ name: qa-use
8
+ description: E2E testing and browser automation with qa-use CLI. Use when the user needs to run tests, verify features, automate browser interactions, or debug test failures.
9
+ allowed-tools: Bash(qa-use *)
10
+ ---
11
+
12
+ # qa-use
13
+
14
+ E2E testing and browser automation for AI-driven development workflows.
15
+
16
+ ## Critical Insight: Plugin Commands as Shortcuts
17
+
18
+ **For AI Harnesses (codex, opencode, etc.):**
19
+
20
+ Plugin commands (slash commands like \`/qa-use:verify\`) are **convenience shortcuts** that wrap CLI workflows. Harnesses with only the Bash tool can access ALL functionality via CLI commands documented below.
21
+
22
+ **Pattern throughout this document:**
23
+ - **CLI Workflow**: Step-by-step CLI commands (works for ALL harnesses)
24
+ - **Plugin Shortcut**: Optional slash command (convenience)
25
+
26
+ ## Core Workflow
27
+
28
+ ### 1. Browser Control & Session Lifecycle
29
+
30
+ **CLI Workflow:**
31
+ \`\`\`bash
32
+ # Create browser session
33
+ qa-use browser create --viewport desktop
34
+
35
+ # For localhost testing
36
+ qa-use browser create --tunnel --no-headless
37
+
38
+ # Navigate
39
+ qa-use browser goto https://example.com
40
+
41
+ # Snapshot to get element refs (ALWAYS do this before interacting)
42
+ qa-use browser snapshot
43
+
44
+ # Interact by ref
45
+ qa-use browser click e3
46
+ qa-use browser fill e5 "text"
47
+
48
+ # Close
49
+ qa-use browser close
50
+ \`\`\`
51
+
52
+ **Plugin Shortcut:**
53
+ \`\`\`
54
+ /qa-use:explore https://example.com
55
+ \`\`\`
56
+ (Wraps create + goto + snapshot with autonomous exploration)
57
+
58
+ **Critical:** Always run \`snapshot\` before your **first** interaction on a page. Never guess element refs.
59
+
60
+ **Snapshot Diff Feature (use it to avoid unnecessary snapshots):**
61
+ After each action (goto, click, fill, etc.), the browser automatically shows DOM changes:
62
+ - **Summary**: "5 elements added, 1 element modified"
63
+ - **Added elements**: \`+ [e54] generic "Thanks for agreeing!"\` (green)
64
+ - **Modified elements**: \`~ [e18] checkbox "I agree..."\` with \`+attrs: checked, active\` (yellow)
65
+ - **Removed elements**: \`- [e99] button "Submit"\` (red)
66
+
67
+ **When you can skip a full \`snapshot\`:** If the diff output from your last action already shows the element ref you need to interact with next, use it directly — no need for an intermediate \`snapshot\`. For example, if clicking a button shows \`+ [e54] button "Submit"\` in the diff, you can \`click e54\` immediately.
68
+
69
+ **When you still need a full \`snapshot\`:** Run \`snapshot\` when you need to find elements that weren't in the diff (e.g., pre-existing elements you haven't interacted with yet), or when the diff was truncated (shows "... and N more changes").
70
+
71
+ ### 2. Understanding Blocks
72
+
73
+ **What are blocks?**
74
+
75
+ Blocks are atomic recorded interactions from a browser session. They are:
76
+ - Automatically captured during any browser interaction (click, fill, goto, scroll, etc.)
77
+ - Stored server-side with the session
78
+ - Retrieved via \`qa-use browser get-blocks\`
79
+ - The foundation for test generation
80
+
81
+ **Why blocks matter:**
82
+ - **Record-once, replay-many**: Interactive recording becomes automated test
83
+ - **AI-friendly**: Agents can analyze blocks to understand user intent
84
+ - **Version control**: Blocks stored with session enable test iteration
85
+ - **Bridge CLI → Tests**: Natural workflow from exploration to automation
86
+
87
+ **How blocks work:**
88
+
89
+ \`\`\`bash
90
+ # 1. Create session and interact
91
+ qa-use browser create --tunnel --no-headless
92
+ qa-use browser goto https://example.com
93
+ qa-use browser snapshot # Returns: [ref=e1] button
94
+ qa-use browser click e1 # Records as block
95
+ qa-use browser fill e5 "text" # Records as block
96
+
97
+ # 2. Retrieve blocks (JSON array)
98
+ qa-use browser get-blocks
99
+ # Returns:
100
+ # [
101
+ # {"type": "goto", "url": "...", "timestamp": "..."},
102
+ # {"type": "click", "ref": "e1", "timestamp": "..."},
103
+ # {"type": "fill", "ref": "e5", "value": "text", "timestamp": "..."}
104
+ # ]
105
+
106
+ # 3. Generate test YAML from blocks
107
+ qa-use browser generate-test -n "my_test" -o qa-tests/my_test.yaml
108
+
109
+ # 4. Run generated test
110
+ qa-use test run my_test
111
+ \`\`\`
112
+
113
+ **Plugin Shortcut:**
114
+ \`\`\`
115
+ /qa-use:record start my_test
116
+ # ... perform interactions ...
117
+ /qa-use:record stop
118
+ \`\`\`
119
+ (Wraps the interactive workflow with AI-powered test generation)
120
+
121
+ ### 3. Test Management
122
+
123
+ **CLI Workflow:**
124
+ \`\`\`bash
125
+ # Run test by name
126
+ qa-use test run login
127
+
128
+ # Run with autofix (AI self-healing)
129
+ qa-use test run login --autofix
130
+
131
+ # Validate syntax
132
+ qa-use test validate login
133
+
134
+ # Show test details
135
+ qa-use test info login
136
+
137
+ # List test runs
138
+ qa-use test runs --status failed
139
+ \`\`\`
140
+
141
+ **Plugin Shortcut:**
142
+ \`\`\`
143
+ /qa-use:test-run login --autofix
144
+ \`\`\`
145
+ (Convenience shortcut for common test execution)
146
+
147
+ ### 4. Test Sync Lifecycle
148
+
149
+ **CLI Workflow:**
150
+ \`\`\`bash
151
+ # Pull tests from cloud
152
+ qa-use test sync pull
153
+
154
+ # Push all local tests to cloud
155
+ qa-use test sync push --all
156
+
157
+ # Push specific test
158
+ qa-use test sync push --id <uuid>
159
+
160
+ # Force push (overwrite conflicts)
161
+ qa-use test sync push --force
162
+
163
+ # Compare local vs cloud
164
+ qa-use test diff login.yaml
165
+ \`\`\`
166
+
167
+ **No Plugin Shortcut** - Use CLI commands directly
168
+
169
+ ## Essential Commands
170
+
171
+ ### Browser Session Management
172
+
173
+ | Command | Description |
174
+ |---------|-------------|
175
+ | \`qa-use browser create\` | Create remote browser session |
176
+ | \`qa-use browser create --tunnel\` | Create local browser with API tunnel |
177
+ | \`qa-use browser create --no-headless\` | Show browser window (tunnel mode only) |
178
+ | \`qa-use browser create --viewport <size>\` | Set viewport: \`desktop\`, \`tablet\`, \`mobile\` |
179
+ | \`qa-use browser create --ws-url <url>\` | Connect to existing WebSocket browser |
180
+ | \`qa-use browser create --after-test-id <uuid>\` | Run a test first, then become interactive |
181
+ | \`qa-use browser create --var <key=value>\` | Override app config variables (repeatable) |
182
+ | \`qa-use browser list\` | List active sessions |
183
+ | \`qa-use browser status\` | Show current session details (app_url, recording_url, etc.) |
184
+ | \`qa-use browser close\` | Close active session |
185
+
186
+ Sessions auto-persist in \`~/.qa-use.json\`. One active session = no \`-s\` flag needed.
187
+
188
+ ### Navigation
189
+
190
+ | Command | Description |
191
+ |---------|-------------|
192
+ | \`qa-use browser goto <url>\` | Navigate to URL |
193
+ | \`qa-use browser back\` | Go back |
194
+ | \`qa-use browser forward\` | Go forward |
195
+ | \`qa-use browser reload\` | Reload page |
196
+
197
+ ### Element Interaction
198
+
199
+ | Command | Description |
200
+ |---------|-------------|
201
+ | \`qa-use browser click <ref>\` | Click element by ref |
202
+ | \`qa-use browser click --text "Button"\` | Click by semantic description |
203
+ | \`qa-use browser fill <ref> "value"\` | Fill input field |
204
+ | \`qa-use browser type <ref> "text"\` | Type with delays (for autocomplete) |
205
+ | \`qa-use browser press <key>\` | Press key (e.g., \`Enter\`, \`Tab\`) |
206
+ | \`qa-use browser check <ref>\` | Check checkbox |
207
+ | \`qa-use browser uncheck <ref>\` | Uncheck checkbox |
208
+ | \`qa-use browser select <ref> "option"\` | Select dropdown option |
209
+ | \`qa-use browser hover <ref>\` | Hover over element |
210
+ | \`qa-use browser scroll down 500\` | Scroll by pixels |
211
+ | \`qa-use browser scroll-into-view <ref>\` | Scroll element into view |
212
+ | \`qa-use browser drag <ref> --target <ref>\` | Drag element to target |
213
+ | \`qa-use browser mfa-totp [ref] <secret>\` | Generate TOTP code (optionally fill) |
214
+ | \`qa-use browser upload <ref> <file>...\` | Upload file(s) to input (base64-encoded, works remote & tunnel) |
215
+
216
+ ### Inspection & Snapshot Diff
217
+
218
+ | Command | Description |
219
+ |---------|-------------|
220
+ | \`qa-use browser snapshot\` | Get full ARIA tree with element refs (use only when diff output is insufficient) |
221
+ | \`qa-use browser url\` | Get current URL |
222
+ | \`qa-use browser screenshot\` | Save screenshot.png |
223
+ | \`qa-use browser screenshot file.png\` | Save to custom path |
224
+ | \`qa-use browser screenshot --base64\` | Output base64 to stdout |
225
+ | \`qa-use browser evaluate <expression>\` | Execute JavaScript in browser context |
226
+
227
+ The snapshot-diff feature automatically displays DOM changes after each browser action:
228
+ - **Added elements**: Shown with \`+\` prefix and green color — these refs are immediately usable
229
+ - **Modified elements**: Shown with \`~\` prefix and yellow color, including attribute changes (\`+attrs: checked\`)
230
+ - **Removed elements**: Shown with \`-\` prefix and red color — do NOT use these refs
231
+
232
+ **Downloads:** When an action triggers a file download (e.g., clicking a download link), the response includes download info: filename, size, and a presigned URL. Use \`qa-use browser downloads\` to list all downloads or \`--save <dir>\` to save them locally.
233
+
234
+ Use diff output to interact with newly appeared elements directly, without running a full \`snapshot\` first.
235
+
236
+ ### Test Operations
237
+
238
+ | Command | Description |
239
+ |---------|-------------|
240
+ | \`qa-use test run <name>\` | Run test by name |
241
+ | \`qa-use test run --all\` | Run all tests |
242
+ | \`qa-use test run <name> --tunnel\` | Run with local browser tunnel |
243
+ | \`qa-use test run <name> --autofix\` | Enable AI self-healing |
244
+ | \`qa-use test run <name> --update-local\` | Persist AI fixes to file |
245
+ | \`qa-use test run <name> --download\` | Download assets to \`/tmp/qa-use/downloads/\` |
246
+ | \`qa-use test run <name> --var key=value\` | Override variable |
247
+ | \`qa-use test validate <name>\` | Validate test syntax |
248
+ | \`qa-use test list\` | List available tests |
249
+ | \`qa-use test info <name>\` | Show test details (steps, tags, description) |
250
+ | \`qa-use test info --id <uuid>\` | Show cloud test details by ID |
251
+ | \`qa-use test runs [name]\` | List test run history |
252
+ | \`qa-use test runs --id <uuid>\` | Filter runs by test ID |
253
+ | \`qa-use test runs --status failed\` | Filter runs by status |
254
+ | \`qa-use test init\` | Initialize test directory |
255
+ | \`qa-use test sync pull\` | Pull tests from cloud |
256
+ | \`qa-use test sync push --all\` | Push all local tests to cloud |
257
+ | \`qa-use test sync push --id <uuid>\` | Push specific test |
258
+ | \`qa-use test sync push --force\` | Push tests, overwriting conflicts |
259
+ | \`qa-use test diff <file>\` | Compare local vs cloud test |
260
+ | \`qa-use test schema [path]\` | View test definition schema |
261
+
262
+ ### API Operations (Dynamic OpenAPI)
263
+
264
+ \`qa-use api\` dynamically discovers operations from \`/api/v1/openapi.json\` and caches metadata locally for offline fallback.
265
+
266
+ | Command | Description |
267
+ |---------|-------------|
268
+ | \`qa-use api ls\` | List available \`/api/v1/*\` routes from OpenAPI |
269
+ | \`qa-use api ls --refresh\` | Force refresh OpenAPI cache |
270
+ | \`qa-use api ls --offline\` | Use cached OpenAPI metadata only |
271
+ | \`qa-use api /api/v1/tests\` | Call endpoint (method inferred when possible) |
272
+ | \`qa-use api -X GET /api/v1/test-runs -f limit=5\` | GET with query fields |
273
+ | \`qa-use api -X POST /api/v1/tests-actions/run --input body.json\` | POST with JSON body file |
274
+ | \`qa-use api -X GET /api/v1/test-runs/<id>\` | Fetch detail endpoint by ID |
275
+
276
+ **No Plugin Shortcut** - Use CLI commands directly.
277
+
278
+ ### Logs & Debugging
279
+
280
+ | Command | Description |
281
+ |---------|-------------|
282
+ | \`qa-use browser logs console\` | View console logs from session |
283
+ | \`qa-use browser logs console -s <id>\` | View logs from specific/closed session |
284
+ | \`qa-use browser logs network\` | View network request logs |
285
+ | \`qa-use browser logs network -s <id>\` | View network logs from specific session |
286
+ | \`qa-use browser downloads\` | List downloaded files from session |
287
+ | \`qa-use browser downloads --save <dir>\` | Save downloaded files to local directory |
288
+ | \`qa-use browser downloads --json\` | Output download info as JSON |
289
+
290
+ ### Test Generation
291
+
292
+ | Command | Description |
293
+ |---------|-------------|
294
+ | \`qa-use browser generate-test\` | Generate test YAML from recorded session |
295
+ | \`qa-use browser generate-test -s <id>\` | Generate from specific session |
296
+ | \`qa-use browser generate-test -n <name>\` | Specify test name |
297
+ | \`qa-use browser generate-test -o <path>\` | Specify output path |
298
+ | \`qa-use browser get-blocks\` | Get recorded interaction blocks (JSON) |
299
+
300
+ ### Waiting
301
+
302
+ | Command | Description |
303
+ |---------|-------------|
304
+ | \`qa-use browser wait <ms>\` | Fixed wait |
305
+ | \`qa-use browser wait-for-selector ".class"\` | Wait for selector |
306
+ | \`qa-use browser wait-for-load\` | Wait for page load |
307
+
308
+ ### Variable Overrides
309
+
310
+ Use \`--var\` to override app config variables at runtime. Common variables:
311
+
312
+ | Variable | Description |
313
+ |----------|-------------|
314
+ | \`base_url\` | Base URL for the app (e.g., preview deployment URL) |
315
+ | \`login_url\` | Login page URL |
316
+ | \`login_username\` | Username/email for authentication |
317
+ | \`login_password\` | Password for authentication |
318
+
319
+ Example with ephemeral preview URL:
320
+ \`\`\`bash
321
+ qa-use browser create --after-test-id <login-test-uuid> \\
322
+ --var base_url=https://preview-123.example.com \\
323
+ --var login_url=https://preview-123.example.com/auth/login
324
+ \`\`\`
325
+
326
+ ## Common Patterns
327
+
328
+ ### Pattern 1: Feature Verification
329
+
330
+ **CLI Workflow:**
331
+ \`\`\`bash
332
+ # 1. Search for existing test
333
+ qa-use test list | grep "login"
334
+
335
+ # 2. Run test with autofix
336
+ qa-use test run login --autofix
337
+
338
+ # 3. Debug failures
339
+ qa-use browser logs console
340
+ \`\`\`
341
+
342
+ **Plugin Shortcut:**
343
+ \`\`\`
344
+ /qa-use:verify "login works with valid credentials"
345
+ \`\`\`
346
+ (Wraps the above CLI workflow with AI-powered test discovery and analysis)
347
+
348
+ ### Pattern 2: Record & Generate Test
349
+
350
+ **CLI Workflow:**
351
+ \`\`\`bash
352
+ # 1. Create session
353
+ qa-use browser create --tunnel --no-headless
354
+
355
+ # 2. Navigate and interact
356
+ qa-use browser goto https://example.com
357
+ qa-use browser snapshot
358
+ qa-use browser click e1
359
+ qa-use browser fill e5 "test"
360
+
361
+ # 3. Generate test from blocks
362
+ qa-use browser get-blocks
363
+ qa-use browser generate-test -n "my_test"
364
+
365
+ # 4. Run test
366
+ qa-use test run my_test
367
+ \`\`\`
368
+
369
+ **Plugin Shortcut:**
370
+ \`\`\`
371
+ /qa-use:record start my_test
372
+ # ... perform interactions ...
373
+ /qa-use:record stop
374
+ \`\`\`
375
+
376
+ ### Pattern 3: Authenticated Exploration
377
+
378
+ **CLI Workflow:**
379
+ \`\`\`bash
380
+ # Create session that runs login test first
381
+ qa-use browser create --after-test-id <login-test-uuid>
382
+
383
+ # Session now authenticated, explore
384
+ qa-use browser goto /dashboard
385
+ qa-use browser snapshot
386
+ \`\`\`
387
+
388
+ **Plugin Shortcut:**
389
+ \`\`\`
390
+ /qa-use:explore /dashboard
391
+ \`\`\`
392
+ (Automatically handles auth detection and session creation)
393
+
394
+ ### Pattern 4: Edit Existing Test
395
+
396
+ **CLI Workflow:**
397
+ \`\`\`bash
398
+ # 1. Open test file in editor
399
+ vim qa-tests/login.yaml
400
+
401
+ # 2. Validate syntax
402
+ qa-use test validate login
403
+
404
+ # 3. Run to verify
405
+ qa-use test run login
406
+ \`\`\`
407
+
408
+ **Plugin Shortcut:**
409
+ \`\`\`
410
+ /qa-use:record edit login
411
+ \`\`\`
412
+ (AI-assisted editing with validation)
413
+
414
+ ### Pattern 5: Using Snapshot Diff to Avoid Unnecessary Snapshots
415
+
416
+ **CLI Workflow:**
417
+ \`\`\`bash
418
+ # Create session and navigate
419
+ qa-use browser create --tunnel --no-headless
420
+ qa-use browser goto https://evals.desplega.ai/checkboxes
421
+
422
+ # goto shows diff — initial page load shows all elements:
423
+ # Changes: 45 elements added
424
+ # + [e18] checkbox "I agree to the terms and conditions"
425
+ # + [e19] generic "I agree to the terms and conditions"
426
+
427
+ # ✅ Use ref from diff directly — no snapshot needed!
428
+ qa-use browser click e18
429
+
430
+ # Diff shows what changed:
431
+ # Changes: 5 elements added, 1 element modified
432
+ # + [e54] generic "Thanks for agreeing!"
433
+ # + [e55] link "Terms and Conditions"
434
+ # ~ [e18] checkbox "I agree to the terms and conditions"
435
+ # +attrs: active, checked
436
+
437
+ # ✅ Can click e55 directly from diff output — no snapshot needed!
438
+ qa-use browser click e55
439
+
440
+ # ❌ Need to find an element NOT in the diff? Now run snapshot:
441
+ qa-use browser snapshot
442
+ \`\`\`
443
+
444
+ **Key principle:** Use diff output as your primary source of element refs after actions. Only fall back to \`snapshot\` when you need to find elements that weren't in the diff.
445
+
446
+ **Benefits:**
447
+ - Fewer API calls = faster automation
448
+ - Diff refs are always fresh (just returned from the server)
449
+ - Instantly see what changed (new elements, attribute changes, removals)
450
+
451
+ **No Plugin Shortcut** - Automatic feature in all browser commands
452
+
453
+ ## CI/CD Integration
454
+
455
+ ### Running Tests in CI
456
+
457
+ **Environment Variables:**
458
+ \`\`\`bash
459
+ export QA_USE_API_KEY="your-api-key"
460
+ export QA_USE_REGION="us" # Optional: "us" or "auto"
461
+ \`\`\`
462
+
463
+ **Basic Test Execution:**
464
+ \`\`\`bash
465
+ # Run all tests
466
+ qa-use test run --all
467
+
468
+ # Run specific tag
469
+ qa-use test run --tag smoke
470
+
471
+ # Exit codes: 0 = pass, 1 = fail
472
+ \`\`\`
473
+
474
+ ### GitHub Actions Example
475
+
476
+ \`\`\`yaml
477
+ name: QA Tests
478
+ on: [push, pull_request]
479
+
480
+ jobs:
481
+ test:
482
+ runs-on: ubuntu-latest
483
+ steps:
484
+ - uses: actions/checkout@v3
485
+ - uses: actions/setup-node@v3
486
+ with:
487
+ node-version: '20'
488
+ - name: Install qa-use
489
+ run: npm install -g @desplega.ai/qa-use
490
+ - name: Run tests
491
+ run: qa-use test run --all
492
+ env:
493
+ QA_USE_API_KEY: \${{ secrets.QA_USE_API_KEY }}
494
+ \`\`\`
495
+
496
+ ### Test Artifacts
497
+
498
+ **Screenshots:**
499
+ - Automatically saved on failure
500
+ - Location: \`/tmp/qa-use/downloads/\` (local) or cloud (remote)
501
+
502
+ **Logs:**
503
+ - Console logs: \`qa-use browser logs console -s <session-id>\`
504
+ - Network logs: \`qa-use browser logs network -s <session-id>\`
505
+
506
+ ## Advanced Topics
507
+
508
+ ### Localhost Testing (Tunnel Mode)
509
+
510
+ **When to use tunnel mode:**
511
+
512
+ \`\`\`
513
+ Testing localhost (http://localhost:3000)?
514
+ ├─ YES → Use --tunnel
515
+ │ └─ qa-use browser create --tunnel [--no-headless]
516
+ │ (Starts local Playwright, creates localtunnel, keeps running)
517
+
518
+ └─ NO (Public URL) → Use remote browser (default)
519
+ └─ qa-use browser create
520
+ (Uses desplega.ai cloud browser via WebSocket)
521
+ \`\`\`
522
+
523
+ **The \`--tunnel\` flag is a binary choice:**
524
+ - **Local tunnel mode**: Playwright on your machine + localtunnel
525
+ - **Remote mode**: WebSocket URL to cloud-hosted browser
526
+
527
+ **For test execution:**
528
+ \`\`\`bash
529
+ # Local app
530
+ qa-use test run my_test --tunnel [--headful]
531
+
532
+ # Public app
533
+ qa-use test run my_test
534
+ \`\`\`
535
+
536
+ **Plugin shortcuts handle tunnel detection automatically:**
537
+ \`\`\`
538
+ /qa-use:explore http://localhost:3000
539
+ /qa-use:record start local_test
540
+ \`\`\`
541
+
542
+ See [references/localhost-testing.md](references/localhost-testing.md) for troubleshooting.
543
+
544
+ ### Session Persistence
545
+
546
+ Sessions are stored in \`~/.qa-use.json\` and have:
547
+ - **TTL**: 30 minutes (default)
548
+ - **Auto-resolve**: One active session = no \`-s\` flag needed
549
+ - **Cleanup**: Automatic on timeout or explicit \`browser close\`
550
+
551
+ ### Block Limitations
552
+
553
+ **What's captured:**
554
+ - goto, click, fill, type, check, uncheck, select, hover
555
+ - scroll, scroll-into-view, drag, upload, press
556
+
557
+ **What's NOT captured:**
558
+ - Assertions (must be added manually)
559
+ - Waits (inferred from timing, may need adjustment)
560
+ - Complex interactions (multi-drag, hover sequences)
561
+
562
+ **Manual editing:** Edit generated YAML to add assertions and refine selectors.
563
+
564
+ ### WebSocket Sessions
565
+
566
+ **Sharing sessions across processes:**
567
+ \`\`\`bash
568
+ # Process 1: Create session
569
+ qa-use browser create --tunnel
570
+ # Output: ws://localhost:12345/browser/abc123
571
+
572
+ # Process 2: Connect to session
573
+ qa-use browser goto https://example.com --ws-url ws://localhost:12345/browser/abc123
574
+ \`\`\`
575
+
576
+ ## Deep-Dive References
577
+
578
+ | Document | Description |
579
+ |----------|-------------|
580
+ | [browser-commands.md](references/browser-commands.md) | Complete browser CLI reference with all flags |
581
+ | [test-format.md](references/test-format.md) | Full test YAML specification |
582
+ | [localhost-testing.md](references/localhost-testing.md) | Tunnel setup for local development |
583
+ | [failure-debugging.md](references/failure-debugging.md) | Failure classification and diagnostics |
584
+ | [ci.md](references/ci.md) | CI/CD integration patterns and examples |
585
+
586
+ ## Templates
587
+
588
+ | Template | Description |
589
+ |----------|-------------|
590
+ | [basic-test.yaml](templates/basic-test.yaml) | Simple navigation and assertion |
591
+ | [auth-flow.yaml](templates/auth-flow.yaml) | Login flow with credentials |
592
+ | [form-test.yaml](templates/form-test.yaml) | Form submission with validation |
593
+
594
+ ## Test Format Overview
595
+
596
+ \`\`\`yaml
597
+ name: Login Test
598
+ description: Validates login functionality with valid credentials
599
+ tags:
600
+ - smoke
601
+ - auth
602
+ app_config: <app-config-id>
603
+ variables:
604
+ email: test@example.com
605
+ password: secret123
606
+ depends_on: setup-test # Optional
607
+ steps:
608
+ - action: goto
609
+ url: /login
610
+ - action: fill
611
+ target: email input
612
+ value: $email
613
+ - action: click
614
+ target: login button
615
+ - action: to_be_visible
616
+ target: dashboard
617
+ \`\`\`
618
+
619
+ See [references/test-format.md](references/test-format.md) for complete specification.
620
+
621
+ ## Common Mistakes
622
+
623
+ | ❌ Wrong | ✅ Correct |
624
+ |---------|-----------|
625
+ | \`browser navigate <url>\` | \`browser goto <url>\` |
626
+ | \`browser destroy\` | \`browser close\` |
627
+ | \`browser close <session-id>\` | \`browser close\` |
628
+ | Guessing element refs | Use refs from diff output or \`snapshot\` |
629
+ | Running \`snapshot\` after every action | Use diff output; only \`snapshot\` when needed |
630
+ | Testing localhost without \`--tunnel\` | Use \`--tunnel\` flag |
631
+ | \`test sync --pull\` | \`test sync pull\` (subcommand, not flag) |
632
+ | \`test sync --push\` | \`test sync push\` (subcommand, not flag) |
633
+
634
+ ## npx Alternative
635
+
636
+ All commands use \`qa-use\` assuming global install. For one-off use:
637
+ \`\`\`bash
638
+ npx @desplega.ai/qa-use browser <command>
639
+ \`\`\`
640
+ `;
641
+ export const REFERENCE_DOCS = {
642
+ 'browser-commands': {
643
+ title: 'Browser Commands Reference',
644
+ content: `# Browser Commands Reference
645
+
646
+ Complete reference for \`qa-use browser\` CLI commands.
647
+
648
+ ## Session Management
649
+
650
+ ### create
651
+
652
+ Create a new browser session.
653
+
654
+ \`\`\`bash
655
+ qa-use browser create [options]
656
+ \`\`\`
657
+
658
+ | Flag | Description |
659
+ |------|-------------|
660
+ | \`--viewport <size>\` | Viewport size: \`desktop\` (1280x720), \`tablet\` (768x1024), \`mobile\` (375x667) |
661
+ | \`--tunnel\` | Run local browser with API tunnel (for localhost testing) |
662
+ | \`--headless\` | Run in headless mode (default with \`--tunnel\`) |
663
+ | \`--no-headless\` | Show browser window (use with \`--tunnel\` for debugging) |
664
+ | \`--ws-url <url>\` | Connect to existing WebSocket browser endpoint |
665
+ | \`--after-test-id <uuid>\` | Run a test before session becomes interactive (start after login, etc.) |
666
+
667
+ **Examples:**
668
+ \`\`\`bash
669
+ qa-use browser create # Remote browser, default viewport
670
+ qa-use browser create --viewport mobile # Remote browser, mobile viewport
671
+ qa-use browser create --tunnel # Local headless browser with tunnel
672
+ qa-use browser create --tunnel --no-headless # Local visible browser for debugging
673
+ qa-use browser create --ws-url wss://... # Connect to existing browser
674
+ qa-use browser create --after-test-id <uuid> # Start session after running a test
675
+ \`\`\`
676
+
677
+ **Starting after login (--after-test-id):**
678
+
679
+ The \`--after-test-id\` flag runs an existing test before the session becomes interactive. This is extremely useful for:
680
+ - **Bypassing login walls** - use a test that logs in, then start exploring from the authenticated state
681
+ - **Starting from a specific page state** - run a test that navigates to a complex form, then continue manually
682
+ - **Resuming from checkpoints** - save common setup steps as a test, reuse across explorations
683
+
684
+ \`\`\`bash
685
+ # First, create a login test and get its ID from the test listing
686
+ qa-use test run --list
687
+
688
+ # Then create a session that starts after login
689
+ qa-use browser create --after-test-id 4292938b-338d-4c1c-952e-6bcdf3f7731a
690
+
691
+ # Session is now logged in and ready for exploration
692
+ qa-use browser snapshot
693
+ \`\`\`
694
+
695
+ **Error handling for --after-test-id:**
696
+ - If test not found: "Test not found" (exit 1)
697
+ - If test belongs to different org: "Test belongs to different organization" (exit 1)
698
+ - If test fails: Session status becomes "failed" with error message displayed
699
+
700
+ **Session persistence:** Sessions are stored in \`~/.qa-use.json\`. If only one active session exists, it's used automatically for all commands.
701
+
702
+ ### list
703
+
704
+ List all active browser sessions.
705
+
706
+ \`\`\`bash
707
+ qa-use browser list
708
+ \`\`\`
709
+
710
+ Shows session IDs, creation time, and status.
711
+
712
+ ### status
713
+
714
+ Show detailed status of current session.
715
+
716
+ \`\`\`bash
717
+ qa-use browser status
718
+ qa-use browser -s <session-id> status
719
+ \`\`\`
720
+
721
+ **Output includes:**
722
+ - Session ID
723
+ - Current URL
724
+ - Viewport size
725
+ - \`app_url\` - Web UI for viewing the session
726
+ - \`recording_url\` - URL to download session recording
727
+ - \`har_url\` - URL to download HAR file (network logs)
728
+ - Creation time and deadline
729
+
730
+ ### close
731
+
732
+ Close the active browser session.
733
+
734
+ \`\`\`bash
735
+ qa-use browser close
736
+ \`\`\`
737
+
738
+ **Note:** Takes no arguments. Closes the currently active session. Use \`browser list\` first if you have multiple sessions and need to switch.
739
+
740
+ ## Navigation
741
+
742
+ ### goto
743
+
744
+ Navigate to a URL.
745
+
746
+ \`\`\`bash
747
+ qa-use browser goto <url>
748
+ \`\`\`
749
+
750
+ URL can be absolute (\`https://example.com\`) or relative (\`/login\`).
751
+
752
+ ### back / forward / reload
753
+
754
+ History navigation.
755
+
756
+ \`\`\`bash
757
+ qa-use browser back
758
+ qa-use browser forward
759
+ qa-use browser reload
760
+ \`\`\`
761
+
762
+ ## Element Targeting
763
+
764
+ ### snapshot
765
+
766
+ Get the page's ARIA accessibility tree with element refs.
767
+
768
+ \`\`\`bash
769
+ qa-use browser snapshot [options]
770
+ \`\`\`
771
+
772
+ | Flag | Description |
773
+ |------|-------------|
774
+ | \`-i, --interactive\` | Only include interactive elements (buttons, inputs, links) |
775
+ | \`-c, --compact\` | Remove empty structural elements |
776
+ | \`-d, --max-depth <n>\` | Limit tree depth (1-20, where 1 = top level only) |
777
+ | \`--scope <selector>\` | CSS selector to scope snapshot (e.g., \`#main\`, \`.form\`) |
778
+ | \`--json\` | Output raw JSON including filter_stats |
779
+
780
+ **Output format:**
781
+ \`\`\`
782
+ - heading "Page Title" [level=1] [ref=e2]
783
+ - button "Click Me" [ref=e3]
784
+ - textbox "Email" [ref=e4]
785
+ - link "Sign Up" [ref=e5]
786
+ \`\`\`
787
+
788
+ **Filtering examples:**
789
+ \`\`\`bash
790
+ # Get only interactive elements (great for reducing token count)
791
+ qa-use browser snapshot --interactive
792
+
793
+ # Combine filters for maximum reduction
794
+ qa-use browser snapshot --interactive --compact --max-depth 3
795
+
796
+ # Scope to specific section
797
+ qa-use browser snapshot --scope "#main-content"
798
+ \`\`\`
799
+
800
+ **Typical reductions:**
801
+ - \`--max-depth 3\`: ~98% reduction
802
+ - \`--interactive\`: 0-80% depending on page
803
+ - Combined \`--interactive --max-depth 4\`: ~95% reduction
804
+
805
+ Use the \`[ref=eN]\` values in interaction commands.
806
+
807
+ **Critical workflow:** Run \`snapshot\` before your first interaction on a new page. After that, use the snapshot diff output from actions to get fresh refs — only run \`snapshot\` again when you need elements not shown in the diff. Refs are session-specific and change between page loads.
808
+
809
+ ## Interactions
810
+
811
+ ### click
812
+
813
+ Click an element.
814
+
815
+ \`\`\`bash
816
+ qa-use browser click <ref>
817
+ qa-use browser click --text "Button label"
818
+ \`\`\`
819
+
820
+ | Argument | Description |
821
+ |----------|-------------|
822
+ | \`<ref>\` | Element ref from snapshot (e.g., \`e3\`) |
823
+ | \`--text\` | Semantic description for AI selection |
824
+
825
+ ### fill
826
+
827
+ Fill an input field (clears existing content).
828
+
829
+ \`\`\`bash
830
+ qa-use browser fill <ref> "value"
831
+ qa-use browser fill --text "Email field" "user@example.com"
832
+ \`\`\`
833
+
834
+ ### type
835
+
836
+ Type text with keystroke delays (useful for autocomplete).
837
+
838
+ \`\`\`bash
839
+ qa-use browser type <ref> "text"
840
+ \`\`\`
841
+
842
+ ### press
843
+
844
+ Press a keyboard key.
845
+
846
+ \`\`\`bash
847
+ qa-use browser press Enter
848
+ qa-use browser press Tab
849
+ qa-use browser press Escape
850
+ \`\`\`
851
+
852
+ ### check / uncheck
853
+
854
+ Toggle checkboxes.
855
+
856
+ \`\`\`bash
857
+ qa-use browser check <ref>
858
+ qa-use browser uncheck <ref>
859
+ \`\`\`
860
+
861
+ ### select
862
+
863
+ Select dropdown option by value or label.
864
+
865
+ \`\`\`bash
866
+ qa-use browser select <ref> "option value"
867
+ \`\`\`
868
+
869
+ ### hover
870
+
871
+ Hover over an element.
872
+
873
+ \`\`\`bash
874
+ qa-use browser hover <ref>
875
+ \`\`\`
876
+
877
+ ### scroll
878
+
879
+ Scroll the page or viewport.
880
+
881
+ \`\`\`bash
882
+ qa-use browser scroll down 500 # Scroll down 500px
883
+ qa-use browser scroll up 300 # Scroll up 300px
884
+ qa-use browser scroll-into-view <ref> # Scroll element into viewport
885
+ \`\`\`
886
+
887
+ ### drag
888
+
889
+ Drag an element to a target element.
890
+
891
+ \`\`\`bash
892
+ qa-use browser drag <ref> --target <target-ref>
893
+ qa-use browser drag <ref> --target-selector ".drop-zone"
894
+ qa-use browser drag --text "Draggable item" --target <target-ref>
895
+ \`\`\`
896
+
897
+ | Argument | Description |
898
+ |----------|-------------|
899
+ | \`<ref>\` | Source element ref from snapshot |
900
+ | \`--text\` | Semantic source description for AI selection |
901
+ | \`--target <ref>\` | Target element ref |
902
+ | \`--target-selector <sel>\` | Target CSS selector |
903
+
904
+ **Examples:**
905
+ \`\`\`bash
906
+ qa-use browser drag e5 --target e10 # Drag by ref to ref
907
+ qa-use browser drag e5 --target-selector ".canvas" # Drag to CSS selector
908
+ qa-use browser drag --text "Process node" --target e10 # Drag by text
909
+ \`\`\`
910
+
911
+ **Note:** The browser CLI drag command uses element refs from snapshots. This is different from the test YAML format which uses locator chains. See test-format.md for YAML test syntax.
912
+
913
+ ### mfa-totp
914
+
915
+ Generate TOTP code and optionally fill into an input field.
916
+
917
+ \`\`\`bash
918
+ qa-use browser mfa-totp <secret> # Generate only
919
+ qa-use browser mfa-totp <ref> <secret> # Generate and fill by ref
920
+ qa-use browser mfa-totp --text "OTP input" <secret> # Generate and fill by text
921
+ \`\`\`
922
+
923
+ | Argument | Description |
924
+ |----------|-------------|
925
+ | \`<secret>\` | TOTP secret (base32 encoded) |
926
+ | \`<ref>\` | Element ref to fill (optional) |
927
+ | \`--text\` | Semantic element description for AI selection |
928
+
929
+ **Examples:**
930
+ \`\`\`bash
931
+ qa-use browser mfa-totp JBSWY3DPEHPK3PXP # Generate code only
932
+ qa-use browser mfa-totp e15 JBSWY3DPEHPK3PXP # Fill into element e15
933
+ qa-use browser mfa-totp --text "verification code" JBSWY3DPEHPK3PXP
934
+ \`\`\`
935
+
936
+ ### upload
937
+
938
+ Upload file(s) to a file input element.
939
+
940
+ \`\`\`bash
941
+ qa-use browser upload <ref> <file>...
942
+ qa-use browser upload --text "Choose file" <file>...
943
+ \`\`\`
944
+
945
+ | Argument | Description |
946
+ |----------|-------------|
947
+ | \`<ref>\` | File input element ref from snapshot |
948
+ | \`--text\` | Semantic element description for AI selection |
949
+ | \`<file>...\` | One or more file paths to upload |
950
+
951
+ **Examples:**
952
+ \`\`\`bash
953
+ qa-use browser upload e8 /tmp/document.pdf # Single file
954
+ qa-use browser upload e8 /tmp/file1.pdf /tmp/file2.pdf # Multiple files
955
+ qa-use browser upload --text "Upload attachment" /tmp/doc.pdf # By text
956
+ \`\`\`
957
+
958
+ **Upload encoding:** Files are read locally and sent as base64-encoded data. This works in both remote and tunnel modes — no need for the browser to have direct access to the file system.
959
+
960
+ ## Downloads
961
+
962
+ ### downloads
963
+
964
+ List or save files downloaded during the browser session.
965
+
966
+ \`\`\`bash
967
+ qa-use browser downloads # List downloads
968
+ qa-use browser downloads --json # Output as JSON
969
+ qa-use browser downloads --save /tmp/dl # Save files to directory
970
+ qa-use browser downloads -s <id> # Downloads from specific/closed session
971
+ \`\`\`
972
+
973
+ | Flag | Description |
974
+ |------|-------------|
975
+ | \`--json\` | Output raw JSON with URLs and metadata |
976
+ | \`--save <dir>\` | Download files to local directory |
977
+ | \`-s, --session-id <id>\` | Specify session (default: auto-resolved) |
978
+
979
+ **Download detection:** When any browser action triggers a file download (e.g., clicking a download link), the action response automatically includes download info (filename, size, presigned URL). The \`downloads\` command retrieves the full list.
980
+
981
+ ## Inspection
982
+
983
+ ### url
984
+
985
+ Get current page URL.
986
+
987
+ \`\`\`bash
988
+ qa-use browser url
989
+ \`\`\`
990
+
991
+ ### screenshot
992
+
993
+ Capture a screenshot.
994
+
995
+ \`\`\`bash
996
+ qa-use browser screenshot # Saves as screenshot.png
997
+ qa-use browser screenshot myfile.png # Custom filename
998
+ qa-use browser screenshot /path/to/file.png # Custom path
999
+ qa-use browser screenshot --base64 # Output base64 to stdout
1000
+ \`\`\`
1001
+
1002
+ **Note:** Path is a positional argument, not a flag. Do NOT use \`--output\` or \`--path\`.
1003
+
1004
+ ### get-blocks
1005
+
1006
+ Get recorded interaction blocks from the session.
1007
+
1008
+ \`\`\`bash
1009
+ qa-use browser get-blocks
1010
+ \`\`\`
1011
+
1012
+ Returns structured data of interactions performed during the session.
1013
+
1014
+ ## Logs
1015
+
1016
+ ### logs console
1017
+
1018
+ View browser console logs.
1019
+
1020
+ \`\`\`bash
1021
+ qa-use browser logs console # Current session
1022
+ qa-use browser logs console -s <id> # Specific or closed session
1023
+ \`\`\`
1024
+
1025
+ Shows console.log, console.error, and other console output from the page.
1026
+
1027
+ ### logs network
1028
+
1029
+ View network request logs.
1030
+
1031
+ \`\`\`bash
1032
+ qa-use browser logs network # Current session
1033
+ qa-use browser logs network -s <id> # Specific or closed session
1034
+ \`\`\`
1035
+
1036
+ Shows HTTP requests, responses, and timing information.
1037
+
1038
+ ## Test Generation
1039
+
1040
+ ### generate-test
1041
+
1042
+ Generate a test YAML file from recorded session interactions.
1043
+
1044
+ \`\`\`bash
1045
+ qa-use browser generate-test # Current session
1046
+ qa-use browser generate-test -s <id> # Specific session
1047
+ qa-use browser generate-test --output my-test.yaml # Custom output path
1048
+ \`\`\`
1049
+
1050
+ Creates a test definition based on the interactions performed during the session.
1051
+
1052
+ ## Waiting
1053
+
1054
+ ### wait
1055
+
1056
+ Fixed time wait.
1057
+
1058
+ \`\`\`bash
1059
+ qa-use browser wait 2000 # Wait 2 seconds
1060
+ \`\`\`
1061
+
1062
+ ### wait-for-selector
1063
+
1064
+ Wait for an element to appear.
1065
+
1066
+ \`\`\`bash
1067
+ qa-use browser wait-for-selector ".content"
1068
+ qa-use browser wait-for-selector ".modal" --state visible
1069
+ qa-use browser wait-for-selector ".loading" --state hidden
1070
+ \`\`\`
1071
+
1072
+ | Flag | Description |
1073
+ |------|-------------|
1074
+ | \`--state\` | Wait for state: \`visible\`, \`hidden\`, \`attached\`, \`detached\` |
1075
+ | \`--timeout\` | Max wait time in ms (default: 30000) |
1076
+
1077
+ ### wait-for-load
1078
+
1079
+ Wait for page load state.
1080
+
1081
+ \`\`\`bash
1082
+ qa-use browser wait-for-load
1083
+ qa-use browser wait-for-load --state networkidle
1084
+ qa-use browser wait-for-load --state domcontentloaded
1085
+ \`\`\`
1086
+
1087
+ | State | Description |
1088
+ |-------|-------------|
1089
+ | \`load\` | Wait for load event (default) |
1090
+ | \`domcontentloaded\` | Wait for DOMContentLoaded |
1091
+ | \`networkidle\` | Wait for no network activity |
1092
+
1093
+ ## Session Flag Position
1094
+
1095
+ When working with multiple sessions, use \`-s <id>\` BEFORE the command:
1096
+
1097
+ \`\`\`bash
1098
+ qa-use browser -s abc123 goto https://example.com # ✅ Correct
1099
+ qa-use browser goto -s abc123 https://example.com # ❌ Wrong
1100
+ qa-use browser goto https://example.com -s abc123 # ❌ Wrong
1101
+ \`\`\`
1102
+
1103
+ ## Interactive Mode
1104
+
1105
+ For extended multi-command sessions:
1106
+
1107
+ \`\`\`bash
1108
+ qa-use browser run
1109
+ qa-use browser run --after-test-id <uuid> # Start REPL from post-test state
1110
+ \`\`\`
1111
+
1112
+ Opens interactive REPL for browser commands. Use \`--after-test-id\` to start the REPL in an authenticated or pre-configured state.
1113
+
1114
+ ## Local Browser with Tunnel
1115
+
1116
+ The \`--tunnel\` flag starts a real browser on your machine with a tunnel for API control:
1117
+
1118
+ 1. **Browser runs locally** - you can see it (with \`--no-headless\`)
1119
+ 2. **API controls via tunnel** - cloud API sends commands through the tunnel
1120
+ 3. **Auto-cleanup** - session closes when you press Ctrl+C or run \`browser close\`
1121
+
1122
+ **Use cases:**
1123
+ - Debugging tests visually
1124
+ - Testing localhost URLs
1125
+ - Developing tests interactively
1126
+
1127
+ \`\`\`bash
1128
+ # Start visible local browser
1129
+ qa-use browser create --tunnel --no-headless
1130
+
1131
+ # Now interact normally
1132
+ qa-use browser goto http://localhost:3000
1133
+ qa-use browser snapshot
1134
+ qa-use browser click e3
1135
+
1136
+ # Watch the browser respond in real-time
1137
+ \`\`\`
1138
+ `,
1139
+ },
1140
+ ci: {
1141
+ title: 'CI Integration Guide',
1142
+ content: `# CI Integration Guide
1143
+
1144
+ Run qa-use verification in GitHub Actions and other CI environments.
1145
+
1146
+ ## GitHub Actions Setup
1147
+
1148
+ ### Basic Workflow
1149
+
1150
+ \`\`\`yaml
1151
+ # .github/workflows/pr-verify.yml
1152
+ name: PR Verification
1153
+
1154
+ on:
1155
+ pull_request:
1156
+ types: [opened, synchronize, reopened]
1157
+
1158
+ jobs:
1159
+ verify-pr:
1160
+ runs-on: ubuntu-latest
1161
+ # Optional: only run on PRs with frontend changes
1162
+ # if: contains(github.event.pull_request.labels.*.name, 'frontend')
1163
+
1164
+ steps:
1165
+ - name: Checkout repository
1166
+ uses: actions/checkout@v4
1167
+ with:
1168
+ fetch-depth: 0 # Full history for diff analysis
1169
+
1170
+ - name: Setup Node.js
1171
+ uses: actions/setup-node@v4
1172
+ with:
1173
+ node-version: '20'
1174
+
1175
+ - name: Install Claude Code CLI
1176
+ run: |
1177
+ curl -fsSL https://claude.ai/install.sh | bash
1178
+ echo "$HOME/.local/bin" >> $GITHUB_PATH
1179
+
1180
+ - name: Install qa-use plugin and CLI
1181
+ run: |
1182
+ claude mcp add-from-marketplace qa-use
1183
+ npm install -g @desplega.ai/qa-use
1184
+
1185
+ - name: Run PR Verification
1186
+ env:
1187
+ CLAUDE_CODE_OAUTH_TOKEN: \${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
1188
+ QA_USE_API_KEY: \${{ secrets.QA_USE_API_KEY }}
1189
+ GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
1190
+ CI: true
1191
+ run: |
1192
+ # Run Claude Code with the verify-pr command
1193
+ claude --print "/qa-use:verify-pr #\${{ github.event.pull_request.number }}"
1194
+
1195
+ - name: Post Report to PR
1196
+ if: always() # Post even if verification had warnings
1197
+ env:
1198
+ GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
1199
+ run: |
1200
+ if [ -f /tmp/pr-verify-report-\${{ github.event.pull_request.number }}.md ]; then
1201
+ gh pr comment \${{ github.event.pull_request.number }} \\
1202
+ --body-file /tmp/pr-verify-report-\${{ github.event.pull_request.number }}.md
1203
+ fi
1204
+ \`\`\`
1205
+
1206
+ ### With Preview Deployment (Vercel/Netlify)
1207
+
1208
+ \`\`\`yaml
1209
+ # .github/workflows/pr-verify.yml
1210
+ name: PR Verification
1211
+
1212
+ on:
1213
+ pull_request:
1214
+ branches:
1215
+ - main
1216
+ types: [opened, synchronize, reopened, ready_for_review]
1217
+ workflow_dispatch:
1218
+ inputs:
1219
+ pr_number:
1220
+ description: "PR number to verify"
1221
+ required: true
1222
+ type: number
1223
+
1224
+ concurrency:
1225
+ group: pr-verify-\${{ github.event.pull_request.number || inputs.pr_number }}
1226
+ cancel-in-progress: true
1227
+
1228
+ jobs:
1229
+ verify-pr:
1230
+ if: github.event_name == 'workflow_dispatch' || github.event.pull_request.draft == false
1231
+ runs-on: ubuntu-latest
1232
+ permissions:
1233
+ contents: read
1234
+ deployments: read
1235
+ pull-requests: write
1236
+ statuses: read
1237
+
1238
+ steps:
1239
+ - name: Checkout repository
1240
+ uses: actions/checkout@v4
1241
+ with:
1242
+ fetch-depth: 0 # Full history for diff analysis
1243
+
1244
+ - name: Check PR approval status
1245
+ id: approval
1246
+ env:
1247
+ GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
1248
+ run: |
1249
+ # REVIEW_DECISION=$(gh pr view \${{ github.event.pull_request.number || inputs.pr_number }} --json reviewDecision -q '.reviewDecision')
1250
+ # echo "Review decision: $REVIEW_DECISION"
1251
+ # if [ "$REVIEW_DECISION" != "APPROVED" ]; then
1252
+ # echo "PR is not approved yet. Skipping verification."
1253
+ # echo "approved=false" >> $GITHUB_OUTPUT
1254
+ # else
1255
+ # echo "approved=true" >> $GITHUB_OUTPUT
1256
+ # fi
1257
+ # For demonstration purposes, we will assume all PRs are approved.
1258
+ echo "approved=true" >> $GITHUB_OUTPUT
1259
+
1260
+ - name: Setup Node.js
1261
+ if: steps.approval.outputs.approved == 'true'
1262
+ uses: actions/setup-node@v4
1263
+ with:
1264
+ node-version: "20"
1265
+
1266
+ - name: Install Claude Code CLI
1267
+ if: steps.approval.outputs.approved == 'true'
1268
+ run: |
1269
+ curl -fsSL https://claude.ai/install.sh | bash
1270
+ echo "$HOME/.local/bin" >> $GITHUB_PATH
1271
+
1272
+ - name: Verify Claude CLI Installation
1273
+ if: steps.approval.outputs.approved == 'true'
1274
+ run: |
1275
+ claude --version || (echo "Claude CLI installation failed" && exit 1)
1276
+
1277
+ - name: Install qa-use plugin and CLI
1278
+ if: steps.approval.outputs.approved == 'true'
1279
+ run: |
1280
+ claude plugin marketplace add desplega-ai/qa-use
1281
+ claude plugin install qa-use@desplega.ai
1282
+ npm install -g @desplega.ai/qa-use
1283
+
1284
+ - name: Wait for Vercel Preview
1285
+ if: steps.approval.outputs.approved == 'true'
1286
+ uses: patrickedqvist/wait-for-vercel-preview@v1.3.1
1287
+ id: vercel
1288
+ with:
1289
+ token: \${{ secrets.GITHUB_TOKEN }}
1290
+ max_timeout: 300
1291
+
1292
+ - name: Run PR Verification
1293
+ if: steps.approval.outputs.approved == 'true'
1294
+ env:
1295
+ CLAUDE_CODE_OAUTH_TOKEN: \${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
1296
+ QA_USE_API_KEY: \${{ secrets.QA_USE_API_KEY }}
1297
+ GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
1298
+ CI: true
1299
+ run: |
1300
+ # Run Claude Code with the verify-pr command using Vercel preview URL
1301
+ claude --print --verbose --dangerously-skip-permissions --output-format stream-json --model haiku "/qa-use:verify-pr #\${{ github.event.pull_request.number || inputs.pr_number }} --base-url \${{ steps.vercel.outputs.url }}" 2>&1 | jq -c 'select(.type == "assistant" or .type == "tool_use" or .type == "result")'
1302
+
1303
+ - name: Post Report to PR
1304
+ if: always() && steps.approval.outputs.approved == 'true'
1305
+ env:
1306
+ GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
1307
+ run: |
1308
+ if [ -f /tmp/pr-verify-report-\${{ github.event.pull_request.number || inputs.pr_number }}.md ]; then
1309
+ gh pr comment \${{ github.event.pull_request.number || inputs.pr_number }} \\
1310
+ --body-file /tmp/pr-verify-report-\${{ github.event.pull_request.number || inputs.pr_number }}.md
1311
+ fi
1312
+
1313
+ - name: Upload Verification Artifacts
1314
+ if: always() && steps.approval.outputs.approved == 'true'
1315
+ uses: actions/upload-artifact@v4
1316
+ with:
1317
+ name: pr-verification-\${{ github.event.pull_request.number || inputs.pr_number }}
1318
+ path: |
1319
+ /tmp/pr-verify-*.png
1320
+ /tmp/pr-verify-*.json
1321
+ /tmp/pr-verify-*.jsonl
1322
+ /tmp/pr-verify-*.log
1323
+ /tmp/pr-verify-report-*.md
1324
+ \`\`\`
1325
+
1326
+ ### Netlify Preview Deployment
1327
+
1328
+ \`\`\`yaml
1329
+ # Wait for Netlify preview deployment
1330
+ - name: Wait for Netlify Preview
1331
+ uses: jlevy-io/wait-for-netlify-deploy-with-headers@v1.0.1
1332
+ id: netlify
1333
+ with:
1334
+ site_name: 'your-netlify-site-name'
1335
+ max_timeout: 300
1336
+
1337
+ - name: Run PR Verification
1338
+ env:
1339
+ CLAUDE_CODE_OAUTH_TOKEN: \${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
1340
+ QA_USE_API_KEY: \${{ secrets.QA_USE_API_KEY }}
1341
+ GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
1342
+ CI: true
1343
+ run: |
1344
+ claude --print "/qa-use:verify-pr #\${{ github.event.pull_request.number }} --base-url \${{ steps.netlify.outputs.url }}"
1345
+ \`\`\`
1346
+
1347
+ ## Variable Overrides
1348
+
1349
+ When running tests against preview deployments, you can override app config variables using \`--var\`:
1350
+
1351
+ \`\`\`bash
1352
+ qa-use browser create --after-test-id <login-test-uuid> \\
1353
+ --var base_url=https://preview-123.example.com \\
1354
+ --var login_url=https://preview-123.example.com/auth/login
1355
+ \`\`\`
1356
+
1357
+ Common app config variables:
1358
+
1359
+ | Variable | Description |
1360
+ |----------|-------------|
1361
+ | \`base_url\` | Base URL for the app (e.g., preview deployment) |
1362
+ | \`login_url\` | Login page URL |
1363
+ | \`login_username\` | Username/email for authentication |
1364
+ | \`login_password\` | Password for authentication |
1365
+
1366
+ The \`/qa-use:verify-pr\` command handles this automatically when you pass \`--base-url\`.
1367
+
1368
+ ## Pre-installed Tools on GitHub Runners
1369
+
1370
+ GitHub-hosted runners include:
1371
+
1372
+ | Tool | Status | Notes |
1373
+ |------|--------|-------|
1374
+ | \`gh\` CLI | Pre-installed | Auto-authenticated via \`GITHUB_TOKEN\` |
1375
+ | Node.js | Available | Pin version for consistency |
1376
+ | git | Pre-installed | Full functionality |
1377
+ | curl | Pre-installed | For fallback API calls |
1378
+
1379
+ ## Required Secrets
1380
+
1381
+ | Secret | Description | How to Get |
1382
+ |--------|-------------|------------|
1383
+ | \`CLAUDE_CODE_OAUTH_TOKEN\` | OAuth token for Claude Code authentication | Run \`claude setup-token\` locally (see below) |
1384
+ | \`QA_USE_API_KEY\` | qa-use/desplega.ai API key | From [desplega.ai dashboard](https://desplega.ai) |
1385
+ | \`GITHUB_TOKEN\` | Auto-provided by GitHub Actions | No setup needed (automatic) |
1386
+
1387
+ ### Getting CLAUDE_CODE_OAUTH_TOKEN
1388
+
1389
+ Run locally to generate and retrieve your OAuth token:
1390
+
1391
+ \`\`\`bash
1392
+ # This will authenticate and store the token locally
1393
+ claude setup-token
1394
+
1395
+ # The token is stored in ~/.claude/.credentials.json
1396
+ # Copy the token value and add it as a GitHub secret
1397
+ \`\`\`
1398
+
1399
+ Claude Code automatically picks up \`CLAUDE_CODE_OAUTH_TOKEN\` from the environment when running in CI.
1400
+
1401
+ ## Headless/Autonomous Mode
1402
+
1403
+ When \`CI=true\` or \`GITHUB_ACTIONS=true\` is set, the verify-pr command operates in fully autonomous mode:
1404
+
1405
+ | Behavior | Description |
1406
+ |----------|-------------|
1407
+ | No user prompts | Makes autonomous decisions with sensible defaults |
1408
+ | Auto-select first match | When multiple options exist (e.g., login tests) |
1409
+ | Continue on soft failures | Reports issues but doesn't block execution |
1410
+ | Fail fast on hard failures | Missing API key, no PR context, etc. |
1411
+
1412
+ ## Exit Codes
1413
+
1414
+ | Code | Meaning |
1415
+ |------|---------|
1416
+ | 0 | Verification completed (even with warnings/partial results) |
1417
+ | 1 | Hard failure (no PR context, API key missing, session creation failed) |
1418
+
1419
+ The report is always generated regardless of exit code, allowing PR comments to be posted even on partial failures.
1420
+
1421
+ ## Filtering by Label
1422
+
1423
+ To only run verification on PRs with specific labels:
1424
+
1425
+ \`\`\`yaml
1426
+ jobs:
1427
+ verify-pr:
1428
+ runs-on: ubuntu-latest
1429
+ if: contains(github.event.pull_request.labels.*.name, 'needs-verification')
1430
+ \`\`\`
1431
+
1432
+ Or to only run on frontend changes:
1433
+
1434
+ \`\`\`yaml
1435
+ on:
1436
+ pull_request:
1437
+ paths:
1438
+ - 'src/**/*.tsx'
1439
+ - 'src/**/*.jsx'
1440
+ - 'src/**/*.ts'
1441
+ - 'src/**/*.js'
1442
+ - 'src/**/*.vue'
1443
+ - 'src/**/*.svelte'
1444
+ \`\`\`
1445
+
1446
+ ## Debugging
1447
+
1448
+ ### View Raw Output
1449
+
1450
+ The command outputs a markdown report to stdout. To see raw output:
1451
+
1452
+ \`\`\`yaml
1453
+ - name: Run PR Verification
1454
+ run: |
1455
+ claude --print "/qa-use:verify-pr #\${{ github.event.pull_request.number }}" 2>&1 | tee /tmp/verification-output.txt
1456
+ \`\`\`
1457
+
1458
+ ### Check Session Artifacts
1459
+
1460
+ After verification, session artifacts are available:
1461
+
1462
+ \`\`\`yaml
1463
+ - name: Upload Verification Artifacts
1464
+ uses: actions/upload-artifact@v4
1465
+ if: always()
1466
+ with:
1467
+ name: pr-verification-\${{ github.event.pull_request.number }}
1468
+ path: |
1469
+ /tmp/pr-verify-*.png
1470
+ /tmp/pr-verify-*.json
1471
+ /tmp/pr-verify-report-*.md
1472
+ \`\`\`
1473
+
1474
+ ### Common Issues
1475
+
1476
+ | Issue | Solution |
1477
+ |-------|----------|
1478
+ | "API key not configured" | Ensure \`QA_USE_API_KEY\` secret is set |
1479
+ | "No login test found" | Either upload a login test or the command will proceed without auth |
1480
+ | "Session creation failed" | Check if \`QA_USE_API_KEY\` is valid and not expired |
1481
+ | "gh: command not found" | \`gh\` should be pre-installed; ensure checkout step runs first |
1482
+ `,
1483
+ },
1484
+ 'failure-debugging': {
1485
+ title: 'Failure Debugging',
1486
+ content: `# Failure Debugging
1487
+
1488
+ Guide for analyzing E2E test failures and determining root causes.
1489
+
1490
+ ## Failure Classification
1491
+
1492
+ Every test failure falls into one of three categories:
1493
+
1494
+ | Category | Meaning | Who Fixes |
1495
+ |----------|---------|-----------|
1496
+ | **CODE BUG** | Feature doesn't work | Developer (fix application code) |
1497
+ | **TEST BUG** | Test is outdated | Developer/QA (update test) |
1498
+ | **ENVIRONMENT** | External issue | Ops (fix infrastructure) |
1499
+
1500
+ Getting the classification right determines the correct fix approach.
1501
+
1502
+ ## CODE BUG
1503
+
1504
+ **The feature doesn't work as expected. The application code is broken.**
1505
+
1506
+ ### Indicators
1507
+
1508
+ - Expected behavior doesn't happen (redirect doesn't occur, data isn't saved)
1509
+ - JavaScript errors in browser console
1510
+ - API calls returning error responses (4xx, 5xx)
1511
+ - Application crashes or shows error pages
1512
+ - Form submission has no effect
1513
+ - Data not persisting
1514
+
1515
+ ### Diagnostic Questions
1516
+
1517
+ 1. Does the feature work when tested manually in a browser?
1518
+ 2. Are there related recent code changes?
1519
+ 3. Is the backend API responding correctly?
1520
+ 4. Are there JavaScript errors in the console? (\`qa-use browser logs console\`)
1521
+ 5. Are API requests failing? (\`qa-use browser logs network\`)
1522
+
1523
+ ### Investigation Steps
1524
+
1525
+ \`\`\`bash
1526
+ # 1. Get console logs
1527
+ qa-use browser logs console -s <session-id>
1528
+
1529
+ # 2. Get network logs
1530
+ qa-use browser logs network -s <session-id>
1531
+
1532
+ # 3. Check for errors
1533
+ # Look for: console.error, failed requests, 4xx/5xx responses
1534
+ \`\`\`
1535
+
1536
+ ### Suggested Actions
1537
+
1538
+ - **Locate relevant code:**
1539
+ - URL \`/login\` → look for \`pages/login\`, \`routes/login\`, \`auth/\`
1540
+ - Component "dashboard" → look for \`Dashboard.tsx\`, \`components/dashboard\`
1541
+ - Form submission → look for \`handleSubmit\`, form handlers, API calls
1542
+
1543
+ - **Check recent changes:**
1544
+ \`\`\`bash
1545
+ git log --oneline -20 -- src/
1546
+ git diff HEAD~5 -- src/auth/
1547
+ \`\`\`
1548
+
1549
+ - **Debug manually** - reproduce the issue in a browser with DevTools open
1550
+
1551
+ ## TEST BUG
1552
+
1553
+ **The test definition is outdated or incorrect. The feature works, but the test doesn't match it.**
1554
+
1555
+ ### Indicators
1556
+
1557
+ - Element selector/target no longer matches
1558
+ - Timing issues (element appears with different delay)
1559
+ - Expected value changed (button text "Submit" → "Sign In")
1560
+ - Test assumes old workflow that was redesigned
1561
+ - Assertion expects outdated content
1562
+
1563
+ ### Diagnostic Questions
1564
+
1565
+ 1. Has the UI changed recently (button text, layout, element attributes)?
1566
+ 2. Is this a timing/race condition issue?
1567
+ 3. Does the test pass with \`--autofix\`?
1568
+ 4. Did someone refactor the component without updating tests?
1569
+
1570
+ ### Investigation Steps
1571
+
1572
+ \`\`\`bash
1573
+ # 1. Run with autofix to see if AI can fix it
1574
+ qa-use test run my-test --autofix
1575
+
1576
+ # 2. If autofix works, persist the fix
1577
+ qa-use test run my-test --autofix --update-local
1578
+
1579
+ # 3. Check what changed
1580
+ git diff qa-tests/my-test.yaml
1581
+ \`\`\`
1582
+
1583
+ ### Suggested Actions
1584
+
1585
+ - **Update target description** to match current UI
1586
+ - **Add wait steps** for timing issues
1587
+ - **Run with \`--autofix --update-local\`** to let AI fix and persist
1588
+ - **Review the diff** to understand what changed
1589
+
1590
+ ### Common Test Bug Patterns
1591
+
1592
+ | Symptom | Likely Cause | Fix |
1593
+ |---------|--------------|-----|
1594
+ | "Element not found: submit button" | Button text changed | Update target to new text |
1595
+ | "Timeout waiting for dashboard" | Slower load time | Add \`wait\` or increase timeout |
1596
+ | "Expected 'Welcome' but got 'Hello'" | Copy changed | Update assertion value |
1597
+ | "Element not interactable" | Overlay blocking | Add wait for overlay to close |
1598
+
1599
+ ## ENVIRONMENT
1600
+
1601
+ **External factors are causing the failure. The code and test are correct.**
1602
+
1603
+ ### Indicators
1604
+
1605
+ - Network timeouts or connection errors
1606
+ - Authentication failures (session expired, invalid credentials)
1607
+ - Missing test data (database not seeded, user doesn't exist)
1608
+ - Service unavailable (third-party API down)
1609
+ - Rate limiting errors
1610
+ - SSL/TLS certificate errors
1611
+
1612
+ ### Diagnostic Questions
1613
+
1614
+ 1. Does the app work when accessed manually?
1615
+ 2. Are API credentials valid and not expired?
1616
+ 3. Is test data in the expected state?
1617
+ 4. Are external services (APIs, databases) accessible?
1618
+ 5. Is this a transient network issue?
1619
+
1620
+ ### Investigation Steps
1621
+
1622
+ \`\`\`bash
1623
+ # 1. Check if app is accessible
1624
+ curl https://your-app.com/health
1625
+
1626
+ # 2. Check network logs for failed requests
1627
+ qa-use browser logs network -s <session-id>
1628
+
1629
+ # 3. Verify credentials haven't expired
1630
+ # Check .qa-use-tests.json or environment variables
1631
+ \`\`\`
1632
+
1633
+ ### Suggested Actions
1634
+
1635
+ - **Retry the test** - transient issues often resolve themselves
1636
+ - **Refresh credentials** - update expired API keys or tokens
1637
+ - **Reset test data** - re-seed database, recreate test user
1638
+ - **Check service status** - verify third-party services are up
1639
+ - **Wait and retry** - for rate limiting, wait before retrying
1640
+
1641
+ ## Debugging Workflow
1642
+
1643
+ \`\`\`
1644
+ Test Failed
1645
+
1646
+
1647
+ ┌──────────────────────────────────────┐
1648
+ │ 1. Get session logs │
1649
+ │ qa-use browser logs console -s ID │
1650
+ │ qa-use browser logs network -s ID │
1651
+ └──────────────────┬───────────────────┘
1652
+
1653
+
1654
+ ┌──────────────────────────────────────┐
1655
+ │ 2. Check for JS errors or API fails │
1656
+ │ - Console errors = CODE BUG │
1657
+ │ - 4xx/5xx responses = CODE BUG │
1658
+ │ - Network timeout = ENVIRONMENT │
1659
+ └──────────────────┬───────────────────┘
1660
+
1661
+
1662
+ ┌──────────────────────────────────────┐
1663
+ │ 3. Try --autofix │
1664
+ │ qa-use test run name --autofix │
1665
+ │ - Works = TEST BUG, use │
1666
+ │ --update-local to persist │
1667
+ │ - Still fails = probably CODE BUG │
1668
+ └──────────────────┬───────────────────┘
1669
+
1670
+
1671
+ ┌──────────────────────────────────────┐
1672
+ │ 4. Manual verification │
1673
+ │ - Open app in browser │
1674
+ │ - Try the same flow manually │
1675
+ │ - Works manually = TEST BUG │
1676
+ │ - Fails manually = CODE BUG │
1677
+ └──────────────────────────────────────┘
1678
+ \`\`\`
1679
+
1680
+ ## Error Message Reference
1681
+
1682
+ | Error Message | Category | Likely Fix |
1683
+ |---------------|----------|------------|
1684
+ | "Element not found: ..." | TEST BUG | Update target description |
1685
+ | "Timeout waiting for ..." | TEST BUG/ENV | Add wait or check service |
1686
+ | "Expected ... but got ..." | TEST BUG/CODE | Verify expected value |
1687
+ | "Navigation to ... failed" | TEST BUG/CODE | Check URL and redirects |
1688
+ | "Element not interactable" | TEST BUG | Wait for overlays |
1689
+ | "Network request failed" | ENVIRONMENT | Check service health |
1690
+ | "Unauthorized" / "401" | ENVIRONMENT | Refresh credentials |
1691
+ | "Internal Server Error" / "500" | CODE BUG | Check server logs |
1692
+ | "Not Found" / "404" | CODE BUG | Check routing |
1693
+ | "TypeError: Cannot read ..." | CODE BUG | Fix JavaScript error |
1694
+
1695
+ ## Using AI Self-Healing
1696
+
1697
+ The \`--autofix\` flag enables AI-powered test repair:
1698
+
1699
+ \`\`\`bash
1700
+ # Try autofix
1701
+ qa-use test run my-test --autofix
1702
+
1703
+ # If it works, persist the changes
1704
+ qa-use test run my-test --autofix --update-local
1705
+
1706
+ # Review what changed
1707
+ git diff qa-tests/my-test.yaml
1708
+ \`\`\`
1709
+
1710
+ **What autofix can fix:**
1711
+ - Selector/target changes
1712
+ - Timing issues (adds waits)
1713
+ - Minor assertion value changes
1714
+
1715
+ **What autofix cannot fix:**
1716
+ - Broken application code
1717
+ - Major workflow changes
1718
+ - Missing features
1719
+ - Authentication issues
1720
+ `,
1721
+ },
1722
+ 'localhost-testing': {
1723
+ title: 'Localhost Testing',
1724
+ content: `# Localhost Testing
1725
+
1726
+ Testing applications running on \`localhost\` requires a tunnel because the cloud-hosted browser cannot access your local machine.
1727
+
1728
+ ## Why Tunnels Are Needed
1729
+
1730
+ \`\`\`
1731
+ Your Machine Cloud
1732
+ ┌─────────────────┐ ┌─────────────────┐
1733
+ │ localhost:3000 │ ✗ │ Cloud Browser │
1734
+ │ (your app) │ ◄──────────│ (qa-use API) │
1735
+ └─────────────────┘ └─────────────────┘
1736
+
1737
+ Without tunnel: Cloud cannot reach localhost
1738
+ \`\`\`
1739
+
1740
+ \`\`\`
1741
+ Your Machine Cloud
1742
+ ┌─────────────────┐ ┌─────────────────┐
1743
+ │ localhost:3000 │ │ Cloud Browser │
1744
+ │ (your app) │ │ (qa-use API) │
1745
+ └────────┬────────┘ └────────┬────────┘
1746
+ │ │
1747
+ └──────────┐ ┌──────────────┘
1748
+ │ │
1749
+ ┌─────▼────▼─────┐
1750
+ │ Local Browser │
1751
+ │ + Tunnel │
1752
+ └────────────────┘
1753
+
1754
+ With tunnel: Local browser accesses localhost,
1755
+ API controls browser through tunnel
1756
+ \`\`\`
1757
+
1758
+ ## Using \`--tunnel\` Flag
1759
+
1760
+ The simplest approach - add \`--tunnel\` to your test run command:
1761
+
1762
+ \`\`\`bash
1763
+ qa-use test run my-test --tunnel
1764
+ \`\`\`
1765
+
1766
+ This:
1767
+ 1. Starts a local headless browser
1768
+ 2. Creates a tunnel for API control
1769
+ 3. Runs the test
1770
+ 4. Cleans up automatically
1771
+
1772
+ ### With Visible Browser
1773
+
1774
+ For debugging, add \`--headful\`:
1775
+
1776
+ \`\`\`bash
1777
+ qa-use test run my-test --tunnel --headful
1778
+ \`\`\`
1779
+
1780
+ ## Persistent Tunnel Session
1781
+
1782
+ For running multiple tests or interactive development, create a persistent tunnel session:
1783
+
1784
+ ### Terminal 1: Start Tunnel
1785
+
1786
+ \`\`\`bash
1787
+ qa-use browser create --tunnel --no-headless
1788
+ \`\`\`
1789
+
1790
+ Output:
1791
+ \`\`\`
1792
+ Session created: abc123
1793
+ WebSocket URL: wss://tunnel.desplega.ai/abc123
1794
+ Tunnel active. Press Ctrl+C to stop.
1795
+ \`\`\`
1796
+
1797
+ ### Terminal 2: Run Tests
1798
+
1799
+ \`\`\`bash
1800
+ # Run test against the tunneled browser
1801
+ qa-use test run my-test --ws-url wss://tunnel.desplega.ai/abc123
1802
+
1803
+ # Or run multiple tests
1804
+ qa-use test run login --ws-url wss://tunnel.desplega.ai/abc123
1805
+ qa-use test run checkout --ws-url wss://tunnel.desplega.ai/abc123
1806
+ \`\`\`
1807
+
1808
+ ### Benefits
1809
+
1810
+ - **Reuse browser session** - no startup time between tests
1811
+ - **Watch execution** - see what's happening in real-time
1812
+ - **Debug interactively** - use browser commands between test runs
1813
+ - **Inspect state** - check page state after failures
1814
+
1815
+ ## Browser Session Commands with Tunnel
1816
+
1817
+ You can also use browser commands directly for exploration:
1818
+
1819
+ \`\`\`bash
1820
+ # Create tunneled session
1821
+ qa-use browser create --tunnel --no-headless
1822
+
1823
+ # Navigate to your local app
1824
+ qa-use browser goto http://localhost:3000
1825
+
1826
+ # Explore
1827
+ qa-use browser snapshot
1828
+ qa-use browser click e3
1829
+ qa-use browser screenshot
1830
+
1831
+ # Close when done
1832
+ qa-use browser close
1833
+ \`\`\`
1834
+
1835
+ ## Environment-Specific URLs
1836
+
1837
+ If your app runs on different ports in different environments, use variables:
1838
+
1839
+ \`\`\`yaml
1840
+ # test.yaml
1841
+ name: Local Test
1842
+ app_config: my-app
1843
+ variables:
1844
+ base_url: http://localhost:3000
1845
+ steps:
1846
+ - action: goto
1847
+ url: $base_url/login
1848
+ \`\`\`
1849
+
1850
+ Override at runtime:
1851
+
1852
+ \`\`\`bash
1853
+ # Local development
1854
+ qa-use test run my-test --tunnel --var base_url=http://localhost:3000
1855
+
1856
+ # Staging
1857
+ qa-use test run my-test --var base_url=https://staging.example.com
1858
+ \`\`\`
1859
+
1860
+ ## Common Issues
1861
+
1862
+ ### "Connection refused" / "Network error"
1863
+
1864
+ Your local server isn't running or is on a different port.
1865
+
1866
+ **Fix:** Verify your app is running:
1867
+ \`\`\`bash
1868
+ curl http://localhost:3000
1869
+ \`\`\`
1870
+
1871
+ ### Tunnel disconnects
1872
+
1873
+ The tunnel process was interrupted.
1874
+
1875
+ **Fix:** Restart the tunnel:
1876
+ \`\`\`bash
1877
+ qa-use browser create --tunnel
1878
+ \`\`\`
1879
+
1880
+ ### "localhost" resolved differently
1881
+
1882
+ Some setups resolve \`localhost\` differently than \`127.0.0.1\`.
1883
+
1884
+ **Fix:** Try the explicit IP:
1885
+ \`\`\`bash
1886
+ qa-use browser goto http://127.0.0.1:3000
1887
+ \`\`\`
1888
+
1889
+ ### HTTPS localhost with self-signed cert
1890
+
1891
+ Local HTTPS with self-signed certificates may fail.
1892
+
1893
+ **Fix:** Use HTTP for local testing, or configure your browser to accept the cert:
1894
+ \`\`\`bash
1895
+ # Use HTTP locally
1896
+ qa-use browser goto http://localhost:3000
1897
+
1898
+ # Test HTTPS only in staging/prod environments
1899
+ \`\`\`
1900
+
1901
+ ## Best Practices
1902
+
1903
+ 1. **Use \`--tunnel\` for all localhost tests** - Don't forget, or tests will fail with confusing network errors
1904
+
1905
+ 2. **Keep tunnel running during development** - Create once, run many tests
1906
+
1907
+ 3. **Use \`--no-headless\` for debugging** - Watch what's happening
1908
+
1909
+ 4. **Save WebSocket URL** - Copy it from tunnel output for reuse in \`--ws-url\`
1910
+
1911
+ 5. **Clean up sessions** - Run \`qa-use browser close\` when done to free resources
1912
+ `,
1913
+ },
1914
+ 'test-format': {
1915
+ title: 'Test Format Reference',
1916
+ content: `# Test Format Reference
1917
+
1918
+ Complete specification for qa-use test YAML files.
1919
+
1920
+ ## Basic Structure
1921
+
1922
+ \`\`\`yaml
1923
+ name: Test Name
1924
+ description: Optional description of what this test verifies
1925
+ tags:
1926
+ - smoke
1927
+ - auth
1928
+ app_config: <app-config-id>
1929
+ variables:
1930
+ key: value
1931
+ depends_on: optional-prerequisite-test
1932
+ steps:
1933
+ - action: goto
1934
+ url: /path
1935
+ \`\`\`
1936
+
1937
+ ## Required Fields
1938
+
1939
+ | Field | Description |
1940
+ |-------|-------------|
1941
+ | \`name\` | Human-readable test name |
1942
+ | \`app_config\` | App configuration ID from desplega.ai (or use default from \`.qa-use-tests.json\`) |
1943
+ | \`steps\` | Array of test steps |
1944
+
1945
+ ## Optional Fields
1946
+
1947
+ | Field | Description |
1948
+ |-------|-------------|
1949
+ | \`description\` | What this test verifies |
1950
+ | \`tags\` | Array of strings for categorization (e.g., \`smoke\`, \`auth\`, \`critical\`) |
1951
+ | \`variables\` | Key-value pairs for parameterization |
1952
+ | \`depends_on\` | Name of test that must run first |
1953
+
1954
+ ## Variables
1955
+
1956
+ Define variables at the top level:
1957
+
1958
+ \`\`\`yaml
1959
+ variables:
1960
+ email: test@example.com
1961
+ password: secret123
1962
+ base_path: /app
1963
+ \`\`\`
1964
+
1965
+ Reference with \`$\` prefix:
1966
+
1967
+ \`\`\`yaml
1968
+ steps:
1969
+ - action: fill
1970
+ target: email input
1971
+ value: $email
1972
+ - action: goto
1973
+ url: $base_path/dashboard
1974
+ \`\`\`
1975
+
1976
+ Variables can be overridden at runtime:
1977
+
1978
+ \`\`\`bash
1979
+ qa-use test run my-test --var email=other@example.com
1980
+ \`\`\`
1981
+
1982
+ ## Dependencies
1983
+
1984
+ Run prerequisite tests first:
1985
+
1986
+ \`\`\`yaml
1987
+ name: Checkout Test
1988
+ depends_on: login-test
1989
+ steps:
1990
+ - action: goto
1991
+ url: /checkout
1992
+ \`\`\`
1993
+
1994
+ Dependencies are resolved recursively. If \`checkout-test\` depends on \`login-test\`, and \`login-test\` depends on \`setup-test\`, all three run in order.
1995
+
1996
+ ## Step Format
1997
+
1998
+ Each step has an \`action\` and action-specific fields:
1999
+
2000
+ \`\`\`yaml
2001
+ - action: <action-type>
2002
+ target: <element description> # For interactions
2003
+ value: <value> # For fill, type, assertions
2004
+ url: <path> # For navigation
2005
+ \`\`\`
2006
+
2007
+ ## Available Actions
2008
+
2009
+ ### Navigation
2010
+
2011
+ | Action | Fields | Description |
2012
+ |--------|--------|-------------|
2013
+ | \`goto\` | \`url\` | Navigate to URL (absolute or relative) |
2014
+ | \`back\` | - | Browser back |
2015
+ | \`forward\` | - | Browser forward |
2016
+ | \`reload\` | - | Reload page |
2017
+
2018
+ \`\`\`yaml
2019
+ - action: goto
2020
+ url: /login
2021
+
2022
+ - action: goto
2023
+ url: https://example.com/page
2024
+ \`\`\`
2025
+
2026
+ ### Interactions
2027
+
2028
+ | Action | Fields | Description |
2029
+ |--------|--------|-------------|
2030
+ | \`click\` | \`target\` | Click element |
2031
+ | \`fill\` | \`target\`, \`value\` | Fill input (clears first) |
2032
+ | \`type\` | \`target\`, \`value\` | Type with delays |
2033
+ | \`press\` | \`value\` | Press keyboard key |
2034
+ | \`check\` | \`target\` | Check checkbox |
2035
+ | \`uncheck\` | \`target\` | Uncheck checkbox |
2036
+ | \`select\` | \`target\`, \`value\` | Select dropdown option |
2037
+ | \`hover\` | \`target\` | Hover over element |
2038
+ | \`scroll\` | \`target\` or direction | Scroll page or element |
2039
+ | \`mfa_totp\` | \`target\` (optional), \`secret\` | Generate TOTP and optionally fill |
2040
+ | \`set_input_files\` | \`target\`, \`files\` | Upload files to input |
2041
+
2042
+ \`\`\`yaml
2043
+ - action: click
2044
+ target: submit button
2045
+
2046
+ - action: fill
2047
+ target: email input
2048
+ value: $email
2049
+
2050
+ - action: type
2051
+ target: search box
2052
+ value: search query
2053
+
2054
+ - action: press
2055
+ value: Enter
2056
+
2057
+ - action: select
2058
+ target: country dropdown
2059
+ value: United States
2060
+
2061
+ - action: mfa_totp
2062
+ target: OTP input field
2063
+ secret: $totp_secret
2064
+
2065
+ - action: set_input_files
2066
+ target: file upload button
2067
+ files:
2068
+ - /path/to/file1.pdf
2069
+ - /path/to/file2.pdf
2070
+ \`\`\`
2071
+
2072
+ ### Assertions
2073
+
2074
+ | Action | Fields | Description |
2075
+ |--------|--------|-------------|
2076
+ | \`to_be_visible\` | \`target\` | Assert element is visible |
2077
+ | \`to_be_hidden\` | \`target\` | Assert element is hidden |
2078
+ | \`to_have_text\` | \`target\`, \`value\` | Assert element has text |
2079
+ | \`to_have_value\` | \`target\`, \`value\` | Assert input has value |
2080
+ | \`to_be_checked\` | \`target\` | Assert checkbox is checked |
2081
+ | \`to_be_unchecked\` | \`target\` | Assert checkbox is unchecked |
2082
+
2083
+ \`\`\`yaml
2084
+ - action: to_be_visible
2085
+ target: success message
2086
+
2087
+ - action: to_have_text
2088
+ target: page heading
2089
+ value: Welcome
2090
+
2091
+ - action: to_be_checked
2092
+ target: remember me checkbox
2093
+ \`\`\`
2094
+
2095
+ ### Waiting
2096
+
2097
+ | Action | Fields | Description |
2098
+ |--------|--------|-------------|
2099
+ | \`wait\` | \`value\` | Wait fixed time (ms) |
2100
+ | \`wait_for_url\` | \`url\` | Wait for URL to match |
2101
+ | \`wait_for_selector\` | \`target\`, \`state\` | Wait for element state |
2102
+
2103
+ \`\`\`yaml
2104
+ - action: wait
2105
+ value: 2000
2106
+
2107
+ - action: wait_for_url
2108
+ url: /dashboard
2109
+
2110
+ - action: wait_for_selector
2111
+ target: .modal
2112
+ state: hidden
2113
+ \`\`\`
2114
+
2115
+ ### AI-Powered Actions
2116
+
2117
+ Use when human-readable selectors are insufficient:
2118
+
2119
+ | Action | Fields | Description |
2120
+ |--------|--------|-------------|
2121
+ | \`ai_action\` | \`value\` | AI performs action from description |
2122
+ | \`ai_assertion\` | \`value\` | AI verifies condition from description |
2123
+
2124
+ \`\`\`yaml
2125
+ - action: ai_action
2126
+ value: scroll to the pricing section
2127
+
2128
+ - action: ai_action
2129
+ value: dismiss the cookie banner if present
2130
+
2131
+ - action: ai_assertion
2132
+ value: verify the cart shows exactly 3 items
2133
+
2134
+ - action: ai_assertion
2135
+ value: confirm the total price is greater than $50
2136
+ \`\`\`
2137
+
2138
+ AI actions are more flexible but slower and less deterministic. Prefer explicit actions when possible.
2139
+
2140
+ ### Extended Step Format
2141
+
2142
+ For actions not available in simple format (like drag operations), use the extended format:
2143
+
2144
+ | Action | Description |
2145
+ |--------|-------------|
2146
+ | \`drag_and_drop\` | Drag source element to target |
2147
+ | \`relative_drag_and_drop\` | Drag with relative positioning |
2148
+ | \`mfa_totp\` | Generate and enter TOTP code |
2149
+ | \`set_input_files\` | Upload files |
2150
+
2151
+ #### Drag and Drop Example
2152
+
2153
+ \`\`\`yaml
2154
+ - type: extended
2155
+ name: Drag item to drop zone
2156
+ action:
2157
+ action: drag_and_drop
2158
+ value:
2159
+ target_locator: "#drop-zone" # Playwright locator string
2160
+ locator:
2161
+ chain:
2162
+ - method: get_by_text
2163
+ args: ["draggable item"]
2164
+ \`\`\`
2165
+
2166
+ The \`target_locator\` must be a valid Playwright locator string:
2167
+ - \`"#drop-zone"\` - CSS ID selector
2168
+ - \`".drop-area"\` - CSS class selector
2169
+ - \`"text=Drop here"\` - Text selector
2170
+ - \`"[data-testid='target']"\` - Attribute selector
2171
+
2172
+ #### TOTP Example
2173
+
2174
+ \`\`\`yaml
2175
+ - type: extended
2176
+ name: Enter MFA code
2177
+ action:
2178
+ action: mfa_totp
2179
+ value:
2180
+ target_locator: "#otp-input"
2181
+ locator:
2182
+ chain:
2183
+ - method: get_by_label
2184
+ args: ["Enter your code"]
2185
+ \`\`\`
2186
+
2187
+ **Tip:** Use \`qa-use test schema\` to explore all available actions and their schemas.
2188
+
2189
+ ## Target Descriptions
2190
+
2191
+ The \`target\` field uses natural language descriptions:
2192
+
2193
+ \`\`\`yaml
2194
+ # Good - specific and unambiguous
2195
+ target: submit button in the login form
2196
+ target: email input field
2197
+ target: first product card
2198
+ target: navigation menu item labeled "Settings"
2199
+
2200
+ # Avoid - too generic
2201
+ target: button
2202
+ target: input
2203
+ target: link
2204
+ \`\`\`
2205
+
2206
+ The AI matches your description against the page's ARIA accessibility tree. Be specific enough to uniquely identify the element.
2207
+
2208
+ ## Complete Example
2209
+
2210
+ \`\`\`yaml
2211
+ name: User Registration
2212
+ description: Tests the full user registration flow
2213
+ tags:
2214
+ - smoke
2215
+ - registration
2216
+ - critical
2217
+ app_config: my-app-config-id
2218
+ variables:
2219
+ email: newuser@example.com
2220
+ password: SecurePass123!
2221
+ name: Test User
2222
+ depends_on: clear-test-data
2223
+
2224
+ steps:
2225
+ # Navigate to registration
2226
+ - action: goto
2227
+ url: /register
2228
+
2229
+ # Fill registration form
2230
+ - action: fill
2231
+ target: name input
2232
+ value: $name
2233
+
2234
+ - action: fill
2235
+ target: email input
2236
+ value: $email
2237
+
2238
+ - action: fill
2239
+ target: password input
2240
+ value: $password
2241
+
2242
+ - action: fill
2243
+ target: confirm password input
2244
+ value: $password
2245
+
2246
+ # Accept terms
2247
+ - action: check
2248
+ target: terms and conditions checkbox
2249
+
2250
+ # Submit
2251
+ - action: click
2252
+ target: create account button
2253
+
2254
+ # Wait for redirect
2255
+ - action: wait_for_url
2256
+ url: /welcome
2257
+
2258
+ # Verify success
2259
+ - action: to_be_visible
2260
+ target: welcome message
2261
+
2262
+ - action: to_have_text
2263
+ target: user greeting
2264
+ value: Hello, Test User
2265
+ \`\`\`
2266
+
2267
+ ## File Location
2268
+
2269
+ Tests should be placed in the test directory (default: \`qa-tests/\`):
2270
+
2271
+ \`\`\`
2272
+ qa-tests/
2273
+ ├── login.yaml
2274
+ ├── registration.yaml
2275
+ ├── checkout.yaml
2276
+ └── setup/
2277
+ └── seed-data.yaml
2278
+ \`\`\`
2279
+
2280
+ Configure the test directory in \`.qa-use-tests.json\`:
2281
+
2282
+ \`\`\`json
2283
+ {
2284
+ "test_directory": "./qa-tests"
2285
+ }
2286
+ \`\`\`
2287
+ `,
2288
+ },
2289
+ };
2290
+ export const TEMPLATES = {
2291
+ 'auth-flow': {
2292
+ title: 'Auth Flow Template',
2293
+ content: `# Authentication Flow Template
2294
+ # Login with credentials and verify dashboard access
2295
+
2296
+ name: Authentication Flow
2297
+ description: Login with credentials and verify successful authentication
2298
+
2299
+ # Replace with your app config ID from desplega.ai
2300
+ app_config: $APP_CONFIG_ID
2301
+
2302
+ # Variables for credentials
2303
+ # Override at runtime: qa-use test run auth-flow --var email=real@example.com
2304
+ variables:
2305
+ email: test@example.com
2306
+ password: "********"
2307
+
2308
+ steps:
2309
+ # Navigate to login page
2310
+ - action: goto
2311
+ url: /login
2312
+
2313
+ # Fill login form
2314
+ - action: fill
2315
+ target: email input
2316
+ value: $email
2317
+
2318
+ - action: fill
2319
+ target: password input
2320
+ value: $password
2321
+
2322
+ # Submit the form
2323
+ - action: click
2324
+ target: sign in button
2325
+
2326
+ # Wait for successful redirect
2327
+ - action: wait_for_url
2328
+ url: /dashboard
2329
+
2330
+ # Verify dashboard is visible
2331
+ - action: to_be_visible
2332
+ target: dashboard content
2333
+
2334
+ # Optional: verify user greeting
2335
+ # - action: to_be_visible
2336
+ # target: welcome message
2337
+ `,
2338
+ },
2339
+ 'basic-test': {
2340
+ title: 'Basic Test Template',
2341
+ content: `# Basic Test Template
2342
+ # A simple navigation and assertion test
2343
+
2344
+ name: Basic Test
2345
+ description: Navigate to a page and verify an element is visible
2346
+
2347
+ # Replace with your app config ID from desplega.ai
2348
+ # Or set default_app_config_id in .qa-use-tests.json
2349
+ app_config: $APP_CONFIG_ID
2350
+
2351
+ steps:
2352
+ # Navigate to the starting page
2353
+ - action: goto
2354
+ url: /
2355
+
2356
+ # Verify the main content is visible
2357
+ - action: to_be_visible
2358
+ target: main content area
2359
+
2360
+ # Optional: verify page heading
2361
+ # - action: to_have_text
2362
+ # target: page heading
2363
+ # value: Welcome
2364
+ `,
2365
+ },
2366
+ 'form-test': {
2367
+ title: 'Form Test Template',
2368
+ content: `# Form Submission Template
2369
+ # Fill out a form and verify successful submission
2370
+
2371
+ name: Form Submission
2372
+ description: Fill a contact form and verify submission success
2373
+
2374
+ # Replace with your app config ID from desplega.ai
2375
+ app_config: $APP_CONFIG_ID
2376
+
2377
+ # Variables for form data
2378
+ variables:
2379
+ name: Test User
2380
+ email: test@example.com
2381
+ message: This is a test message from automated testing.
2382
+
2383
+ steps:
2384
+ # Navigate to the form page
2385
+ - action: goto
2386
+ url: /contact
2387
+
2388
+ # Fill form fields
2389
+ - action: fill
2390
+ target: name input
2391
+ value: $name
2392
+
2393
+ - action: fill
2394
+ target: email input
2395
+ value: $email
2396
+
2397
+ - action: fill
2398
+ target: message textarea
2399
+ value: $message
2400
+
2401
+ # Optional: handle checkbox/consent
2402
+ # - action: check
2403
+ # target: consent checkbox
2404
+
2405
+ # Submit the form
2406
+ - action: click
2407
+ target: submit button
2408
+
2409
+ # Verify success
2410
+ - action: to_be_visible
2411
+ target: success message
2412
+
2413
+ # Optional: verify specific success text
2414
+ # - action: to_have_text
2415
+ # target: confirmation message
2416
+ # value: Thank you for your message
2417
+ `,
2418
+ },
2419
+ };
2420
+ //# sourceMappingURL=docs-content.js.map