@matware/e2e-runner 1.1.1 → 1.3.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/.claude-plugin/marketplace.json +21 -0
  2. package/.claude-plugin/plugin.json +9 -0
  3. package/.mcp.json +9 -0
  4. package/.opencode/commands/create-test.md +63 -0
  5. package/.opencode/commands/run.md +50 -0
  6. package/.opencode/commands/verify-issue.md +62 -0
  7. package/.opencode/skills/e2e-testing/SKILL.md +181 -0
  8. package/.opencode/skills/e2e-testing/references/action-types.md +143 -0
  9. package/.opencode/skills/e2e-testing/references/auth-strategies.md +91 -0
  10. package/.opencode/skills/e2e-testing/references/graphql.md +59 -0
  11. package/.opencode/skills/e2e-testing/references/issue-verification.md +59 -0
  12. package/.opencode/skills/e2e-testing/references/multi-pool.md +60 -0
  13. package/.opencode/skills/e2e-testing/references/network-debugging.md +62 -0
  14. package/.opencode/skills/e2e-testing/references/test-json-format.md +163 -0
  15. package/.opencode/skills/e2e-testing/references/troubleshooting.md +224 -0
  16. package/.opencode/skills/e2e-testing/references/variables.md +41 -0
  17. package/.opencode/skills/e2e-testing/references/visual-verification.md +89 -0
  18. package/OPENCODE.md +166 -0
  19. package/README.md +990 -296
  20. package/agents/test-analyzer.md +81 -0
  21. package/agents/test-creator.md +155 -0
  22. package/agents/test-improver.md +177 -0
  23. package/bin/cli.js +602 -22
  24. package/commands/create-test.md +65 -0
  25. package/commands/run.md +49 -0
  26. package/commands/verify-issue.md +63 -0
  27. package/opencode.json +11 -0
  28. package/package.json +15 -2
  29. package/scripts/setup-opencode.sh +113 -0
  30. package/skills/e2e-testing/SKILL.md +173 -0
  31. package/skills/e2e-testing/references/action-types.md +143 -0
  32. package/skills/e2e-testing/references/auth-strategies.md +91 -0
  33. package/skills/e2e-testing/references/graphql.md +59 -0
  34. package/skills/e2e-testing/references/issue-verification.md +59 -0
  35. package/skills/e2e-testing/references/multi-pool.md +60 -0
  36. package/skills/e2e-testing/references/network-debugging.md +62 -0
  37. package/skills/e2e-testing/references/test-json-format.md +163 -0
  38. package/skills/e2e-testing/references/troubleshooting.md +224 -0
  39. package/skills/e2e-testing/references/variables.md +41 -0
  40. package/skills/e2e-testing/references/visual-verification.md +89 -0
  41. package/src/actions.js +597 -20
  42. package/src/ai-generate.js +142 -12
  43. package/src/config.js +171 -0
  44. package/src/dashboard.js +299 -17
  45. package/src/db.js +335 -13
  46. package/src/index.js +15 -8
  47. package/src/learner-markdown.js +177 -0
  48. package/src/learner-neo4j.js +255 -0
  49. package/src/learner-sqlite.js +658 -0
  50. package/src/learner.js +418 -0
  51. package/src/mcp-tools.js +1558 -50
  52. package/src/module-resolver.js +310 -0
  53. package/src/narrate.js +262 -0
  54. package/src/neo4j-pool.js +124 -0
  55. package/src/pool-manager.js +223 -0
  56. package/src/reporter.js +117 -3
  57. package/src/runner.js +274 -71
  58. package/src/sync/auth.js +354 -0
  59. package/src/sync/client.js +572 -0
  60. package/src/sync/hub-routes.js +816 -0
  61. package/src/sync/index.js +68 -0
  62. package/src/sync/middleware.js +347 -0
  63. package/src/sync/queue.js +209 -0
  64. package/src/sync/schema.js +540 -0
  65. package/src/verify.js +14 -9
  66. package/src/watch.js +384 -0
  67. package/templates/build-dashboard.js +69 -0
  68. package/templates/dashboard/js/api.js +60 -0
  69. package/templates/dashboard/js/init.js +13 -0
  70. package/templates/dashboard/js/keyboard.js +46 -0
  71. package/templates/dashboard/js/state.js +40 -0
  72. package/templates/dashboard/js/toast.js +41 -0
  73. package/templates/dashboard/js/utils.js +196 -0
  74. package/templates/dashboard/js/view-live.js +143 -0
  75. package/templates/dashboard/js/view-runs.js +572 -0
  76. package/templates/dashboard/js/view-tests.js +294 -0
  77. package/templates/dashboard/js/view-watch.js +242 -0
  78. package/templates/dashboard/js/websocket.js +110 -0
  79. package/templates/dashboard/styles/base.css +69 -0
  80. package/templates/dashboard/styles/components.css +110 -0
  81. package/templates/dashboard/styles/view-live.css +74 -0
  82. package/templates/dashboard/styles/view-runs.css +207 -0
  83. package/templates/dashboard/styles/view-tests.css +96 -0
  84. package/templates/dashboard/styles/view-watch.css +53 -0
  85. package/templates/dashboard/template.html +267 -0
  86. package/templates/dashboard.html +2171 -530
  87. package/templates/docker-compose-neo4j.yml +19 -0
  88. package/templates/e2e.config.js +3 -0
  89. package/templates/sample-test.json +0 -8
