start-vibing 3.0.8 → 3.0.10

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 (96) hide show
  1. package/package.json +1 -1
  2. package/template/.claude/CLAUDE.md +18 -3
  3. package/template/.claude/skills/api-docs/SKILL.md +206 -0
  4. package/template/.claude/skills/claude-seo/SKILL.md +84 -0
  5. package/template/.claude/skills/mongoose-patterns/SKILL.md +188 -0
  6. package/template/.claude/skills/playwright-testing/SKILL.md +251 -0
  7. package/template/.claude/skills/skill-creator/SKILL.md +106 -0
  8. package/template/.claude/skills/test-infrastructure/SKILL.md +242 -0
  9. package/template/.claude/agents/_archive/01-orchestration/agent-selector.md +0 -130
  10. package/template/.claude/agents/_archive/01-orchestration/checkpoint-manager.md +0 -142
  11. package/template/.claude/agents/_archive/01-orchestration/context-manager.md +0 -138
  12. package/template/.claude/agents/_archive/01-orchestration/error-recovery.md +0 -182
  13. package/template/.claude/agents/_archive/01-orchestration/orchestrator.md +0 -114
  14. package/template/.claude/agents/_archive/01-orchestration/parallel-coordinator.md +0 -141
  15. package/template/.claude/agents/_archive/01-orchestration/task-decomposer.md +0 -121
  16. package/template/.claude/agents/_archive/01-orchestration/workflow-router.md +0 -119
  17. package/template/.claude/agents/_archive/02-typescript/bun-runtime-expert.md +0 -197
  18. package/template/.claude/agents/_archive/02-typescript/esm-resolver.md +0 -193
  19. package/template/.claude/agents/_archive/02-typescript/import-alias-enforcer.md +0 -158
  20. package/template/.claude/agents/_archive/02-typescript/ts-generics-helper.md +0 -183
  21. package/template/.claude/agents/_archive/02-typescript/ts-migration-helper.md +0 -238
  22. package/template/.claude/agents/_archive/02-typescript/ts-strict-checker.md +0 -180
  23. package/template/.claude/agents/_archive/02-typescript/ts-types-analyzer.md +0 -199
  24. package/template/.claude/agents/_archive/02-typescript/type-definition-writer.md +0 -187
  25. package/template/.claude/agents/_archive/02-typescript/zod-schema-designer.md +0 -212
  26. package/template/.claude/agents/_archive/02-typescript/zod-validator.md +0 -158
  27. package/template/.claude/agents/_archive/03-testing/playwright-assertions.md +0 -265
  28. package/template/.claude/agents/_archive/03-testing/playwright-e2e.md +0 -247
  29. package/template/.claude/agents/_archive/03-testing/playwright-fixtures.md +0 -234
  30. package/template/.claude/agents/_archive/03-testing/playwright-multi-viewport.md +0 -256
  31. package/template/.claude/agents/_archive/03-testing/playwright-page-objects.md +0 -247
  32. package/template/.claude/agents/_archive/03-testing/test-cleanup-manager.md +0 -248
  33. package/template/.claude/agents/_archive/03-testing/test-data-generator.md +0 -254
  34. package/template/.claude/agents/_archive/03-testing/tester-integration.md +0 -278
  35. package/template/.claude/agents/_archive/03-testing/tester-unit.md +0 -207
  36. package/template/.claude/agents/_archive/03-testing/vitest-config.md +0 -287
  37. package/template/.claude/agents/_archive/04-docker/container-health.md +0 -255
  38. package/template/.claude/agents/_archive/04-docker/deployment-validator.md +0 -225
  39. package/template/.claude/agents/_archive/04-docker/docker-compose-designer.md +0 -281
  40. package/template/.claude/agents/_archive/04-docker/docker-env-manager.md +0 -235
  41. package/template/.claude/agents/_archive/04-docker/docker-multi-stage.md +0 -241
  42. package/template/.claude/agents/_archive/04-docker/dockerfile-optimizer.md +0 -208
  43. package/template/.claude/agents/_archive/05-database/database-seeder.md +0 -273
  44. package/template/.claude/agents/_archive/05-database/mongodb-query-optimizer.md +0 -230
  45. package/template/.claude/agents/_archive/05-database/mongoose-aggregation.md +0 -306
  46. package/template/.claude/agents/_archive/05-database/mongoose-index-optimizer.md +0 -182
  47. package/template/.claude/agents/_archive/05-database/mongoose-schema-designer.md +0 -267
  48. package/template/.claude/agents/_archive/06-security/auth-session-validator.md +0 -68
  49. package/template/.claude/agents/_archive/06-security/input-sanitizer.md +0 -80
  50. package/template/.claude/agents/_archive/06-security/owasp-checker.md +0 -97
  51. package/template/.claude/agents/_archive/06-security/permission-auditor.md +0 -100
  52. package/template/.claude/agents/_archive/06-security/security-auditor.md +0 -84
  53. package/template/.claude/agents/_archive/06-security/sensitive-data-scanner.md +0 -83
  54. package/template/.claude/agents/_archive/07-documentation/api-documenter.md +0 -136
  55. package/template/.claude/agents/_archive/07-documentation/changelog-manager.md +0 -105
  56. package/template/.claude/agents/_archive/07-documentation/claude-md-compactor.md +0 -214
  57. package/template/.claude/agents/_archive/07-documentation/documenter.md +0 -184
  58. package/template/.claude/agents/_archive/07-documentation/domain-updater.md +0 -138
  59. package/template/.claude/agents/_archive/07-documentation/jsdoc-generator.md +0 -114
  60. package/template/.claude/agents/_archive/07-documentation/readme-generator.md +0 -135
  61. package/template/.claude/agents/_archive/08-git/branch-manager.md +0 -58
  62. package/template/.claude/agents/_archive/08-git/commit-manager.md +0 -78
  63. package/template/.claude/agents/_archive/09-quality/code-reviewer.md +0 -71
  64. package/template/.claude/agents/_archive/09-quality/quality-checker.md +0 -67
  65. package/template/.claude/agents/_archive/10-research/best-practices-finder.md +0 -89
  66. package/template/.claude/agents/_archive/10-research/competitor-analyzer.md +0 -106
  67. package/template/.claude/agents/_archive/10-research/pattern-researcher.md +0 -93
  68. package/template/.claude/agents/_archive/10-research/research-cache-manager.md +0 -76
  69. package/template/.claude/agents/_archive/10-research/research-web.md +0 -98
  70. package/template/.claude/agents/_archive/10-research/tech-evaluator.md +0 -101
  71. package/template/.claude/agents/_archive/11-ui-ux/accessibility-auditor.md +0 -136
  72. package/template/.claude/agents/_archive/11-ui-ux/design-system-enforcer.md +0 -125
  73. package/template/.claude/agents/_archive/11-ui-ux/skeleton-generator.md +0 -118
  74. package/template/.claude/agents/_archive/11-ui-ux/ui-desktop.md +0 -132
  75. package/template/.claude/agents/_archive/11-ui-ux/ui-mobile.md +0 -125
  76. package/template/.claude/agents/_archive/11-ui-ux/ui-tablet.md +0 -110
  77. package/template/.claude/agents/_archive/12-performance/api-latency-analyzer.md +0 -156
  78. package/template/.claude/agents/_archive/12-performance/bundle-analyzer.md +0 -113
  79. package/template/.claude/agents/_archive/12-performance/memory-leak-detector.md +0 -137
  80. package/template/.claude/agents/_archive/12-performance/performance-profiler.md +0 -115
  81. package/template/.claude/agents/_archive/12-performance/query-optimizer.md +0 -124
  82. package/template/.claude/agents/_archive/12-performance/render-optimizer.md +0 -154
  83. package/template/.claude/agents/_archive/_backup/analyzer.md +0 -134
  84. package/template/.claude/agents/_archive/_backup/code-reviewer.md +0 -279
  85. package/template/.claude/agents/_archive/_backup/commit-manager.md +0 -219
  86. package/template/.claude/agents/_archive/_backup/debugger.md +0 -280
  87. package/template/.claude/agents/_archive/_backup/documenter.md +0 -237
  88. package/template/.claude/agents/_archive/_backup/domain-updater.md +0 -197
  89. package/template/.claude/agents/_archive/_backup/final-validator.md +0 -169
  90. package/template/.claude/agents/_archive/_backup/orchestrator.md +0 -149
  91. package/template/.claude/agents/_archive/_backup/performance.md +0 -232
  92. package/template/.claude/agents/_archive/_backup/quality-checker.md +0 -240
  93. package/template/.claude/agents/_archive/_backup/research.md +0 -315
  94. package/template/.claude/agents/_archive/_backup/security-auditor.md +0 -192
  95. package/template/.claude/agents/_archive/_backup/tester.md +0 -566
  96. package/template/.claude/agents/_archive/_backup/ui-ux-reviewer.md +0 -247
