ai-flow-dev 1.0.1

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 (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +408 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +791 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/fs-utils.d.ts +2 -0
  8. package/dist/fs-utils.d.ts.map +1 -0
  9. package/dist/fs-utils.js +46 -0
  10. package/dist/fs-utils.js.map +1 -0
  11. package/package.json +71 -0
  12. package/prompts/backend/flow-dev-feature.md +1318 -0
  13. package/prompts/backend/flow-dev-fix.md +903 -0
  14. package/prompts/backend/flow-dev-refactor.md +715 -0
  15. package/prompts/backend/flow-dev-review.md +401 -0
  16. package/prompts/backend/flow-dev-work.md +1129 -0
  17. package/prompts/backend/flow-docs-gen-phase-0.md +1840 -0
  18. package/prompts/backend/flow-docs-gen-phase-1.md +435 -0
  19. package/prompts/backend/flow-docs-gen-phase-2.md +460 -0
  20. package/prompts/backend/flow-docs-gen-phase-3.md +684 -0
  21. package/prompts/backend/flow-docs-gen-phase-4.md +516 -0
  22. package/prompts/backend/flow-docs-gen-phase-5.md +637 -0
  23. package/prompts/backend/flow-docs-gen-phase-6.md +465 -0
  24. package/prompts/backend/flow-docs-gen-phase-7.md +1207 -0
  25. package/prompts/backend/flow-docs-gen.md +820 -0
  26. package/prompts/backend/flow-docs-sync.md +526 -0
  27. package/prompts/backend/flow-project-init.md +248 -0
  28. package/prompts/backend/flow-project-roadmap.md +1159 -0
  29. package/prompts/frontend/flow-docs-gen-phase-0.md +494 -0
  30. package/prompts/frontend/flow-docs-gen-phase-1.md +449 -0
  31. package/prompts/frontend/flow-docs-gen-phase-2.md +983 -0
  32. package/prompts/frontend/flow-docs-gen-phase-3.md +685 -0
  33. package/prompts/frontend/flow-docs-gen-phase-4.md +480 -0
  34. package/prompts/frontend/flow-docs-gen-phase-5.md +483 -0
  35. package/prompts/frontend/flow-docs-gen-phase-6.md +570 -0
  36. package/prompts/frontend/flow-docs-gen-phase-7.md +582 -0
  37. package/prompts/frontend/flow-docs-gen.md +413 -0
  38. package/prompts/frontend/flow-docs-sync.md +561 -0
  39. package/prompts/mobile/flow-docs-gen-phase-0.md +387 -0
  40. package/prompts/mobile/flow-docs-gen-phase-1.md +530 -0
  41. package/prompts/mobile/flow-docs-gen-phase-2.md +584 -0
  42. package/prompts/mobile/flow-docs-gen-phase-3.md +659 -0
  43. package/prompts/mobile/flow-docs-gen-phase-4.md +363 -0
  44. package/prompts/mobile/flow-docs-gen-phase-5.md +369 -0
  45. package/prompts/mobile/flow-docs-gen-phase-6.md +490 -0
  46. package/prompts/mobile/flow-docs-gen-phase-7.md +407 -0
  47. package/prompts/mobile/flow-docs-gen.md +430 -0
  48. package/prompts/mobile/flow-docs-sync.md +634 -0
  49. package/templates/backend/.clauderules.template +111 -0
  50. package/templates/backend/.cursorrules.template +102 -0
  51. package/templates/backend/.env.example.template +122 -0
  52. package/templates/backend/README.template.md +200 -0
  53. package/templates/backend/ai-instructions.template.md +354 -0
  54. package/templates/backend/copilot-instructions.template.md +160 -0
  55. package/templates/backend/docs/api.template.md +251 -0
  56. package/templates/backend/docs/architecture.template.md +612 -0
  57. package/templates/backend/docs/business-flows.template.md +109 -0
  58. package/templates/backend/docs/code-standards.template.md +828 -0
  59. package/templates/backend/docs/contributing.template.md +163 -0
  60. package/templates/backend/docs/data-model.template.md +416 -0
  61. package/templates/backend/docs/operations.template.md +591 -0
  62. package/templates/backend/docs/testing.template.md +762 -0
  63. package/templates/backend/project-brief.template.md +176 -0
  64. package/templates/backend/specs/configuration.template.md +133 -0
  65. package/templates/backend/specs/security.template.md +422 -0
  66. package/templates/frontend/README.template.md +121 -0
  67. package/templates/frontend/ai-instructions.template.md +368 -0
  68. package/templates/frontend/docs/api-integration.template.md +390 -0
  69. package/templates/frontend/docs/components.template.md +567 -0
  70. package/templates/frontend/docs/error-handling.template.md +385 -0
  71. package/templates/frontend/docs/operations.template.md +123 -0
  72. package/templates/frontend/docs/performance.template.md +140 -0
  73. package/templates/frontend/docs/pwa.template.md +135 -0
  74. package/templates/frontend/docs/state-management.template.md +394 -0
  75. package/templates/frontend/docs/styling.template.md +779 -0
  76. package/templates/frontend/docs/testing.template.md +736 -0
  77. package/templates/frontend/project-brief.template.md +55 -0
  78. package/templates/frontend/specs/accessibility.template.md +111 -0
  79. package/templates/frontend/specs/configuration.template.md +520 -0
  80. package/templates/frontend/specs/security.template.md +197 -0
  81. package/templates/fullstack/README.template.md +282 -0
  82. package/templates/fullstack/ai-instructions.template.md +487 -0
  83. package/templates/fullstack/project-brief.template.md +197 -0
  84. package/templates/fullstack/specs/configuration.template.md +380 -0
  85. package/templates/mobile/AGENT.template.md +251 -0
  86. package/templates/mobile/README.template.md +195 -0
  87. package/templates/mobile/ai-instructions.template.md +221 -0
  88. package/templates/mobile/docs/app-store.template.md +163 -0
  89. package/templates/mobile/docs/architecture.template.md +100 -0
  90. package/templates/mobile/docs/native-features.template.md +137 -0
  91. package/templates/mobile/docs/navigation.template.md +81 -0
  92. package/templates/mobile/docs/offline-strategy.template.md +90 -0
  93. package/templates/mobile/docs/permissions.template.md +70 -0
  94. package/templates/mobile/docs/state-management.template.md +116 -0
  95. package/templates/mobile/docs/testing.template.md +146 -0
  96. package/templates/mobile/project-brief.template.md +97 -0
  97. package/templates/mobile/specs/build-configuration.template.md +116 -0
  98. package/templates/mobile/specs/deployment.template.md +114 -0
  99. package/templates/shared/AGENT.template.md +252 -0
@@ -0,0 +1,736 @@
1
+ # Testing Strategy
2
+
3
+ > Testing approach and best practices for {{PROJECT_NAME}}
4
+
5
+ ---
6
+
7
+ ## 🎯 Testing Philosophy
8
+
9
+ **Goal:** Ship with confidence through comprehensive automated testing
10
+
11
+ **Principles:**
12
+ 1. **Test user behavior, not implementation** - Tests should reflect how users interact with the app
13
+ 2. **Write tests that give confidence** - Focus on tests that catch real bugs
14
+ 3. **Avoid testing implementation details** - Refactors shouldn't break tests
15
+ 4. **Fast feedback loops** - Unit tests run in milliseconds, E2E in seconds
16
+
17
+ ---
18
+
19
+ ## 🏗️ Testing Pyramid
20
+
21
+ ```
22
+ /\
23
+ /E2E\ ← Few (Critical user journeys)
24
+ /------\
25
+ /Integration\ ← Some (Component interaction, API calls)
26
+ /------------\
27
+ / Unit Tests \ ← Many (Business logic, utilities)
28
+ /----------------\
29
+ ```
30
+
31
+ **Distribution:**
32
+ - **70%** Unit Tests (fast, isolated)
33
+ - **20%** Integration Tests (component + hooks + API)
34
+ - **10%** E2E Tests (full user flows)
35
+
36
+ ---
37
+
38
+ ## 🧪 Testing Stack
39
+
40
+ ### Test Frameworks
41
+
42
+ **Unit & Integration:** {{UNIT_TEST_FRAMEWORK}}
43
+ **Component Testing:** {{COMPONENT_TEST_LIBRARY}}
44
+ **E2E Testing:** {{E2E_FRAMEWORK}}
45
+
46
+ ### Supporting Libraries
47
+
48
+ - **Mocking:** {{MOCKING_LIBRARY}}
49
+ - **Code Coverage:** {{COVERAGE_TOOL}}
50
+ - **Visual Regression:** {{VISUAL_REGRESSION_TOOL}}
51
+
52
+ ---
53
+
54
+ ## 📦 Unit Testing
55
+
56
+ ### What to Unit Test
57
+
58
+ ✅ **DO test:**
59
+ - Pure functions (utilities, helpers)
60
+ - Business logic (validation, calculations)
61
+ - Custom hooks (isolated)
62
+ - Reducers/stores (state logic)
63
+
64
+ ❌ **DON'T test:**
65
+ - Third-party libraries
66
+ - Framework internals
67
+ - Trivial code (getters/setters)
68
+
69
+ ### Unit Test Patterns
70
+
71
+ #### Testing Pure Functions
72
+
73
+ ```typescript
74
+ // utils/formatCurrency.ts
75
+ export const formatCurrency = (amount: number, currency = 'USD'): string => {
76
+ return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(amount);
77
+ };
78
+
79
+ // utils/formatCurrency.test.ts
80
+ import { formatCurrency } from './formatCurrency';
81
+
82
+ describe('formatCurrency', () => {
83
+ it('formats USD correctly', () => {
84
+ expect(formatCurrency(1234.56)).toBe('$1,234.56');
85
+ });
86
+
87
+ it('formats EUR correctly', () => {
88
+ expect(formatCurrency(1234.56, 'EUR')).toBe('€1,234.56');
89
+ });
90
+
91
+ it('handles zero', () => {
92
+ expect(formatCurrency(0)).toBe('$0.00');
93
+ });
94
+
95
+ it('handles negative values', () => {
96
+ expect(formatCurrency(-100)).toBe('-$100.00');
97
+ });
98
+ });
99
+ ```
100
+
101
+ #### Testing Custom Hooks
102
+
103
+ ```typescript
104
+ // hooks/useCounter.ts
105
+ import { useState } from 'react';
106
+
107
+ export const useCounter = (initialValue = 0) => {
108
+ const [count, setCount] = useState(initialValue);
109
+
110
+ const increment = () => setCount(c => c + 1);
111
+ const decrement = () => setCount(c => c - 1);
112
+ const reset = () => setCount(initialValue);
113
+
114
+ return { count, increment, decrement, reset };
115
+ };
116
+
117
+ // hooks/useCounter.test.ts
118
+ import { renderHook, act } from '@testing-library/react';
119
+ import { useCounter } from './useCounter';
120
+
121
+ describe('useCounter', () => {
122
+ it('initializes with default value', () => {
123
+ const { result } = renderHook(() => useCounter());
124
+ expect(result.current.count).toBe(0);
125
+ });
126
+
127
+ it('increments count', () => {
128
+ const { result } = renderHook(() => useCounter());
129
+
130
+ act(() => {
131
+ result.current.increment();
132
+ });
133
+
134
+ expect(result.current.count).toBe(1);
135
+ });
136
+
137
+ it('resets to initial value', () => {
138
+ const { result } = renderHook(() => useCounter(10));
139
+
140
+ act(() => {
141
+ result.current.increment();
142
+ result.current.reset();
143
+ });
144
+
145
+ expect(result.current.count).toBe(10);
146
+ });
147
+ });
148
+ ```
149
+
150
+ ---
151
+
152
+ ## 🔗 Integration Testing
153
+
154
+ ### What to Integration Test
155
+
156
+ ✅ **DO test:**
157
+ - Component + hooks interaction
158
+ - API calls + data fetching
159
+ - Form submission flows
160
+ - Navigation between views
161
+ - State management integration
162
+
163
+ ### Integration Test Patterns
164
+
165
+ #### Testing Components with API Calls
166
+
167
+ ```typescript
168
+ // UserProfile.tsx
169
+ import { useQuery } from '@tanstack/react-query';
170
+ import { fetchUser } from './api';
171
+
172
+ export const UserProfile = ({ userId }: { userId: string }) => {
173
+ const { data, isLoading, error } = useQuery({
174
+ queryKey: ['user', userId],
175
+ queryFn: () => fetchUser(userId)
176
+ });
177
+
178
+ if (isLoading) return <div>Loading...</div>;
179
+ if (error) return <div>Error: {error.message}</div>;
180
+
181
+ return (
182
+ <div>
183
+ <h1>{data.name}</h1>
184
+ <p>{data.email}</p>
185
+ </div>
186
+ );
187
+ };
188
+
189
+ // UserProfile.test.tsx
190
+ import { render, screen, waitFor } from '@testing-library/react';
191
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
192
+ import { rest } from 'msw';
193
+ import { setupServer } from 'msw/node';
194
+ import { UserProfile } from './UserProfile';
195
+
196
+ const server = setupServer(
197
+ rest.get('/api/users/:id', (req, res, ctx) => {
198
+ return res(ctx.json({
199
+ id: '1',
200
+ name: 'Alice Johnson',
201
+ email: 'alice@example.com'
202
+ }));
203
+ })
204
+ );
205
+
206
+ beforeAll(() => server.listen());
207
+ afterEach(() => server.resetHandlers());
208
+ afterAll(() => server.close());
209
+
210
+ const createWrapper = () => {
211
+ const queryClient = new QueryClient({
212
+ defaultOptions: { queries: { retry: false } }
213
+ });
214
+ return ({ children }) => (
215
+ <QueryClientProvider client={queryClient}>
216
+ {children}
217
+ </QueryClientProvider>
218
+ );
219
+ };
220
+
221
+ describe('UserProfile', () => {
222
+ it('displays user data', async () => {
223
+ render(<UserProfile userId="1" />, { wrapper: createWrapper() });
224
+
225
+ expect(screen.getByText('Loading...')).toBeInTheDocument();
226
+
227
+ await waitFor(() => {
228
+ expect(screen.getByText('Alice Johnson')).toBeInTheDocument();
229
+ expect(screen.getByText('alice@example.com')).toBeInTheDocument();
230
+ });
231
+ });
232
+
233
+ it('displays error message on failure', async () => {
234
+ server.use(
235
+ rest.get('/api/users/:id', (req, res, ctx) => {
236
+ return res(ctx.status(500));
237
+ })
238
+ );
239
+
240
+ render(<UserProfile userId="1" />, { wrapper: createWrapper() });
241
+
242
+ await waitFor(() => {
243
+ expect(screen.getByText(/error/i)).toBeInTheDocument();
244
+ });
245
+ });
246
+ });
247
+ ```
248
+
249
+ #### Testing Forms
250
+
251
+ ```typescript
252
+ // LoginForm.test.tsx
253
+ import { render, screen, waitFor } from '@testing-library/react';
254
+ import userEvent from '@testing-library/user-event';
255
+ import { LoginForm } from './LoginForm';
256
+
257
+ describe('LoginForm', () => {
258
+ it('submits form with valid data', async () => {
259
+ const onSubmit = vi.fn();
260
+ const user = userEvent.setup();
261
+
262
+ render(<LoginForm onSubmit={onSubmit} />);
263
+
264
+ await user.type(screen.getByLabelText(/email/i), 'test@example.com');
265
+ await user.type(screen.getByLabelText(/password/i), 'password123');
266
+ await user.click(screen.getByRole('button', { name: /sign in/i }));
267
+
268
+ await waitFor(() => {
269
+ expect(onSubmit).toHaveBeenCalledWith({
270
+ email: 'test@example.com',
271
+ password: 'password123'
272
+ });
273
+ });
274
+ });
275
+
276
+ it('displays validation errors', async () => {
277
+ const user = userEvent.setup();
278
+
279
+ render(<LoginForm onSubmit={vi.fn()} />);
280
+
281
+ // Submit without filling fields
282
+ await user.click(screen.getByRole('button', { name: /sign in/i }));
283
+
284
+ expect(await screen.findByText(/email is required/i)).toBeInTheDocument();
285
+ expect(await screen.findByText(/password is required/i)).toBeInTheDocument();
286
+ });
287
+
288
+ it('disables submit button while loading', async () => {
289
+ const onSubmit = vi.fn(() => new Promise(resolve => setTimeout(resolve, 100)));
290
+ const user = userEvent.setup();
291
+
292
+ render(<LoginForm onSubmit={onSubmit} />);
293
+
294
+ await user.type(screen.getByLabelText(/email/i), 'test@example.com');
295
+ await user.type(screen.getByLabelText(/password/i), 'password123');
296
+
297
+ const submitButton = screen.getByRole('button', { name: /sign in/i });
298
+ await user.click(submitButton);
299
+
300
+ expect(submitButton).toBeDisabled();
301
+ });
302
+ });
303
+ ```
304
+
305
+ ---
306
+
307
+ ## 🌐 E2E Testing
308
+
309
+ ### What to E2E Test
310
+
311
+ ✅ **DO test:**
312
+ - Critical user journeys (signup, checkout)
313
+ - Cross-page flows
314
+ - Authentication flows
315
+ - Payment processing
316
+ - Real browser interactions
317
+
318
+ ❌ **DON'T test:**
319
+ - Every feature (too slow)
320
+ - Edge cases (use integration tests)
321
+ - Visual details (use visual regression)
322
+
323
+ ### E2E Test Patterns ({{E2E_FRAMEWORK}})
324
+
325
+ #### User Journey Test
326
+
327
+ ```typescript
328
+ // e2e/checkout.spec.ts
329
+ import { test, expect } from '@playwright/test';
330
+
331
+ test.describe('Checkout Flow', () => {
332
+ test.beforeEach(async ({ page }) => {
333
+ // Login before each test
334
+ await page.goto('/login');
335
+ await page.fill('[name="email"]', 'test@example.com');
336
+ await page.fill('[name="password"]', 'password123');
337
+ await page.click('button[type="submit"]');
338
+ await expect(page).toHaveURL('/dashboard');
339
+ });
340
+
341
+ test('completes purchase successfully', async ({ page }) => {
342
+ // Add item to cart
343
+ await page.goto('/products');
344
+ await page.click('[data-testid="product-1"]');
345
+ await page.click('button:has-text("Add to Cart")');
346
+
347
+ // Verify cart badge
348
+ await expect(page.locator('[data-testid="cart-badge"]')).toHaveText('1');
349
+
350
+ // Go to checkout
351
+ await page.click('[data-testid="cart-icon"]');
352
+ await page.click('button:has-text("Checkout")');
353
+
354
+ // Fill shipping info
355
+ await page.fill('[name="address"]', '123 Main St');
356
+ await page.fill('[name="city"]', 'New York');
357
+ await page.fill('[name="zipCode"]', '10001');
358
+ await page.click('button:has-text("Continue to Payment")');
359
+
360
+ // Fill payment info (test mode)
361
+ await page.fill('[name="cardNumber"]', '4242424242424242');
362
+ await page.fill('[name="expiry"]', '12/25');
363
+ await page.fill('[name="cvc"]', '123');
364
+ await page.click('button:has-text("Place Order")');
365
+
366
+ // Verify success
367
+ await expect(page).toHaveURL(/\/order\/[a-z0-9]+/);
368
+ await expect(page.locator('h1')).toHaveText('Order Confirmed!');
369
+ });
370
+
371
+ test('validates payment information', async ({ page }) => {
372
+ await page.goto('/checkout');
373
+
374
+ // Try to submit with invalid card
375
+ await page.fill('[name="cardNumber"]', '1234');
376
+ await page.click('button:has-text("Place Order")');
377
+
378
+ await expect(page.locator('.error')).toContainText('Invalid card number');
379
+ });
380
+ });
381
+ ```
382
+
383
+ #### API Mocking in E2E
384
+
385
+ ```typescript
386
+ // e2e/dashboard.spec.ts
387
+ import { test, expect } from '@playwright/test';
388
+
389
+ test('displays dashboard with mocked data', async ({ page }) => {
390
+ // Mock API response
391
+ await page.route('/api/stats', route => {
392
+ route.fulfill({
393
+ status: 200,
394
+ contentType: 'application/json',
395
+ body: JSON.stringify({
396
+ totalSales: 15420,
397
+ orders: 234,
398
+ customers: 1250
399
+ })
400
+ });
401
+ });
402
+
403
+ await page.goto('/dashboard');
404
+
405
+ await expect(page.locator('[data-testid="total-sales"]')).toHaveText('$15,420');
406
+ await expect(page.locator('[data-testid="total-orders"]')).toHaveText('234');
407
+ });
408
+ ```
409
+
410
+ ---
411
+
412
+ ## 🎨 Visual Regression Testing
413
+
414
+ ### Strategy: {{VISUAL_REGRESSION_TOOL}}
415
+
416
+ ```typescript
417
+ // Using Playwright
418
+ import { test, expect } from '@playwright/test';
419
+
420
+ test('homepage looks correct', async ({ page }) => {
421
+ await page.goto('/');
422
+ await expect(page).toHaveScreenshot('homepage.png');
423
+ });
424
+
425
+ test('button variants', async ({ page }) => {
426
+ await page.goto('/storybook/button');
427
+ await expect(page.locator('.button-primary')).toHaveScreenshot('button-primary.png');
428
+ await expect(page.locator('.button-secondary')).toHaveScreenshot('button-secondary.png');
429
+ });
430
+ ```
431
+
432
+ ---
433
+
434
+ ## 🧩 Testing Best Practices
435
+
436
+ ### 1. Query Priorities (Testing Library)
437
+
438
+ **Priority order:**
439
+
440
+ 1. **Accessible by everyone:** `getByRole`, `getByLabelText`, `getByPlaceholderText`, `getByText`
441
+ 2. **Semantic queries:** `getByAltText`, `getByTitle`
442
+ 3. **Test IDs (last resort):** `getByTestId`
443
+
444
+ ```typescript
445
+ // ✅ Good - Accessible queries
446
+ screen.getByRole('button', { name: /submit/i });
447
+ screen.getByLabelText(/email address/i);
448
+
449
+ // ❌ Bad - Fragile test IDs
450
+ screen.getByTestId('submit-btn');
451
+ ```
452
+
453
+ ### 2. Async Utilities
454
+
455
+ ```typescript
456
+ // ✅ Good - waitFor for async changes
457
+ await waitFor(() => {
458
+ expect(screen.getByText('Success!')).toBeInTheDocument();
459
+ });
460
+
461
+ // ✅ Good - findBy for async queries (combines getBy + waitFor)
462
+ const element = await screen.findByText('Success!');
463
+
464
+ // ❌ Bad - Manual timeout
465
+ await new Promise(resolve => setTimeout(resolve, 1000));
466
+ expect(screen.getByText('Success!')).toBeInTheDocument();
467
+ ```
468
+
469
+ ### 3. User Interactions
470
+
471
+ ```typescript
472
+ import userEvent from '@testing-library/user-event';
473
+
474
+ // ✅ Good - userEvent (realistic)
475
+ const user = userEvent.setup();
476
+ await user.type(input, 'hello');
477
+ await user.click(button);
478
+
479
+ // ❌ Bad - fireEvent (synthetic)
480
+ fireEvent.change(input, { target: { value: 'hello' } });
481
+ fireEvent.click(button);
482
+ ```
483
+
484
+ ### 4. Test Organization
485
+
486
+ ```typescript
487
+ describe('UserDashboard', () => {
488
+ // Setup
489
+ let mockUser: User;
490
+
491
+ beforeEach(() => {
492
+ mockUser = { id: '1', name: 'Alice' };
493
+ });
494
+
495
+ describe('when logged in', () => {
496
+ it('displays welcome message', () => {
497
+ // Test
498
+ });
499
+
500
+ it('shows user statistics', () => {
501
+ // Test
502
+ });
503
+ });
504
+
505
+ describe('when logged out', () => {
506
+ it('redirects to login', () => {
507
+ // Test
508
+ });
509
+ });
510
+ });
511
+ ```
512
+
513
+ ---
514
+
515
+ ## 📊 Code Coverage
516
+
517
+ ### Coverage Targets
518
+
519
+ - **Statements:** {{COVERAGE_STATEMENTS}}%
520
+ - **Branches:** {{COVERAGE_BRANCHES}}%
521
+ - **Functions:** {{COVERAGE_FUNCTIONS}}%
522
+ - **Lines:** {{COVERAGE_LINES}}%
523
+
524
+ ### Running Coverage
525
+
526
+ ```bash
527
+ # Generate coverage report
528
+ {{PACKAGE_MANAGER}} run test:coverage
529
+
530
+ # View HTML report
531
+ open coverage/index.html
532
+ ```
533
+
534
+ ### Coverage Configuration
535
+
536
+ ```typescript
537
+ // vitest.config.ts
538
+ export default defineConfig({
539
+ test: {
540
+ coverage: {
541
+ provider: 'v8',
542
+ reporter: ['text', 'html', 'lcov'],
543
+ include: ['src/**/*.{ts,tsx}'],
544
+ exclude: [
545
+ 'src/**/*.test.{ts,tsx}',
546
+ 'src/**/*.spec.{ts,tsx}',
547
+ 'src/**/*.stories.{ts,tsx}',
548
+ 'src/types/**'
549
+ ],
550
+ thresholds: {
551
+ statements: 80,
552
+ branches: 75,
553
+ functions: 80,
554
+ lines: 80
555
+ }
556
+ }
557
+ }
558
+ });
559
+ ```
560
+
561
+ ---
562
+
563
+ ## 🔧 Mocking Strategies
564
+
565
+ ### 1. Mock Service Worker (API Mocking)
566
+
567
+ ```typescript
568
+ // mocks/handlers.ts
569
+ import { rest } from 'msw';
570
+
571
+ export const handlers = [
572
+ rest.get('/api/users/:id', (req, res, ctx) => {
573
+ return res(
574
+ ctx.status(200),
575
+ ctx.json({ id: req.params.id, name: 'Alice' })
576
+ );
577
+ }),
578
+
579
+ rest.post('/api/login', async (req, res, ctx) => {
580
+ const { email, password } = await req.json();
581
+
582
+ if (email === 'test@example.com' && password === 'password123') {
583
+ return res(
584
+ ctx.status(200),
585
+ ctx.json({ token: 'fake-jwt-token' })
586
+ );
587
+ }
588
+
589
+ return res(
590
+ ctx.status(401),
591
+ ctx.json({ error: 'Invalid credentials' })
592
+ );
593
+ })
594
+ ];
595
+
596
+ // mocks/server.ts
597
+ import { setupServer } from 'msw/node';
598
+ import { handlers } from './handlers';
599
+
600
+ export const server = setupServer(...handlers);
601
+ ```
602
+
603
+ ### 2. Module Mocking
604
+
605
+ ```typescript
606
+ // vi.mock for Vitest
607
+ vi.mock('./api', () => ({
608
+ fetchUser: vi.fn(() => Promise.resolve({ id: '1', name: 'Alice' }))
609
+ }));
610
+
611
+ // jest.mock for Jest
612
+ jest.mock('./api', () => ({
613
+ fetchUser: jest.fn(() => Promise.resolve({ id: '1', name: 'Alice' }))
614
+ }));
615
+ ```
616
+
617
+ ### 3. Component Mocking
618
+
619
+ ```typescript
620
+ // Mock child component
621
+ vi.mock('./ComplexChart', () => ({
622
+ ComplexChart: () => <div>Chart Mock</div>
623
+ }));
624
+
625
+ test('renders dashboard', () => {
626
+ render(<Dashboard />);
627
+ expect(screen.getByText('Chart Mock')).toBeInTheDocument();
628
+ });
629
+ ```
630
+
631
+ ---
632
+
633
+ ## ⚠️ Common Testing Pitfalls
634
+
635
+ ### 1. Testing Implementation Details
636
+
637
+ ```typescript
638
+ // ❌ Bad - Tests internal state
639
+ const { container } = render(<Counter />);
640
+ const button = container.querySelector('.increment-btn');
641
+ expect(button.className).toBe('increment-btn active');
642
+
643
+ // ✅ Good - Tests user-visible behavior
644
+ render(<Counter />);
645
+ const button = screen.getByRole('button', { name: /increment/i });
646
+ await userEvent.click(button);
647
+ expect(screen.getByText('Count: 1')).toBeInTheDocument();
648
+ ```
649
+
650
+ ### 2. Not Cleaning Up
651
+
652
+ ```typescript
653
+ // ❌ Bad - State leaks between tests
654
+ let component;
655
+
656
+ test('test 1', () => {
657
+ component = render(<App />);
658
+ // No cleanup
659
+ });
660
+
661
+ // ✅ Good - Automatic cleanup
662
+ import { render, cleanup } from '@testing-library/react';
663
+
664
+ afterEach(() => {
665
+ cleanup();
666
+ });
667
+ ```
668
+
669
+ ### 3. Over-Mocking
670
+
671
+ ```typescript
672
+ // ❌ Bad - Mocking everything
673
+ vi.mock('./Button', () => ({ Button: () => <div>Button</div> }));
674
+ vi.mock('./Input', () => ({ Input: () => <div>Input</div> }));
675
+ vi.mock('./Form', () => ({ Form: () => <div>Form</div> }));
676
+
677
+ // ✅ Good - Only mock external dependencies
678
+ vi.mock('./api', () => ({ fetchData: vi.fn() }));
679
+ ```
680
+
681
+ ---
682
+
683
+ ## 🚀 CI/CD Integration
684
+
685
+ ### GitHub Actions Example
686
+
687
+ ```yaml
688
+ # .github/workflows/test.yml
689
+ name: Tests
690
+
691
+ on: [push, pull_request]
692
+
693
+ jobs:
694
+ test:
695
+ runs-on: ubuntu-latest
696
+
697
+ steps:
698
+ - uses: actions/checkout@v3
699
+ - uses: actions/setup-node@v3
700
+ with:
701
+ node-version: 18
702
+
703
+ - name: Install dependencies
704
+ run: npm ci
705
+
706
+ - name: Run unit & integration tests
707
+ run: npm run test:coverage
708
+
709
+ - name: Upload coverage
710
+ uses: codecov/codecov-action@v3
711
+
712
+ - name: Run E2E tests
713
+ run: npm run test:e2e
714
+
715
+ - name: Upload E2E artifacts
716
+ if: failure()
717
+ uses: actions/upload-artifact@v3
718
+ with:
719
+ name: playwright-screenshots
720
+ path: test-results/
721
+ ```
722
+
723
+ ---
724
+
725
+ ## 🔗 Related Documents
726
+
727
+ - [Component Architecture](components.md) - Component structure to test
728
+ - [State Management](state-management.md) - Testing stores and hooks
729
+ - [AI Instructions](../ai-instructions.md) - Testing requirements
730
+ - [Contributing](contributing.md) - How to write tests
731
+
732
+ ---
733
+
734
+ **Last Updated:** {{GENERATION_DATE}}
735
+
736
+ **Testing Stack:** {{UNIT_TEST_FRAMEWORK}} + {{COMPONENT_TEST_LIBRARY}} + {{E2E_FRAMEWORK}}