@@ -0,0 +1,224 @@
1
+ # Troubleshooting Guide
2
+
3
+ ## Pool Connection Issues
4
+
5
+ ### "Pool not reachable" / Connection refused
6
+
7
+ **Cause**: Chrome pool (browserless/chrome Docker container) is not running.
8
+
9
+ **Fix**:
10
+ ```bash
11
+ npx e2e-runner pool start
12
+ npx e2e-runner pool status # verify it's running
13
+ ```
14
+
15
+ Pool management is CLI-only — `pool start` and `pool stop` are not available via MCP.
16
+
17
+ ### "Pool at capacity" / Tests queuing
18
+
19
+ **Cause**: All Chrome sessions are occupied.
20
+
21
+ **Fix**: Increase capacity or reduce concurrency:
22
+ ```bash
23
+ npx e2e-runner pool stop
24
+ npx e2e-runner pool start --max-sessions 10
25
+ ```
26
+ Or reduce test concurrency: `--concurrency 2`
27
+
28
+ The runner checks `/pressure` before each connection and waits up to 60s for a free slot.
29
+
30
+ ### Docker not running
31
+
32
+ **Cause**: Docker daemon is not started.
33
+
34
+ **Fix**: Start Docker Desktop or `sudo systemctl start docker`, then `npx e2e-runner pool start`.
35
+
36
+ ## React / SPA Issues
37
+
38
+ ### React inputs not updating state
39
+
40
+ **Symptom**: `type` action enters text but React state doesn't change (form validation fails, submit disabled).
41
+
42
+ **Fix**: Use `type_react` instead of `type` for React controlled inputs:
43
+ ```json
44
+ { "type": "type_react", "selector": "#email", "value": "user@test.com" }
45
+ ```
46
+
47
+ `type_react` uses the native value setter and dispatches `input` + `change` events that React's synthetic event system recognizes.
48
+
49
+ ### SPA navigation not completing
50
+
51
+ **Symptom**: `goto` hangs or times out on client-side route changes.
52
+
53
+ **Fix**: Use `navigate` instead of `goto` for SPA route changes:
54
+ ```json
55
+ { "type": "navigate", "value": "/new-page" }
56
+ ```
57
+
58
+ `navigate` uses a 5s race timeout and won't block if `load` doesn't fire (common in SPAs).
59
+
60
+ ### MUI autocomplete not opening
61
+
62
+ **Symptom**: Clicking or typing in an MUI Autocomplete doesn't open the dropdown.
63
+
64
+ **Fix**: Use `focus_autocomplete` to properly focus by label text:
65
+ ```json
66
+ { "type": "focus_autocomplete", "text": "Search by name" },
67
+ { "type": "type_react", "selector": "#autocomplete-input", "value": "search term" },
68
+ { "type": "click_option", "text": "Desired option" }
69
+ ```
70
+
71
+ ## Flaky Tests
72
+
73
+ ### Intermittent failures on dynamic content
74
+
75
+ **Symptom**: Tests pass sometimes, fail others. Usually timing-related.
76
+
77
+ **Fixes**:
78
+ 1. Add explicit `wait` before assertions:
79
+ ```json
80
+ { "type": "wait", "selector": ".data-loaded" },
81
+ { "type": "assert_text", "text": "Expected content" }
82
+ ```
83
+
84
+ 2. Use action-level retries for known flaky selectors:
85
+ ```json
86
+ { "type": "click", "selector": "#dynamic-btn", "retries": 3 }
87
+ ```
88
+
89
+ 3. Use test-level retries:
90
+ ```json
91
+ { "name": "flaky-test", "retries": 2, "actions": [...] }
92
+ ```
93
+
94
+ 4. Check the learning system for patterns:
95
+ ```
96
+ e2e_learnings("flaky") → identify consistently flaky tests
97
+ e2e_learnings("selectors") → find unstable selectors
98
+ ```
99
+
100
+ ### Tests interfering with each other
101
+
102
+ **Symptom**: Tests pass individually but fail when run together.
103
+
104
+ **Fix**: Mark tests that share mutable state as `serial`:
105
+ ```json
106
+ { "name": "create-item", "serial": true, "actions": [...] },
107
+ { "name": "verify-item", "serial": true, "actions": [...] }
108
+ ```
109
+
110
+ ## Timeout Issues
111
+
112
+ ### Test timeout (default 60s)
113
+
114
+ **Fix**: Increase per-test or globally:
115
+ ```json
116
+ { "name": "slow-test", "timeout": 120000, "actions": [...] }
117
+ ```
118
+ Or globally: `--test-timeout 120000`
119
+
120
+ ### Action timeout (default 10s)
121
+
122
+ Each action's `waitForSelector` uses the default timeout. Override per-action:
123
+ ```json
124
+ { "type": "wait", "selector": ".slow-element", "timeout": 30000 }
125
+ ```
126
+ Or globally: `--timeout 30000`
127
+
128
+ ## Network Errors
129
+
130
+ ### Tests passing but network requests failing
131
+
132
+ **Symptom**: Tests pass but `networkSummary` shows failed requests.
133
+
134
+ **Fix**: Enable strict mode to fail tests with network errors:
135
+ ```
136
+ e2e_run({ all: true, failOnNetworkError: true })
137
+ ```
138
+
139
+ Or use `assert_no_network_errors` at specific points:
140
+ ```json
141
+ { "type": "goto", "value": "/api-heavy-page" },
142
+ { "type": "wait", "selector": ".loaded" },
143
+ { "type": "assert_no_network_errors" }
144
+ ```
145
+
146
+ ### Investigating specific failures
147
+
148
+ Use network log drill-down:
149
+ ```
150
+ e2e_network_logs(runDbId, errorsOnly: true) → see all failed requests
151
+ e2e_network_logs(runDbId, urlPattern: "/api/users") → filter by URL
152
+ e2e_network_logs(runDbId, testName: "create-user", includeBodies: true) → full request/response
153
+ ```
154
+
155
+ ## Common Mistakes
156
+
157
+ ### Using `beforeAll` for browser state
158
+
159
+ `beforeAll` runs on a separate page that closes before tests. Use `beforeEach` for state setup.
160
+
161
+ ### Using `evaluate` for simple assertions
162
+
163
+ Prefer granular assertion actions over `evaluate` with inline JS:
164
+ ```json
165
+ // Bad: verbose, error-prone
166
+ { "type": "evaluate", "value": "if (!document.querySelector('h1').textContent.includes('Dashboard')) throw 'not found'" }
167
+
168
+ // Good: clear, auto-waits
169
+ { "type": "assert_element_text", "selector": "h1", "text": "Dashboard" }
170
+ ```
171
+
172
+ ### Forgetting `cwd` in MCP calls
173
+
174
+ All MCP tools need `cwd` to resolve config files and test directories. Always pass the project root.
175
+
176
+ ### Path-only `assert_url`
177
+
178
+ When checking paths, use path-only format (starts with `/`):
179
+ ```json
180
+ { "type": "assert_url", "value": "/dashboard" }
181
+ ```
182
+ This compares against the pathname only, ignoring the `host.docker.internal` origin.
183
+
184
+ ## Action Type Pre-Validation
185
+
186
+ All action types are validated at **load time** (before any browser connections). If a test file contains an unknown action type (e.g., a typo like `"clik"`), loading throws immediately with the location:
187
+
188
+ ```
189
+ Unknown action type(s) in auth.json: "clik" in test "login-test"
190
+ ```
191
+
192
+ The `KNOWN_ACTION_TYPES` Set in `src/actions.js` is the single source of truth. Unknown actions also throw at runtime as a safety net.
193
+
194
+ ## Screenshot Hashes
195
+
196
+ Every screenshot captured during a run is assigned a short hash (`ss:a3f2b1c9`) — the first 8 hex chars of the SHA-256 of its file path. Hashes are deterministic and computed identically on the server (Node `crypto`) and in the browser (Web Crypto API).
197
+
198
+ **Flow**: screenshot saved on disk → `saveRun()` registers hash in SQLite `screenshot_hashes` table → dashboard shows `[ss:XXXXXXXX]` badge (click to copy) → user pastes hash in Claude Code → `e2e_screenshot` MCP tool looks up hash, reads file, returns the image.
199
+
200
+ - Hashes are registered inside the `saveRun()` transaction (covers action, error, verification, and baseline screenshots)
201
+ - The `ss:` prefix is optional when calling `e2e_screenshot` — stripped during lookup
202
+ - Dashboard computes hashes client-side (Web Crypto) for the Live view (before `persistRun()` writes to DB)
203
+ - Run detail API (`/api/db/runs/:id`) includes `screenshotHashes` map per test result
204
+ - Dashboard endpoint `/api/screenshot-hash/:hash` serves the image by hash
205
+ - Dashboard Screenshots view has a **search bar** — type a hash to find and display the screenshot
206
+
207
+ ## Web Dashboard
208
+
209
+ **`src/dashboard.js`** — HTTP server, REST API, WebSocket broadcast, pool polling.
210
+ **`templates/dashboard.html`** — SPA, dark theme, vanilla JS, safe DOM (textContent + createEl helper).
211
+
212
+ **Features:**
213
+ - Live test execution with WebSocket updates
214
+ - Run history with inline detail expansion
215
+ - Screenshots gallery with hash badges and hash search
216
+ - Network request logs with clickable expandable rows (full request/response detail)
217
+ - Pool status monitoring
218
+ - Multi-project support via project selector
219
+ - Variables tab with masked values, inline edit, add, and delete
220
+
221
+ **CLI:** `e2e-runner dashboard [--port 8484]`
222
+ **MCP tools:** `e2e_dashboard_start`, `e2e_dashboard_stop`
223
+
224
+ Config defaults: `dashboardPort: 8484`, `maxHistoryRuns: 100`
@@ -0,0 +1,41 @@
1
+ # Variables Reference
2
+
3
+ Variables replace hardcoded sensitive values (JWT tokens, user IDs, API keys, etc.) in test JSON. Stored in SQLite (`~/.e2e-runner/dashboard.db`), scoped per project and per suite, editable from the dashboard UI.
4
+
5
+ ## Syntax
6
+
7
+ ```
8
+ {{var.TOKEN}} → resolves from DB (suite scope → project scope)
9
+ {{env.MY_VAR}} → resolves from process.env
10
+ {{param}} → existing module param substitution (unchanged)
11
+ ```
12
+
13
+ **Resolution priority:** suite vars > project vars > error if not found.
14
+
15
+ ## Usage in Test JSON
16
+
17
+ ```json
18
+ { "$use": "auth-jwt", "params": { "token": "{{var.JWT_TOKEN}}", "orgId": "{{var.ORG_ID}}" } }
19
+ { "type": "goto", "value": "/users/{{var.USER_ID}}/profile" }
20
+ { "type": "gql", "value": "{ user(id: \"{{var.USER_ID}}\") { name } }" }
21
+ ```
22
+
23
+ ## MCP Tool (`e2e_vars`)
24
+
25
+ ```
26
+ e2e_vars({ action: "set", key: "TOKEN", value: "abc123", scope: "project" })
27
+ e2e_vars({ action: "set", key: "TOKEN", value: "xyz789", scope: "auth" }) // suite-specific override
28
+ e2e_vars({ action: "list" })
29
+ e2e_vars({ action: "get", key: "TOKEN" })
30
+ e2e_vars({ action: "delete", key: "TOKEN", scope: "project" })
31
+ ```
32
+
33
+ ## Dashboard UI
34
+
35
+ Variables tab shows all variables grouped by scope. Values are masked by default (click to reveal). Inline edit, add new, and delete are supported.
36
+
37
+ ## REST API
38
+
39
+ - `GET /api/db/projects/:id/variables` — list all vars for project
40
+ - `PUT /api/db/projects/:id/variables` — set a variable `{ scope, key, value }`
41
+ - `DELETE /api/db/projects/:id/variables/:scope/:key` — delete a variable
@@ -0,0 +1,89 @@
1
+ # Visual Verification Reference
2
+
3
+ Tests can include an `expect` field for AI-powered visual verification. No API key required — Claude Code itself does the visual judgment.
4
+
5
+ ## Expect Field Formats
6
+
7
+ ### String form — free-form description
8
+ ```json
9
+ {
10
+ "name": "dashboard-loads",
11
+ "expect": "Should show the data table with at least 3 rows, no error messages, and the sidebar with navigation links",
12
+ "actions": [
13
+ { "type": "goto", "value": "/dashboard" },
14
+ { "type": "wait", "selector": ".data-table" }
15
+ ]
16
+ }
17
+ ```
18
+
19
+ ### Array form — per-criterion checklist (each evaluated independently as PASS/FAIL)
20
+ ```json
21
+ {
22
+ "name": "dashboard-loads",
23
+ "expect": [
24
+ "Data table visible with at least 3 rows",
25
+ "No error messages or red banners",
26
+ "Sidebar shows navigation links"
27
+ ],
28
+ "actions": [
29
+ { "type": "goto", "value": "/dashboard" },
30
+ { "type": "wait", "selector": ".data-table" }
31
+ ]
32
+ }
33
+ ```
34
+
35
+ ## Double Screenshot (Before/After)
36
+
37
+ When `expect` is present, the runner captures TWO screenshots:
38
+ 1. **Baseline** (`baseline-{name}-{timestamp}.png`) — captured BEFORE test actions run (after `beforeEach` hooks)
39
+ 2. **Verification** (`verify-{name}-{timestamp}.png`) — captured AFTER all actions complete
40
+
41
+ Both hashes are registered in SQLite and returned in the MCP response for before/after comparison.
42
+
43
+ ## Verification Strictness
44
+
45
+ Controls how strictly Claude Code evaluates visual verification. Set via:
46
+ - Config: `verificationStrictness: 'moderate'`
47
+ - CLI: `--verification-strictness strict`
48
+ - Env: `VERIFICATION_STRICTNESS=strict`
49
+ - MCP: `verificationStrictness: 'strict'` in `e2e_run` args
50
+
51
+ | Level | Behavior |
52
+ |-------|----------|
53
+ | **`strict`** | No ambiguity allowed. If any criterion is unclear, not fully visible, or doubtful → FAIL. |
54
+ | **`moderate`** (default) | Reasonable judgment. Minor cosmetic differences acceptable, functional mismatches → FAIL. |
55
+ | **`lenient`** | Only fail on clear, obvious contradictions. |
56
+
57
+ ## MCP Response Format
58
+
59
+ The `e2e_run` response includes a `verifications` array:
60
+ ```json
61
+ {
62
+ "verifications": [
63
+ {
64
+ "name": "dashboard-loads",
65
+ "expect": ["Data table visible...", "No error messages..."],
66
+ "success": true,
67
+ "screenshotHash": "ss:a3f2b1c9",
68
+ "baselineScreenshotHash": "ss:b4e1c2d8",
69
+ "isChecklist": true
70
+ }
71
+ ],
72
+ "verificationInstructions": "Verification strictness: MODERATE — ..."
73
+ }
74
+ ```
75
+
76
+ ## Verdict Format
77
+
78
+ After calling `e2e_screenshot` for each hash (after + baseline), Claude Code reports a structured verdict:
79
+
80
+ ```
81
+ TEST: dashboard-loads
82
+ VERDICT: PASS
83
+ STATE CHANGE: Page loaded from blank to populated dashboard
84
+ CRITERIA:
85
+ - "Data table visible with at least 3 rows": PASS
86
+ - "No error messages or red banners": PASS
87
+ - "Sidebar shows navigation links": PASS
88
+ REASON: All criteria met, dashboard fully loaded with expected content
89
+ ```