cursor-quality-suite 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.
- package/README.md +155 -0
- package/bin/cli.js +303 -0
- package/commands/code-quality/churn-map.md +431 -0
- package/commands/code-quality/code-standards.md +219 -0
- package/commands/code-quality/pattern-drift.md +295 -0
- package/commands/code-quality/visualize-architecture.md +464 -0
- package/commands/testing/mutation-audit.md +229 -0
- package/commands/testing/risk-test-gen.md +232 -0
- package/commands/testing/write-unit-tests.md +42 -0
- package/package.json +36 -0
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Generate Mermaid diagrams for code architecture visualization (v4.1 Frontend-Enhanced)
|
|
3
|
+
category: Analysis & Documentation
|
|
4
|
+
aliases: [diagram, architecture, mermaid, sequence, class, xstate, dataflow]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Visualize Architecture - Generate Diagrams (v4.1)
|
|
8
|
+
|
|
9
|
+
Create visual diagrams (Mermaid) for architecture, data flow, component relationships, and **frontend-specific patterns**.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
/visualize-architecture {SCOPE}
|
|
15
|
+
/visualize-architecture {SCOPE} --type={diagram_type}
|
|
16
|
+
/visualize-architecture {SCOPE} --data-flow # Props vs Context analysis
|
|
17
|
+
/visualize-architecture {SCOPE} --boundaries # Suspense/Error boundaries
|
|
18
|
+
/visualize-architecture {SCOPE} --xstate # XState-compatible state chart
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Diagram Types
|
|
22
|
+
|
|
23
|
+
### Available Types
|
|
24
|
+
|
|
25
|
+
| Type | Use Case |
|
|
26
|
+
| ------------ | ------------------------------------------- |
|
|
27
|
+
| `component` | Component hierarchy and relationships |
|
|
28
|
+
| `sequence` | Request/data flow through system |
|
|
29
|
+
| `class` | Class/interface relationships |
|
|
30
|
+
| `state` | State machine for complex logic |
|
|
31
|
+
| `flowchart` | Decision trees and workflows |
|
|
32
|
+
| `er` | Entity relationships (data models) |
|
|
33
|
+
| `dataflow` | **NEW:** Props vs Context data flow |
|
|
34
|
+
| `boundaries` | **NEW:** Suspense/ErrorBoundary locations |
|
|
35
|
+
| `xstate` | **NEW:** XState-compatible state definition |
|
|
36
|
+
|
|
37
|
+
### Auto-Detection
|
|
38
|
+
|
|
39
|
+
If `--type` not specified, I'll auto-detect based on scope:
|
|
40
|
+
|
|
41
|
+
- React components → `component` diagram
|
|
42
|
+
- API/hooks → `sequence` diagram
|
|
43
|
+
- Types/interfaces → `class` diagram
|
|
44
|
+
- State machines / reducers → `state` diagram
|
|
45
|
+
- Context providers → `dataflow` diagram
|
|
46
|
+
|
|
47
|
+
## Examples
|
|
48
|
+
|
|
49
|
+
### Component Hierarchy
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
/visualize-architecture src/features/checkout/src/components/Packages
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Output:
|
|
56
|
+
|
|
57
|
+
```mermaid
|
|
58
|
+
graph TD
|
|
59
|
+
subgraph Packages
|
|
60
|
+
A[PackagesV2] --> B[ProtectionPackageCard]
|
|
61
|
+
A --> C[ExtrasPackageCard]
|
|
62
|
+
A --> D[PackagesSkeleton]
|
|
63
|
+
|
|
64
|
+
B --> E[LineItems]
|
|
65
|
+
B --> F[PackageHeader]
|
|
66
|
+
B --> G[PackagePricing]
|
|
67
|
+
|
|
68
|
+
E --> H[LineItem]
|
|
69
|
+
E --> I[TooltipTitle]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
style A fill:#ff6b35
|
|
73
|
+
style B fill:#4ecdc4
|
|
74
|
+
style C fill:#4ecdc4
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Sequence Diagram (Data Flow)
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
/visualize-architecture useBookingData --type=sequence
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Output:
|
|
84
|
+
|
|
85
|
+
```mermaid
|
|
86
|
+
sequenceDiagram
|
|
87
|
+
participant C as Component
|
|
88
|
+
participant H as useBookingData
|
|
89
|
+
participant API as BookingAPI
|
|
90
|
+
participant S as Store
|
|
91
|
+
|
|
92
|
+
C->>H: Initialize hook
|
|
93
|
+
H->>API: fetchBooking(id)
|
|
94
|
+
API-->>H: BookingResponse
|
|
95
|
+
H->>S: updateStore(data)
|
|
96
|
+
S-->>C: Re-render with data
|
|
97
|
+
|
|
98
|
+
Note over H: AbortController cleanup on unmount
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### State Diagram
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
/visualize-architecture BookingFlow --type=state
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Output:
|
|
108
|
+
|
|
109
|
+
```mermaid
|
|
110
|
+
stateDiagram-v2
|
|
111
|
+
[*] --> Idle
|
|
112
|
+
Idle --> Loading: fetchBooking
|
|
113
|
+
Loading --> Success: data received
|
|
114
|
+
Loading --> Error: request failed
|
|
115
|
+
Success --> Updating: modifyBooking
|
|
116
|
+
Updating --> Success: update complete
|
|
117
|
+
Error --> Loading: retry
|
|
118
|
+
Success --> [*]: complete
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Class Diagram (Types)
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
/visualize-architecture src/types/Booking --type=class
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Output:
|
|
128
|
+
|
|
129
|
+
```mermaid
|
|
130
|
+
classDiagram
|
|
131
|
+
class Booking {
|
|
132
|
+
+string id
|
|
133
|
+
+BookingStatus status
|
|
134
|
+
+Vehicle vehicle
|
|
135
|
+
+Customer customer
|
|
136
|
+
+getTotal() number
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
class Vehicle {
|
|
140
|
+
+string id
|
|
141
|
+
+string name
|
|
142
|
+
+VehicleCategory category
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
class Customer {
|
|
146
|
+
+string id
|
|
147
|
+
+string email
|
|
148
|
+
+Address address
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
Booking "1" --> "1" Vehicle
|
|
152
|
+
Booking "1" --> "1" Customer
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## AI Execution
|
|
156
|
+
|
|
157
|
+
When user runs `/visualize-architecture {SCOPE}`:
|
|
158
|
+
|
|
159
|
+
### Step 1: Analyze Scope
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
1. Identify files/folders in scope
|
|
163
|
+
2. Detect primary pattern (components, hooks, types)
|
|
164
|
+
3. Select appropriate diagram type
|
|
165
|
+
4. Extract relationships
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Step 2: Generate Diagram
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
1. Parse code structure
|
|
172
|
+
2. Identify nodes (components, functions, types)
|
|
173
|
+
3. Map relationships (imports, props, calls)
|
|
174
|
+
4. Generate Mermaid syntax
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Step 3: Render
|
|
178
|
+
|
|
179
|
+
```mermaid
|
|
180
|
+
{generated_diagram}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Step 4: Offer Variations
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
📊 Architecture Diagram Generated
|
|
187
|
+
|
|
188
|
+
Variations available:
|
|
189
|
+
1. Add more detail (show props/methods)
|
|
190
|
+
2. Simplify (high-level only)
|
|
191
|
+
3. Different view (sequence instead of component)
|
|
192
|
+
4. Focus on specific path
|
|
193
|
+
|
|
194
|
+
Which variation? (1/2/3/4/done)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Integration
|
|
198
|
+
|
|
199
|
+
### With Documentation
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
/visualize-architecture {SCOPE} --output=docs/architecture/
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Creates:
|
|
206
|
+
|
|
207
|
+
- `{scope}-diagram.md` with Mermaid
|
|
208
|
+
- Links from relevant component docs
|
|
209
|
+
|
|
210
|
+
### With PR Description
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
/visualize-architecture --pr-diff
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Generates diagram showing:
|
|
217
|
+
|
|
218
|
+
- Files changed
|
|
219
|
+
- Relationships affected
|
|
220
|
+
- New connections added
|
|
221
|
+
|
|
222
|
+
## Tips
|
|
223
|
+
|
|
224
|
+
1. **Start broad, then narrow**
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
/visualize-architecture src/features/checkout # Overview
|
|
228
|
+
/visualize-architecture src/features/checkout/src/hooks # Focus
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
2. **Use for onboarding**
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
/visualize-architecture --key-flows
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Generates diagrams for critical paths
|
|
238
|
+
|
|
239
|
+
3. **Before refactoring**
|
|
240
|
+
```
|
|
241
|
+
/visualize-architecture {target} --show-coupling
|
|
242
|
+
```
|
|
243
|
+
Highlights tightly coupled components
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## 🆕 Frontend-Specific Diagrams (v4.1)
|
|
248
|
+
|
|
249
|
+
### Data Flow Diagram (Props vs Context)
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
/visualize-architecture src/features/checkout/src/components/Checkout --data-flow
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Output:
|
|
256
|
+
|
|
257
|
+
```mermaid
|
|
258
|
+
graph TD
|
|
259
|
+
subgraph "Data Sources"
|
|
260
|
+
API[BookingAPI]
|
|
261
|
+
CTX[BookingContext]
|
|
262
|
+
PROPS[Parent Props]
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
subgraph "Components"
|
|
266
|
+
A[CheckoutPage]
|
|
267
|
+
B[VehicleSection]
|
|
268
|
+
C[ProtectionSection]
|
|
269
|
+
D[PaymentSection]
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
API -->|"useBookingData()"| A
|
|
273
|
+
A -->|"Context.Provider"| CTX
|
|
274
|
+
|
|
275
|
+
CTX -.->|"useBooking()"| B
|
|
276
|
+
CTX -.->|"useBooking()"| C
|
|
277
|
+
CTX -.->|"useBooking()"| D
|
|
278
|
+
|
|
279
|
+
A -->|"vehicle: Vehicle"| B
|
|
280
|
+
A -->|"packages: Package[]"| C
|
|
281
|
+
|
|
282
|
+
style CTX fill:#e1f5fe
|
|
283
|
+
style PROPS fill:#fff3e0
|
|
284
|
+
|
|
285
|
+
classDef contextData stroke:#0288d1,stroke-width:2px
|
|
286
|
+
classDef propData stroke:#ff9800,stroke-width:2px
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
**Legend:**
|
|
290
|
+
|
|
291
|
+
- Solid lines = Props drilling
|
|
292
|
+
- Dashed lines = Context consumption
|
|
293
|
+
- Blue = Context-based data
|
|
294
|
+
- Orange = Prop-based data
|
|
295
|
+
|
|
296
|
+
### Suspense & Error Boundaries Map
|
|
297
|
+
|
|
298
|
+
```
|
|
299
|
+
/visualize-architecture src/features/checkout --boundaries
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Output:
|
|
303
|
+
|
|
304
|
+
```mermaid
|
|
305
|
+
graph TD
|
|
306
|
+
subgraph "App Root"
|
|
307
|
+
ROOT[App]
|
|
308
|
+
EB1[ErrorBoundary: AppError]
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
subgraph "Routes"
|
|
312
|
+
R1[/checkout]
|
|
313
|
+
R2[/checkout/payment]
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
subgraph "Suspense Zones"
|
|
317
|
+
S1[Suspense: CheckoutSkeleton]
|
|
318
|
+
S2[Suspense: PaymentSkeleton]
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
subgraph "Async Components"
|
|
322
|
+
AC1[VehicleDetails - lazy]
|
|
323
|
+
AC2[PackageList - lazy]
|
|
324
|
+
AC3[PaymentForm - lazy]
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
ROOT --> EB1
|
|
328
|
+
EB1 --> R1
|
|
329
|
+
EB1 --> R2
|
|
330
|
+
|
|
331
|
+
R1 --> S1
|
|
332
|
+
S1 --> AC1
|
|
333
|
+
S1 --> AC2
|
|
334
|
+
|
|
335
|
+
R2 --> S2
|
|
336
|
+
S2 --> AC3
|
|
337
|
+
|
|
338
|
+
style EB1 fill:#ffcdd2
|
|
339
|
+
style S1 fill:#c8e6c9
|
|
340
|
+
style S2 fill:#c8e6c9
|
|
341
|
+
|
|
342
|
+
classDef errorBoundary fill:#ffcdd2,stroke:#c62828
|
|
343
|
+
classDef suspense fill:#c8e6c9,stroke:#2e7d32
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
**Analysis includes:**
|
|
347
|
+
|
|
348
|
+
- ErrorBoundary coverage (red zones)
|
|
349
|
+
- Suspense boundaries (green zones)
|
|
350
|
+
- Lazy-loaded components
|
|
351
|
+
- Missing boundaries (warnings)
|
|
352
|
+
|
|
353
|
+
### XState-Compatible State Chart
|
|
354
|
+
|
|
355
|
+
```
|
|
356
|
+
/visualize-architecture useCheckoutFlow --xstate
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Output:
|
|
360
|
+
|
|
361
|
+
```mermaid
|
|
362
|
+
stateDiagram-v2
|
|
363
|
+
[*] --> idle
|
|
364
|
+
|
|
365
|
+
state idle {
|
|
366
|
+
[*] --> ready
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
idle --> loading: FETCH_VEHICLE
|
|
370
|
+
loading --> vehicleLoaded: VEHICLE_SUCCESS
|
|
371
|
+
loading --> error: VEHICLE_ERROR
|
|
372
|
+
|
|
373
|
+
vehicleLoaded --> selectingPackages: CONTINUE
|
|
374
|
+
selectingPackages --> packageSelected: SELECT_PACKAGE
|
|
375
|
+
packageSelected --> selectingPackages: CHANGE_PACKAGE
|
|
376
|
+
packageSelected --> payment: CONTINUE_TO_PAYMENT
|
|
377
|
+
|
|
378
|
+
payment --> processing: SUBMIT
|
|
379
|
+
processing --> success: PAYMENT_SUCCESS
|
|
380
|
+
processing --> error: PAYMENT_ERROR
|
|
381
|
+
|
|
382
|
+
error --> idle: RETRY
|
|
383
|
+
success --> [*]
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
**XState Export:**
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
// Generated XState machine definition
|
|
390
|
+
export const checkoutMachine = createMachine({
|
|
391
|
+
id: 'checkout',
|
|
392
|
+
initial: 'idle',
|
|
393
|
+
states: {
|
|
394
|
+
idle: {
|
|
395
|
+
on: { FETCH_VEHICLE: 'loading' },
|
|
396
|
+
},
|
|
397
|
+
loading: {
|
|
398
|
+
invoke: {
|
|
399
|
+
src: 'fetchVehicle',
|
|
400
|
+
onDone: 'vehicleLoaded',
|
|
401
|
+
onError: 'error',
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
// ... full machine
|
|
405
|
+
},
|
|
406
|
+
});
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Component Render Tree with Re-render Analysis
|
|
410
|
+
|
|
411
|
+
```
|
|
412
|
+
/visualize-architecture {SCOPE} --render-analysis
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
Shows:
|
|
416
|
+
|
|
417
|
+
- Which components re-render on state changes
|
|
418
|
+
- Memo boundaries
|
|
419
|
+
- Context consumer impact zones
|
|
420
|
+
|
|
421
|
+
```mermaid
|
|
422
|
+
graph TD
|
|
423
|
+
subgraph "Re-renders on booking change"
|
|
424
|
+
A[CheckoutPage 🔄]
|
|
425
|
+
B[VehicleSection 🔄]
|
|
426
|
+
C[PriceDisplay 🔄]
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
subgraph "Memoized (stable)"
|
|
430
|
+
D[Header ⚡]
|
|
431
|
+
E[Footer ⚡]
|
|
432
|
+
F[StaticContent ⚡]
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
A --> B
|
|
436
|
+
A --> C
|
|
437
|
+
A --> D
|
|
438
|
+
A --> E
|
|
439
|
+
|
|
440
|
+
style A fill:#ffecb3
|
|
441
|
+
style B fill:#ffecb3
|
|
442
|
+
style C fill:#ffecb3
|
|
443
|
+
style D fill:#c8e6c9
|
|
444
|
+
style E fill:#c8e6c9
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
**Legend:**
|
|
448
|
+
|
|
449
|
+
- 🔄 Yellow = Re-renders on state change
|
|
450
|
+
- ⚡ Green = Memoized / Stable
|
|
451
|
+
|
|
452
|
+
## Integration with /plan-and-budget
|
|
453
|
+
|
|
454
|
+
When running `/plan-and-budget`, optionally generate:
|
|
455
|
+
|
|
456
|
+
```
|
|
457
|
+
/plan-and-budget "Add new feature" --with-diagram
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
Includes architecture diagram in the plan showing:
|
|
461
|
+
|
|
462
|
+
- Current state
|
|
463
|
+
- Proposed changes
|
|
464
|
+
- Impact zones
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Run mutation tests to verify test quality, catch shallow coverage
|
|
3
|
+
category: Testing
|
|
4
|
+
aliases: [mutation, test-quality]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Mutation Audit - Test Quality via Mutation Testing
|
|
8
|
+
|
|
9
|
+
Run mutation tests to verify test suite effectiveness and catch shallow coverage.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
/mutation-audit {FILE_PATH}
|
|
15
|
+
/mutation-audit {PR_NUMBER}
|
|
16
|
+
/mutation-audit --scope changed # Only mutate changed files
|
|
17
|
+
/mutation-audit --threshold 80 # Fail if mutation score < 80%
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## What This Does
|
|
21
|
+
|
|
22
|
+
1. **Introduces mutations** - Small code changes (mutants)
|
|
23
|
+
2. **Runs test suite** - Checks if tests catch mutations
|
|
24
|
+
3. **Calculates mutation score** - % of mutants killed
|
|
25
|
+
4. **Identifies weak tests** - Tests that don't catch logic changes
|
|
26
|
+
5. **Suggests improvements** - Better assertions for coverage
|
|
27
|
+
|
|
28
|
+
## Mutation Types
|
|
29
|
+
|
|
30
|
+
| Mutation | Example | What It Tests |
|
|
31
|
+
| --------------- | ----------------------------- | -------------------- |
|
|
32
|
+
| **Boundary** | `>` → `>=` | Off-by-one errors |
|
|
33
|
+
| **Negation** | `true` → `false` | Boolean logic |
|
|
34
|
+
| **Arithmetic** | `+` → `-` | Math operations |
|
|
35
|
+
| **Return** | `return x` → `return null` | Return value usage |
|
|
36
|
+
| **Conditional** | `if(a && b)` → `if(a \|\| b)` | Logic branches |
|
|
37
|
+
| **Remove** | `fn()` → `// fn()` | Side effect reliance |
|
|
38
|
+
|
|
39
|
+
## Output Format
|
|
40
|
+
|
|
41
|
+
````
|
|
42
|
+
📋 Running mutation audit on PackagesV2.tsx...
|
|
43
|
+
|
|
44
|
+
════════════════════════════════════════════════════════════════
|
|
45
|
+
MUTATION TESTING RESULTS
|
|
46
|
+
════════════════════════════════════════════════════════════════
|
|
47
|
+
|
|
48
|
+
File: src/features/checkout/src/components/CoverageAndAddOns/PackagesV2.tsx
|
|
49
|
+
Tests: PackagesV2.test.tsx (12 test cases)
|
|
50
|
+
|
|
51
|
+
## Summary
|
|
52
|
+
|
|
53
|
+
| Metric | Value |
|
|
54
|
+
|--------|-------|
|
|
55
|
+
| Total Mutants | 45 |
|
|
56
|
+
| Killed | 32 |
|
|
57
|
+
| Survived | 13 |
|
|
58
|
+
| **Mutation Score** | **71%** 🟠 |
|
|
59
|
+
|
|
60
|
+
## Survived Mutants (Tests Failed to Catch)
|
|
61
|
+
|
|
62
|
+
### 🔴 Critical: Logic not tested
|
|
63
|
+
|
|
64
|
+
| Line | Original | Mutation | Why It Matters |
|
|
65
|
+
|------|----------|----------|----------------|
|
|
66
|
+
| 78 | `price > 0` | `price >= 0` | Zero-price packages slip through |
|
|
67
|
+
| 112 | `isSelected && isAvailable` | `isSelected \|\| isAvailable` | Wrong selection state |
|
|
68
|
+
| 145 | `return total` | `return 0` | Total calculation not verified |
|
|
69
|
+
|
|
70
|
+
### 🟠 Medium: Weak assertions
|
|
71
|
+
|
|
72
|
+
| Line | Original | Mutation | Issue |
|
|
73
|
+
|------|----------|----------|-------|
|
|
74
|
+
| 56 | `setLoading(true)` | `// removed` | Loading state not asserted |
|
|
75
|
+
| 89 | `onSelect(pkg)` | `// removed` | Callback not verified |
|
|
76
|
+
|
|
77
|
+
### 🟢 Minor: Edge cases
|
|
78
|
+
|
|
79
|
+
| Line | Original | Mutation | Issue |
|
|
80
|
+
|------|----------|----------|-------|
|
|
81
|
+
| 23 | `packages.length` | `packages.length + 1` | Off-by-one not tested |
|
|
82
|
+
|
|
83
|
+
════════════════════════════════════════════════════════════════
|
|
84
|
+
SURVIVING MUTANT DETAILS
|
|
85
|
+
════════════════════════════════════════════════════════════════
|
|
86
|
+
|
|
87
|
+
## Mutant #1: Boundary Condition (Line 78)
|
|
88
|
+
|
|
89
|
+
**Original:**
|
|
90
|
+
```typescript
|
|
91
|
+
if (price > 0) {
|
|
92
|
+
showPrice = true;
|
|
93
|
+
}
|
|
94
|
+
````
|
|
95
|
+
|
|
96
|
+
**Mutation:**
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
if (price >= 0) {
|
|
100
|
+
// Changed > to >=
|
|
101
|
+
showPrice = true;
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Why survived:** No test checks behavior when `price === 0`
|
|
106
|
+
|
|
107
|
+
**Suggested test:**
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
it('should hide price when price is exactly 0', () => {
|
|
111
|
+
render(<PackagesV2 packages={[{ price: 0 }]} />);
|
|
112
|
+
expect(screen.queryByTestId('price-display')).not.toBeInTheDocument();
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Mutant #2: Callback Removal (Line 89)
|
|
119
|
+
|
|
120
|
+
**Original:**
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
const handleSelect = (pkg: IPackage) => {
|
|
124
|
+
onSelect(pkg);
|
|
125
|
+
setSelected(pkg.id);
|
|
126
|
+
};
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Mutation:**
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
const handleSelect = (pkg: IPackage) => {
|
|
133
|
+
// onSelect(pkg); // Removed
|
|
134
|
+
setSelected(pkg.id);
|
|
135
|
+
};
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Why survived:** Test only checks UI state, not callback invocation
|
|
139
|
+
|
|
140
|
+
**Suggested test:**
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
it('should call onSelect with package when clicked', () => {
|
|
144
|
+
const onSelect = jest.fn();
|
|
145
|
+
render(<PackagesV2 onSelect={onSelect} packages={mockPackages} />);
|
|
146
|
+
|
|
147
|
+
userEvent.click(screen.getByTestId('package-premium'));
|
|
148
|
+
|
|
149
|
+
expect(onSelect).toHaveBeenCalledWith(
|
|
150
|
+
expect.objectContaining({ id: 'premium' })
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
════════════════════════════════════════════════════════════════
|
|
156
|
+
RECOMMENDATIONS
|
|
157
|
+
════════════════════════════════════════════════════════════════
|
|
158
|
+
|
|
159
|
+
## Test Quality Score: 71% (🟠 Needs Improvement)
|
|
160
|
+
|
|
161
|
+
### Priority Fixes:
|
|
162
|
+
|
|
163
|
+
1. **Add boundary tests** (3 mutants)
|
|
164
|
+
|
|
165
|
+
- Test `price === 0` case
|
|
166
|
+
- Test empty `packages` array
|
|
167
|
+
- Test single-item arrays
|
|
168
|
+
|
|
169
|
+
2. **Assert callbacks** (2 mutants)
|
|
170
|
+
|
|
171
|
+
- Verify `onSelect` is called
|
|
172
|
+
- Verify `onChange` is called with correct args
|
|
173
|
+
|
|
174
|
+
3. **Check return values** (1 mutant)
|
|
175
|
+
- Assert calculated total
|
|
176
|
+
- Don't just check "truthy"
|
|
177
|
+
|
|
178
|
+
### Good Practices Already Present:
|
|
179
|
+
|
|
180
|
+
✅ Error states tested
|
|
181
|
+
✅ Loading states tested
|
|
182
|
+
✅ Render without crash
|
|
183
|
+
|
|
184
|
+
### Target: 85% mutation score for critical paths
|
|
185
|
+
|
|
186
|
+
════════════════════════════════════════════════════════════════
|
|
187
|
+
MUTATION SCORE HISTORY
|
|
188
|
+
════════════════════════════════════════════════════════════════
|
|
189
|
+
|
|
190
|
+
| Date | Score | Change |
|
|
191
|
+
| ------------- | ----- | ------ |
|
|
192
|
+
| 2024-12-23 | 71% | - |
|
|
193
|
+
| (After fixes) | ~85% | +14% |
|
|
194
|
+
|
|
195
|
+
````
|
|
196
|
+
|
|
197
|
+
## Commands Used
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
# Using Stryker for mutation testing
|
|
201
|
+
npx stryker run --mutate "src/features/checkout/src/**/*.tsx"
|
|
202
|
+
|
|
203
|
+
# Quick mutation check (fewer mutators)
|
|
204
|
+
npx stryker run --mutators "['BooleanLiteral', 'ConditionalExpression']"
|
|
205
|
+
|
|
206
|
+
# Generate HTML report
|
|
207
|
+
npx stryker run --reporters html
|
|
208
|
+
````
|
|
209
|
+
|
|
210
|
+
## Mutation Score Thresholds
|
|
211
|
+
|
|
212
|
+
| Score | Rating | Action |
|
|
213
|
+
| ------- | ------------ | ------------------------ |
|
|
214
|
+
| 90-100% | ✅ Excellent | Maintain |
|
|
215
|
+
| 80-89% | ✅ Good | Minor improvements |
|
|
216
|
+
| 70-79% | 🟠 Fair | Add missing assertions |
|
|
217
|
+
| 60-69% | 🟠 Poor | Significant test gaps |
|
|
218
|
+
| <60% | 🔴 Critical | Major refactoring needed |
|
|
219
|
+
|
|
220
|
+
## AI Execution
|
|
221
|
+
|
|
222
|
+
When user runs `/mutation-audit {PATH}`:
|
|
223
|
+
|
|
224
|
+
1. **Parse code** - Identify mutable expressions
|
|
225
|
+
2. **Generate mutants** - Create code variations
|
|
226
|
+
3. **Run tests** - Execute against mutants
|
|
227
|
+
4. **Analyze survivors** - Why tests didn't catch them
|
|
228
|
+
5. **Generate suggestions** - Specific test improvements
|
|
229
|
+
6. **Report score** - With historical comparison
|