omgkit 2.22.7 โ 2.22.9
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/lib/cli.js +2 -1
- package/package.json +2 -2
- package/plugin/commands/dev/test-write.md +216 -0
- package/plugin/registry.yaml +2 -2
- package/templates/CLAUDE.md +75 -1
- package/templates/stdrules/TESTING_STANDARDS.md +271 -0
package/lib/cli.js
CHANGED
|
@@ -396,7 +396,8 @@ export function initProject(options = {}) {
|
|
|
396
396
|
{ src: 'devlogs/README.md', dest: '.omgkit/devlogs/README.md' },
|
|
397
397
|
{ src: 'stdrules/README.md', dest: '.omgkit/stdrules/README.md' },
|
|
398
398
|
{ src: 'stdrules/SKILL_STANDARDS.md', dest: '.omgkit/stdrules/SKILL_STANDARDS.md' },
|
|
399
|
-
{ src: 'stdrules/BEFORE_COMMIT.md', dest: '.omgkit/stdrules/BEFORE_COMMIT.md' }
|
|
399
|
+
{ src: 'stdrules/BEFORE_COMMIT.md', dest: '.omgkit/stdrules/BEFORE_COMMIT.md' },
|
|
400
|
+
{ src: 'stdrules/TESTING_STANDARDS.md', dest: '.omgkit/stdrules/TESTING_STANDARDS.md' }
|
|
400
401
|
];
|
|
401
402
|
|
|
402
403
|
templates.forEach(({ src, dest }) => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omgkit",
|
|
3
|
-
"version": "2.22.
|
|
4
|
-
"description": "Omega-Level Development Kit - AI Team System for Claude Code. 41 agents,
|
|
3
|
+
"version": "2.22.9",
|
|
4
|
+
"description": "Omega-Level Development Kit - AI Team System for Claude Code. 41 agents, 151 commands, 151 skills, 67 workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
7
7
|
"ai",
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Write comprehensive tests following OMGKIT Omega Testing methodology
|
|
3
|
+
allowed-tools: Task, Read, Write, Bash, Glob
|
|
4
|
+
argument-hint: <function-or-file>
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Write Omega-Level Tests
|
|
8
|
+
|
|
9
|
+
You are writing tests for the specified function, component, or file using the OMGKIT Omega Testing methodology.
|
|
10
|
+
|
|
11
|
+
## MANDATORY: Read First
|
|
12
|
+
Before writing any test, read `.omgkit/stdrules/TESTING_STANDARDS.md` for full methodology.
|
|
13
|
+
|
|
14
|
+
## Execution Steps
|
|
15
|
+
|
|
16
|
+
### Step 1: Analyze Target
|
|
17
|
+
1. Read the target function/component code
|
|
18
|
+
2. Identify input types and expected outputs
|
|
19
|
+
3. List all code paths (if/else, try/catch, loops)
|
|
20
|
+
4. Identify user input points (security-relevant)
|
|
21
|
+
|
|
22
|
+
### Step 2: Apply 4D Testing
|
|
23
|
+
|
|
24
|
+
**Dimension 1: Accuracy**
|
|
25
|
+
- Unit tests for each function
|
|
26
|
+
- Integration tests for component interaction
|
|
27
|
+
- E2E tests for critical flows
|
|
28
|
+
|
|
29
|
+
**Dimension 2: Performance** (if critical path)
|
|
30
|
+
```javascript
|
|
31
|
+
it('should complete within SLA', async () => {
|
|
32
|
+
const start = performance.now();
|
|
33
|
+
await operation();
|
|
34
|
+
expect(performance.now() - start).toBeLessThan(100);
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Dimension 3: Security** (if user input)
|
|
39
|
+
```javascript
|
|
40
|
+
const MALICIOUS = [
|
|
41
|
+
"'; DROP TABLE users; --",
|
|
42
|
+
"<script>alert('xss')</script>",
|
|
43
|
+
"../../../etc/passwd"
|
|
44
|
+
];
|
|
45
|
+
MALICIOUS.forEach(input => {
|
|
46
|
+
it(`should sanitize: ${input.slice(0, 20)}...`, () => {
|
|
47
|
+
expect(() => processInput(input)).not.toThrow();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Dimension 4: Accessibility** (if UI)
|
|
53
|
+
- Keyboard navigation
|
|
54
|
+
- ARIA labels
|
|
55
|
+
- Screen reader compatibility
|
|
56
|
+
|
|
57
|
+
### Step 3: Boundary Value Testing (NEVER SKIP)
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
// Numbers
|
|
61
|
+
[0, -0, 1, -1, Number.MAX_SAFE_INTEGER, NaN, Infinity]
|
|
62
|
+
|
|
63
|
+
// Strings
|
|
64
|
+
['', ' ', 'a'.repeat(10000), '\n\t\r', '๐ฎ', '\x00']
|
|
65
|
+
|
|
66
|
+
// Arrays
|
|
67
|
+
[[], [null], [undefined], Array(10000).fill(0)]
|
|
68
|
+
|
|
69
|
+
// Objects
|
|
70
|
+
[{}, null, undefined, {nested: {deep: {}}}]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Step 4: Test Structure
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
describe('FunctionName', () => {
|
|
77
|
+
// Setup
|
|
78
|
+
beforeEach(() => {});
|
|
79
|
+
|
|
80
|
+
// 1. Happy path
|
|
81
|
+
describe('when given valid input', () => {
|
|
82
|
+
it('should return expected output', () => {});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// 2. Edge cases
|
|
86
|
+
describe('edge cases', () => {
|
|
87
|
+
it('should handle empty input', () => {});
|
|
88
|
+
it('should handle null/undefined', () => {});
|
|
89
|
+
it('should handle boundary values', () => {});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// 3. Error handling
|
|
93
|
+
describe('error handling', () => {
|
|
94
|
+
it('should throw on invalid input', () => {});
|
|
95
|
+
it('should return error for edge cases', () => {});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// 4. Security (if applicable)
|
|
99
|
+
describe('security', () => {
|
|
100
|
+
it('should sanitize malicious input', () => {});
|
|
101
|
+
it('should prevent injection attacks', () => {});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// 5. Performance (if critical)
|
|
105
|
+
describe('performance', () => {
|
|
106
|
+
it('should complete within SLA', () => {});
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Step 5: Run and Verify
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Run tests
|
|
115
|
+
npm test
|
|
116
|
+
|
|
117
|
+
# Check coverage
|
|
118
|
+
npm run test:coverage
|
|
119
|
+
|
|
120
|
+
# Run mutation testing (if available)
|
|
121
|
+
npx stryker run
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Output Checklist
|
|
125
|
+
|
|
126
|
+
Before completing, verify:
|
|
127
|
+
- [ ] Happy path tested
|
|
128
|
+
- [ ] All edge cases covered (empty, null, undefined, boundaries)
|
|
129
|
+
- [ ] Error handling tested
|
|
130
|
+
- [ ] Security inputs tested (if user-facing)
|
|
131
|
+
- [ ] Coverage > 80%
|
|
132
|
+
- [ ] Tests are Fast, Independent, Repeatable
|
|
133
|
+
|
|
134
|
+
## Example Output
|
|
135
|
+
|
|
136
|
+
For a function `calculateDiscount(price, percentage)`:
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
import { describe, it, expect } from 'vitest';
|
|
140
|
+
import { calculateDiscount } from './pricing';
|
|
141
|
+
|
|
142
|
+
describe('calculateDiscount', () => {
|
|
143
|
+
// Happy path
|
|
144
|
+
it('should calculate 10% discount correctly', () => {
|
|
145
|
+
expect(calculateDiscount(100, 10)).toBe(90);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should calculate 50% discount correctly', () => {
|
|
149
|
+
expect(calculateDiscount(200, 50)).toBe(100);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Edge cases - boundaries
|
|
153
|
+
describe('boundary values', () => {
|
|
154
|
+
it('should handle 0% discount', () => {
|
|
155
|
+
expect(calculateDiscount(100, 0)).toBe(100);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should handle 100% discount', () => {
|
|
159
|
+
expect(calculateDiscount(100, 100)).toBe(0);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('should handle price of 0', () => {
|
|
163
|
+
expect(calculateDiscount(0, 50)).toBe(0);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('should handle very large prices', () => {
|
|
167
|
+
expect(calculateDiscount(Number.MAX_SAFE_INTEGER, 10))
|
|
168
|
+
.toBeLessThan(Number.MAX_SAFE_INTEGER);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// Edge cases - null/undefined
|
|
173
|
+
describe('null and undefined handling', () => {
|
|
174
|
+
it('should throw on null price', () => {
|
|
175
|
+
expect(() => calculateDiscount(null, 10)).toThrow();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('should throw on undefined percentage', () => {
|
|
179
|
+
expect(() => calculateDiscount(100, undefined)).toThrow();
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// Error handling
|
|
184
|
+
describe('invalid input', () => {
|
|
185
|
+
it('should throw on negative price', () => {
|
|
186
|
+
expect(() => calculateDiscount(-100, 10)).toThrow('Price must be positive');
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('should throw on percentage > 100', () => {
|
|
190
|
+
expect(() => calculateDiscount(100, 150)).toThrow('Invalid percentage');
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('should throw on negative percentage', () => {
|
|
194
|
+
expect(() => calculateDiscount(100, -10)).toThrow('Invalid percentage');
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Security (if applicable)
|
|
199
|
+
describe('security', () => {
|
|
200
|
+
it('should reject string injection in price', () => {
|
|
201
|
+
expect(() => calculateDiscount("100; DROP TABLE", 10)).toThrow();
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// Performance
|
|
206
|
+
describe('performance', () => {
|
|
207
|
+
it('should calculate 1000 discounts under 10ms', () => {
|
|
208
|
+
const start = performance.now();
|
|
209
|
+
for (let i = 0; i < 1000; i++) {
|
|
210
|
+
calculateDiscount(100, 10);
|
|
211
|
+
}
|
|
212
|
+
expect(performance.now() - start).toBeLessThan(10);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
```
|
package/plugin/registry.yaml
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# OMGKIT Component Registry
|
|
2
2
|
# Single Source of Truth for Agents, Skills, Commands, Workflows, and MCPs
|
|
3
|
-
# Version: 2.22.
|
|
3
|
+
# Version: 2.22.9
|
|
4
4
|
# Updated: 2026-01-03
|
|
5
5
|
|
|
6
|
-
version: "2.22.
|
|
6
|
+
version: "2.22.9"
|
|
7
7
|
|
|
8
8
|
# =============================================================================
|
|
9
9
|
# OPTIMIZED ALIGNMENT PRINCIPLE (OAP)
|
package/templates/CLAUDE.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## OMGKIT-Powered Project
|
|
4
4
|
|
|
5
|
-
This project uses **OMGKIT** - an AI Team System for Claude Code with
|
|
5
|
+
This project uses **OMGKIT** - an AI Team System for Claude Code with 41 Agents, 151 Commands, 151 Skills, and 10 Modes.
|
|
6
6
|
|
|
7
7
|
## Project Structure
|
|
8
8
|
|
|
@@ -12,10 +12,21 @@ This project uses **OMGKIT** - an AI Team System for Claude Code with 23 Agents,
|
|
|
12
12
|
โโโ sprints/ # Sprint management files
|
|
13
13
|
โ โโโ vision.yaml # Product vision and goals
|
|
14
14
|
โ โโโ backlog.yaml # Product backlog items
|
|
15
|
+
โโโ stdrules/ # Standards and rules (MUST READ)
|
|
16
|
+
โ โโโ TESTING_STANDARDS.md # Testing methodology
|
|
17
|
+
โ โโโ BEFORE_COMMIT.md # Pre-commit checklist
|
|
15
18
|
โโโ devlogs/ # Development logs (git-ignored)
|
|
16
19
|
โโโ settings.json # Local settings
|
|
17
20
|
```
|
|
18
21
|
|
|
22
|
+
## MANDATORY: Read Before Tasks
|
|
23
|
+
|
|
24
|
+
| Task Type | Read First |
|
|
25
|
+
|-----------|------------|
|
|
26
|
+
| Writing Tests | `.omgkit/stdrules/TESTING_STANDARDS.md` |
|
|
27
|
+
| Before Commit | `.omgkit/stdrules/BEFORE_COMMIT.md` |
|
|
28
|
+
| New Feature | `.omgkit/config.yaml` for project settings |
|
|
29
|
+
|
|
19
30
|
## Development Workflow Rules
|
|
20
31
|
|
|
21
32
|
### `.omgkit/devlogs/` Folder
|
|
@@ -81,4 +92,67 @@ Before completing any task:
|
|
|
81
92
|
|
|
82
93
|
---
|
|
83
94
|
|
|
95
|
+
## AUTOMATIC RULES: Testing (Always Apply)
|
|
96
|
+
|
|
97
|
+
When writing ANY test, Claude MUST automatically apply these rules:
|
|
98
|
+
|
|
99
|
+
### 1. Minimum Test Coverage (MANDATORY)
|
|
100
|
+
Every function/component MUST have tests for:
|
|
101
|
+
- โ
Happy path (normal input)
|
|
102
|
+
- โ
Empty/null/undefined inputs
|
|
103
|
+
- โ
Boundary values (0, -1, MAX_INT, empty string, etc.)
|
|
104
|
+
- โ
Error cases (invalid input โ throw/return error)
|
|
105
|
+
- โ
Security inputs (if user-facing): `"'; DROP TABLE; --"`, `"<script>alert('xss')</script>"`
|
|
106
|
+
|
|
107
|
+
### 2. Test Template (ALWAYS USE)
|
|
108
|
+
```javascript
|
|
109
|
+
describe('functionName', () => {
|
|
110
|
+
// 1. Happy path
|
|
111
|
+
it('should handle normal input', () => {});
|
|
112
|
+
|
|
113
|
+
// 2. Edge cases (NEVER SKIP)
|
|
114
|
+
it('should handle empty input', () => {});
|
|
115
|
+
it('should handle null/undefined', () => {});
|
|
116
|
+
it('should handle boundary values', () => {});
|
|
117
|
+
|
|
118
|
+
// 3. Error handling
|
|
119
|
+
it('should throw/return error for invalid input', () => {});
|
|
120
|
+
|
|
121
|
+
// 4. Security (if user input)
|
|
122
|
+
it('should sanitize malicious input', () => {});
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 3. Boundary Values Reference
|
|
127
|
+
```javascript
|
|
128
|
+
// Always test these values
|
|
129
|
+
const BOUNDARIES = {
|
|
130
|
+
numbers: [0, -0, 1, -1, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER, NaN, Infinity],
|
|
131
|
+
strings: ['', ' ', 'a'.repeat(10000), '\n\t\r', '๐ฎ๐', '\x00'],
|
|
132
|
+
arrays: [[], [null], [undefined], new Array(10000).fill(0)]
|
|
133
|
+
};
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 4. Security Test Inputs
|
|
137
|
+
```javascript
|
|
138
|
+
// ALWAYS test with these if function handles user input
|
|
139
|
+
const MALICIOUS = [
|
|
140
|
+
"'; DROP TABLE users; --",
|
|
141
|
+
"<script>alert('xss')</script>",
|
|
142
|
+
"../../../etc/passwd",
|
|
143
|
+
"{{constructor.constructor('return this')()}}"
|
|
144
|
+
];
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 5. F.I.R.S.T Principles
|
|
148
|
+
- **Fast**: Unit < 1ms, Integration < 100ms
|
|
149
|
+
- **Independent**: No shared state between tests
|
|
150
|
+
- **Repeatable**: No random, no time-dependent
|
|
151
|
+
- **Self-Validating**: Explicit assertions
|
|
152
|
+
- **Timely**: Write with code
|
|
153
|
+
|
|
154
|
+
> **Full documentation**: `.omgkit/stdrules/TESTING_STANDARDS.md`
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
84
158
|
*Think Omega. Build Omega. Be Omega.*
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# OMGKIT Testing Standards
|
|
2
|
+
|
|
3
|
+
This document defines the testing philosophy and standards for this project. Claude Code MUST follow these guidelines when writing tests.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Core Philosophy
|
|
8
|
+
|
|
9
|
+
### F.I.R.S.T. Principles (MANDATORY)
|
|
10
|
+
|
|
11
|
+
| Principle | Requirement | Example |
|
|
12
|
+
|-----------|-------------|---------|
|
|
13
|
+
| **Fast** | Unit tests < 1ms, Integration < 100ms | Use mocks for slow dependencies |
|
|
14
|
+
| **Independent** | Tests don't share state | Fresh setup for each test |
|
|
15
|
+
| **Repeatable** | Same result every run | No random data, no time-dependent logic |
|
|
16
|
+
| **Self-Validating** | Clear pass/fail | Explicit assertions, no manual inspection |
|
|
17
|
+
| **Timely** | Write with code (TDD preferred) | Test before or during implementation |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 4D Testing Methodology
|
|
22
|
+
|
|
23
|
+
Every feature MUST be tested across 4 dimensions:
|
|
24
|
+
|
|
25
|
+
### 1. Accuracy Testing
|
|
26
|
+
```javascript
|
|
27
|
+
// REQUIRED: Unit tests for all functions
|
|
28
|
+
describe('functionName', () => {
|
|
29
|
+
// Happy path
|
|
30
|
+
it('should handle normal input correctly', () => {});
|
|
31
|
+
|
|
32
|
+
// Edge cases (MANDATORY)
|
|
33
|
+
it('should handle empty input', () => {});
|
|
34
|
+
it('should handle null/undefined', () => {});
|
|
35
|
+
it('should handle boundary values', () => {});
|
|
36
|
+
|
|
37
|
+
// Error cases
|
|
38
|
+
it('should throw on invalid input', () => {});
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 2. Performance Testing
|
|
43
|
+
```javascript
|
|
44
|
+
// REQUIRED for critical paths
|
|
45
|
+
it('should complete within SLA', async () => {
|
|
46
|
+
const start = performance.now();
|
|
47
|
+
await operation();
|
|
48
|
+
expect(performance.now() - start).toBeLessThan(100); // 100ms max
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 3. Security Testing
|
|
53
|
+
```javascript
|
|
54
|
+
// REQUIRED for user input handling
|
|
55
|
+
const MALICIOUS_INPUTS = [
|
|
56
|
+
"'; DROP TABLE users; --", // SQL injection
|
|
57
|
+
"<script>alert('xss')</script>", // XSS
|
|
58
|
+
"../../../etc/passwd", // Path traversal
|
|
59
|
+
"{{constructor.constructor('return this')()}}", // Prototype pollution
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
MALICIOUS_INPUTS.forEach(input => {
|
|
63
|
+
it(`should sanitize: ${input.slice(0, 20)}...`, () => {
|
|
64
|
+
expect(() => processInput(input)).not.toThrow();
|
|
65
|
+
expect(processInput(input)).not.toContain(input);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 4. Accessibility Testing (for UI)
|
|
71
|
+
```javascript
|
|
72
|
+
// REQUIRED for all UI components
|
|
73
|
+
it('should be keyboard accessible', () => {});
|
|
74
|
+
it('should have proper ARIA labels', () => {});
|
|
75
|
+
it('should meet WCAG AA contrast', () => {});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Boundary Value Testing (MANDATORY)
|
|
81
|
+
|
|
82
|
+
Always test these boundaries:
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
// Numbers
|
|
86
|
+
const BOUNDARY_NUMBERS = [
|
|
87
|
+
0, -0, 1, -1,
|
|
88
|
+
Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER,
|
|
89
|
+
Number.MAX_VALUE, Number.MIN_VALUE,
|
|
90
|
+
Infinity, -Infinity, NaN
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
// Strings
|
|
94
|
+
const BOUNDARY_STRINGS = [
|
|
95
|
+
'', ' ', ' ',
|
|
96
|
+
'a'.repeat(10000), // Very long
|
|
97
|
+
'\n\t\r', // Whitespace
|
|
98
|
+
'๐ฎ๐', // Unicode/emoji
|
|
99
|
+
'\x00\x01', // Control chars
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
// Arrays
|
|
103
|
+
const BOUNDARY_ARRAYS = [
|
|
104
|
+
[], [null], [undefined],
|
|
105
|
+
new Array(10000).fill(0), // Large array
|
|
106
|
+
[1, [2, [3]]], // Nested
|
|
107
|
+
];
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## "Naughty" Data Patterns
|
|
113
|
+
|
|
114
|
+
When testing user input, ALWAYS include:
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
const NAUGHTY_STRINGS = [
|
|
118
|
+
// Injection attacks
|
|
119
|
+
"'; DROP TABLE users; --",
|
|
120
|
+
"1; UPDATE users SET role='admin'",
|
|
121
|
+
|
|
122
|
+
// XSS attacks
|
|
123
|
+
"<script>alert('xss')</script>",
|
|
124
|
+
"<img src=x onerror=alert('xss')>",
|
|
125
|
+
"javascript:alert('xss')",
|
|
126
|
+
|
|
127
|
+
// Format strings
|
|
128
|
+
"%s%s%s%s%s",
|
|
129
|
+
"{0}{1}{2}",
|
|
130
|
+
|
|
131
|
+
// Unicode edge cases
|
|
132
|
+
"ฮฉโรงโโซ",
|
|
133
|
+
"็ฐไธญใใใซใใใฆไธใใ",
|
|
134
|
+
"่กจใใA้ณฅๅ",
|
|
135
|
+
|
|
136
|
+
// Null bytes
|
|
137
|
+
"test\x00hidden",
|
|
138
|
+
|
|
139
|
+
// Path traversal
|
|
140
|
+
"../../../etc/passwd",
|
|
141
|
+
"....//....//etc/passwd",
|
|
142
|
+
];
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Test Structure
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
tests/
|
|
151
|
+
โโโ unit/ # Fast, isolated tests
|
|
152
|
+
โ โโโ *.test.ts # Co-located or separate
|
|
153
|
+
โโโ integration/ # Component interaction
|
|
154
|
+
โ โโโ api.integration.ts
|
|
155
|
+
โ โโโ db.integration.ts
|
|
156
|
+
โโโ e2e/ # Full user flows
|
|
157
|
+
โ โโโ checkout.e2e.ts
|
|
158
|
+
โโโ security/ # Security-specific
|
|
159
|
+
โ โโโ injection.test.ts
|
|
160
|
+
โ โโโ auth.test.ts
|
|
161
|
+
โโโ performance/ # Performance benchmarks
|
|
162
|
+
โโโ benchmarks.test.ts
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Coverage Requirements
|
|
168
|
+
|
|
169
|
+
| Type | Minimum | Target |
|
|
170
|
+
|------|---------|--------|
|
|
171
|
+
| Statements | 80% | 90% |
|
|
172
|
+
| Branches | 75% | 85% |
|
|
173
|
+
| Functions | 80% | 90% |
|
|
174
|
+
| Lines | 80% | 90% |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Property-Based Testing
|
|
179
|
+
|
|
180
|
+
For complex logic, use property-based testing:
|
|
181
|
+
|
|
182
|
+
```javascript
|
|
183
|
+
import { fc } from 'fast-check';
|
|
184
|
+
|
|
185
|
+
// Instead of specific examples, test properties
|
|
186
|
+
test('sort is idempotent', () => {
|
|
187
|
+
fc.assert(
|
|
188
|
+
fc.property(fc.array(fc.integer()), (arr) => {
|
|
189
|
+
const sorted = sort(arr);
|
|
190
|
+
return JSON.stringify(sort(sorted)) === JSON.stringify(sorted);
|
|
191
|
+
})
|
|
192
|
+
);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test('reverse is its own inverse', () => {
|
|
196
|
+
fc.assert(
|
|
197
|
+
fc.property(fc.array(fc.anything()), (arr) => {
|
|
198
|
+
return JSON.stringify(reverse(reverse(arr))) === JSON.stringify(arr);
|
|
199
|
+
})
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Anti-Patterns (AVOID)
|
|
207
|
+
|
|
208
|
+
1. **Testing Implementation** - Test behavior, not internal details
|
|
209
|
+
2. **Flaky Tests** - No random, no timing-dependent
|
|
210
|
+
3. **Over-Mocking** - Don't mock everything
|
|
211
|
+
4. **Copy-Paste Tests** - Use `it.each()` or `describe.each()`
|
|
212
|
+
5. **No Assertions** - Every test MUST assert
|
|
213
|
+
6. **Ignoring Edge Cases** - Boundaries are where bugs hide
|
|
214
|
+
7. **Massive Test Files** - Split by functionality
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Mutation Testing (Quality Check)
|
|
219
|
+
|
|
220
|
+
Run mutation testing to verify test quality:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
npx stryker run
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Target: **Mutation score > 80%**
|
|
227
|
+
|
|
228
|
+
If tests pass but mutations survive, tests are too weak.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## When Claude Code Writes Tests
|
|
233
|
+
|
|
234
|
+
Claude Code MUST:
|
|
235
|
+
|
|
236
|
+
1. **Read this file first** when asked to write tests
|
|
237
|
+
2. **Apply 4D methodology** - not just happy path
|
|
238
|
+
3. **Include boundary values** from this document
|
|
239
|
+
4. **Test security** for any user input
|
|
240
|
+
5. **Use property-based testing** for complex logic
|
|
241
|
+
6. **Check coverage** after writing tests
|
|
242
|
+
7. **Run mutation testing** if available
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Quick Reference
|
|
247
|
+
|
|
248
|
+
```javascript
|
|
249
|
+
// Minimum test template for any function
|
|
250
|
+
describe('functionName', () => {
|
|
251
|
+
// 1. Happy path
|
|
252
|
+
it('should work with valid input', () => {});
|
|
253
|
+
|
|
254
|
+
// 2. Edge cases
|
|
255
|
+
it('should handle empty/null/undefined', () => {});
|
|
256
|
+
it('should handle boundary values', () => {});
|
|
257
|
+
|
|
258
|
+
// 3. Error handling
|
|
259
|
+
it('should throw/return error for invalid input', () => {});
|
|
260
|
+
|
|
261
|
+
// 4. Security (if user input)
|
|
262
|
+
it('should sanitize malicious input', () => {});
|
|
263
|
+
|
|
264
|
+
// 5. Performance (if critical path)
|
|
265
|
+
it('should complete within SLA', () => {});
|
|
266
|
+
});
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
*Think Omega. Test Omega. Be Omega.* ๐ฎ
|