qaa-agent 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/.claude/commands/create-test.md +40 -0
  2. package/.claude/commands/qa-analyze.md +60 -0
  3. package/.claude/commands/qa-audit.md +37 -0
  4. package/.claude/commands/qa-blueprint.md +54 -0
  5. package/.claude/commands/qa-fix.md +36 -0
  6. package/.claude/commands/qa-from-ticket.md +88 -0
  7. package/.claude/commands/qa-gap.md +54 -0
  8. package/.claude/commands/qa-pom.md +36 -0
  9. package/.claude/commands/qa-pyramid.md +37 -0
  10. package/.claude/commands/qa-report.md +38 -0
  11. package/.claude/commands/qa-start.md +33 -0
  12. package/.claude/commands/qa-testid.md +54 -0
  13. package/.claude/commands/qa-validate.md +54 -0
  14. package/.claude/commands/update-test.md +58 -0
  15. package/.claude/settings.json +19 -0
  16. package/.claude/skills/qa-bug-detective/SKILL.md +122 -0
  17. package/.claude/skills/qa-repo-analyzer/SKILL.md +88 -0
  18. package/.claude/skills/qa-self-validator/SKILL.md +109 -0
  19. package/.claude/skills/qa-template-engine/SKILL.md +113 -0
  20. package/.claude/skills/qa-testid-injector/SKILL.md +93 -0
  21. package/.claude/skills/qa-workflow-documenter/SKILL.md +87 -0
  22. package/CLAUDE.md +543 -0
  23. package/README.md +418 -0
  24. package/agents/qa-pipeline-orchestrator.md +1217 -0
  25. package/agents/qaa-analyzer.md +508 -0
  26. package/agents/qaa-bug-detective.md +444 -0
  27. package/agents/qaa-executor.md +618 -0
  28. package/agents/qaa-planner.md +374 -0
  29. package/agents/qaa-scanner.md +422 -0
  30. package/agents/qaa-testid-injector.md +583 -0
  31. package/agents/qaa-validator.md +450 -0
  32. package/bin/install.cjs +176 -0
  33. package/bin/lib/commands.cjs +709 -0
  34. package/bin/lib/config.cjs +307 -0
  35. package/bin/lib/core.cjs +497 -0
  36. package/bin/lib/frontmatter.cjs +299 -0
  37. package/bin/lib/init.cjs +989 -0
  38. package/bin/lib/milestone.cjs +241 -0
  39. package/bin/lib/model-profiles.cjs +60 -0
  40. package/bin/lib/phase.cjs +911 -0
  41. package/bin/lib/roadmap.cjs +306 -0
  42. package/bin/lib/state.cjs +748 -0
  43. package/bin/lib/template.cjs +222 -0
  44. package/bin/lib/verify.cjs +842 -0
  45. package/bin/qaa-tools.cjs +607 -0
  46. package/package.json +34 -0
  47. package/templates/failure-classification.md +391 -0
  48. package/templates/gap-analysis.md +409 -0
  49. package/templates/pr-template.md +48 -0
  50. package/templates/qa-analysis.md +381 -0
  51. package/templates/qa-audit-report.md +465 -0
  52. package/templates/qa-repo-blueprint.md +636 -0
  53. package/templates/scan-manifest.md +312 -0
  54. package/templates/test-inventory.md +582 -0
  55. package/templates/testid-audit-report.md +354 -0
  56. package/templates/validation-report.md +243 -0