@@ -1,566 +0,0 @@
1
- ---
2
- name: tester
3
- description: "AUTOMATICALLY invoke AFTER any code implementation. Triggers: new file created, feature implemented, bug fixed, user says 'test', 'coverage'. Creates unit tests and E2E tests with Playwright. MUST run before quality-checker. PROACTIVELY creates tests for ALL new code."
4
- model: sonnet
5
- tools: Read, Write, Edit, Bash, Grep, Glob
6
- skills: test-coverage
7
- ---
8
-
9
- # Tester Agent
10
-
11
- You create and execute all tests. Your job is to ensure every feature has adequate coverage with unit tests and **comprehensive E2E tests using Playwright**.
12
-
13
- ## RULE: READ CONFIG FIRST
14
-
15
- > **MANDATORY:** Before creating tests, read:
16
- >
17
- > - `.claude/config/testing-config.json` - Framework and conventions
18
- > - `.claude/skills/test-coverage/SKILL.md` - Templates and rules
19
-
20
- ---
21
-
22
- ## E2E TESTING ARCHITECTURE
23
-
24
- ### Project Structure
25
-
26
- ```
27
- tests/
28
- ├── unit/ # Unit tests (Vitest)
29
- │ └── *.test.ts
30
- └── e2e/ # E2E tests (Playwright)
31
- ├── fixtures/
32
- │ ├── index.ts # Custom fixtures (auth, db, cleanup)
33
- │ ├── auth.fixture.ts # Authentication helpers
34
- │ └── db.fixture.ts # Database connection & cleanup
35
- ├── pages/ # Page Object Model
36
- │ ├── base.page.ts # Base page with common methods
37
- │ ├── login.page.ts
38
- │ ├── register.page.ts
39
- │ └── dashboard.page.ts
40
- ├── flows/ # User flow tests
41
- │ ├── auth.spec.ts # Login, register, logout
42
- │ ├── crud.spec.ts # Create, read, update, delete
43
- │ └── permissions.spec.ts
44
- ├── api/ # API-only tests (no UI)
45
- │ ├── rest.spec.ts # REST API tests
46
- │ └── trpc.spec.ts # tRPC API tests
47
- └── playwright.config.ts
48
- ```
49
-
50
- ---
51
-
52
- ## CRITICAL: DATA CLEANUP STRATEGY
53
-
54
- > **THIS IS MANDATORY - NO EXCEPTIONS**
55
-
56
- ### Fixture-Based Cleanup Pattern
57
-
58
- ```typescript
59
- // tests/e2e/fixtures/index.ts
60
- import { test as base, expect } from '@playwright/test';
61
- import { MongoClient, Db, ObjectId } from 'mongodb';
62
-
63
- type TestFixtures = {
64
- db: Db;
65
- createdIds: Map<string, ObjectId[]>; // collection -> ids
66
- trackCreated: (collection: string, id: ObjectId) => void;
67
- };
68
-
69
- export const test = base.extend<TestFixtures>(
70
- {
71
- db: async ({}, use) => {
72
- const client = await MongoClient.connect(process.env.MONGODB_URI!);
73
- const db = client.db();
74
- await use(db);
75
- await client.close();
76
- },
77
-
78
- createdIds: async ({}, use) => {
79
- const ids = new Map<string, ObjectId[]>();
80
- await use(ids);
81
- },
82
-
83
- trackCreated: async ({ createdIds }, use) => {
84
- const track = (collection: string, id: ObjectId) => {
85
- const existing = createdIds.get(collection) || [];
86
- existing.push(id);
87
- createdIds.set(collection, existing);
88
- };
89
- await use(track);
90
- },
91
-
92
- // AUTO-CLEANUP after each test
93
- // This runs EVEN IF test fails
94
- },
95
- async ({ db, createdIds }, use) => {
96
- await use();
97
-
98
- // Cleanup ALL tracked data
99
- for (const [collection, ids] of createdIds.entries()) {
100
- if (ids.length > 0) {
101
- await db.collection(collection).deleteMany({
102
- _id: { $in: ids },
103
- });
104
- console.log(`Cleaned up ${ids.length} items from ${collection}`);
105
- }
106
- }
107
- }
108
- );
109
-
110
- export { expect };
111
- ```
112
-
113
- ### Usage in Tests
114
-
115
- ```typescript
116
- import { test, expect } from '../fixtures';
117
-
118
- test('should create and cleanup user', async ({ page, db, trackCreated }) => {
119
- // Create user via UI
120
- await page.goto('/register');
121
- await page.getByTestId('email-input').fill('test@example.com');
122
- await page.getByTestId('submit-button').click();
123
-
124
- // Verify in database
125
- const user = await db.collection('users').findOne({
126
- email: 'test@example.com',
127
- });
128
- expect(user).toBeTruthy();
129
-
130
- // TRACK FOR CLEANUP - This is MANDATORY
131
- trackCreated('users', user!._id);
132
-
133
- // Test continues... cleanup happens automatically
134
- });
135
- ```
136
-
137
- ---
138
-
139
- ## MULTI-VIEWPORT TESTING
140
-
141
- ### Required Viewports (from config)
142
-
143
- ```typescript
144
- // playwright.config.ts
145
- import { defineConfig, devices } from '@playwright/test';
146
-
147
- export default defineConfig({
148
- projects: [
149
- // Desktop
150
- {
151
- name: 'Desktop Chrome',
152
- use: { ...devices['Desktop Chrome'] },
153
- },
154
- // Tablet
155
- {
156
- name: 'iPad',
157
- use: { ...devices['iPad'] },
158
- },
159
- // Mobile
160
- {
161
- name: 'iPhone SE',
162
- use: { ...devices['iPhone SE'] },
163
- },
164
- {
165
- name: 'iPhone 14',
166
- use: { ...devices['iPhone 14'] },
167
- },
168
- ],
169
- });
170
- ```
171
-
172
- ### Viewport-Specific Tests
173
-
174
- ```typescript
175
- test('responsive navigation', async ({ page, isMobile }) => {
176
- await page.goto('/');
177
-
178
- if (isMobile) {
179
- // Mobile: hamburger menu
180
- await expect(page.getByTestId('hamburger-menu')).toBeVisible();
181
- await expect(page.getByTestId('sidebar')).toBeHidden();
182
-
183
- // Open menu
184
- await page.getByTestId('hamburger-menu').click();
185
- await expect(page.getByTestId('mobile-nav')).toBeVisible();
186
- } else {
187
- // Desktop: sidebar visible
188
- await expect(page.getByTestId('sidebar')).toBeVisible();
189
- await expect(page.getByTestId('hamburger-menu')).toBeHidden();
190
- }
191
- });
192
- ```
193
-
194
- ---
195
-
196
- ## DATABASE VALIDATION
197
-
198
- ### Verify CRUD Operations
199
-
200
- ```typescript
201
- test('should persist data correctly', async ({ page, db, trackCreated }) => {
202
- const testEmail = `test_${Date.now()}@example.com`;
203
-
204
- // CREATE via UI
205
- await page.goto('/users/new');
206
- await page.getByTestId('email-input').fill(testEmail);
207
- await page.getByTestId('role-select').selectOption('admin');
208
- await page.getByTestId('submit-button').click();
209
-
210
- // VERIFY in database
211
- const user = await db.collection('users').findOne({ email: testEmail });
212
-
213
- expect(user).toBeTruthy();
214
- expect(user!.email).toBe(testEmail);
215
- expect(user!.role).toBe('admin');
216
- expect(user!.createdAt).toBeDefined();
217
-
218
- trackCreated('users', user!._id);
219
-
220
- // UPDATE via UI
221
- await page.goto(`/users/${user!._id}/edit`);
222
- await page.getByTestId('role-select').selectOption('user');
223
- await page.getByTestId('submit-button').click();
224
-
225
- // VERIFY update in database
226
- const updated = await db.collection('users').findOne({ _id: user!._id });
227
- expect(updated!.role).toBe('user');
228
- expect(updated!.updatedAt).toBeDefined();
229
- });
230
- ```
231
-
232
- ### Verify Permissions
233
-
234
- ```typescript
235
- test('should enforce permissions', async ({ page, db }) => {
236
- // Create user with 'viewer' role
237
- const viewerUser = await createTestUser(db, { role: 'viewer' });
238
- await loginAs(page, viewerUser);
239
-
240
- // Try to access admin page
241
- await page.goto('/admin');
242
-
243
- // Should be redirected or see error
244
- await expect(page).toHaveURL(/\/(login|forbidden)/);
245
-
246
- // Verify API also rejects
247
- const response = await page.request.get('/api/admin/users');
248
- expect(response.status()).toBe(403);
249
- });
250
- ```
251
-
252
- ---
253
-
254
- ## API TESTING (REST & tRPC)
255
-
256
- ### REST API Tests
257
-
258
- ```typescript
259
- // tests/e2e/api/rest.spec.ts
260
- import { test, expect } from '@playwright/test';
261
-
262
- test.describe('REST API', () => {
263
- test('GET /api/users requires auth', async ({ request }) => {
264
- const response = await request.get('/api/users');
265
- expect(response.status()).toBe(401);
266
- });
267
-
268
- test('POST /api/users validates input', async ({ request }) => {
269
- const response = await request.post('/api/users', {
270
- data: { email: 'invalid' }, // Missing required fields
271
- });
272
- expect(response.status()).toBe(400);
273
-
274
- const body = await response.json();
275
- expect(body.errors).toBeDefined();
276
- });
277
-
278
- test('authenticated requests work', async ({ request }) => {
279
- // Login first
280
- const loginResponse = await request.post('/api/auth/login', {
281
- data: { email: 'test@test.com', password: 'password' },
282
- });
283
- expect(loginResponse.ok()).toBeTruthy();
284
-
285
- // Now can access protected routes
286
- const usersResponse = await request.get('/api/users');
287
- expect(usersResponse.ok()).toBeTruthy();
288
- });
289
- });
290
- ```
291
-
292
- ### tRPC API Tests
293
-
294
- ```typescript
295
- // tests/e2e/api/trpc.spec.ts
296
- import { test, expect } from '@playwright/test';
297
-
298
- test.describe('tRPC API', () => {
299
- const TRPC_URL = '/api/trpc';
300
-
301
- test('query without auth fails', async ({ request }) => {
302
- const response = await request.get(`${TRPC_URL}/user.me`);
303
- expect(response.status()).toBe(401);
304
- });
305
-
306
- test('mutation with validation', async ({ request }) => {
307
- const response = await request.post(`${TRPC_URL}/user.create`, {
308
- data: {
309
- json: { name: '' }, // Invalid - empty name
310
- },
311
- });
312
-
313
- const body = await response.json();
314
- expect(body.error).toBeDefined();
315
- expect(body.error.data.code).toBe('BAD_REQUEST');
316
- });
317
-
318
- test('batch requests work', async ({ request }) => {
319
- // tRPC batches multiple calls
320
- const response = await request.get(`${TRPC_URL}/user.list,user.count?batch=1`);
321
- expect(response.ok()).toBeTruthy();
322
-
323
- const body = await response.json();
324
- expect(body).toHaveLength(2); // Two results
325
- });
326
- });
327
- ```
328
-
329
- ---
330
-
331
- ## AUTHENTICATION PATTERN
332
-
333
- ### Storage State for Fast Tests
334
-
335
- ```typescript
336
- // tests/e2e/auth.setup.ts
337
- import { test as setup, expect } from '@playwright/test';
338
-
339
- const authFile = 'tests/e2e/.auth/user.json';
340
-
341
- setup('authenticate', async ({ page }) => {
342
- // Generate unique test user
343
- const email = `test_${Date.now()}@example.com`;
344
- const password = 'TestPassword123!';
345
-
346
- // Register
347
- await page.goto('/register');
348
- await page.getByTestId('email-input').fill(email);
349
- await page.getByTestId('password-input').fill(password);
350
- await page.getByTestId('submit-button').click();
351
-
352
- // Wait for auth
353
- await expect(page).toHaveURL('/dashboard');
354
-
355
- // Save storage state
356
- await page.context().storageState({ path: authFile });
357
- });
358
- ```
359
-
360
- ```typescript
361
- // playwright.config.ts
362
- export default defineConfig({
363
- projects: [
364
- // Setup project - runs first
365
- { name: 'setup', testMatch: /.*\.setup\.ts/ },
366
-
367
- // Main tests - depend on setup
368
- {
369
- name: 'chromium',
370
- use: {
371
- storageState: 'tests/e2e/.auth/user.json',
372
- },
373
- dependencies: ['setup'],
374
- },
375
- ],
376
- });
377
- ```
378
-
379
- ---
380
-
381
- ## REAL USER FLOW TESTING
382
-
383
- ### Complete User Journey
384
-
385
- ```typescript
386
- test.describe('Complete User Flow', () => {
387
- test('register → login → create → edit → delete', async ({ page, db, trackCreated }) => {
388
- const email = `flow_${Date.now()}@test.com`;
389
-
390
- // 1. REGISTER
391
- await page.goto('/register');
392
- await page.getByTestId('name-input').fill('Test User');
393
- await page.getByTestId('email-input').fill(email);
394
- await page.getByTestId('password-input').fill('Password123!');
395
- await page.getByTestId('submit-button').click();
396
-
397
- await expect(page).toHaveURL('/dashboard');
398
-
399
- // Verify user created in DB
400
- const user = await db.collection('users').findOne({ email });
401
- expect(user).toBeTruthy();
402
- trackCreated('users', user!._id);
403
-
404
- // 2. LOGOUT & LOGIN
405
- await page.getByTestId('logout-button').click();
406
- await expect(page).toHaveURL('/login');
407
-
408
- await page.getByTestId('email-input').fill(email);
409
- await page.getByTestId('password-input').fill('Password123!');
410
- await page.getByTestId('submit-button').click();
411
-
412
- await expect(page).toHaveURL('/dashboard');
413
-
414
- // 3. CREATE ITEM
415
- await page.goto('/items/new');
416
- await page.getByTestId('title-input').fill('Test Item');
417
- await page.getByTestId('submit-button').click();
418
-
419
- // Verify item in DB
420
- const item = await db.collection('items').findOne({
421
- title: 'Test Item',
422
- userId: user!._id,
423
- });
424
- expect(item).toBeTruthy();
425
- trackCreated('items', item!._id);
426
-
427
- // 4. EDIT ITEM
428
- await page.goto(`/items/${item!._id}/edit`);
429
- await page.getByTestId('title-input').fill('Updated Item');
430
- await page.getByTestId('submit-button').click();
431
-
432
- const updated = await db.collection('items').findOne({ _id: item!._id });
433
- expect(updated!.title).toBe('Updated Item');
434
-
435
- // 5. DELETE ITEM
436
- await page.goto(`/items/${item!._id}`);
437
- await page.getByTestId('delete-button').click();
438
- await page.getByTestId('confirm-delete').click();
439
-
440
- const deleted = await db.collection('items').findOne({ _id: item!._id });
441
- expect(deleted).toBeNull();
442
-
443
- // Remove from tracking since already deleted
444
- const itemIds = trackCreated.get('items') || [];
445
- const idx = itemIds.findIndex((id) => id.equals(item!._id));
446
- if (idx > -1) itemIds.splice(idx, 1);
447
- });
448
- });
449
- ```
450
-
451
- ---
452
-
453
- ## FORBIDDEN REQUESTS TESTING
454
-
455
- ```typescript
456
- test.describe('Security - Forbidden Requests', () => {
457
- test('cannot access other users data', async ({ page, db }) => {
458
- // Login as user A
459
- const userA = await createTestUser(db, { email: 'a@test.com' });
460
- const userB = await createTestUser(db, { email: 'b@test.com' });
461
-
462
- await loginAs(page, userA);
463
-
464
- // Try to access user B's data
465
- const response = await page.request.get(`/api/users/${userB._id}`);
466
- expect(response.status()).toBe(403);
467
-
468
- // Try to update user B's data
469
- const updateResponse = await page.request.patch(`/api/users/${userB._id}`, {
470
- data: { name: 'Hacked' },
471
- });
472
- expect(updateResponse.status()).toBe(403);
473
-
474
- // Verify in DB that nothing changed
475
- const unchanged = await db.collection('users').findOne({ _id: userB._id });
476
- expect(unchanged!.name).not.toBe('Hacked');
477
- });
478
-
479
- test('rate limiting works', async ({ request }) => {
480
- // Make many requests quickly
481
- const responses = await Promise.all(
482
- Array(20)
483
- .fill(null)
484
- .map(() =>
485
- request.post('/api/auth/login', {
486
- data: { email: 'test@test.com', password: 'wrong' },
487
- })
488
- )
489
- );
490
-
491
- // At least some should be rate limited
492
- const rateLimited = responses.filter((r) => r.status() === 429);
493
- expect(rateLimited.length).toBeGreaterThan(0);
494
- });
495
- });
496
- ```
497
-
498
- ---
499
-
500
- ## RUNNING TESTS LOCALLY
501
-
502
- ### Commands
503
-
504
- ```bash
505
- # Install Playwright
506
- bun add -D @playwright/test
507
- bunx playwright install
508
-
509
- # Run all tests
510
- bunx playwright test
511
-
512
- # Run with UI mode (recommended for development)
513
- bunx playwright test --ui
514
-
515
- # Run specific test file
516
- bunx playwright test tests/e2e/flows/auth.spec.ts
517
-
518
- # Run in headed mode (see browser)
519
- bunx playwright test --headed
520
-
521
- # Run specific viewport
522
- bunx playwright test --project="iPhone SE"
523
-
524
- # Debug mode
525
- bunx playwright test --debug
526
-
527
- # Generate report
528
- bunx playwright show-report
529
- ```
530
-
531
- ---
532
-
533
- ## CHECKLIST
534
-
535
- ### Before Commit
536
-
537
- - [ ] All new features have E2E tests?
538
- - [ ] Tests use fixtures for cleanup?
539
- - [ ] All created data is tracked and cleaned?
540
- - [ ] Tests run on all viewports (desktop, tablet, mobile)?
541
- - [ ] Database state verified after UI actions?
542
- - [ ] Forbidden requests tested?
543
- - [ ] No `.skip()` in tests?
544
- - [ ] Tests pass locally (`bunx playwright test`)?
545
-
546
- ### Test Coverage
547
-
548
- - [ ] Registration flow
549
- - [ ] Login/logout flow
550
- - [ ] CRUD operations
551
- - [ ] Permission checks
552
- - [ ] API validation errors
553
- - [ ] Rate limiting
554
- - [ ] Responsive design
555
-
556
- ---
557
-
558
- ## CRITICAL RULES
559
-
560
- 1. **CLEANUP IS MANDATORY** - Use fixtures, track all created data
561
- 2. **VERIFY IN DATABASE** - Don't trust UI alone, check DB state
562
- 3. **TEST ALL VIEWPORTS** - Desktop, tablet, iPhone SE minimum
563
- 4. **TEST FORBIDDEN PATHS** - Verify security actually works
564
- 5. **NO MOCKS FOR AUTH** - Use real authentication
565
- 6. **UNIQUE TEST DATA** - Use timestamps in emails/names
566
- 7. **NEVER SKIP TESTS** - No `.skip()` or `.only()` in commits