start-vibing 2.0.11 → 2.0.13

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 (131) hide show
  1. package/README.md +177 -177
  2. package/dist/cli.js +19 -2
  3. package/package.json +42 -42
  4. package/template/.claude/CLAUDE.md +174 -174
  5. package/template/.claude/agents/01-orchestration/agent-selector.md +130 -130
  6. package/template/.claude/agents/01-orchestration/checkpoint-manager.md +142 -142
  7. package/template/.claude/agents/01-orchestration/context-manager.md +138 -138
  8. package/template/.claude/agents/01-orchestration/error-recovery.md +182 -182
  9. package/template/.claude/agents/01-orchestration/orchestrator.md +114 -114
  10. package/template/.claude/agents/01-orchestration/parallel-coordinator.md +141 -141
  11. package/template/.claude/agents/01-orchestration/task-decomposer.md +121 -121
  12. package/template/.claude/agents/01-orchestration/workflow-router.md +114 -114
  13. package/template/.claude/agents/02-typescript/bun-runtime-expert.md +197 -197
  14. package/template/.claude/agents/02-typescript/esm-resolver.md +193 -193
  15. package/template/.claude/agents/02-typescript/import-alias-enforcer.md +158 -158
  16. package/template/.claude/agents/02-typescript/ts-generics-helper.md +183 -183
  17. package/template/.claude/agents/02-typescript/ts-migration-helper.md +238 -238
  18. package/template/.claude/agents/02-typescript/ts-strict-checker.md +180 -180
  19. package/template/.claude/agents/02-typescript/ts-types-analyzer.md +199 -199
  20. package/template/.claude/agents/02-typescript/type-definition-writer.md +187 -187
  21. package/template/.claude/agents/02-typescript/zod-schema-designer.md +212 -212
  22. package/template/.claude/agents/02-typescript/zod-validator.md +158 -158
  23. package/template/.claude/agents/03-testing/playwright-assertions.md +265 -265
  24. package/template/.claude/agents/03-testing/playwright-e2e.md +247 -247
  25. package/template/.claude/agents/03-testing/playwright-fixtures.md +234 -234
  26. package/template/.claude/agents/03-testing/playwright-multi-viewport.md +256 -256
  27. package/template/.claude/agents/03-testing/playwright-page-objects.md +247 -247
  28. package/template/.claude/agents/03-testing/test-cleanup-manager.md +248 -248
  29. package/template/.claude/agents/03-testing/test-data-generator.md +254 -254
  30. package/template/.claude/agents/03-testing/tester-integration.md +278 -278
  31. package/template/.claude/agents/03-testing/tester-unit.md +207 -207
  32. package/template/.claude/agents/03-testing/vitest-config.md +287 -287
  33. package/template/.claude/agents/04-docker/container-health.md +255 -255
  34. package/template/.claude/agents/04-docker/deployment-validator.md +225 -225
  35. package/template/.claude/agents/04-docker/docker-compose-designer.md +281 -281
  36. package/template/.claude/agents/04-docker/docker-env-manager.md +235 -235
  37. package/template/.claude/agents/04-docker/docker-multi-stage.md +241 -241
  38. package/template/.claude/agents/04-docker/dockerfile-optimizer.md +208 -208
  39. package/template/.claude/agents/05-database/database-seeder.md +273 -273
  40. package/template/.claude/agents/05-database/mongodb-query-optimizer.md +230 -230
  41. package/template/.claude/agents/05-database/mongoose-aggregation.md +306 -306
  42. package/template/.claude/agents/05-database/mongoose-index-optimizer.md +182 -182
  43. package/template/.claude/agents/05-database/mongoose-schema-designer.md +267 -267
  44. package/template/.claude/agents/06-security/auth-session-validator.md +68 -68
  45. package/template/.claude/agents/06-security/input-sanitizer.md +80 -80
  46. package/template/.claude/agents/06-security/owasp-checker.md +97 -97
  47. package/template/.claude/agents/06-security/permission-auditor.md +100 -100
  48. package/template/.claude/agents/06-security/security-auditor.md +84 -84
  49. package/template/.claude/agents/06-security/sensitive-data-scanner.md +83 -83
  50. package/template/.claude/agents/07-documentation/api-documenter.md +136 -136
  51. package/template/.claude/agents/07-documentation/changelog-manager.md +105 -105
  52. package/template/.claude/agents/07-documentation/documenter.md +76 -76
  53. package/template/.claude/agents/07-documentation/domain-updater.md +81 -81
  54. package/template/.claude/agents/07-documentation/jsdoc-generator.md +114 -114
  55. package/template/.claude/agents/07-documentation/readme-generator.md +135 -135
  56. package/template/.claude/agents/08-git/branch-manager.md +58 -58
  57. package/template/.claude/agents/08-git/commit-manager.md +63 -63
  58. package/template/.claude/agents/08-git/pr-creator.md +76 -76
  59. package/template/.claude/agents/09-quality/code-reviewer.md +71 -71
  60. package/template/.claude/agents/09-quality/quality-checker.md +67 -67
  61. package/template/.claude/agents/10-research/best-practices-finder.md +89 -89
  62. package/template/.claude/agents/10-research/competitor-analyzer.md +106 -106
  63. package/template/.claude/agents/10-research/pattern-researcher.md +93 -93
  64. package/template/.claude/agents/10-research/research-cache-manager.md +76 -76
  65. package/template/.claude/agents/10-research/research-web.md +98 -98
  66. package/template/.claude/agents/10-research/tech-evaluator.md +101 -101
  67. package/template/.claude/agents/11-ui-ux/accessibility-auditor.md +136 -136
  68. package/template/.claude/agents/11-ui-ux/design-system-enforcer.md +125 -125
  69. package/template/.claude/agents/11-ui-ux/skeleton-generator.md +118 -118
  70. package/template/.claude/agents/11-ui-ux/ui-desktop.md +132 -132
  71. package/template/.claude/agents/11-ui-ux/ui-mobile.md +98 -98
  72. package/template/.claude/agents/11-ui-ux/ui-tablet.md +110 -110
  73. package/template/.claude/agents/12-performance/api-latency-analyzer.md +156 -156
  74. package/template/.claude/agents/12-performance/bundle-analyzer.md +113 -113
  75. package/template/.claude/agents/12-performance/memory-leak-detector.md +137 -137
  76. package/template/.claude/agents/12-performance/performance-profiler.md +115 -115
  77. package/template/.claude/agents/12-performance/query-optimizer.md +124 -124
  78. package/template/.claude/agents/12-performance/render-optimizer.md +154 -154
  79. package/template/.claude/agents/13-debugging/build-error-fixer.md +207 -207
  80. package/template/.claude/agents/13-debugging/debugger.md +149 -149
  81. package/template/.claude/agents/13-debugging/error-stack-analyzer.md +141 -141
  82. package/template/.claude/agents/13-debugging/network-debugger.md +208 -208
  83. package/template/.claude/agents/13-debugging/runtime-error-fixer.md +181 -181
  84. package/template/.claude/agents/13-debugging/type-error-resolver.md +185 -185
  85. package/template/.claude/agents/14-validation/final-validator.md +93 -93
  86. package/template/.claude/agents/_backup/analyzer.md +134 -134
  87. package/template/.claude/agents/_backup/code-reviewer.md +279 -279
  88. package/template/.claude/agents/_backup/commit-manager.md +219 -219
  89. package/template/.claude/agents/_backup/debugger.md +280 -280
  90. package/template/.claude/agents/_backup/documenter.md +237 -237
  91. package/template/.claude/agents/_backup/domain-updater.md +197 -197
  92. package/template/.claude/agents/_backup/final-validator.md +169 -169
  93. package/template/.claude/agents/_backup/orchestrator.md +149 -149
  94. package/template/.claude/agents/_backup/performance.md +232 -232
  95. package/template/.claude/agents/_backup/quality-checker.md +240 -240
  96. package/template/.claude/agents/_backup/research.md +315 -315
  97. package/template/.claude/agents/_backup/security-auditor.md +192 -192
  98. package/template/.claude/agents/_backup/tester.md +566 -566
  99. package/template/.claude/agents/_backup/ui-ux-reviewer.md +247 -247
  100. package/template/.claude/config/README.md +30 -30
  101. package/template/.claude/config/mcp-config.json +344 -344
  102. package/template/.claude/config/project-config.json +53 -53
  103. package/template/.claude/config/quality-gates.json +46 -46
  104. package/template/.claude/config/security-rules.json +45 -45
  105. package/template/.claude/config/testing-config.json +164 -164
  106. package/template/.claude/hooks/SETUP.md +126 -126
  107. package/template/.claude/hooks/run-hook.ts +176 -176
  108. package/template/.claude/hooks/stop-validator.ts +914 -824
  109. package/template/.claude/hooks/user-prompt-submit.ts +886 -886
  110. package/template/.claude/scripts/mcp-quick-install.ts +151 -151
  111. package/template/.claude/scripts/setup-mcps.ts +651 -651
  112. package/template/.claude/settings.json +275 -275
  113. package/template/.claude/skills/bun-runtime/SKILL.md +430 -430
  114. package/template/.claude/skills/codebase-knowledge/domains/claude-system.md +431 -431
  115. package/template/.claude/skills/codebase-knowledge/domains/mcp-integration.md +295 -295
  116. package/template/.claude/skills/debugging-patterns/SKILL.md +485 -485
  117. package/template/.claude/skills/docker-patterns/SKILL.md +555 -555
  118. package/template/.claude/skills/git-workflow/SKILL.md +454 -454
  119. package/template/.claude/skills/mongoose-patterns/SKILL.md +499 -499
  120. package/template/.claude/skills/nextjs-app-router/SKILL.md +327 -327
  121. package/template/.claude/skills/performance-patterns/SKILL.md +547 -547
  122. package/template/.claude/skills/playwright-automation/SKILL.md +438 -438
  123. package/template/.claude/skills/react-patterns/SKILL.md +389 -389
  124. package/template/.claude/skills/research-cache/SKILL.md +222 -222
  125. package/template/.claude/skills/shadcn-ui/SKILL.md +511 -511
  126. package/template/.claude/skills/tailwind-patterns/SKILL.md +465 -465
  127. package/template/.claude/skills/test-coverage/SKILL.md +467 -467
  128. package/template/.claude/skills/trpc-api/SKILL.md +434 -434
  129. package/template/.claude/skills/typescript-strict/SKILL.md +367 -367
  130. package/template/.claude/skills/zod-validation/SKILL.md +403 -403
  131. package/template/CLAUDE.md +117 -117
