start-vibing 4.4.0 → 4.4.2
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.
- package/package.json +2 -2
- package/template/.claude/commands/e2e-audit.md +16 -0
- package/template/.claude/hooks/e2e-audit-session-start.sh +4 -0
- package/template/.claude/hooks/mcp-usage-session-start.sh +4 -0
- package/template/.claude/settings.json +8 -0
- package/template/.claude/skills/e2e-audit/SKILL.md +216 -660
- package/template/.claude/skills/e2e-audit/findings.schema.json +98 -0
- package/template/.claude/skills/e2e-audit/references/api-contract-playbook.md +66 -0
- package/template/.claude/skills/e2e-audit/references/auth-setup-playbook.md +78 -0
- package/template/.claude/skills/e2e-audit/references/coverage-gap-playbook.md +95 -0
- package/template/.claude/skills/e2e-audit/references/post-run-feedback-playbook.md +80 -0
- package/template/.claude/skills/e2e-audit/scripts/detect-stack.sh +205 -0
- package/template/.claude/skills/e2e-audit/scripts/detect-uncovered.sh +137 -0
- package/template/.claude/skills/e2e-audit/scripts/discover-api-surface.sh +242 -0
- package/template/.claude/skills/e2e-audit/scripts/discover-routes.sh +163 -0
- package/template/.claude/skills/e2e-audit/scripts/inventory-existing-tests.sh +161 -0
- package/template/.claude/skills/e2e-audit/scripts/verify-audit.sh +88 -0
- package/template/.claude/skills/e2e-audit/templates/auth-setup.ts.tpl +24 -0
- package/template/.claude/skills/e2e-audit/templates/base-fixture.ts.tpl +75 -0
- package/template/.claude/skills/e2e-audit/templates/findings-report.md.tpl +54 -0
- package/template/.claude/skills/e2e-audit/templates/post-run-feedback.md.tpl +36 -0
- package/template/.claude/skills/e2e-audit/DESIGN.md +0 -294
- package/template/.claude/skills/e2e-audit/e2e/fixtures/auth.setup.ts +0 -70
- package/template/.claude/skills/e2e-audit/e2e/fixtures/auth.ts +0 -21
- package/template/.claude/skills/e2e-audit/e2e/fixtures/base.ts +0 -90
- package/template/.claude/skills/e2e-audit/e2e/fixtures/storage/.gitkeep +0 -0
- package/template/.claude/skills/e2e-audit/e2e/fixtures/storage/admin.json +0 -50
- package/template/.claude/skills/e2e-audit/e2e/fixtures/storage/manager.json +0 -50
- package/template/.claude/skills/e2e-audit/e2e/fixtures/storage/member.json +0 -50
- package/template/.claude/skills/e2e-audit/e2e/fixtures/storage/owner.json +0 -50
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-admin.page.ts +0 -141
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-billing.page.ts +0 -47
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-chat.page.ts +0 -35
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-home.page.ts +0 -134
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-integrations.page.ts +0 -334
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-knowledge.page.ts +0 -30
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-ontology.page.ts +0 -71
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-profile.page.ts +0 -38
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-teams.page.ts +0 -123
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-transcripts.page.ts +0 -109
- package/template/.claude/skills/e2e-audit/e2e/specs/auth/login.spec.ts +0 -59
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-admin.spec.ts +0 -233
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-billing.spec.ts +0 -44
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-chat.spec.ts +0 -50
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-home.spec.ts +0 -243
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-integrations.spec.ts +0 -472
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-knowledge.spec.ts +0 -57
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-ontology.spec.ts +0 -72
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-profile.spec.ts +0 -48
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-teams.spec.ts +0 -247
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-transcripts.spec.ts +0 -122
- package/template/.claude/skills/e2e-audit/e2e/specs/security/headers.spec.ts +0 -39
- package/template/.claude/skills/e2e-audit/e2e/specs/security/rbac.spec.ts +0 -92
- package/template/.claude/skills/e2e-audit/e2e/specs/security/xss.spec.ts +0 -74
- package/template/.claude/skills/e2e-audit/e2e/utils/console-collector.ts +0 -89
- package/template/.claude/skills/e2e-audit/e2e/utils/security-helpers.ts +0 -114
- package/template/.claude/skills/e2e-audit/e2e/utils/test-data.ts +0 -64
- package/template/.claude/skills/e2e-audit/runbook.md +0 -115
|
@@ -1,660 +1,216 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: e2e-audit
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
#
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
#
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
#
|
|
31
|
-
|
|
32
|
-
#
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
- Complete wizard → verify redirect to detail/list page
|
|
218
|
-
- Verify the created item is VISIBLE on the destination page
|
|
219
|
-
- Verify the item's data matches what was entered in the wizard
|
|
220
|
-
d. NEVER mark a submit flow as ✅ if you only verified the button click
|
|
221
|
-
or the toast — you MUST verify the outcome on the destination page
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
**CRITICAL**: Seeing a filter combobox open is NOT testing. You must select each
|
|
225
|
-
option and VERIFY the list changes correctly. Same for search, create, delete, etc.
|
|
226
|
-
|
|
227
|
-
**CRITICAL**: "I clicked Next and saw step 2" is NOT testing step 2. You must
|
|
228
|
-
interact with EVERY element in step 2 (fill inputs, open dropdowns, click buttons)
|
|
229
|
-
before advancing to step 3. Each step is its own mini-page that needs full audit.
|
|
230
|
-
|
|
231
|
-
**PROJECT-SPECIFIC NOTE (Hakutaku)**: For features requiring external services
|
|
232
|
-
(OAuth integrations, file uploads with S3), use `https://dev.hakutaku.ai` instead
|
|
233
|
-
of `localhost:3000` — Upstash and OAuth callbacks require the real domain. You can
|
|
234
|
-
still verify the UI flow steps on localhost, but actual sync/upload operations need
|
|
235
|
-
the tunnel running. When hitting an OAuth/external blocker, mark the step `[~]` and
|
|
236
|
-
document what UI elements are present — do NOT skip the entire wizard path.
|
|
237
|
-
|
|
238
|
-
**NEVER DELETE OR EDIT EXISTING DEV DATA.** When testing CRUD operations:
|
|
239
|
-
- Always CREATE new items for testing (new integration, new chat, new file, etc.)
|
|
240
|
-
- NEVER delete or modify data that already exists in the dev database — other
|
|
241
|
-
developers may be using it.
|
|
242
|
-
- Only delete/edit items YOU created during the current audit session.
|
|
243
|
-
- If you need specific data states (error, paused, etc.), create new items and
|
|
244
|
-
put them in that state — don't change existing ones.
|
|
245
|
-
|
|
246
|
-
**CLONE STRATEGY FOR OAUTH INTEGRATIONS**: When testing integration types that
|
|
247
|
-
require OAuth credentials you don't have (Google Drive, OneDrive, Notion, Slack,
|
|
248
|
-
GitHub), you can't create new ones through the wizard. Instead:
|
|
249
|
-
1. Check if an existing integration of that type already exists in the org
|
|
250
|
-
2. If it does, CLONE it via the tRPC API or database (create a copy with a
|
|
251
|
-
test name like "E2E Test Clone - {Type} - {Date}")
|
|
252
|
-
3. Test the CLONE's detail page fully: all tabs (Files, History, Settings),
|
|
253
|
-
all action buttons (Sync, Force Sync, Pause, Configure, Delete), all
|
|
254
|
-
settings (access control, sync frequency if applicable)
|
|
255
|
-
4. After testing, DELETE the clone you created
|
|
256
|
-
5. This lets you test detail page functionality for OAuth types without
|
|
257
|
-
needing actual OAuth credentials
|
|
258
|
-
6. If NO existing integration of that type exists, mark those detail-page
|
|
259
|
-
tests as `[~]` with "no existing integration to clone"
|
|
260
|
-
|
|
261
|
-
### 2.5. ANALYZE ERRORS
|
|
262
|
-
|
|
263
|
-
After discovery, collect and classify ALL console errors and toast notifications:
|
|
264
|
-
|
|
265
|
-
```
|
|
266
|
-
1. Run browser_console_messages(level: "error") — capture all errors
|
|
267
|
-
2. Check for error toasts visible in the snapshot
|
|
268
|
-
3. Classify each error:
|
|
269
|
-
|
|
270
|
-
ENV/CONFIG — Missing env vars, DB connection, external service down
|
|
271
|
-
→ Document but don't block. Note what env is needed.
|
|
272
|
-
Example: "500 on /api/billing/status — likely missing STRIPE_SECRET_KEY"
|
|
273
|
-
|
|
274
|
-
BUG — Real code issues that happen regardless of env
|
|
275
|
-
→ Flag as HIGH priority finding. Create fix recommendation.
|
|
276
|
-
Example: "tRPC returns HTML instead of JSON on batch error — missing error boundary"
|
|
277
|
-
|
|
278
|
-
EXPECTED — Known warnings, dev-only messages, React strict mode
|
|
279
|
-
→ Document and skip.
|
|
280
|
-
Example: "React DevTools extension warning"
|
|
281
|
-
|
|
282
|
-
4. Check for:
|
|
283
|
-
- Stack traces exposed in UI (security issue)
|
|
284
|
-
- Sensitive data in error messages (API keys, DB URLs, user data)
|
|
285
|
-
- Error messages that leak implementation details
|
|
286
|
-
- Failed API calls that should have fallback/retry
|
|
287
|
-
- Toast storms (>3 error toasts = bad UX, should consolidate)
|
|
288
|
-
|
|
289
|
-
5. Record ALL findings in the page spec under "## Error Analysis"
|
|
290
|
-
6. Add actionable items to the audit report
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
This phase is CRITICAL — errors found during discovery often reveal:
|
|
294
|
-
- Missing error boundaries
|
|
295
|
-
- Unhandled API failures
|
|
296
|
-
- Environment-dependent code without fallbacks
|
|
297
|
-
- UX issues (toast spam, unhelpful error messages)
|
|
298
|
-
- Security leaks (stack traces, internal paths in errors)
|
|
299
|
-
|
|
300
|
-
### 2.7. TRIANGULATE (DB + Source Code + UI)
|
|
301
|
-
|
|
302
|
-
After discovery and error analysis, **cross-reference** what the UI shows against the
|
|
303
|
-
database and the component source code to verify correctness:
|
|
304
|
-
|
|
305
|
-
```
|
|
306
|
-
1. READ SOURCE CODE for the page's components:
|
|
307
|
-
- Find the page component in src/app/(app)/dashboard/{page}/
|
|
308
|
-
- Read _components/ subfolder for page-specific components
|
|
309
|
-
- Read src/components/{feature}/ for shared feature components
|
|
310
|
-
- Identify which tRPC procedures are called (trpc.{router}.{procedure})
|
|
311
|
-
- Understand expected data flow: tRPC query → component props → UI rendering
|
|
312
|
-
|
|
313
|
-
2. CHECK DATABASE for test data:
|
|
314
|
-
- Query the database (via Prisma/tRPC or MCP) to see what data exists
|
|
315
|
-
- Verify the UI accurately reflects what's in the DB:
|
|
316
|
-
* Counts match (e.g., "10 integrations" in UI = 10 rows in DB)
|
|
317
|
-
* Names/labels match (no stale cache, no wrong field displayed)
|
|
318
|
-
* Statuses match (e.g., "active" in DB shown as active in UI)
|
|
319
|
-
* Dates/timestamps are formatted correctly
|
|
320
|
-
- If data is EMPTY or INSUFFICIENT for testing:
|
|
321
|
-
a. Check if a seed script exists (schema/seeders/) and enrich it
|
|
322
|
-
b. OR use the UI flow to CREATE test data (e.g., create an integration,
|
|
323
|
-
upload a file, start a chat) — this also audits the creation flow
|
|
324
|
-
c. Document what data was needed and how it was obtained
|
|
325
|
-
|
|
326
|
-
3. VERIFY BEHAVIOR matches expectations:
|
|
327
|
-
- Does clicking "Delete" actually delete from DB? (check before/after)
|
|
328
|
-
- Does creating an item show it in the list without refresh?
|
|
329
|
-
- Do filters actually filter the correct data? (cross-check with DB query)
|
|
330
|
-
- Do pagination counts match total DB records?
|
|
331
|
-
- Does sorting work correctly? (verify order matches DB ORDER BY)
|
|
332
|
-
- Do role-based visibility rules match ZenStack policies?
|
|
333
|
-
|
|
334
|
-
4. FLAG MISMATCHES as findings:
|
|
335
|
-
- UI shows data that doesn't exist in DB → stale cache or mock data
|
|
336
|
-
- DB has data not shown in UI → missing query, wrong filter, permission issue
|
|
337
|
-
- UI count != DB count → pagination bug, filter leak, or policy issue
|
|
338
|
-
- Component code expects field X but API returns field Y → type mismatch
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
**Why this matters**: A UI can "look correct" while showing wrong data. Triangulating
|
|
342
|
-
DB ↔ Source Code ↔ UI catches data integrity bugs that snapshot-only testing misses.
|
|
343
|
-
|
|
344
|
-
### 2.9. VALIDATE CHECKLIST (GATE — BLOCKS GENERATE)
|
|
345
|
-
|
|
346
|
-
Before writing ANY test code (POM or spec), the page spec checklist MUST be 100% validated.
|
|
347
|
-
|
|
348
|
-
**What "validated" means for each element type:**
|
|
349
|
-
- **Button**: You CLICKED it and documented what happened
|
|
350
|
-
- **Combobox/Dropdown**: You OPENED it, listed ALL options, SELECTED each one
|
|
351
|
-
- **Input**: You TYPED into it and verified validation
|
|
352
|
-
- **Tab**: You CLICKED it and snapshotted the panel content
|
|
353
|
-
- **Link**: You CLICKED it and verified the destination
|
|
354
|
-
- **Modal/Dialog**: You OPENED it and listed all elements inside
|
|
355
|
-
- **Wizard step**: You NAVIGATED to it, interacted with ALL its elements
|
|
356
|
-
- **Action**: You TRIGGERED it and verified the outcome
|
|
357
|
-
|
|
358
|
-
**TRIANGULATION REQUIREMENT**: For every page, the checklist MUST include a
|
|
359
|
-
dedicated `## Triangulation` section with THREE explicit sub-checks:
|
|
360
|
-
|
|
361
|
-
```markdown
|
|
362
|
-
## Triangulation
|
|
363
|
-
|
|
364
|
-
### DB Verification
|
|
365
|
-
- [ ] Count in UI matches DB count (e.g., "11 integrations" = 11 rows in DB)
|
|
366
|
-
- [ ] Status values in UI match DB status column
|
|
367
|
-
- [ ] Action outcomes confirmed in DB (e.g., Pausar → status changed to PAUSED)
|
|
368
|
-
- [ ] Created items appear in DB with correct fields
|
|
369
|
-
|
|
370
|
-
### Source Code Verification
|
|
371
|
-
- [ ] Component file identified and read (path noted)
|
|
372
|
-
- [ ] tRPC procedures identified (router.procedure names)
|
|
373
|
-
- [ ] Known bugs traced to source (file:line noted)
|
|
374
|
-
|
|
375
|
-
### UI vs DB Mismatch Check
|
|
376
|
-
- [ ] No stale data displayed (UI reflects current DB state)
|
|
377
|
-
- [ ] Filter/search results match what DB query would return
|
|
378
|
-
- [ ] Pagination count matches total DB records for this org
|
|
379
|
-
```
|
|
380
|
-
|
|
381
|
-
Use `bunx dotenvx run -f artifacts/.env.local -f artifacts/.env.development -- prisma studio`
|
|
382
|
-
to open Prisma Studio for DB inspection. For quick queries, write a temp script
|
|
383
|
-
and run with `bunx dotenvx run ... -- bun run tmp-query.ts`, then delete it.
|
|
384
|
-
|
|
385
|
-
```
|
|
386
|
-
1. Open the page spec at docs/e2e-audit/page-specs/{page-name}.md
|
|
387
|
-
2. Scan for EVERY `[ ]` (unchecked) item
|
|
388
|
-
3. If ANY unchecked items remain:
|
|
389
|
-
a. DO NOT proceed to step 3 (GENERATE)
|
|
390
|
-
b. Go back and interact with each unchecked element via Playwright
|
|
391
|
-
c. After verifying, update the checklist: `[ ]` → `[x]` with ✅
|
|
392
|
-
d. If an element cannot be verified (missing, broken), mark with ❌
|
|
393
|
-
and explain why (e.g., "BUG: button not rendered")
|
|
394
|
-
e. If an element requires external service, mark with `[~]` and explain
|
|
395
|
-
(e.g., "[~] requires dev.hakutaku.ai for OAuth")
|
|
396
|
-
4. ONLY when the spec has ZERO `[ ]` items may you proceed to GENERATE
|
|
397
|
-
5. Final counts MUST be documented at the top of the spec:
|
|
398
|
-
- Total elements: N
|
|
399
|
-
- Validated [x]: N
|
|
400
|
-
- Blocked [~]: N (with reasons)
|
|
401
|
-
- Failed [❌]: N (with bug reports)
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
**CRITICAL**: Writing tests for elements you haven't actually clicked, opened,
|
|
405
|
-
or interacted with produces unreliable tests. The checklist IS the proof of work.
|
|
406
|
-
A page spec full of `[ ]` means the audit is NOT done — it's just a draft.
|
|
407
|
-
|
|
408
|
-
**SELF-CHECK before proceeding**: Read the page spec top to bottom. For each `[x]`
|
|
409
|
-
item, can you recall EXACTLY what happened when you interacted with it? If not,
|
|
410
|
-
you didn't actually test it — you just checked the box. Go back and test it.
|
|
411
|
-
|
|
412
|
-
### 3. GENERATE
|
|
413
|
-
|
|
414
|
-
Write three files per page:
|
|
415
|
-
|
|
416
|
-
#### Page Spec (`docs/e2e-audit/page-specs/{page-name}.md`)
|
|
417
|
-
- Complete inventory of all PAGE-SPECIFIC elements found
|
|
418
|
-
- Checklist format for tracking test coverage
|
|
419
|
-
- Notes on states, permissions, edge cases
|
|
420
|
-
|
|
421
|
-
**IMPORTANT — Shared vs Page-Specific Elements:**
|
|
422
|
-
- **Sidebar navigation, user menu, toast region, FAB button** are SHARED layout
|
|
423
|
-
elements. They appear on EVERY page and are NOT part of the page audit.
|
|
424
|
-
- Audit shared layout elements ONCE in a dedicated `shared-layout.md` spec.
|
|
425
|
-
- Each page spec should ONLY contain elements unique to THAT page's content
|
|
426
|
-
(inside `<main>`). Do NOT duplicate sidebar links in every page spec.
|
|
427
|
-
- If a shared element behaves DIFFERENTLY on a specific page (e.g., sidebar
|
|
428
|
-
highlights a different link), note the difference but don't re-audit the
|
|
429
|
-
entire sidebar.
|
|
430
|
-
|
|
431
|
-
#### Page Object Model (`tests/e2e/pages/{page-name}.page.ts`)
|
|
432
|
-
```typescript
|
|
433
|
-
import { type Page, type Locator } from '@playwright/test'
|
|
434
|
-
|
|
435
|
-
export class DashboardHomePage {
|
|
436
|
-
readonly page: Page
|
|
437
|
-
readonly heading: Locator
|
|
438
|
-
readonly createButton: Locator
|
|
439
|
-
|
|
440
|
-
constructor(page: Page) {
|
|
441
|
-
this.page = page
|
|
442
|
-
this.heading = page.getByRole('heading', { name: 'Home' })
|
|
443
|
-
this.createButton = page.getByRole('button', { name: 'Create' })
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
async goto() {
|
|
447
|
-
await this.page.goto('/dashboard/home')
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
async waitForLoad() {
|
|
451
|
-
await this.heading.waitFor()
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
```
|
|
455
|
-
|
|
456
|
-
#### Test Spec (`tests/e2e/specs/{page-name}.spec.ts`)
|
|
457
|
-
```typescript
|
|
458
|
-
import { test, expect } from '../fixtures/base'
|
|
459
|
-
import { DashboardHomePage } from '../pages/dashboard-home.page'
|
|
460
|
-
|
|
461
|
-
test.describe('Dashboard Home @smoke', () => {
|
|
462
|
-
let home: DashboardHomePage
|
|
463
|
-
|
|
464
|
-
test.beforeEach(async ({ authenticatedPage, apiErrors: _apiErrors }) => {
|
|
465
|
-
home = new DashboardHomePage(authenticatedPage)
|
|
466
|
-
await home.goto()
|
|
467
|
-
await home.waitForLoad()
|
|
468
|
-
})
|
|
469
|
-
|
|
470
|
-
test('loads and displays heading', async ({ authenticatedPage }) => {
|
|
471
|
-
await expect(authenticatedPage, 'Should navigate to home page').toHaveURL(/dashboard\/home/)
|
|
472
|
-
await expect(home.heading).toBeVisible()
|
|
473
|
-
})
|
|
474
|
-
|
|
475
|
-
test('displays hero section', async () => {
|
|
476
|
-
await expect(home.heroTitle, 'Hero section should render after data loads').toBeVisible()
|
|
477
|
-
})
|
|
478
|
-
})
|
|
479
|
-
```
|
|
480
|
-
|
|
481
|
-
### 4. VALIDATE
|
|
482
|
-
|
|
483
|
-
Run the generated tests:
|
|
484
|
-
```bash
|
|
485
|
-
bunx playwright test tests/e2e/specs/{page-name}.spec.ts
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
Fix any failures before moving on.
|
|
489
|
-
|
|
490
|
-
### 5. REPORT
|
|
491
|
-
|
|
492
|
-
Update `docs/e2e-audit/reports/master-audit.md` with:
|
|
493
|
-
- Elements found vs tested
|
|
494
|
-
- Security findings
|
|
495
|
-
- UX/UI issues
|
|
496
|
-
- Missing test-ids
|
|
497
|
-
- Accessibility gaps
|
|
498
|
-
|
|
499
|
-
## API Error Tracking (MANDATORY)
|
|
500
|
-
|
|
501
|
-
Every test MUST use the `apiErrors` fixture to automatically detect and report API failures.
|
|
502
|
-
This replaces generic "TimeoutError: waiting for heading" with actionable messages like
|
|
503
|
-
`"API errors detected: GET /api/v1/integration.list → 500 Internal Server Error"`.
|
|
504
|
-
|
|
505
|
-
### How It Works
|
|
506
|
-
|
|
507
|
-
The `apiErrors` fixture in `tests/e2e/fixtures/base.ts`:
|
|
508
|
-
1. Listens to ALL network responses on the authenticated page
|
|
509
|
-
2. Captures any 4xx/5xx responses from `/api/` or `/v1/` endpoints
|
|
510
|
-
3. After the test completes, if any API errors were collected, it FAILS the test
|
|
511
|
-
with a detailed report including method, URL, status code, and status text
|
|
512
|
-
4. Known env-dependent endpoints (billing, ontology) are excluded via `IGNORED_API_PATTERNS`
|
|
513
|
-
|
|
514
|
-
### Usage Pattern
|
|
515
|
-
|
|
516
|
-
```typescript
|
|
517
|
-
// REQUIRED: Destructure apiErrors in beforeEach (even if unused in test body)
|
|
518
|
-
test.beforeEach(async ({ authenticatedPage, apiErrors: _apiErrors }) => {
|
|
519
|
-
// apiErrors starts listening immediately — no setup needed
|
|
520
|
-
page = new SomePage(authenticatedPage)
|
|
521
|
-
await page.goto()
|
|
522
|
-
await page.waitForLoad()
|
|
523
|
-
})
|
|
524
|
-
|
|
525
|
-
// For standalone tests without beforeEach:
|
|
526
|
-
test('standalone test', async ({ authenticatedPage, apiErrors: _apiErrors }) => {
|
|
527
|
-
// apiErrors is active for this test
|
|
528
|
-
})
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
### Adding Ignored Endpoints
|
|
532
|
-
|
|
533
|
-
When an API returns errors due to missing env vars (not real bugs), add the pattern:
|
|
534
|
-
|
|
535
|
-
```typescript
|
|
536
|
-
// In tests/e2e/fixtures/base.ts
|
|
537
|
-
const IGNORED_API_PATTERNS = [
|
|
538
|
-
/\/api\/billing\//, // Missing Stripe key in dev
|
|
539
|
-
/ontology\.getGraph/, // Missing ontology service
|
|
540
|
-
]
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
### Custom Assertion Messages (MANDATORY)
|
|
544
|
-
|
|
545
|
-
Every `expect()` call MUST include a descriptive second argument explaining what the
|
|
546
|
-
assertion checks and what might be wrong if it fails:
|
|
547
|
-
|
|
548
|
-
```typescript
|
|
549
|
-
// BAD — gives useless error: "expected locator to be visible"
|
|
550
|
-
await expect(cards.first()).toBeVisible()
|
|
551
|
-
|
|
552
|
-
// GOOD — gives actionable error with debugging hint
|
|
553
|
-
await expect(cards.first(), 'At least 1 integration card should render (is integration.list returning data?)').toBeVisible()
|
|
554
|
-
|
|
555
|
-
// BAD — gives "expected 0 to be greater than 0"
|
|
556
|
-
expect(count).toBeGreaterThan(0)
|
|
557
|
-
|
|
558
|
-
// GOOD — explains what's missing
|
|
559
|
-
expect(count, 'Integration cards not found — check if tRPC integration.list returns data for this org').toBeGreaterThan(0)
|
|
560
|
-
```
|
|
561
|
-
|
|
562
|
-
**Why this matters**: When a test fails in CI, the developer sees the custom message
|
|
563
|
-
immediately — no need to reproduce locally or dig through Playwright traces.
|
|
564
|
-
|
|
565
|
-
## Test Categories per Page
|
|
566
|
-
|
|
567
|
-
Every page MUST have tests for:
|
|
568
|
-
|
|
569
|
-
### Navigation
|
|
570
|
-
- All links resolve (no 404s)
|
|
571
|
-
- Breadcrumbs correct
|
|
572
|
-
- Back/forward browser navigation works
|
|
573
|
-
|
|
574
|
-
### Interactions
|
|
575
|
-
- All buttons clickable and produce expected result
|
|
576
|
-
- All modals open/close correctly
|
|
577
|
-
- All forms submit with valid data
|
|
578
|
-
- All dropdowns open and select options
|
|
579
|
-
|
|
580
|
-
### Validation
|
|
581
|
-
- Required fields show errors when empty
|
|
582
|
-
- Invalid input shows appropriate error
|
|
583
|
-
- Max length enforced
|
|
584
|
-
- Special characters handled
|
|
585
|
-
|
|
586
|
-
### UX/UI
|
|
587
|
-
- Loading states display (skeletons/spinners)
|
|
588
|
-
- Empty states display when no data
|
|
589
|
-
- Error states display on failure
|
|
590
|
-
- Toasts appear with correct message and type
|
|
591
|
-
- Tooltips show on hover
|
|
592
|
-
- Focus management (modals trap focus, inputs auto-focus)
|
|
593
|
-
|
|
594
|
-
### Security
|
|
595
|
-
- Console has no sensitive data leaks
|
|
596
|
-
- XSS payloads in inputs don't execute
|
|
597
|
-
- RBAC: unauthorized roles can't access/see restricted elements
|
|
598
|
-
- No stack traces in UI error messages
|
|
599
|
-
|
|
600
|
-
## Locator Strategy
|
|
601
|
-
|
|
602
|
-
Priority order:
|
|
603
|
-
1. `getByRole()` — semantic, accessible
|
|
604
|
-
2. `getByText()` — visible text
|
|
605
|
-
3. `getByLabel()` — form fields
|
|
606
|
-
4. `getByPlaceholder()` — inputs
|
|
607
|
-
5. `getByTestId()` — last resort (flag missing semantic labels)
|
|
608
|
-
|
|
609
|
-
**NEVER use CSS selectors** (`.class`, `#id`, `div > span`).
|
|
610
|
-
|
|
611
|
-
## File Structure
|
|
612
|
-
|
|
613
|
-
```
|
|
614
|
-
tests/e2e/
|
|
615
|
-
├── fixtures/
|
|
616
|
-
│ ├── auth.ts # Storage state paths + UserRole type
|
|
617
|
-
│ ├── auth.setup.ts # Auth setup (preserves valid sessions)
|
|
618
|
-
│ ├── base.ts # Extended fixtures (authenticatedPage, apiErrors)
|
|
619
|
-
│ └── storage/ # Auth state files (gitignored)
|
|
620
|
-
│ ├── owner.json
|
|
621
|
-
│ ├── admin.json
|
|
622
|
-
│ ├── manager.json
|
|
623
|
-
│ └── member.json
|
|
624
|
-
├── pages/ # Page Object Models
|
|
625
|
-
│ ├── dashboard-home.page.ts
|
|
626
|
-
│ ├── dashboard-integrations.page.ts
|
|
627
|
-
│ ├── dashboard-teams.page.ts
|
|
628
|
-
│ └── ...
|
|
629
|
-
├── specs/ # Test specifications
|
|
630
|
-
│ ├── dashboard-home.spec.ts
|
|
631
|
-
│ ├── dashboard-integrations.spec.ts
|
|
632
|
-
│ ├── dashboard-teams.spec.ts
|
|
633
|
-
│ ├── security/
|
|
634
|
-
│ │ ├── rbac.spec.ts
|
|
635
|
-
│ │ └── headers.spec.ts
|
|
636
|
-
│ └── ...
|
|
637
|
-
└── utils/
|
|
638
|
-
├── console-collector.ts # Console message interceptor + sensitive data scanner
|
|
639
|
-
├── security-helpers.ts # XSS payloads, header checks
|
|
640
|
-
└── test-data.ts # Shared test data
|
|
641
|
-
```
|
|
642
|
-
|
|
643
|
-
## Running
|
|
644
|
-
|
|
645
|
-
```bash
|
|
646
|
-
# All tests
|
|
647
|
-
bun run test:e2e
|
|
648
|
-
|
|
649
|
-
# Smoke tests only
|
|
650
|
-
bunx playwright test --grep @smoke
|
|
651
|
-
|
|
652
|
-
# Security tests only
|
|
653
|
-
bunx playwright test --grep @security
|
|
654
|
-
|
|
655
|
-
# Specific page
|
|
656
|
-
bunx playwright test tests/e2e/specs/dashboard-home.spec.ts
|
|
657
|
-
|
|
658
|
-
# UI mode (visual debugging)
|
|
659
|
-
bunx playwright test --ui
|
|
660
|
-
```
|
|
1
|
+
---
|
|
2
|
+
name: e2e-audit
|
|
3
|
+
version: 0.2.0
|
|
4
|
+
description: Comprehensive E2E audit that maps all routes, APIs, tRPC procedures, middleware auth, and forms from SOURCE first, cross-references against existing tests and the current branch diff, runs Playwright against dev, then reports coverage gaps and problems with a SHOT+TRACE+ASSERT+SOURCE evidence quad. Invoke when the user mentions "e2e audit", "run the e2e", "integration test audit", "test coverage gaps", "roda o e2e", end-to-end tests, API contract check, RBAC coverage, or auditing integration tests. Report-then-ask: stop after mapping, run only on confirmation, emit a post-run-feedback report before writing findings.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# e2e-audit — source-first integration-test audit
|
|
8
|
+
|
|
9
|
+
> **Operating principle:** you cannot audit what you never opened. Playwright traffic logs only cover flows you already know. Read the source first, then drive the browser to close the gaps the source revealed.
|
|
10
|
+
|
|
11
|
+
## Entry contract (non-negotiable)
|
|
12
|
+
|
|
13
|
+
1. **Mapping before clicking.** Run discovery scripts, write all JSON inventories, then STOP and report. Do NOT spin up the browser before the user confirms scope.
|
|
14
|
+
2. **Existing tests are load-bearing.** If `tests/e2e/` (or equivalent) exists, inventory it FIRST. Reuse fixtures, auth storage state, and page objects. Warn on drift between runs.
|
|
15
|
+
3. **Evidence quad.** Every non-meta finding ships SHOT+TRACE+ASSERT+SOURCE — screenshot path, Playwright trace path, literal assertion string, and implicated source file. Coverage gaps (`rule=coverage-gap-*` / `uncovered-*`) are the only exceptions.
|
|
16
|
+
4. **Dev, not prod.** Always audit against the local dev server. Detect HTML-instead-of-JSON crashes (500 responses that render the Next/Remix error page) and surface them.
|
|
17
|
+
5. **Report-then-ask → run → feedback → findings.** Four gates, in order. Do not merge them.
|
|
18
|
+
|
|
19
|
+
## Output layout
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
.e2e-audit/<YYYY-MM-DD-HHMMSS>/
|
|
23
|
+
├── stack.json # detect-stack.sh
|
|
24
|
+
├── routes.json # discover-routes.sh
|
|
25
|
+
├── api-surface.json # discover-api-surface.sh
|
|
26
|
+
├── existing-tests.json # inventory-existing-tests.sh
|
|
27
|
+
├── uncovered.json # detect-uncovered.sh
|
|
28
|
+
├── map.md # human-readable summary of the above
|
|
29
|
+
├── traces/ # Playwright trace.zip per test
|
|
30
|
+
├── screenshots/ # PNGs per assertion moment
|
|
31
|
+
├── logs/
|
|
32
|
+
│ ├── dev-server.log # piped stdout+stderr of dev server
|
|
33
|
+
│ └── playwright.log
|
|
34
|
+
├── post-run-feedback.json # emitted AFTER runs, BEFORE findings
|
|
35
|
+
├── post-run-feedback.md # human copy
|
|
36
|
+
└── findings.json # final — schema at findings.schema.json
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Pipeline
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
PREFLIGHT → detect-stack, inventory-existing-tests, compute drift-hash
|
|
43
|
+
DISCOVERY → discover-routes, discover-api-surface, detect-uncovered
|
|
44
|
+
REPORT-THEN-ASK → write map.md, present to user, WAIT for confirmation
|
|
45
|
+
RUN → start dev server, tail logs, drive Playwright
|
|
46
|
+
FEEDBACK → post-run-feedback.json from logs + trace + console
|
|
47
|
+
FINDINGS → findings.json with SHOT+TRACE+ASSERT+SOURCE quad
|
|
48
|
+
VERIFY → bash scripts/verify-audit.sh <session_dir>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Step 1 — Preflight
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
SESSION_DIR=".e2e-audit/$(date +%Y-%m-%d-%H%M%S)"
|
|
57
|
+
mkdir -p "$SESSION_DIR/traces" "$SESSION_DIR/screenshots" "$SESSION_DIR/logs"
|
|
58
|
+
|
|
59
|
+
bash .claude/skills/e2e-audit/scripts/detect-stack.sh > "$SESSION_DIR/stack.json"
|
|
60
|
+
bash .claude/skills/e2e-audit/scripts/inventory-existing-tests.sh > "$SESSION_DIR/existing-tests.json"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Drift check.** If a previous session exists at `.e2e-audit/.last-hash`, compare `existing-tests.json.hash` against it. On mismatch, surface a `test-drift` meta finding (non-fatal) showing which files were added, removed, or resized. Write the new hash after the run completes.
|
|
64
|
+
|
|
65
|
+
**Stack fallback.** If `stack.test_runner == "none"`, emit a `meta` finding prompting the user to install Playwright (`bun add -D @playwright/test`) and stop the pipeline. Do not proceed blind.
|
|
66
|
+
|
|
67
|
+
## Step 2 — Source-first discovery
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
bash .claude/skills/e2e-audit/scripts/discover-routes.sh > "$SESSION_DIR/routes.json"
|
|
71
|
+
bash .claude/skills/e2e-audit/scripts/discover-api-surface.sh > "$SESSION_DIR/api-surface.json"
|
|
72
|
+
bash .claude/skills/e2e-audit/scripts/detect-uncovered.sh \
|
|
73
|
+
"$SESSION_DIR/routes.json" \
|
|
74
|
+
"$SESSION_DIR/api-surface.json" \
|
|
75
|
+
"$SESSION_DIR/existing-tests.json" \
|
|
76
|
+
"${BASE_REF:-origin/main}" > "$SESSION_DIR/uncovered.json"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Then write `map.md` summarising:
|
|
80
|
+
|
|
81
|
+
- **Stack**: framework + router style + test runner + auth providers + ORMs.
|
|
82
|
+
- **Surface counts**: routes, HTTP handlers, tRPC procedures (by auth tier), server actions.
|
|
83
|
+
- **Branch diff**: files changed vs `BASE_REF`; highlight those without test references.
|
|
84
|
+
- **Uncovered**: bulleted list of every item in `uncovered_routes / uncovered_http / uncovered_trpc / uncovered_actions`.
|
|
85
|
+
- **Existing test inventory**: count + hash + drift status.
|
|
86
|
+
|
|
87
|
+
## Step 3 — Report-then-ask (HARD STOP)
|
|
88
|
+
|
|
89
|
+
Present `map.md` to the user with a short prompt:
|
|
90
|
+
|
|
91
|
+
> Mapping complete. Found N routes, M uncovered surfaces, K existing specs. Scope to run:
|
|
92
|
+
> - (a) uncovered + changed (default, recommended)
|
|
93
|
+
> - (b) full suite (all existing specs + uncovered surfaces)
|
|
94
|
+
> - (c) custom subset (user lists paths)
|
|
95
|
+
> Reply with a/b/c before I touch the browser.
|
|
96
|
+
|
|
97
|
+
Do NOT proceed to Step 4 without a reply. This is the mandatory report-then-ask gate.
|
|
98
|
+
|
|
99
|
+
## Step 4 — Run against dev
|
|
100
|
+
|
|
101
|
+
1. **Start dev server in background**, redirect stdout+stderr to `$SESSION_DIR/logs/dev-server.log`:
|
|
102
|
+
```bash
|
|
103
|
+
nohup sh -c "$(jq -r .dev_command "$SESSION_DIR/stack.json")" \
|
|
104
|
+
> "$SESSION_DIR/logs/dev-server.log" 2>&1 &
|
|
105
|
+
echo $! > "$SESSION_DIR/logs/dev.pid"
|
|
106
|
+
```
|
|
107
|
+
2. **Wait** for `$(jq -r .base_url stack.json)` to respond 200 within 90s. Fail loud if not.
|
|
108
|
+
3. **Auth setup**: if `stack.auth` is non-empty, use/create `storageState` per role. Start from any existing state in `existing-tests.storage_states`; only synthesize new states via explicit user-provided credentials (never read env files and print them). See `references/auth-setup-playbook.md`.
|
|
109
|
+
4. **Spec selection** per Step 3 answer. Prefer existing specs when coverage exists.
|
|
110
|
+
5. **Run Playwright** with tracing forced on:
|
|
111
|
+
```bash
|
|
112
|
+
npx playwright test \
|
|
113
|
+
--trace=on \
|
|
114
|
+
--output="$SESSION_DIR/traces" \
|
|
115
|
+
--reporter=list,json \
|
|
116
|
+
2>&1 | tee "$SESSION_DIR/logs/playwright.log"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Capture for each test:
|
|
120
|
+
|
|
121
|
+
- Screenshot at the key assertion step (`await page.screenshot({path, fullPage: true})`).
|
|
122
|
+
- Trace zip (auto when `--trace=on`).
|
|
123
|
+
- All `page.on('console')` messages with level + URL + line.
|
|
124
|
+
- All responses via `page.on('response')`: filter 4xx/5xx on `/api/` `/v1/` `/trpc/` paths.
|
|
125
|
+
- HTML-instead-of-JSON: any response where `Content-Type: text/html` hits an API path → `server-crash` rule.
|
|
126
|
+
|
|
127
|
+
## Step 5 — Post-run feedback
|
|
128
|
+
|
|
129
|
+
BEFORE writing `findings.json`, consolidate into `post-run-feedback.json`:
|
|
130
|
+
|
|
131
|
+
```jsonc
|
|
132
|
+
{
|
|
133
|
+
"session": "<session_dir>",
|
|
134
|
+
"duration_s": 128,
|
|
135
|
+
"tests_total": 42,
|
|
136
|
+
"tests_failed": 3,
|
|
137
|
+
"problems": [
|
|
138
|
+
{ "kind": "api-5xx", "where": "POST /api/users", "count": 2, "sample_trace": "traces/users-create-1.zip" },
|
|
139
|
+
{ "kind": "console-error", "where": "dashboard", "count": 7, "sample": "Uncaught TypeError: Cannot read ..." },
|
|
140
|
+
{ "kind": "rbac-bypass", "where": "member sees /admin", "count": 1 },
|
|
141
|
+
{ "kind": "server-crash", "where": "POST /api/x returned text/html 500" },
|
|
142
|
+
{ "kind": "auth-flow-broken","where": "login redirect loop after valid credentials" },
|
|
143
|
+
{ "kind": "dev-server-log", "where": "unhandledRejection at server:1234" }
|
|
144
|
+
],
|
|
145
|
+
"uncovered_carried_forward": { "routes": 4, "http": 2, "trpc": 9, "actions": 1 }
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Also mirror to `post-run-feedback.md`. Present a short summary to the user; do not dump the full JSON.
|
|
150
|
+
|
|
151
|
+
## Step 6 — Write findings
|
|
152
|
+
|
|
153
|
+
For every problem in `post-run-feedback.problems` that is tied to a specific failure, emit one finding. Allocate IDs `E2E-0001`, `E2E-0002`, … sequentially.
|
|
154
|
+
|
|
155
|
+
- Evidence quad required (`screenshot_path`, `trace_path`, `assertion`, `source_file`).
|
|
156
|
+
- `source_file` must point at the route handler / procedure / action / middleware implicated — not the spec file.
|
|
157
|
+
- Add `http.method`, `http.path`, `http.status`, `http.response_snippet` for api-contract + server-crash findings.
|
|
158
|
+
|
|
159
|
+
Meta findings (no evidence quad required):
|
|
160
|
+
|
|
161
|
+
- `coverage-gap-routes` / `coverage-gap-http` / `coverage-gap-trpc` / `coverage-gap-actions` — one per non-empty `uncovered.*` array, with the array echoed into `detail`.
|
|
162
|
+
- `test-drift` — emitted by Step 1 when the test-corpus hash changed since last run.
|
|
163
|
+
- `stack-detect` — info-level snapshot of `stack.json` for traceability.
|
|
164
|
+
- `post-run-feedback` — aggregate, links to `post-run-feedback.json`.
|
|
165
|
+
|
|
166
|
+
Schema: `.claude/skills/e2e-audit/findings.schema.json`. Validate with `jq --slurpfile schema findings.schema.json` or skip strict validation and lean on `verify-audit.sh`.
|
|
167
|
+
|
|
168
|
+
## Step 7 — Verify + persist
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
bash .claude/skills/e2e-audit/scripts/verify-audit.sh "$SESSION_DIR"
|
|
172
|
+
jq -r '.hash' "$SESSION_DIR/existing-tests.json" > .e2e-audit/.last-hash
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Kill the dev server: `kill "$(cat "$SESSION_DIR/logs/dev.pid")"`.
|
|
176
|
+
|
|
177
|
+
## Final response to user
|
|
178
|
+
|
|
179
|
+
≤5 sentences. Report: session dir, # findings, # coverage gaps, # problems, and one-line guidance on whether to invoke a fix agent or hand-fix. Do NOT paste `map.md` or `findings.json` bodies.
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Invocation triggers (already enforced by SessionStart hook)
|
|
184
|
+
|
|
185
|
+
Keywords that MUST trigger this skill: `e2e audit`, `roda o e2e`, `run the e2e`, `integration test audit`, `test coverage gaps`, `coverage gap`, `audit my tests`, `api contract check`, `rbac coverage`, `end-to-end tests`. Claude must read this file before improvising a plan.
|
|
186
|
+
|
|
187
|
+
## Boundaries (what this skill does NOT do)
|
|
188
|
+
|
|
189
|
+
- Does not write fixes. Fix work is out of scope; hand the finding list to a sd-fix-style agent or the user.
|
|
190
|
+
- Does not audit design / UX — that's `super-design`. If the user asked for a UX audit, hand off.
|
|
191
|
+
- Does not run against production. Only local dev. If `stack.base_url` points to prod, refuse.
|
|
192
|
+
- Does not invent credentials. Never read `.env*` files; only use credentials the user provides inline for the session.
|
|
193
|
+
- Does not delete existing tests. Drift is reported, never "resolved" by removing specs.
|
|
194
|
+
|
|
195
|
+
## References
|
|
196
|
+
|
|
197
|
+
- `references/auth-setup-playbook.md` — storageState + role patterns per auth provider.
|
|
198
|
+
- `references/api-contract-playbook.md` — HTTP-4xx / HTTP-5xx / HTML-instead-of-JSON detection.
|
|
199
|
+
- `references/coverage-gap-playbook.md` — how to translate `uncovered.*` into meta findings + suggested specs.
|
|
200
|
+
- `references/post-run-feedback-playbook.md` — how to consolidate Playwright run signals into feedback.
|
|
201
|
+
|
|
202
|
+
## Templates
|
|
203
|
+
|
|
204
|
+
- `templates/base-fixture.ts.tpl` — `test.extend` with `apiErrors` + `authenticatedPage` fixtures.
|
|
205
|
+
- `templates/auth-setup.ts.tpl` — globalSetup shape that writes storageState per role.
|
|
206
|
+
- `templates/findings-report.md.tpl` — human-readable summary rendered from findings.json.
|
|
207
|
+
- `templates/post-run-feedback.md.tpl` — the mirror of post-run-feedback.json.
|
|
208
|
+
|
|
209
|
+
## Attention points
|
|
210
|
+
|
|
211
|
+
- **tRPC v10 vs v11.** Procedure nesting works differently; `createCaller()` exists in both but the router introspection APIs diverge. Treat `discover-api-surface.sh` output as names-only.
|
|
212
|
+
- **Route groups.** Next `(marketing)` style segments are stripped in URL computation; don't emit findings that name the parenthesis.
|
|
213
|
+
- **Parallel & intercepting routes.** `@modal` slots and `(.)photo` shortcuts are surfaces that Playwright can miss; the route discovery already flags them — propose specs that hit them directly.
|
|
214
|
+
- **Middleware.** If `middleware.has_auth_guard == true` and a public matcher exists, any public URL the audit hit should not have triggered auth redirects. Mismatches = findings.
|
|
215
|
+
- **Windows paths.** `.claude/skills/e2e-audit/scripts/*.sh` must run via Git Bash or WSL. If `bash` isn't available, abort with a meta finding; never fall back to half-runs.
|
|
216
|
+
- **Dev server crashes mid-run.** If `dev.pid` exits unexpectedly during Playwright execution, mark all remaining tests as inconclusive and emit `server-crash` findings with the last 40 lines of `dev-server.log` in `detail`.
|