opencode-agile-agent 1.0.1 → 1.0.2
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 +61 -71
- package/bin/cli.js +344 -434
- package/bin/sync-templates.js +45 -0
- package/bin/validate-templates.js +44 -6
- package/package.json +2 -1
- package/templates/.opencode/ARCHITECTURE.md +82 -368
- package/templates/.opencode/README.md +110 -391
- package/templates/.opencode/agents/api-designer.md +45 -312
- package/templates/.opencode/agents/backend-specialist.md +46 -214
- package/templates/.opencode/agents/code-archaeologist.md +45 -260
- package/templates/.opencode/agents/context-gatherer.md +51 -0
- package/templates/.opencode/agents/database-architect.md +45 -212
- package/templates/.opencode/agents/debugger.md +45 -302
- package/templates/.opencode/agents/developer.md +45 -523
- package/templates/.opencode/agents/devops-engineer.md +45 -253
- package/templates/.opencode/agents/documentation-writer.md +45 -247
- package/templates/.opencode/agents/explorer-agent.md +49 -233
- package/templates/.opencode/agents/feature-lead.md +62 -302
- package/templates/.opencode/agents/frontend-specialist.md +46 -186
- package/templates/.opencode/agents/game-developer.md +45 -391
- package/templates/.opencode/agents/mobile-developer.md +45 -264
- package/templates/.opencode/agents/orchestrator.md +48 -463
- package/templates/.opencode/agents/penetration-tester.md +44 -254
- package/templates/.opencode/agents/performance-optimizer.md +45 -292
- package/templates/.opencode/agents/pr-reviewer.md +45 -468
- package/templates/.opencode/agents/product-manager.md +46 -225
- package/templates/.opencode/agents/project-planner.md +45 -248
- package/templates/.opencode/agents/qa-automation-engineer.md +45 -275
- package/templates/.opencode/agents/security-auditor.md +44 -258
- package/templates/.opencode/agents/seo-specialist.md +45 -266
- package/templates/.opencode/agents/system-analyst.md +48 -428
- package/templates/.opencode/agents/test-engineer.md +45 -229
- package/templates/.opencode/archive/README.md +24 -0
- package/templates/.opencode/commands/brainstorm.md +10 -0
- package/templates/.opencode/commands/create.md +11 -0
- package/templates/.opencode/commands/debug.md +10 -0
- package/templates/.opencode/commands/plan.md +9 -0
- package/templates/.opencode/commands/review.md +11 -0
- package/templates/.opencode/commands/status.md +9 -0
- package/templates/.opencode/commands/test.md +10 -0
- package/templates/.opencode/skills/api-patterns/SKILL.md +25 -149
- package/templates/.opencode/skills/brainstorming/SKILL.md +26 -242
- package/templates/.opencode/skills/clean-code/SKILL.md +27 -339
- package/templates/.opencode/skills/code-philosophy/SKILL.md +27 -499
- package/templates/.opencode/skills/context-archive/SKILL.md +47 -0
- package/templates/.opencode/skills/context-gathering/SKILL.md +51 -0
- package/templates/.opencode/skills/frontend-design/SKILL.md +26 -224
- package/templates/.opencode/skills/intelligent-routing/SKILL.md +25 -182
- package/templates/.opencode/skills/parallel-agents/SKILL.md +25 -261
- package/templates/.opencode/skills/plan-writing/SKILL.md +28 -238
- package/templates/.opencode/skills/redteam-validation/SKILL.md +33 -0
- package/templates/.opencode/skills/security-gate/SKILL.md +33 -0
- package/templates/.opencode/skills/systematic-debugging/SKILL.md +25 -197
- package/templates/.opencode/skills/testing-patterns/SKILL.md +25 -238
- package/templates/AGENTS.template.md +300 -426
- package/templates/.opencode/agents/product-owner.md +0 -264
- package/templates/.opencode/workflows/brainstorm.md +0 -110
- package/templates/.opencode/workflows/create.md +0 -108
- package/templates/.opencode/workflows/debug.md +0 -128
- package/templates/.opencode/workflows/deploy.md +0 -160
- package/templates/.opencode/workflows/enhance.md +0 -253
- package/templates/.opencode/workflows/orchestrate.md +0 -130
- package/templates/.opencode/workflows/plan.md +0 -163
- package/templates/.opencode/workflows/review.md +0 -135
- package/templates/.opencode/workflows/status.md +0 -102
- package/templates/.opencode/workflows/test.md +0 -146
|
@@ -1,210 +1,38 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: systematic-debugging
|
|
3
|
-
description:
|
|
4
|
-
version: 1.0.0
|
|
3
|
+
description: Reproduce, isolate, test hypotheses, fix the root cause, and verify the recovery.
|
|
5
4
|
---
|
|
6
5
|
|
|
7
6
|
# Systematic Debugging
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
## Philosophy
|
|
9
|
+
Fix the cause, not the shape of the symptom. Debugging is a search for truth, not a guessing game.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Use When
|
|
12
|
+
- Something is broken, flaky, or behaving unexpectedly.
|
|
13
|
+
- You need root-cause analysis before a fix.
|
|
14
|
+
- A regression, crash, or slowdown needs a controlled investigation.
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
## Core Moves
|
|
17
|
+
- Reproduce the issue with the smallest reliable steps.
|
|
18
|
+
- Change one variable at a time.
|
|
19
|
+
- Use evidence from logs, traces, and diffs.
|
|
20
|
+
- Confirm the fix with the original reproduction path and edge cases.
|
|
14
21
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
5. **Fix** - Address the root cause
|
|
20
|
-
6. **Verify** - Confirm fix works
|
|
21
|
-
7. **Document** - Record for future
|
|
22
|
+
## Default Moves
|
|
23
|
+
- Capture exact steps, environment, and recent changes first.
|
|
24
|
+
- Test the highest-probability hypothesis before broad changes.
|
|
25
|
+
- Add a regression test or safeguard once the fix is proven.
|
|
22
26
|
|
|
23
|
-
##
|
|
27
|
+
## Anti-Patterns
|
|
28
|
+
- Shotgun debugging, symptom-only fixes, excessive logging, and changing multiple things at once.
|
|
24
29
|
|
|
25
|
-
|
|
30
|
+
## Variation
|
|
31
|
+
- Use bisect for regressions, profiler for perf, and traces for async bugs.
|
|
32
|
+
- Use the cheapest evidence source that can disprove the current hypothesis.
|
|
26
33
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
1. Open browser
|
|
30
|
-
2. Navigate to /dashboard
|
|
31
|
-
3. Click "Export" button
|
|
32
|
-
4. Error appears
|
|
34
|
+
## Output
|
|
35
|
+
- Return the reproduction, root cause, minimal fix, verification, and prevention step.
|
|
33
36
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
- OS: macOS 14
|
|
37
|
-
- Node: v20.10.0
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### Step 2: Gather Information
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
# Check logs
|
|
44
|
-
tail -f /var/log/app.log
|
|
45
|
-
|
|
46
|
-
# Check recent changes
|
|
47
|
-
git log --oneline -10
|
|
48
|
-
|
|
49
|
-
# Check error stack trace
|
|
50
|
-
Error: Cannot read property 'map' of undefined
|
|
51
|
-
at exportData (src/utils/export.ts:45)
|
|
52
|
-
at handleClick (src/components/ExportButton.tsx:23)
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### Step 3: Hypothesize
|
|
56
|
-
|
|
57
|
-
```markdown
|
|
58
|
-
Possible causes (ranked by likelihood):
|
|
59
|
-
1. data is null/undefined when exportData is called
|
|
60
|
-
2. data structure changed but exportData not updated
|
|
61
|
-
3. Race condition in data loading
|
|
62
|
-
4. API returning unexpected format
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### Step 4: Test Hypotheses
|
|
66
|
-
|
|
67
|
-
```typescript
|
|
68
|
-
// Add defensive logging
|
|
69
|
-
console.log('exportData called with:', { data, type: typeof data });
|
|
70
|
-
|
|
71
|
-
// Add type guard
|
|
72
|
-
if (!data || !Array.isArray(data)) {
|
|
73
|
-
console.error('Invalid data for export:', data);
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### Step 5: Fix Root Cause
|
|
79
|
-
|
|
80
|
-
```typescript
|
|
81
|
-
// ❌ Fix symptom only
|
|
82
|
-
const items = data?.items || []; // Hides the real problem
|
|
83
|
-
|
|
84
|
-
// ✅ Fix root cause
|
|
85
|
-
// Investigate WHY data is undefined and fix upstream
|
|
86
|
-
async function loadData() {
|
|
87
|
-
const response = await fetch('/api/data');
|
|
88
|
-
if (!response.ok) {
|
|
89
|
-
throw new Error(`Failed to load data: ${response.status}`);
|
|
90
|
-
}
|
|
91
|
-
return response.json();
|
|
92
|
-
}
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## Common Bug Patterns
|
|
96
|
-
|
|
97
|
-
### Null/Undefined Errors
|
|
98
|
-
|
|
99
|
-
```typescript
|
|
100
|
-
// ❌ Crashes on null
|
|
101
|
-
const name = user.profile.name;
|
|
102
|
-
|
|
103
|
-
// ✅ Safe access
|
|
104
|
-
const name = user?.profile?.name ?? 'Unknown';
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Race Conditions
|
|
108
|
-
|
|
109
|
-
```typescript
|
|
110
|
-
// ❌ Race condition
|
|
111
|
-
let data;
|
|
112
|
-
fetchData().then(result => { data = result; });
|
|
113
|
-
console.log(data); // undefined!
|
|
114
|
-
|
|
115
|
-
// ✅ Proper async handling
|
|
116
|
-
const data = await fetchData();
|
|
117
|
-
console.log(data);
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### State Sync Issues
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
// ❌ Stale closure
|
|
124
|
-
const [count, setCount] = useState(0);
|
|
125
|
-
useEffect(() => {
|
|
126
|
-
const interval = setInterval(() => {
|
|
127
|
-
console.log(count); // Always 0!
|
|
128
|
-
}, 1000);
|
|
129
|
-
return () => clearInterval(interval);
|
|
130
|
-
}, []);
|
|
131
|
-
|
|
132
|
-
// ✅ Use ref or dependency
|
|
133
|
-
const countRef = useRef(count);
|
|
134
|
-
countRef.current = count;
|
|
135
|
-
// Or add count to dependencies
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## Debugging Tools
|
|
139
|
-
|
|
140
|
-
### Console Debugging
|
|
141
|
-
|
|
142
|
-
```typescript
|
|
143
|
-
// Strategic logging
|
|
144
|
-
console.log('1. Before fetch');
|
|
145
|
-
const data = await fetch(url);
|
|
146
|
-
console.log('2. After fetch:', data);
|
|
147
|
-
const processed = processData(data);
|
|
148
|
-
console.log('3. After process:', processed);
|
|
149
|
-
|
|
150
|
-
// Performance timing
|
|
151
|
-
console.time('operation');
|
|
152
|
-
doSomething();
|
|
153
|
-
console.timeEnd('operation');
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
### Browser DevTools
|
|
157
|
-
|
|
158
|
-
```
|
|
159
|
-
1. Sources panel - Set breakpoints
|
|
160
|
-
2. Network panel - Check API calls
|
|
161
|
-
3. Console - Run expressions
|
|
162
|
-
4. React DevTools - Component tree
|
|
163
|
-
5. Performance - Record profile
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Node.js Debugging
|
|
167
|
-
|
|
168
|
-
```bash
|
|
169
|
-
# Inspector mode
|
|
170
|
-
node --inspect app.js
|
|
171
|
-
|
|
172
|
-
# Then open chrome://inspect
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
## Debugging Checklist
|
|
176
|
-
|
|
177
|
-
- [ ] **Reproduced**: Can consistently reproduce
|
|
178
|
-
- [ ] **Isolated**: Narrowed to specific area
|
|
179
|
-
- [ ] **Root cause**: Understand WHY
|
|
180
|
-
- [ ] **Fix implemented**: Addresses cause, not symptom
|
|
181
|
-
- [ ] **Verified**: Fix resolves the issue
|
|
182
|
-
- [ ] **No regressions**: Other functionality intact
|
|
183
|
-
- [ ] **Tests added**: Prevents future occurrences
|
|
184
|
-
|
|
185
|
-
## Anti-Patterns to Avoid
|
|
186
|
-
|
|
187
|
-
### Shotgun Debugging
|
|
188
|
-
|
|
189
|
-
```
|
|
190
|
-
❌ Change random things hoping it works
|
|
191
|
-
✅ Change one thing at a time, verify each
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
### Console.log Everything
|
|
195
|
-
|
|
196
|
-
```
|
|
197
|
-
❌ console.log everywhere
|
|
198
|
-
✅ Strategic, minimal logging with context
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
### Fix Symptom, Not Cause
|
|
202
|
-
|
|
203
|
-
```
|
|
204
|
-
❌ Add null check to hide error
|
|
205
|
-
✅ Find why null occurs and fix upstream
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
---
|
|
209
|
-
|
|
210
|
-
**Systematic debugging finds root causes faster.**
|
|
37
|
+
## Remember
|
|
38
|
+
A good debug session leaves the system easier to reason about than before.
|
|
@@ -1,252 +1,39 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: testing-patterns
|
|
3
|
-
description:
|
|
4
|
-
version: 1.0.0
|
|
3
|
+
description: Choose unit, integration, or E2E tests that prove behavior without overspecifying implementation.
|
|
5
4
|
---
|
|
6
5
|
|
|
7
6
|
# Testing Patterns
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
## Philosophy
|
|
9
|
+
Tests are executable specs. They should protect behavior, not lock you into internals.
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Use When
|
|
12
|
+
- You are adding tests or choosing the right test layer.
|
|
13
|
+
- Coverage needs to increase without making the suite flaky.
|
|
14
|
+
- A feature needs confidence before merge or release.
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
/----------\
|
|
19
|
-
/ Unit \ Many, fast, isolated
|
|
20
|
-
/--------------\
|
|
21
|
-
```
|
|
16
|
+
## Core Moves
|
|
17
|
+
- Follow the pyramid: many unit tests, some integration tests, few E2E tests.
|
|
18
|
+
- Test behavior over implementation details.
|
|
19
|
+
- Keep tests deterministic, isolated, and readable.
|
|
20
|
+
- Use resilient selectors and stable fixtures.
|
|
22
21
|
|
|
23
|
-
##
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
describe('calculateTotal', () => {
|
|
29
|
-
it('should sum item prices', () => {
|
|
30
|
-
// Arrange
|
|
31
|
-
const items = [{ price: 10 }, { price: 20 }];
|
|
32
|
-
|
|
33
|
-
// Act
|
|
34
|
-
const result = calculateTotal(items);
|
|
35
|
-
|
|
36
|
-
// Assert
|
|
37
|
-
expect(result).toBe(30);
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Test Edge Cases
|
|
43
|
-
|
|
44
|
-
```typescript
|
|
45
|
-
describe('calculateTotal', () => {
|
|
46
|
-
it('should handle empty array', () => {
|
|
47
|
-
expect(calculateTotal([])).toBe(0);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('should handle null', () => {
|
|
51
|
-
expect(calculateTotal(null)).toBe(0);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('should handle negative prices', () => {
|
|
55
|
-
expect(calculateTotal([{ price: -5 }])).toBe(-5);
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### Mocking
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
// Mock external dependency
|
|
64
|
-
jest.mock('./api');
|
|
65
|
-
api.fetchUser.mockResolvedValue({ id: 1, name: 'Test' });
|
|
66
|
-
|
|
67
|
-
// Mock function
|
|
68
|
-
const mockCallback = jest.fn();
|
|
69
|
-
mockCallback.mockReturnValue(true);
|
|
70
|
-
mockCallback.mockImplementation(x => x * 2);
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Integration Testing
|
|
74
|
-
|
|
75
|
-
### API Testing
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
describe('POST /api/users', () => {
|
|
79
|
-
it('should create user with valid data', async () => {
|
|
80
|
-
const response = await request(app)
|
|
81
|
-
.post('/api/users')
|
|
82
|
-
.send({ name: 'Test', email: 'test@example.com' });
|
|
83
|
-
|
|
84
|
-
expect(response.status).toBe(201);
|
|
85
|
-
expect(response.body.data.name).toBe('Test');
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it('should reject invalid email', async () => {
|
|
89
|
-
const response = await request(app)
|
|
90
|
-
.post('/api/users')
|
|
91
|
-
.send({ name: 'Test', email: 'invalid' });
|
|
92
|
-
|
|
93
|
-
expect(response.status).toBe(400);
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### Database Testing
|
|
99
|
-
|
|
100
|
-
```typescript
|
|
101
|
-
describe('UserService', () => {
|
|
102
|
-
beforeAll(async () => {
|
|
103
|
-
await setupTestDatabase();
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
afterAll(async () => {
|
|
107
|
-
await teardownTestDatabase();
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
beforeEach(async () => {
|
|
111
|
-
await clearDatabase();
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('should create user', async () => {
|
|
115
|
-
const user = await UserService.create({ name: 'Test' });
|
|
116
|
-
expect(user.id).toBeDefined();
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
## E2E Testing
|
|
122
|
-
|
|
123
|
-
### Page Object Model
|
|
124
|
-
|
|
125
|
-
```typescript
|
|
126
|
-
// pages/LoginPage.ts
|
|
127
|
-
export class LoginPage {
|
|
128
|
-
constructor(private page: Page) {}
|
|
129
|
-
|
|
130
|
-
async goto() {
|
|
131
|
-
await this.page.goto('/login');
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
async login(email: string, password: string) {
|
|
135
|
-
await this.page.fill('[data-testid="email"]', email);
|
|
136
|
-
await this.page.fill('[data-testid="password"]', password);
|
|
137
|
-
await this.page.click('[data-testid="login-btn"]');
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// tests/auth.spec.ts
|
|
142
|
-
test('should login successfully', async ({ page }) => {
|
|
143
|
-
const loginPage = new LoginPage(page);
|
|
144
|
-
await loginPage.goto();
|
|
145
|
-
await loginPage.login('user@example.com', 'password');
|
|
146
|
-
|
|
147
|
-
await expect(page).toHaveURL('/dashboard');
|
|
148
|
-
});
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### Test Selectors
|
|
152
|
-
|
|
153
|
-
```typescript
|
|
154
|
-
// ❌ Brittle
|
|
155
|
-
await page.locator('.card > .title').click();
|
|
156
|
-
|
|
157
|
-
// ✅ Resilient
|
|
158
|
-
await page.locator('[data-testid="product-title"]').click();
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
## Test Organization
|
|
162
|
-
|
|
163
|
-
```
|
|
164
|
-
tests/
|
|
165
|
-
├── unit/
|
|
166
|
-
│ ├── utils/
|
|
167
|
-
│ │ └── calculate.test.ts
|
|
168
|
-
│ └── components/
|
|
169
|
-
│ └── Button.test.tsx
|
|
170
|
-
├── integration/
|
|
171
|
-
│ ├── api/
|
|
172
|
-
│ │ └── users.test.ts
|
|
173
|
-
│ └── services/
|
|
174
|
-
│ └── auth.test.ts
|
|
175
|
-
└── e2e/
|
|
176
|
-
├── auth.spec.ts
|
|
177
|
-
└── checkout.spec.ts
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## Coverage Guidelines
|
|
181
|
-
|
|
182
|
-
| Type | Target |
|
|
183
|
-
|------|--------|
|
|
184
|
-
| Statements | 80% |
|
|
185
|
-
| Branches | 75% |
|
|
186
|
-
| Functions | 85% |
|
|
187
|
-
| Lines | 80% |
|
|
188
|
-
|
|
189
|
-
## Best Practices
|
|
190
|
-
|
|
191
|
-
### Descriptive Names
|
|
192
|
-
|
|
193
|
-
```typescript
|
|
194
|
-
// ❌ Vague
|
|
195
|
-
test('user', () => {});
|
|
196
|
-
|
|
197
|
-
// ✅ Descriptive
|
|
198
|
-
test('should create user with valid email', () => {});
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
### One Concept Per Test
|
|
202
|
-
|
|
203
|
-
```typescript
|
|
204
|
-
// ❌ Multiple concepts
|
|
205
|
-
test('user operations', () => {
|
|
206
|
-
// Test create
|
|
207
|
-
// Test update
|
|
208
|
-
// Test delete
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
// ✅ One concept
|
|
212
|
-
test('should create user', () => {});
|
|
213
|
-
test('should update user', () => {});
|
|
214
|
-
test('should delete user', () => {});
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
### Test Behavior, Not Implementation
|
|
218
|
-
|
|
219
|
-
```typescript
|
|
220
|
-
// ❌ Tests implementation
|
|
221
|
-
expect(component.state.count).toBe(1);
|
|
222
|
-
|
|
223
|
-
// ✅ Tests behavior
|
|
224
|
-
expect(screen.getByText('Count: 1')).toBeInTheDocument();
|
|
225
|
-
```
|
|
22
|
+
## Default Moves
|
|
23
|
+
- Use unit tests for pure logic, integration tests for boundaries, and E2E for critical journeys.
|
|
24
|
+
- Use AAA or Given-When-Then for clarity.
|
|
25
|
+
- Add the cheapest test that proves the risk.
|
|
226
26
|
|
|
227
27
|
## Anti-Patterns
|
|
28
|
+
- Testing internals, shared state, flaky timing, overspecifying every property, and too many E2E tests.
|
|
228
29
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
✅ Test the output/behavior
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
### Shared State
|
|
30
|
+
## Variation
|
|
31
|
+
- Use page objects for complex browser flows.
|
|
32
|
+
- Mock only at the boundary you do not want to test.
|
|
33
|
+
- Choose a lower layer when the same confidence can be achieved more cheaply.
|
|
237
34
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
✅ Each test is independent
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
### Overspecifying
|
|
244
|
-
|
|
245
|
-
```
|
|
246
|
-
❌ Assert every property
|
|
247
|
-
✅ Assert essential behavior
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
---
|
|
35
|
+
## Output
|
|
36
|
+
- Return the test plan, the coverage gap, and the recommended layer for each risk.
|
|
251
37
|
|
|
252
|
-
|
|
38
|
+
## Remember
|
|
39
|
+
The best test suite is small enough to trust and broad enough to matter.
|