@@ -1,467 +1,467 @@
1
- ---
2
- name: test-coverage
3
- description: Manages test coverage with Playwright E2E and Vitest unit tests. Tracks which files need tests, provides templates with fixture-based cleanup, enforces multi-viewport testing and database validation.
4
- allowed-tools: Read, Write, Edit, Bash, Grep, Glob
5
- ---
6
-
7
- # Test Coverage - Testing Management System
8
-
9
- ## Purpose
10
-
11
- This skill manages test coverage with **Playwright E2E** and **Vitest unit tests**:
12
-
13
- - **Detects** new files that need tests
14
- - **Maps** components consuming API routes (tRPC/REST)
15
- - **Tracks** which pages have E2E coverage
16
- - **Generates** test templates with cleanup
17
- - **Validates** real authentication usage (MANDATORY)
18
- - **Ensures** database validation after UI actions
19
- - **Enforces** multi-viewport testing
20
-
21
- ---
22
-
23
- ## CRITICAL RULES
24
-
25
- > **MANDATORY - NO EXCEPTIONS:**
26
-
27
- 1. **CLEANUP ALL TEST DATA** - Use fixture-based tracking
28
- 2. **VERIFY IN DATABASE** - Check DB state after UI actions
29
- 3. **TEST ALL VIEWPORTS** - Desktop, tablet, iPhone SE minimum
30
- 4. **REAL AUTH ONLY** - Never mock authentication
31
- 5. **UNIQUE DATA** - Timestamps in emails/names
32
- 6. **NO SKIP** - Never use `.skip()` or `.only()`
33
-
34
- ---
35
-
36
- ## Test Structure
37
-
38
- ```
39
- tests/
40
- ├── unit/ # Unit tests (Vitest)
41
- │ └── *.test.ts
42
- └── e2e/ # E2E tests (Playwright)
43
- ├── fixtures/
44
- │ ├── index.ts # Custom fixtures (auth, db, cleanup)
45
- │ ├── auth.fixture.ts # Authentication helpers
46
- │ └── db.fixture.ts # Database connection & cleanup
47
- ├── pages/ # Page Object Model
48
- │ ├── base.page.ts # Base page with common methods
49
- │ ├── login.page.ts
50
- │ └── register.page.ts
51
- ├── flows/ # User flow tests
52
- │ ├── auth.spec.ts # Login, register, logout
53
- │ ├── crud.spec.ts # Create, read, update, delete
54
- │ └── permissions.spec.ts
55
- ├── api/ # API-only tests (no UI)
56
- │ ├── rest.spec.ts # REST API tests
57
- │ └── trpc.spec.ts # tRPC API tests
58
- └── playwright.config.ts
59
- ```
60
-
61
- ---
62
-
63
- ## Cleanup Fixture (MANDATORY)
64
-
65
- Every project MUST have cleanup fixtures:
66
-
67
- ```typescript
68
- // tests/e2e/fixtures/index.ts
69
- import { test as base, expect } from '@playwright/test';
70
- import { MongoClient, Db, ObjectId } from 'mongodb';
71
-
72
- type TestFixtures = {
73
- db: Db;
74
- createdIds: Map<string, ObjectId[]>;
75
- trackCreated: (collection: string, id: ObjectId) => void;
76
- };
77
-
78
- export const test = base.extend<TestFixtures>(
79
- {
80
- db: async ({}, use) => {
81
- const client = await MongoClient.connect(process.env.MONGODB_URI!);
82
- const db = client.db();
83
- await use(db);
84
- await client.close();
85
- },
86
-
87
- createdIds: async ({}, use) => {
88
- const ids = new Map<string, ObjectId[]>();
89
- await use(ids);
90
- },
91
-
92
- trackCreated: async ({ createdIds }, use) => {
93
- const track = (collection: string, id: ObjectId) => {
94
- const existing = createdIds.get(collection) || [];
95
- existing.push(id);
96
- createdIds.set(collection, existing);
97
- };
98
- await use(track);
99
- },
100
-
101
- // AUTO-CLEANUP runs EVEN IF test fails
102
- },
103
- async ({ db, createdIds }, use) => {
104
- await use();
105
-
106
- for (const [collection, ids] of createdIds.entries()) {
107
- if (ids.length > 0) {
108
- await db.collection(collection).deleteMany({
109
- _id: { $in: ids },
110
- });
111
- }
112
- }
113
- }
114
- );
115
-
116
- export { expect };
117
- ```
118
-
119
- ---
120
-
121
- ## Auth Helper (MANDATORY)
122
-
123
- ```typescript
124
- // tests/e2e/fixtures/auth.fixture.ts
125
- import { Page } from '@playwright/test';
126
-
127
- export interface TestUser {
128
- name: string;
129
- email: string;
130
- password: string;
131
- }
132
-
133
- export function generateTestUser(): TestUser {
134
- const timestamp = Date.now();
135
- const random = Math.random().toString(36).substring(7);
136
- return {
137
- name: `Test User ${timestamp}`,
138
- email: `testuser_${timestamp}_${random}@test.com`,
139
- password: 'TestPassword123!',
140
- };
141
- }
142
-
143
- export async function registerUser(page: Page, user: TestUser): Promise<void> {
144
- await page.goto('/auth/register');
145
- await page.getByTestId('name-input').fill(user.name);
146
- await page.getByTestId('email-input').fill(user.email);
147
- await page.getByTestId('password-input').fill(user.password);
148
- await page.getByTestId('confirm-password-input').fill(user.password);
149
- await page.getByTestId('submit-button').click();
150
- await page.waitForURL(/\/app/, { timeout: 10000 });
151
- }
152
-
153
- export async function loginUser(page: Page, user: TestUser): Promise<void> {
154
- await page.goto('/auth/login');
155
- await page.getByTestId('email-input').fill(user.email);
156
- await page.getByTestId('password-input').fill(user.password);
157
- await page.getByTestId('submit-button').click();
158
- await page.waitForURL(/\/app/, { timeout: 10000 });
159
- }
160
- ```
161
-
162
- ---
163
-
164
- ## Test Templates
165
-
166
- ### E2E Flow Test (with cleanup)
167
-
168
- ```typescript
169
- import { test, expect } from '../fixtures';
170
- import { generateTestUser, registerUser } from '../fixtures/auth.fixture';
171
-
172
- test.describe('[Feature] Flow', () => {
173
- test('complete user journey', async ({ page, db, trackCreated }) => {
174
- const user = generateTestUser();
175
-
176
- // 1. Register
177
- await registerUser(page, user);
178
-
179
- // 2. Verify in database
180
- const dbUser = await db.collection('users').findOne({
181
- email: user.email,
182
- });
183
- expect(dbUser).toBeTruthy();
184
- trackCreated('users', dbUser!._id); // TRACK FOR CLEANUP
185
-
186
- // 3. Create item
187
- await page.goto('/items/new');
188
- await page.getByTestId('title-input').fill('Test Item');
189
- await page.getByTestId('submit-button').click();
190
-
191
- // 4. Verify item in DB
192
- const item = await db.collection('items').findOne({
193
- userId: dbUser!._id,
194
- });
195
- expect(item).toBeTruthy();
196
- trackCreated('items', item!._id); // TRACK FOR CLEANUP
197
-
198
- // Test continues... cleanup is automatic
199
- });
200
- });
201
- ```
202
-
203
- ### Multi-Viewport Test
204
-
205
- ```typescript
206
- import { test, expect } from '../fixtures';
207
-
208
- test.describe('Responsive Design', () => {
209
- const viewports = [
210
- { name: 'mobile', width: 375, height: 667 },
211
- { name: 'tablet', width: 768, height: 1024 },
212
- { name: 'desktop', width: 1280, height: 800 },
213
- ];
214
-
215
- for (const viewport of viewports) {
216
- test(`layout works on ${viewport.name}`, async ({ page }) => {
217
- await page.setViewportSize(viewport);
218
- await page.goto('/');
219
-
220
- if (viewport.width < 768) {
221
- // Mobile: hamburger menu
222
- await expect(page.getByTestId('hamburger-menu')).toBeVisible();
223
- await expect(page.getByTestId('sidebar')).toBeHidden();
224
- } else {
225
- // Desktop: sidebar visible
226
- await expect(page.getByTestId('sidebar')).toBeVisible();
227
- }
228
- });
229
- }
230
- });
231
- ```
232
-
233
- ### API Test (REST)
234
-
235
- ```typescript
236
- import { test, expect } from '@playwright/test';
237
-
238
- test.describe('REST API', () => {
239
- test('requires authentication', async ({ request }) => {
240
- const response = await request.get('/api/users');
241
- expect(response.status()).toBe(401);
242
- });
243
-
244
- test('validates input', async ({ request }) => {
245
- const response = await request.post('/api/users', {
246
- data: { email: 'invalid' },
247
- });
248
- expect(response.status()).toBe(400);
249
- });
250
- });
251
- ```
252
-
253
- ### API Test (tRPC)
254
-
255
- ```typescript
256
- import { test, expect } from '@playwright/test';
257
-
258
- test.describe('tRPC API', () => {
259
- test('query without auth fails', async ({ request }) => {
260
- const response = await request.get('/api/trpc/user.me');
261
- expect(response.status()).toBe(401);
262
- });
263
-
264
- test('mutation validates input', async ({ request }) => {
265
- const response = await request.post('/api/trpc/user.create', {
266
- data: { json: { name: '' } },
267
- });
268
- const body = await response.json();
269
- expect(body.error).toBeDefined();
270
- });
271
- });
272
- ```
273
-
274
- ### Security Test
275
-
276
- ```typescript
277
- import { test, expect } from '../fixtures';
278
-
279
- test.describe('Security - Forbidden Requests', () => {
280
- test('cannot access other users data', async ({ page, db }) => {
281
- const userA = await createTestUser(db);
282
- const userB = await createTestUser(db);
283
-
284
- await loginAs(page, userA);
285
-
286
- // Try to access user B's data
287
- const response = await page.request.get(`/api/users/${userB._id}`);
288
- expect(response.status()).toBe(403);
289
-
290
- // Verify nothing changed in DB
291
- const unchanged = await db.collection('users').findOne({
292
- _id: userB._id,
293
- });
294
- expect(unchanged).toEqual(userB);
295
- });
296
- });
297
- ```
298
-
299
- ### Unit Test
300
-
301
- ```typescript
302
- import { describe, it, expect } from 'vitest';
303
-
304
- describe('[Feature]', () => {
305
- describe('success cases', () => {
306
- it('should [expected behavior] when [condition]', () => {
307
- // Arrange
308
- // Act
309
- // Assert
310
- });
311
- });
312
-
313
- describe('error cases', () => {
314
- it('should throw when [invalid condition]', () => {
315
- expect(() => fn(invalid)).toThrow();
316
- });
317
- });
318
- });
319
- ```
320
-
321
- ---
322
-
323
- ## Files That NEED Tests
324
-
325
- | Type | Location | Test Expected | Required |
326
- | --------- | --------------------- | --------------------------- | -------------- |
327
- | API Route | `server/routers/*.ts` | `tests/unit/*.test.ts` | **YES** |
328
- | API Route | `app/api/**/*.ts` | `tests/e2e/api/*.spec.ts` | **YES** |
329
- | Model | `server/models/*.ts` | `tests/unit/*.test.ts` | **YES** |
330
- | Page | `app/**/page.tsx` | `tests/e2e/flows/*.spec.ts` | **YES** |
331
- | Component | `components/**/*.tsx` | `tests/e2e/*.spec.ts` | If interactive |
332
- | Hook | `hooks/*.ts` | `tests/unit/*.test.ts` | YES |
333
- | Util | `lib/*.ts` | `tests/unit/*.test.ts` | If exported |
334
-
335
- ---
336
-
337
- ## Required Flows (E2E)
338
-
339
- Every app MUST have tests for:
340
-
341
- - [ ] **Registration** - Create new user, verify in DB
342
- - [ ] **Login/Logout** - Auth state changes correctly
343
- - [ ] **CRUD Create** - Item created, visible, in DB
344
- - [ ] **CRUD Read** - Item displayed correctly
345
- - [ ] **CRUD Update** - Item updated, changes in DB
346
- - [ ] **CRUD Delete** - Item removed from DB
347
- - [ ] **Permissions** - Forbidden requests blocked
348
- - [ ] **Responsive** - Works on all viewports
349
-
350
- ---
351
-
352
- ## Required data-testid
353
-
354
- ```html
355
- <!-- Forms -->
356
- <input data-testid="name-input" />
357
- <input data-testid="email-input" />
358
- <input data-testid="password-input" />
359
- <input data-testid="confirm-password-input" />
360
- <button data-testid="submit-button" />
361
-
362
- <!-- Feedback -->
363
- <div data-testid="error-message" />
364
- <div data-testid="success-message" />
365
- <div data-testid="loading-spinner" />
366
-
367
- <!-- Navigation -->
368
- <nav data-testid="sidebar" />
369
- <button data-testid="hamburger-menu" />
370
- <nav data-testid="mobile-nav" />
371
- <button data-testid="logout-button" />
372
-
373
- <!-- Actions -->
374
- <button data-testid="delete-button" />
375
- <button data-testid="edit-button" />
376
- <button data-testid="confirm-delete" />
377
- ```
378
-
379
- ---
380
-
381
- ## Playwright Commands
382
-
383
- ```bash
384
- # Install
385
- bun add -D @playwright/test
386
- bunx playwright install
387
-
388
- # Run
389
- bunx playwright test # All tests
390
- bunx playwright test --ui # UI mode (recommended)
391
- bunx playwright test --headed # See browser
392
- bunx playwright test --debug # Debug mode
393
-
394
- # Specific
395
- bunx playwright test flows/auth # Specific folder
396
- bunx playwright test --project="iPhone SE" # Specific viewport
397
-
398
- # Reports
399
- bunx playwright show-report
400
- ```
401
-
402
- ---
403
-
404
- ## Checklist
405
-
406
- ### Before Commit
407
-
408
- - [ ] All new features have E2E tests?
409
- - [ ] Tests use fixtures for cleanup?
410
- - [ ] All created data is tracked and cleaned?
411
- - [ ] Database state verified after UI actions?
412
- - [ ] Tests run on all viewports?
413
- - [ ] Forbidden requests tested?
414
- - [ ] No `.skip()` in tests?
415
- - [ ] `bunx playwright test` passes?
416
- - [ ] `bun run test` passes?
417
-
418
- ---
419
-
420
- ## FORBIDDEN (Never Do)
421
-
422
- ```typescript
423
- // WRONG - Skipping tests
424
- test.skip("should work when authenticated", ...);
425
-
426
- // WRONG - Mocking auth
427
- const mockAuth = () => { /* fake */ };
428
-
429
- // WRONG - Fixed test user
430
- const testUser = { email: "test@test.com" };
431
-
432
- // WRONG - No cleanup
433
- const user = await db.create({ ... }); // Orphaned!
434
-
435
- // WRONG - No DB validation
436
- await page.click('submit');
437
- // Just trust the UI? NO!
438
- ```
439
-
440
- ---
441
-
442
- ## Progressive Disclosure
443
-
444
- For detailed patterns and templates, see:
445
-
446
- - **[reference/playwright-patterns.md](reference/playwright-patterns.md)** - Page Object Model, fixtures, API testing
447
- - **[scripts/coverage-check.sh](scripts/coverage-check.sh)** - Coverage threshold checker
448
-
449
- ### Quick Commands
450
-
451
- ```bash
452
- # Check coverage meets threshold
453
- bash .claude/skills/test-coverage/scripts/coverage-check.sh 80
454
-
455
- # Run E2E tests
456
- bunx playwright test
457
-
458
- # Run with UI
459
- bunx playwright test --ui
460
- ```
461
-
462
- ---
463
-
464
- ## Version
465
-
466
- - **v3.1.0** - Added progressive disclosure with reference files and scripts
467
- - **v3.0.0** - Complete E2E architecture with cleanup, DB validation, multi-viewport
1
+ ---
2
+ name: test-coverage
3
+ description: Manages test coverage with Playwright E2E and Vitest unit tests. Tracks which files need tests, provides templates with fixture-based cleanup, enforces multi-viewport testing and database validation.
4
+ allowed-tools: Read, Write, Edit, Bash, Grep, Glob
5
+ ---
6
+
7
+ # Test Coverage - Testing Management System
8
+
9
+ ## Purpose
10
+
11
+ This skill manages test coverage with **Playwright E2E** and **Vitest unit tests**:
12
+
13
+ - **Detects** new files that need tests
14
+ - **Maps** components consuming API routes (tRPC/REST)
15
+ - **Tracks** which pages have E2E coverage
16
+ - **Generates** test templates with cleanup
17
+ - **Validates** real authentication usage (MANDATORY)
18
+ - **Ensures** database validation after UI actions
19
+ - **Enforces** multi-viewport testing
20
+
21
+ ---
22
+
23
+ ## CRITICAL RULES
24
+
25
+ > **MANDATORY - NO EXCEPTIONS:**
26
+
27
+ 1. **CLEANUP ALL TEST DATA** - Use fixture-based tracking
28
+ 2. **VERIFY IN DATABASE** - Check DB state after UI actions
29
+ 3. **TEST ALL VIEWPORTS** - Desktop, tablet, iPhone SE minimum
30
+ 4. **REAL AUTH ONLY** - Never mock authentication
31
+ 5. **UNIQUE DATA** - Timestamps in emails/names
32
+ 6. **NO SKIP** - Never use `.skip()` or `.only()`
33
+
34
+ ---
35
+
36
+ ## Test Structure
37
+
38
+ ```
39
+ tests/
40
+ ├── unit/ # Unit tests (Vitest)
41
+ │ └── *.test.ts
42
+ └── e2e/ # E2E tests (Playwright)
43
+ ├── fixtures/
44
+ │ ├── index.ts # Custom fixtures (auth, db, cleanup)
45
+ │ ├── auth.fixture.ts # Authentication helpers
46
+ │ └── db.fixture.ts # Database connection & cleanup
47
+ ├── pages/ # Page Object Model
48
+ │ ├── base.page.ts # Base page with common methods
49
+ │ ├── login.page.ts
50
+ │ └── register.page.ts
51
+ ├── flows/ # User flow tests
52
+ │ ├── auth.spec.ts # Login, register, logout
53
+ │ ├── crud.spec.ts # Create, read, update, delete
54
+ │ └── permissions.spec.ts
55
+ ├── api/ # API-only tests (no UI)
56
+ │ ├── rest.spec.ts # REST API tests
57
+ │ └── trpc.spec.ts # tRPC API tests
58
+ └── playwright.config.ts
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Cleanup Fixture (MANDATORY)
64
+
65
+ Every project MUST have cleanup fixtures:
66
+
67
+ ```typescript
68
+ // tests/e2e/fixtures/index.ts
69
+ import { test as base, expect } from '@playwright/test';
70
+ import { MongoClient, Db, ObjectId } from 'mongodb';
71
+
72
+ type TestFixtures = {
73
+ db: Db;
74
+ createdIds: Map<string, ObjectId[]>;
75
+ trackCreated: (collection: string, id: ObjectId) => void;
76
+ };
77
+
78
+ export const test = base.extend<TestFixtures>(
79
+ {
80
+ db: async ({}, use) => {
81
+ const client = await MongoClient.connect(process.env.MONGODB_URI!);
82
+ const db = client.db();
83
+ await use(db);
84
+ await client.close();
85
+ },
86
+
87
+ createdIds: async ({}, use) => {
88
+ const ids = new Map<string, ObjectId[]>();
89
+ await use(ids);
90
+ },
91
+
92
+ trackCreated: async ({ createdIds }, use) => {
93
+ const track = (collection: string, id: ObjectId) => {
94
+ const existing = createdIds.get(collection) || [];
95
+ existing.push(id);
96
+ createdIds.set(collection, existing);
97
+ };
98
+ await use(track);
99
+ },
100
+
101
+ // AUTO-CLEANUP runs EVEN IF test fails
102
+ },
103
+ async ({ db, createdIds }, use) => {
104
+ await use();
105
+
106
+ for (const [collection, ids] of createdIds.entries()) {
107
+ if (ids.length > 0) {
108
+ await db.collection(collection).deleteMany({
109
+ _id: { $in: ids },
110
+ });
111
+ }
112
+ }
113
+ }
114
+ );
115
+
116
+ export { expect };
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Auth Helper (MANDATORY)
122
+
123
+ ```typescript
124
+ // tests/e2e/fixtures/auth.fixture.ts
125
+ import { Page } from '@playwright/test';
126
+
127
+ export interface TestUser {
128
+ name: string;
129
+ email: string;
130
+ password: string;
131
+ }
132
+
133
+ export function generateTestUser(): TestUser {
134
+ const timestamp = Date.now();
135
+ const random = Math.random().toString(36).substring(7);
136
+ return {
137
+ name: `Test User ${timestamp}`,
138
+ email: `testuser_${timestamp}_${random}@test.com`,
139
+ password: 'TestPassword123!',
140
+ };
141
+ }
142
+
143
+ export async function registerUser(page: Page, user: TestUser): Promise<void> {
144
+ await page.goto('/auth/register');
145
+ await page.getByTestId('name-input').fill(user.name);
146
+ await page.getByTestId('email-input').fill(user.email);
147
+ await page.getByTestId('password-input').fill(user.password);
148
+ await page.getByTestId('confirm-password-input').fill(user.password);
149
+ await page.getByTestId('submit-button').click();
150
+ await page.waitForURL(/\/app/, { timeout: 10000 });
151
+ }
152
+
153
+ export async function loginUser(page: Page, user: TestUser): Promise<void> {
154
+ await page.goto('/auth/login');
155
+ await page.getByTestId('email-input').fill(user.email);
156
+ await page.getByTestId('password-input').fill(user.password);
157
+ await page.getByTestId('submit-button').click();
158
+ await page.waitForURL(/\/app/, { timeout: 10000 });
159
+ }
160
+ ```
161
+
162
+ ---
163
+
164
+ ## Test Templates
165
+
166
+ ### E2E Flow Test (with cleanup)
167
+
168
+ ```typescript
169
+ import { test, expect } from '../fixtures';
170
+ import { generateTestUser, registerUser } from '../fixtures/auth.fixture';
171
+
172
+ test.describe('[Feature] Flow', () => {
173
+ test('complete user journey', async ({ page, db, trackCreated }) => {
174
+ const user = generateTestUser();
175
+
176
+ // 1. Register
177
+ await registerUser(page, user);
178
+
179
+ // 2. Verify in database
180
+ const dbUser = await db.collection('users').findOne({
181
+ email: user.email,
182
+ });
183
+ expect(dbUser).toBeTruthy();
184
+ trackCreated('users', dbUser!._id); // TRACK FOR CLEANUP
185
+
186
+ // 3. Create item
187
+ await page.goto('/items/new');
188
+ await page.getByTestId('title-input').fill('Test Item');
189
+ await page.getByTestId('submit-button').click();
190
+
191
+ // 4. Verify item in DB
192
+ const item = await db.collection('items').findOne({
193
+ userId: dbUser!._id,
194
+ });
195
+ expect(item).toBeTruthy();
196
+ trackCreated('items', item!._id); // TRACK FOR CLEANUP
197
+
198
+ // Test continues... cleanup is automatic
199
+ });
200
+ });
201
+ ```
202
+
203
+ ### Multi-Viewport Test
204
+
205
+ ```typescript
206
+ import { test, expect } from '../fixtures';
207
+
208
+ test.describe('Responsive Design', () => {
209
+ const viewports = [
210
+ { name: 'mobile', width: 375, height: 667 },
211
+ { name: 'tablet', width: 768, height: 1024 },
212
+ { name: 'desktop', width: 1280, height: 800 },
213
+ ];
214
+
215
+ for (const viewport of viewports) {
216
+ test(`layout works on ${viewport.name}`, async ({ page }) => {
217
+ await page.setViewportSize(viewport);
218
+ await page.goto('/');
219
+
220
+ if (viewport.width < 768) {
221
+ // Mobile: hamburger menu
222
+ await expect(page.getByTestId('hamburger-menu')).toBeVisible();
223
+ await expect(page.getByTestId('sidebar')).toBeHidden();
224
+ } else {
225
+ // Desktop: sidebar visible
226
+ await expect(page.getByTestId('sidebar')).toBeVisible();
227
+ }
228
+ });
229
+ }
230
+ });
231
+ ```
232
+
233
+ ### API Test (REST)
234
+
235
+ ```typescript
236
+ import { test, expect } from '@playwright/test';
237
+
238
+ test.describe('REST API', () => {
239
+ test('requires authentication', async ({ request }) => {
240
+ const response = await request.get('/api/users');
241
+ expect(response.status()).toBe(401);
242
+ });
243
+
244
+ test('validates input', async ({ request }) => {
245
+ const response = await request.post('/api/users', {
246
+ data: { email: 'invalid' },
247
+ });
248
+ expect(response.status()).toBe(400);
249
+ });
250
+ });
251
+ ```
252
+
253
+ ### API Test (tRPC)
254
+
255
+ ```typescript
256
+ import { test, expect } from '@playwright/test';
257
+
258
+ test.describe('tRPC API', () => {
259
+ test('query without auth fails', async ({ request }) => {
260
+ const response = await request.get('/api/trpc/user.me');
261
+ expect(response.status()).toBe(401);
262
+ });
263
+
264
+ test('mutation validates input', async ({ request }) => {
265
+ const response = await request.post('/api/trpc/user.create', {
266
+ data: { json: { name: '' } },
267
+ });
268
+ const body = await response.json();
269
+ expect(body.error).toBeDefined();
270
+ });
271
+ });
272
+ ```
273
+
274
+ ### Security Test
275
+
276
+ ```typescript
277
+ import { test, expect } from '../fixtures';
278
+
279
+ test.describe('Security - Forbidden Requests', () => {
280
+ test('cannot access other users data', async ({ page, db }) => {
281
+ const userA = await createTestUser(db);
282
+ const userB = await createTestUser(db);
283
+
284
+ await loginAs(page, userA);
285
+
286
+ // Try to access user B's data
287
+ const response = await page.request.get(`/api/users/${userB._id}`);
288
+ expect(response.status()).toBe(403);
289
+
290
+ // Verify nothing changed in DB
291
+ const unchanged = await db.collection('users').findOne({
292
+ _id: userB._id,
293
+ });
294
+ expect(unchanged).toEqual(userB);
295
+ });
296
+ });
297
+ ```
298
+
299
+ ### Unit Test
300
+
301
+ ```typescript
302
+ import { describe, it, expect } from 'vitest';
303
+
304
+ describe('[Feature]', () => {
305
+ describe('success cases', () => {
306
+ it('should [expected behavior] when [condition]', () => {
307
+ // Arrange
308
+ // Act
309
+ // Assert
310
+ });
311
+ });
312
+
313
+ describe('error cases', () => {
314
+ it('should throw when [invalid condition]', () => {
315
+ expect(() => fn(invalid)).toThrow();
316
+ });
317
+ });
318
+ });
319
+ ```
320
+
321
+ ---
322
+
323
+ ## Files That NEED Tests
324
+
325
+ | Type | Location | Test Expected | Required |
326
+ | --------- | --------------------- | --------------------------- | -------------- |
327
+ | API Route | `server/routers/*.ts` | `tests/unit/*.test.ts` | **YES** |
328
+ | API Route | `app/api/**/*.ts` | `tests/e2e/api/*.spec.ts` | **YES** |
329
+ | Model | `server/models/*.ts` | `tests/unit/*.test.ts` | **YES** |
330
+ | Page | `app/**/page.tsx` | `tests/e2e/flows/*.spec.ts` | **YES** |
331
+ | Component | `components/**/*.tsx` | `tests/e2e/*.spec.ts` | If interactive |
332
+ | Hook | `hooks/*.ts` | `tests/unit/*.test.ts` | YES |
333
+ | Util | `lib/*.ts` | `tests/unit/*.test.ts` | If exported |
334
+
335
+ ---
336
+
337
+ ## Required Flows (E2E)
338
+
339
+ Every app MUST have tests for:
340
+
341
+ - [ ] **Registration** - Create new user, verify in DB
342
+ - [ ] **Login/Logout** - Auth state changes correctly
343
+ - [ ] **CRUD Create** - Item created, visible, in DB
344
+ - [ ] **CRUD Read** - Item displayed correctly
345
+ - [ ] **CRUD Update** - Item updated, changes in DB
346
+ - [ ] **CRUD Delete** - Item removed from DB
347
+ - [ ] **Permissions** - Forbidden requests blocked
348
+ - [ ] **Responsive** - Works on all viewports
349
+
350
+ ---
351
+
352
+ ## Required data-testid
353
+
354
+ ```html
355
+ <!-- Forms -->
356
+ <input data-testid="name-input" />
357
+ <input data-testid="email-input" />
358
+ <input data-testid="password-input" />
359
+ <input data-testid="confirm-password-input" />
360
+ <button data-testid="submit-button" />
361
+
362
+ <!-- Feedback -->
363
+ <div data-testid="error-message" />
364
+ <div data-testid="success-message" />
365
+ <div data-testid="loading-spinner" />
366
+
367
+ <!-- Navigation -->
368
+ <nav data-testid="sidebar" />
369
+ <button data-testid="hamburger-menu" />
370
+ <nav data-testid="mobile-nav" />
371
+ <button data-testid="logout-button" />
372
+
373
+ <!-- Actions -->
374
+ <button data-testid="delete-button" />
375
+ <button data-testid="edit-button" />
376
+ <button data-testid="confirm-delete" />
377
+ ```
378
+
379
+ ---
380
+
381
+ ## Playwright Commands
382
+
383
+ ```bash
384
+ # Install
385
+ bun add -D @playwright/test
386
+ bunx playwright install
387
+
388
+ # Run
389
+ bunx playwright test # All tests
390
+ bunx playwright test --ui # UI mode (recommended)
391
+ bunx playwright test --headed # See browser
392
+ bunx playwright test --debug # Debug mode
393
+
394
+ # Specific
395
+ bunx playwright test flows/auth # Specific folder
396
+ bunx playwright test --project="iPhone SE" # Specific viewport
397
+
398
+ # Reports
399
+ bunx playwright show-report
400
+ ```
401
+
402
+ ---
403
+
404
+ ## Checklist
405
+
406
+ ### Before Commit
407
+
408
+ - [ ] All new features have E2E tests?
409
+ - [ ] Tests use fixtures for cleanup?
410
+ - [ ] All created data is tracked and cleaned?
411
+ - [ ] Database state verified after UI actions?
412
+ - [ ] Tests run on all viewports?
413
+ - [ ] Forbidden requests tested?
414
+ - [ ] No `.skip()` in tests?
415
+ - [ ] `bunx playwright test` passes?
416
+ - [ ] `bun run test` passes?
417
+
418
+ ---
419
+
420
+ ## FORBIDDEN (Never Do)
421
+
422
+ ```typescript
423
+ // WRONG - Skipping tests
424
+ test.skip("should work when authenticated", ...);
425
+
426
+ // WRONG - Mocking auth
427
+ const mockAuth = () => { /* fake */ };
428
+
429
+ // WRONG - Fixed test user
430
+ const testUser = { email: "test@test.com" };
431
+
432
+ // WRONG - No cleanup
433
+ const user = await db.create({ ... }); // Orphaned!
434
+
435
+ // WRONG - No DB validation
436
+ await page.click('submit');
437
+ // Just trust the UI? NO!
438
+ ```
439
+
440
+ ---
441
+
442
+ ## Progressive Disclosure
443
+
444
+ For detailed patterns and templates, see:
445
+
446
+ - **[reference/playwright-patterns.md](reference/playwright-patterns.md)** - Page Object Model, fixtures, API testing
447
+ - **[scripts/coverage-check.sh](scripts/coverage-check.sh)** - Coverage threshold checker
448
+
449
+ ### Quick Commands
450
+
451
+ ```bash
452
+ # Check coverage meets threshold
453
+ bash .claude/skills/test-coverage/scripts/coverage-check.sh 80
454
+
455
+ # Run E2E tests
456
+ bunx playwright test
457
+
458
+ # Run with UI
459
+ bunx playwright test --ui
460
+ ```
461
+
462
+ ---
463
+
464
+ ## Version
465
+
466
+ - **v3.1.0** - Added progressive disclosure with reference files and scripts
467
+ - **v3.0.0** - Complete E2E architecture with cleanup, DB validation, multi-viewport