@@ -0,0 +1,582 @@
1
+ ---
2
+ template_name: test-inventory
3
+ version: "1.0"
4
+ artifact_type: inventory
5
+ produces: TEST_INVENTORY.md
6
+ producer_agent: qa-analyzer
7
+ consumer_agents:
8
+ - qa-planner
9
+ - qa-executor
10
+ required_sections:
11
+ - summary
12
+ - unit-tests
13
+ - integration-tests
14
+ - api-tests
15
+ - e2e-smoke-tests
16
+ example_domain: shopflow
17
+ ---
18
+
19
+ # TEST_INVENTORY.md Template
20
+
21
+ **Purpose:** Complete, pyramid-based test case inventory with every test specified to the level of detail needed for automated generation. Every test case has a unique ID, specific target, concrete inputs, and an explicit expected outcome. This inventory is the single source of truth for what tests will be generated.
22
+
23
+ **Producer:** `qa-analyzer` agent
24
+ **Consumers:** `qa-planner` (reads inventory to create generation plan with task breakdown and file assignments), `qa-executor` (reads individual test cases to write actual test code)
25
+
26
+ **Input required:** `QA_ANALYSIS.md` must exist before this artifact is produced. The analyzer uses the top 10 unit targets, API targets, risk assessment, and testing pyramid from the analysis to populate this inventory.
27
+
28
+ ---
29
+
30
+ ## Required Sections
31
+
32
+ ### Section 1: Summary
33
+
34
+ **Description:** High-level overview of the complete test inventory. Provides counts and distributions that downstream agents use to estimate effort and validate completeness.
35
+
36
+ **Fields:**
37
+
38
+ | Field | Type | Required | Description |
39
+ |-------|------|----------|-------------|
40
+ | total_tests | number | YES | Total number of test cases across all tiers |
41
+ | unit_count | number | YES | Number of unit tests |
42
+ | unit_percent | number | YES | Percentage of total (target: 60-70%) |
43
+ | integration_count | number | YES | Number of integration tests |
44
+ | integration_percent | number | YES | Percentage of total (target: 10-15%) |
45
+ | api_count | number | YES | Number of API tests |
46
+ | api_percent | number | YES | Percentage of total (target: 20-25%) |
47
+ | e2e_count | number | YES | Number of E2E smoke tests |
48
+ | e2e_percent | number | YES | Percentage of total (target: 3-5%) |
49
+ | p0_count | number | YES | Number of P0 (blocks release) tests |
50
+ | p1_count | number | YES | Number of P1 (should fix) tests |
51
+ | p2_count | number | YES | Number of P2 (nice to have) tests |
52
+ | coverage_narrative | string | YES | 2-3 sentence assessment of what this inventory covers and any known gaps |
53
+
54
+ ---
55
+
56
+ ### Section 2: Unit Tests (60-70%)
57
+
58
+ **Description:** Tests for individual functions, methods, and modules in isolation. Each test case targets a specific function with concrete inputs and an explicit expected outcome. This is the largest tier and covers all business logic, validation, and utility functions.
59
+
60
+ **Per test case -- ALL fields are MANDATORY:**
61
+
62
+ | Field | Type | Required | Description |
63
+ |-------|------|----------|-------------|
64
+ | test_id | string | YES | Format: `UT-MODULE-NNN` (e.g., `UT-PRICE-001`) |
65
+ | target | string | YES | Format: `file_path:function_name` (e.g., `src/utils/priceCalculator.ts:calculateOrderTotal`) |
66
+ | what_to_validate | string | YES | One-sentence description of the behavior being tested |
67
+ | concrete_inputs | string | YES | Actual values to pass -- NOT "valid data" or "correct input" |
68
+ | mocks_needed | string | YES | List of dependencies to mock, or "None (pure function)" |
69
+ | expected_outcome | string | YES | Exact return value, exact error message, or exact state change |
70
+ | priority | enum | YES | `P0` (blocks release), `P1` (should fix), `P2` (nice to have) |
71
+
72
+ **CRITICAL ANTI-PATTERN:**
73
+
74
+ > "Returns correct value" is **NOT** an expected outcome.
75
+ > "Returns 239.47" **IS** an expected outcome.
76
+ >
77
+ > "Handles error correctly" is **NOT** an expected outcome.
78
+ > "Throws InvalidTransitionError with message 'Cannot transition from delivered to pending'" **IS** an expected outcome.
79
+ >
80
+ > Every expected outcome must contain a **concrete value, specific error, or measurable state change**.
81
+
82
+ ---
83
+
84
+ ### Section 3: Integration/Contract Tests (10-15%)
85
+
86
+ **Description:** Tests verifying that two or more modules interact correctly. These test the contracts between components -- not internal logic (that's unit tests) and not HTTP contracts (that's API tests). Focus on database interactions, service-to-service calls, and cross-module state flows.
87
+
88
+ **Per test case -- ALL fields are MANDATORY:**
89
+
90
+ | Field | Type | Required | Description |
91
+ |-------|------|----------|-------------|
92
+ | test_id | string | YES | Format: `INT-MODULE-NNN` (e.g., `INT-ORDER-001`) |
93
+ | components_involved | string | YES | Which modules interact (e.g., "orderService + inventoryService + Prisma") |
94
+ | what_to_validate | string | YES | The interaction contract being tested |
95
+ | setup_required | string | YES | Database state, mock services, or seed data needed before the test |
96
+ | expected_outcome | string | YES | Specific behavior when components interact correctly |
97
+ | priority | enum | YES | `P0`, `P1`, or `P2` |
98
+
99
+ ---
100
+
101
+ ### Section 4: API Tests (20-25%)
102
+
103
+ **Description:** HTTP-level tests verifying request/response contracts for each endpoint. These ensure the API surface area behaves as documented -- correct status codes, response shapes, error formats, and auth enforcement.
104
+
105
+ **Per test case -- ALL fields are MANDATORY:**
106
+
107
+ | Field | Type | Required | Description |
108
+ |-------|------|----------|-------------|
109
+ | test_id | string | YES | Format: `API-RESOURCE-NNN` (e.g., `API-AUTH-001`) |
110
+ | method_endpoint | string | YES | HTTP method + path (e.g., `POST /api/v1/auth/login`) |
111
+ | request_body | string | YES | Exact JSON payload or "N/A" for GET requests |
112
+ | headers | string | YES | Required headers (e.g., `Authorization: Bearer {token}`) or "None" |
113
+ | expected_status | number | YES | Exact HTTP status code (200, 201, 400, 401, 404, etc.) |
114
+ | expected_response | string | YES | Key fields in response body with types or exact values |
115
+ | priority | enum | YES | `P0`, `P1`, or `P2` |
116
+
117
+ ---
118
+
119
+ ### Section 5: E2E Smoke Tests (3-5%)
120
+
121
+ **Description:** End-to-end tests covering the most critical user journeys. These are the minimum set of tests that MUST pass before any release. Maximum 3-8 tests -- each one a multi-step user flow that exercises the full stack.
122
+
123
+ **Per test case -- ALL fields are MANDATORY:**
124
+
125
+ | Field | Type | Required | Description |
126
+ |-------|------|----------|-------------|
127
+ | test_id | string | YES | Format: `E2E-FLOW-NNN` (e.g., `E2E-FLOW-001`) |
128
+ | user_journey | string | YES | Step-by-step description of what the user does |
129
+ | pages_involved | string | YES | List of views/routes the user navigates through |
130
+ | expected_outcome | string | YES | Final state the user observes after completing the journey |
131
+ | priority | enum | YES | Always `P0` -- E2E tests are release-blocking by definition |
132
+
133
+ ---
134
+
135
+ ## Worked Example (ShopFlow E-Commerce API)
136
+
137
+ > The following is a complete, filled TEST_INVENTORY.md for the ShopFlow e-commerce application. This example demonstrates the expected depth, specificity, and concrete values required in every test case.
138
+
139
+ ### Summary
140
+
141
+ | Metric | Value |
142
+ |--------|-------|
143
+ | **Total Tests** | 45 |
144
+ | **Unit Tests** | 28 (62%) |
145
+ | **Integration Tests** | 7 (16%) |
146
+ | **API Tests** | 8 (18%) |
147
+ | **E2E Smoke Tests** | 2 (4%) |
148
+ | **P0 (blocks release)** | 15 |
149
+ | **P1 (should fix)** | 20 |
150
+ | **P2 (nice to have)** | 10 |
151
+
152
+ **Coverage narrative:** This inventory covers all business-critical logic (price calculation, order state machine, payment processing, authentication), the complete API contract surface, key integration points (order-to-inventory, payment-to-order), and the two most critical user journeys (purchase flow and registration). Known gap: admin-only endpoints (product CRUD) are covered at P1 level only -- no E2E test for admin flows since admin UI is out of current scope.
153
+
154
+ ---
155
+
156
+ ### Unit Tests (28 tests -- 62%)
157
+
158
+ #### Price Calculation Module
159
+
160
+ ##### UT-PRICE-001: Calculate Order Total with Multiple Items
161
+ - **Target:** `src/utils/priceCalculator.ts:calculateOrderTotal`
162
+ - **What to validate:** Correctly sums line items with quantity multiplication
163
+ - **Concrete inputs:** `[{sku: 'WIDGET-001', qty: 3, unitPrice: 29.99}, {sku: 'GADGET-002', qty: 1, unitPrice: 149.50}]`
164
+ - **Mocks needed:** None (pure function)
165
+ - **Expected outcome:** Returns `239.47` (29.99 * 3 + 149.50)
166
+ - **Priority:** P0
167
+
168
+ ##### UT-PRICE-002: Apply Percentage Discount
169
+ - **Target:** `src/utils/priceCalculator.ts:applyDiscount`
170
+ - **What to validate:** Applies percentage discount correctly and rounds to 2 decimal places
171
+ - **Concrete inputs:** `{subtotal: 239.47, discountCode: 'SAVE10', discountPercent: 10}`
172
+ - **Mocks needed:** None (pure function)
173
+ - **Expected outcome:** Returns `215.52` (239.47 * 0.90, rounded to 2 decimals)
174
+ - **Priority:** P1
175
+
176
+ ##### UT-PRICE-003: Calculate Tax
177
+ - **Target:** `src/utils/priceCalculator.ts:calculateTax`
178
+ - **What to validate:** Applies state tax rate correctly
179
+ - **Concrete inputs:** `{subtotal: 215.52, state: 'CA', taxRate: 0.0875}`
180
+ - **Mocks needed:** None (pure function)
181
+ - **Expected outcome:** Returns `18.86` (215.52 * 0.0875, rounded to 2 decimals)
182
+ - **Priority:** P1
183
+
184
+ ##### UT-PRICE-004: Calculate Shipping by Weight
185
+ - **Target:** `src/utils/priceCalculator.ts:calculateShipping`
186
+ - **What to validate:** Returns correct shipping cost based on weight tiers
187
+ - **Concrete inputs:** `{totalWeight: 4.5, shippingMethod: 'standard'}`
188
+ - **Mocks needed:** None (pure function)
189
+ - **Expected outcome:** Returns `8.99` (standard rate for 2-5 kg tier)
190
+ - **Priority:** P2
191
+
192
+ ##### UT-PRICE-005: Calculate Order Total with Zero Items
193
+ - **Target:** `src/utils/priceCalculator.ts:calculateOrderTotal`
194
+ - **What to validate:** Returns 0 for empty cart
195
+ - **Concrete inputs:** `[]`
196
+ - **Mocks needed:** None (pure function)
197
+ - **Expected outcome:** Returns `0.00`
198
+ - **Priority:** P1
199
+
200
+ #### Authentication Module
201
+
202
+ ##### UT-AUTH-001: Hash Password with bcrypt
203
+ - **Target:** `src/services/authService.ts:hashPassword`
204
+ - **What to validate:** Produces a bcrypt hash that validates against the original password
205
+ - **Concrete inputs:** `'SecureP@ss123!'`
206
+ - **Mocks needed:** None
207
+ - **Expected outcome:** `bcrypt.compare('SecureP@ss123!', result)` returns `true`; result starts with `$2b$`
208
+ - **Priority:** P0
209
+
210
+ ##### UT-AUTH-002: Verify Password -- Correct Password
211
+ - **Target:** `src/services/authService.ts:verifyPassword`
212
+ - **What to validate:** Returns true for correct password against stored hash
213
+ - **Concrete inputs:** `{password: 'SecureP@ss123!', hash: '$2b$10$...' (pre-computed valid hash)}`
214
+ - **Mocks needed:** None
215
+ - **Expected outcome:** Returns `true`
216
+ - **Priority:** P0
217
+
218
+ ##### UT-AUTH-003: Verify Password -- Wrong Password
219
+ - **Target:** `src/services/authService.ts:verifyPassword`
220
+ - **What to validate:** Returns false for incorrect password
221
+ - **Concrete inputs:** `{password: 'WrongPassword!', hash: '$2b$10$...' (hash of 'SecureP@ss123!')}`
222
+ - **Mocks needed:** None
223
+ - **Expected outcome:** Returns `false`
224
+ - **Priority:** P0
225
+
226
+ ##### UT-AUTH-004: Generate JWT Token with Correct Claims
227
+ - **Target:** `src/services/authService.ts:generateToken`
228
+ - **What to validate:** Generates a JWT with correct user ID, email, and expiration
229
+ - **Concrete inputs:** `{userId: 'usr_abc123', email: 'test@shopflow.com', role: 'customer'}`
230
+ - **Mocks needed:** Mock `jwt.sign` to capture payload
231
+ - **Expected outcome:** Token payload contains `{sub: 'usr_abc123', email: 'test@shopflow.com', role: 'customer', exp: <now + 15min>}`
232
+ - **Priority:** P0
233
+
234
+ ##### UT-AUTH-005: Reject Expired Token
235
+ - **Target:** `src/services/authService.ts:verifyToken`
236
+ - **What to validate:** Throws error when token has expired
237
+ - **Concrete inputs:** JWT token with `exp` set to 1 hour ago
238
+ - **Mocks needed:** None (use real jwt.verify with expired token)
239
+ - **Expected outcome:** Throws `TokenExpiredError` with message "jwt expired"
240
+ - **Priority:** P0
241
+
242
+ #### Order Management Module
243
+
244
+ ##### UT-ORDER-001: Transition Order Status -- Valid Transition (pending -> confirmed)
245
+ - **Target:** `src/services/orderService.ts:transitionOrderStatus`
246
+ - **What to validate:** Accepts valid state transition and returns new status
247
+ - **Concrete inputs:** `{orderId: 'ord_123', currentStatus: 'pending', newStatus: 'confirmed'}`
248
+ - **Mocks needed:** Mock Prisma `order.update` to return updated record
249
+ - **Expected outcome:** Returns `{orderId: 'ord_123', status: 'confirmed', updatedAt: <timestamp>}`
250
+ - **Priority:** P0
251
+
252
+ ##### UT-ORDER-002: Transition Order Status -- Invalid Transition (delivered -> pending)
253
+ - **Target:** `src/services/orderService.ts:transitionOrderStatus`
254
+ - **What to validate:** Rejects invalid state transition with descriptive error
255
+ - **Concrete inputs:** `{orderId: 'ord_456', currentStatus: 'delivered', newStatus: 'pending'}`
256
+ - **Mocks needed:** Mock Prisma `order.findUnique` to return order with status 'delivered'
257
+ - **Expected outcome:** Throws `InvalidTransitionError` with message "Cannot transition from delivered to pending"
258
+ - **Priority:** P0
259
+
260
+ ##### UT-ORDER-003: Transition Order Status -- Cancel from Pending
261
+ - **Target:** `src/services/orderService.ts:transitionOrderStatus`
262
+ - **What to validate:** Allows cancellation from pending status
263
+ - **Concrete inputs:** `{orderId: 'ord_789', currentStatus: 'pending', newStatus: 'cancelled'}`
264
+ - **Mocks needed:** Mock Prisma `order.update` to return updated record
265
+ - **Expected outcome:** Returns `{orderId: 'ord_789', status: 'cancelled', updatedAt: <timestamp>}`
266
+ - **Priority:** P0
267
+
268
+ ##### UT-ORDER-004: Transition Order Status -- Cancel from Shipped (should fail)
269
+ - **Target:** `src/services/orderService.ts:transitionOrderStatus`
270
+ - **What to validate:** Rejects cancellation after shipment
271
+ - **Concrete inputs:** `{orderId: 'ord_012', currentStatus: 'shipped', newStatus: 'cancelled'}`
272
+ - **Mocks needed:** Mock Prisma `order.findUnique` to return order with status 'shipped'
273
+ - **Expected outcome:** Throws `InvalidTransitionError` with message "Cannot cancel an order that has been shipped"
274
+ - **Priority:** P1
275
+
276
+ #### Payment Module
277
+
278
+ ##### UT-PAY-001: Charge Customer -- Success
279
+ - **Target:** `src/services/paymentService.ts:chargeCustomer`
280
+ - **What to validate:** Creates a Stripe charge and returns payment confirmation
281
+ - **Concrete inputs:** `{orderId: 'ord_123', amount: 25846, currency: 'usd', paymentMethodId: 'pm_test_visa'}`
282
+ - **Mocks needed:** Mock `stripe.paymentIntents.create` to return `{id: 'pi_abc', status: 'succeeded', amount: 25846}`
283
+ - **Expected outcome:** Returns `{paymentId: 'pi_abc', status: 'succeeded', amount: 258.46}`
284
+ - **Priority:** P0
285
+
286
+ ##### UT-PAY-002: Charge Customer -- Card Declined
287
+ - **Target:** `src/services/paymentService.ts:chargeCustomer`
288
+ - **What to validate:** Handles Stripe card decline gracefully
289
+ - **Concrete inputs:** `{orderId: 'ord_456', amount: 15000, currency: 'usd', paymentMethodId: 'pm_test_declined'}`
290
+ - **Mocks needed:** Mock `stripe.paymentIntents.create` to throw `StripeCardError` with code 'card_declined'
291
+ - **Expected outcome:** Throws `PaymentFailedError` with message "Card was declined" and does NOT update order status
292
+ - **Priority:** P0
293
+
294
+ ##### UT-PAY-003: Handle Webhook -- Valid Signature
295
+ - **Target:** `src/services/paymentService.ts:handleWebhook`
296
+ - **What to validate:** Processes webhook with valid Stripe signature
297
+ - **Concrete inputs:** `{rawBody: '{"type":"payment_intent.succeeded",...}', signature: 'valid_sig_hash'}`
298
+ - **Mocks needed:** Mock `stripe.webhooks.constructEvent` to return parsed event
299
+ - **Expected outcome:** Returns `{processed: true, eventType: 'payment_intent.succeeded'}`
300
+ - **Priority:** P0
301
+
302
+ ##### UT-PAY-004: Handle Webhook -- Invalid Signature
303
+ - **Target:** `src/services/paymentService.ts:handleWebhook`
304
+ - **What to validate:** Rejects webhook with invalid or missing Stripe signature
305
+ - **Concrete inputs:** `{rawBody: '{"type":"payment_intent.succeeded",...}', signature: 'invalid_sig'}`
306
+ - **Mocks needed:** Mock `stripe.webhooks.constructEvent` to throw `SignatureVerificationError`
307
+ - **Expected outcome:** Throws `WebhookVerificationError` with message "Invalid webhook signature"
308
+ - **Priority:** P0
309
+
310
+ #### Inventory Module
311
+
312
+ ##### UT-INV-001: Reserve Stock -- Sufficient Inventory
313
+ - **Target:** `src/services/inventoryService.ts:reserveStock`
314
+ - **What to validate:** Decrements available stock when sufficient inventory exists
315
+ - **Concrete inputs:** `{productId: 'prod_001', quantity: 3, currentStock: 10}`
316
+ - **Mocks needed:** Mock Prisma `product.update` to return updated stock
317
+ - **Expected outcome:** Returns `{productId: 'prod_001', reserved: 3, remainingStock: 7}`
318
+ - **Priority:** P0
319
+
320
+ ##### UT-INV-002: Reserve Stock -- Insufficient Inventory
321
+ - **Target:** `src/services/inventoryService.ts:reserveStock`
322
+ - **What to validate:** Rejects reservation when insufficient stock
323
+ - **Concrete inputs:** `{productId: 'prod_002', quantity: 5, currentStock: 2}`
324
+ - **Mocks needed:** Mock Prisma `product.findUnique` to return product with stock 2
325
+ - **Expected outcome:** Throws `InsufficientStockError` with message "Only 2 units available for prod_002, requested 5"
326
+ - **Priority:** P0
327
+
328
+ ##### UT-INV-003: Release Stock on Payment Failure
329
+ - **Target:** `src/services/inventoryService.ts:releaseStock`
330
+ - **What to validate:** Increments available stock when releasing a reservation
331
+ - **Concrete inputs:** `{productId: 'prod_001', quantity: 3, currentStock: 7}`
332
+ - **Mocks needed:** Mock Prisma `product.update` to return updated stock
333
+ - **Expected outcome:** Returns `{productId: 'prod_001', released: 3, availableStock: 10}`
334
+ - **Priority:** P1
335
+
336
+ #### Validation Module
337
+
338
+ ##### UT-VAL-001: Validate Email -- Valid Format
339
+ - **Target:** `src/utils/validators.ts:validateEmail`
340
+ - **What to validate:** Accepts valid email format
341
+ - **Concrete inputs:** `'user@shopflow.com'`
342
+ - **Mocks needed:** None (pure function)
343
+ - **Expected outcome:** Returns `true`
344
+ - **Priority:** P1
345
+
346
+ ##### UT-VAL-002: Validate Email -- Invalid Format
347
+ - **Target:** `src/utils/validators.ts:validateEmail`
348
+ - **What to validate:** Rejects invalid email format
349
+ - **Concrete inputs:** `'not-an-email'`
350
+ - **Mocks needed:** None (pure function)
351
+ - **Expected outcome:** Returns `false`
352
+ - **Priority:** P1
353
+
354
+ ##### UT-VAL-003: Validate Password -- Meets Requirements
355
+ - **Target:** `src/utils/validators.ts:validatePassword`
356
+ - **What to validate:** Accepts password meeting minimum requirements (8+ chars, 1 uppercase, 1 number, 1 special)
357
+ - **Concrete inputs:** `'SecureP@ss123!'`
358
+ - **Mocks needed:** None (pure function)
359
+ - **Expected outcome:** Returns `{valid: true, errors: []}`
360
+ - **Priority:** P1
361
+
362
+ ##### UT-VAL-004: Validate Password -- Too Short
363
+ - **Target:** `src/utils/validators.ts:validatePassword`
364
+ - **What to validate:** Rejects password under minimum length
365
+ - **Concrete inputs:** `'Ab1!'`
366
+ - **Mocks needed:** None (pure function)
367
+ - **Expected outcome:** Returns `{valid: false, errors: ['Password must be at least 8 characters']}`
368
+ - **Priority:** P1
369
+
370
+ #### Auth Middleware
371
+
372
+ ##### UT-MID-001: Auth Middleware -- Valid Token
373
+ - **Target:** `src/middleware/authMiddleware.ts:verifyToken`
374
+ - **What to validate:** Attaches decoded user to request when valid token provided
375
+ - **Concrete inputs:** `{headers: {authorization: 'Bearer <valid-jwt>'}, decoded: {sub: 'usr_abc123', email: 'test@shopflow.com'}}`
376
+ - **Mocks needed:** Mock `jwt.verify` to return decoded payload
377
+ - **Expected outcome:** `req.user` is set to `{id: 'usr_abc123', email: 'test@shopflow.com'}`, `next()` is called
378
+ - **Priority:** P0
379
+
380
+ ##### UT-MID-002: Auth Middleware -- Missing Token
381
+ - **Target:** `src/middleware/authMiddleware.ts:verifyToken`
382
+ - **What to validate:** Returns 401 when no Authorization header present
383
+ - **Concrete inputs:** `{headers: {}}`
384
+ - **Mocks needed:** None
385
+ - **Expected outcome:** Response status `401`, body `{error: 'Authentication required'}`
386
+ - **Priority:** P0
387
+
388
+ ---
389
+
390
+ ### Integration Tests (7 tests -- 16%)
391
+
392
+ ##### INT-ORDER-001: Order Creation Reserves Inventory
393
+ - **Components involved:** orderService + inventoryService + Prisma (PostgreSQL)
394
+ - **What to validate:** Creating an order automatically reserves stock for each line item
395
+ - **Setup required:** Seed database with Product (id: 'prod_001', stock: 10) and authenticated User (id: 'usr_001')
396
+ - **Expected outcome:** After `orderService.createOrder({userId: 'usr_001', items: [{productId: 'prod_001', qty: 2}]})`, product stock is decremented to 8 in database, order status is 'pending'
397
+ - **Priority:** P0
398
+
399
+ ##### INT-ORDER-002: Payment Success Updates Order Status
400
+ - **Components involved:** paymentService + orderService + Prisma (PostgreSQL)
401
+ - **What to validate:** Successful payment charge transitions order from pending to confirmed
402
+ - **Setup required:** Seed database with Order (id: 'ord_001', status: 'pending', total: 259.47). Mock Stripe to return successful charge.
403
+ - **Expected outcome:** After `paymentService.chargeCustomer({orderId: 'ord_001', ...})`, order status in database is 'confirmed', payment record exists with status 'succeeded'
404
+ - **Priority:** P0
405
+
406
+ ##### INT-ORDER-003: Payment Failure Releases Inventory
407
+ - **Components involved:** paymentService + inventoryService + orderService + Prisma (PostgreSQL)
408
+ - **What to validate:** Failed payment releases reserved stock and keeps order in pending
409
+ - **Setup required:** Seed database with Order (id: 'ord_002', status: 'pending'), Product (id: 'prod_001', stock: 8, reserved: 2). Mock Stripe to throw card_declined.
410
+ - **Expected outcome:** After payment failure, product stock is restored to 10 in database, order status remains 'pending'
411
+ - **Priority:** P0
412
+
413
+ ##### INT-ORDER-004: Webhook Updates Order After Async Payment
414
+ - **Components involved:** paymentController (webhook handler) + orderService + Prisma (PostgreSQL)
415
+ - **What to validate:** Stripe webhook event triggers order status update
416
+ - **Setup required:** Seed database with Order (id: 'ord_003', status: 'pending'). Construct valid webhook payload with Stripe test signing secret.
417
+ - **Expected outcome:** After webhook delivery with event type 'payment_intent.succeeded', order status in database is 'confirmed'
418
+ - **Priority:** P0
419
+
420
+ ##### INT-AUTH-001: Auth Middleware Blocks Unauthorized Routes
421
+ - **Components involved:** authMiddleware + orderController + Express routing
422
+ - **What to validate:** Protected routes return 401 without valid JWT
423
+ - **Setup required:** Express app with routes mounted, no auth token in request
424
+ - **Expected outcome:** GET /api/v1/orders returns `401 {error: 'Authentication required'}`, POST /api/v1/orders returns `401 {error: 'Authentication required'}`
425
+ - **Priority:** P1
426
+
427
+ ##### INT-AUTH-002: Refresh Token Rotation
428
+ - **Components involved:** authService + authController + Prisma (PostgreSQL)
429
+ - **What to validate:** Refreshing a token invalidates the old refresh token and issues a new pair
430
+ - **Setup required:** Seed database with User and valid refresh token record
431
+ - **Expected outcome:** After POST /api/v1/auth/refresh with old token, response contains new access token and new refresh token, old refresh token is marked invalid in database
432
+ - **Priority:** P1
433
+
434
+ ##### INT-DB-001: Prisma Transaction Rollback on Error
435
+ - **Components involved:** orderService + Prisma (PostgreSQL) transaction
436
+ - **What to validate:** If any step in order creation fails, the entire transaction rolls back
437
+ - **Setup required:** Seed database with Product (stock: 1). Attempt to create order with qty: 2 (should fail on inventory check).
438
+ - **Expected outcome:** No order created in database, product stock unchanged at 1, `InsufficientStockError` thrown
439
+ - **Priority:** P1
440
+
441
+ ---
442
+
443
+ ### API Tests (8 tests -- 18%)
444
+
445
+ ##### API-AUTH-001: Login with Valid Credentials
446
+ - **Method + Endpoint:** `POST /api/v1/auth/login`
447
+ - **Request body:** `{"email": "customer@shopflow.com", "password": "SecureP@ss123!"}`
448
+ - **Headers:** `Content-Type: application/json`
449
+ - **Expected status:** 200
450
+ - **Expected response:** `{token: string (JWT format), refreshToken: string (UUID format), user: {id: string, name: "Test Customer", email: "customer@shopflow.com"}}`
451
+ - **Priority:** P0
452
+
453
+ ##### API-AUTH-002: Login with Invalid Password
454
+ - **Method + Endpoint:** `POST /api/v1/auth/login`
455
+ - **Request body:** `{"email": "customer@shopflow.com", "password": "WrongPassword"}`
456
+ - **Headers:** `Content-Type: application/json`
457
+ - **Expected status:** 401
458
+ - **Expected response:** `{error: "Invalid email or password"}`
459
+ - **Priority:** P0
460
+
461
+ ##### API-AUTH-003: Register New User
462
+ - **Method + Endpoint:** `POST /api/v1/auth/register`
463
+ - **Request body:** `{"name": "New User", "email": "newuser@shopflow.com", "password": "SecureP@ss123!"}`
464
+ - **Headers:** `Content-Type: application/json`
465
+ - **Expected status:** 201
466
+ - **Expected response:** `{id: string (UUID), email: "newuser@shopflow.com", token: string (JWT format)}`
467
+ - **Priority:** P0
468
+
469
+ ##### API-ORDER-001: Create Order with Valid Items
470
+ - **Method + Endpoint:** `POST /api/v1/orders`
471
+ - **Request body:** `{"items": [{"productId": "prod_001", "qty": 2}], "shippingAddress": {"street": "123 Main St", "city": "San Francisco", "state": "CA", "zip": "94102"}}`
472
+ - **Headers:** `Authorization: Bearer {valid_token}`, `Content-Type: application/json`
473
+ - **Expected status:** 201
474
+ - **Expected response:** `{orderId: string (UUID), status: "pending", total: number (> 0), items: [{productId: "prod_001", qty: 2, unitPrice: number}]}`
475
+ - **Priority:** P0
476
+
477
+ ##### API-ORDER-002: Create Order Without Auth Token
478
+ - **Method + Endpoint:** `POST /api/v1/orders`
479
+ - **Request body:** `{"items": [{"productId": "prod_001", "qty": 1}], "shippingAddress": {...}}`
480
+ - **Headers:** None (no Authorization header)
481
+ - **Expected status:** 401
482
+ - **Expected response:** `{error: "Authentication required"}`
483
+ - **Priority:** P0
484
+
485
+ ##### API-ORDER-003: Update Order Status
486
+ - **Method + Endpoint:** `PATCH /api/v1/orders/ord_001/status`
487
+ - **Request body:** `{"status": "confirmed"}`
488
+ - **Headers:** `Authorization: Bearer {valid_token}`, `Content-Type: application/json`
489
+ - **Expected status:** 200
490
+ - **Expected response:** `{orderId: "ord_001", status: "confirmed", updatedAt: string (ISO date)}`
491
+ - **Priority:** P0
492
+
493
+ ##### API-PAY-001: Charge Payment for Order
494
+ - **Method + Endpoint:** `POST /api/v1/payments/charge`
495
+ - **Request body:** `{"orderId": "ord_001", "paymentMethodId": "pm_test_visa"}`
496
+ - **Headers:** `Authorization: Bearer {valid_token}`, `Content-Type: application/json`
497
+ - **Expected status:** 200
498
+ - **Expected response:** `{paymentId: string, status: "succeeded", amount: number (matches order total)}`
499
+ - **Priority:** P0
500
+
501
+ ##### API-PROD-001: List Products with Pagination
502
+ - **Method + Endpoint:** `GET /api/v1/products?page=1&limit=10`
503
+ - **Request body:** N/A
504
+ - **Headers:** None (public endpoint)
505
+ - **Expected status:** 200
506
+ - **Expected response:** `{products: [{id: string, name: string, price: number, sku: string, category: string}], total: number, page: 1}`
507
+ - **Priority:** P1
508
+
509
+ ---
510
+
511
+ ### E2E Smoke Tests (2 tests -- 4%)
512
+
513
+ ##### E2E-FLOW-001: Complete Purchase Flow
514
+ - **User journey:**
515
+ 1. User navigates to homepage (`/`)
516
+ 2. User clicks a product card to view product detail (`/products/:id`)
517
+ 3. User clicks "Add to Cart" button
518
+ 4. User navigates to cart page (`/cart`)
519
+ 5. User verifies item in cart with correct price and quantity
520
+ 6. User clicks "Checkout" button
521
+ 7. User fills checkout form (shipping address + payment card)
522
+ 8. User clicks "Place Order" button
523
+ 9. User sees order confirmation with order ID and "pending" status
524
+ - **Pages involved:** HomePage, ProductDetailPage, CartPage, CheckoutForm, OrderConfirmationPage
525
+ - **Expected outcome:** Order confirmation page displays with a valid order ID (UUID format), status shows "pending", order total matches the product price, and the user can navigate to order history (`/orders`) to see the new order listed
526
+ - **Priority:** P0
527
+
528
+ ##### E2E-FLOW-002: User Registration to First Order
529
+ - **User journey:**
530
+ 1. User navigates to registration page (`/register`)
531
+ 2. User fills registration form (name: "E2E Test User", email: "e2e-test@shopflow.com", password: "SecureP@ss123!")
532
+ 3. User clicks "Create Account" button
533
+ 4. User is redirected to homepage, logged in (sees user name in navbar)
534
+ 5. User adds a product to cart
535
+ 6. User completes checkout flow
536
+ 7. User navigates to order history (`/orders`)
537
+ 8. User sees the new order with correct status
538
+ - **Pages involved:** RegisterPage, HomePage, ProductDetailPage, CartPage, CheckoutForm, OrderConfirmationPage, OrderHistoryPage
539
+ - **Expected outcome:** Order history page shows exactly 1 order with status "pending", the navbar displays "E2E Test User", and the user can log out and log back in successfully
540
+ - **Priority:** P0
541
+
542
+ ---
543
+
544
+ ## Guidelines
545
+
546
+ ### DO
547
+
548
+ - **DO** use concrete values in every input and expected outcome field -- `239.47`, not "the correct total"
549
+ - **DO** include both happy-path and error cases for each module (at minimum 1 success + 1 failure per function)
550
+ - **DO** specify exact error types and messages in expected outcomes -- `Throws InvalidTransitionError` is better than `Throws an error`
551
+ - **DO** fill in the Mocks field for every test case -- "None (pure function)" is a valid and useful answer
552
+ - **DO** group unit tests by module with clear section headers
553
+ - **DO** ensure test IDs are unique across the entire inventory -- no duplicate `UT-PRICE-001` in different sections
554
+ - **DO** match test targets to the Top 10 Unit Test Targets from `QA_ANALYSIS.md`
555
+ - **DO** include the exact JSON payload for API test request bodies
556
+
557
+ ### DON'T
558
+
559
+ - **DON'T** write "returns correct data" as an expected outcome -- specify the exact data
560
+ - **DON'T** write "handles error properly" -- specify what "properly" means (status code, error message, state change)
561
+ - **DON'T** skip the Mocks field -- downstream agents need to know what to mock
562
+ - **DON'T** use "valid data" or "correct input" as concrete inputs -- use actual values
563
+ - **DON'T** assign P2 to payment or authentication tests -- those are always P0
564
+ - **DON'T** include more than 8 E2E tests -- if you need more, some should be API or integration tests instead
565
+ - **DON'T** create test IDs that don't follow the naming convention (UT-MODULE-NNN, INT-MODULE-NNN, API-RESOURCE-NNN, E2E-FLOW-NNN)
566
+
567
+ ---
568
+
569
+ ## Quality Gate
570
+
571
+ Before delivering this artifact, verify all of the following:
572
+
573
+ - [ ] Every test case has a unique ID following the naming convention
574
+ - [ ] Every test case has an explicit expected outcome with a concrete value (not "works correctly")
575
+ - [ ] Every unit test has all 7 mandatory fields filled (ID, target, what to validate, inputs, mocks, outcome, priority)
576
+ - [ ] Every API test includes exact HTTP method, endpoint, request body, and expected status code
577
+ - [ ] Summary counts match the actual number of test cases in each section
578
+ - [ ] Summary percentages approximately match the testing pyramid (60-70% unit, 10-15% integration, 20-25% API, 3-5% E2E)
579
+ - [ ] Priority is assigned to every test case (P0, P1, or P2)
580
+ - [ ] No expected outcome contains vague words: "correct", "proper", "appropriate", "valid", or "works" without defining what those mean
581
+ - [ ] Test targets reference file paths and function names from `QA_ANALYSIS.md`
582
+ - [ ] Both happy-path and error cases are included for critical modules (auth, payments, orders)