-
Notifications
You must be signed in to change notification settings - Fork 190
Expand file tree
/
Copy pathtest-driven-development.mdc
More file actions
135 lines (104 loc) · 2.96 KB
/
Copy pathtest-driven-development.mdc
File metadata and controls
135 lines (104 loc) · 2.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
---
description: Standards for Test-Driven Development in the Browser SDK project
globs:
tags:
- vitest
- browser-mode
alwaysApply: true
---
# Test-Driven Development (TDD) Rule
## 1. RED-GREEN-REFACTOR Cycle
**ALWAYS follow this sequence:**
1. 🔴 **RED**: Write failing test first
2. 🟢 **GREEN**: Write minimal code to make test pass
3. 🔵 **REFACTOR**: Improve code while keeping tests green
## 2. Spec First, Code Second
**Before writing ANY implementation:**
```bash
# Check for existing spec file
ls packages/some-package/src/path/to/feature.spec.ts
# If missing, create spec file first
touch packages/some-package/src/path/to/feature.spec.ts
```
**Spec file must exist BEFORE implementation file**
## 3. Spec Structure (Vitest Browser Mode)
```typescript
import { beforeEach, describe, expect, it, vi } from 'vitest'
describe('FeatureName', () => {
// Setup variables
let feature: FeatureType
let mockDependency: MockType
beforeEach(() => {
// Setup for each test
mockDependency = vi.fn()
feature = new FeatureName(mockDependency)
// Use registerCleanupTask for cleanup
registerCleanupTask(() => {
feature.dispose()
})
})
describe('when condition', () => {
it('should behave correctly', () => {
// Arrange
const input = 'test-input'
// Act
const result = feature.process(input)
// Assert
expect(result).toBe(expectedOutput)
expect(mockDependency).toHaveBeenCalledWith(input)
})
it('should handle edge cases', () => {
// Test edge cases, errors, boundaries
})
})
})
```
## 4. Implementation Process
**Step-by-step workflow:**
1. **Analyze Requirements**
- Understand the feature/bug
- Identify acceptance criteria
- Consider edge cases
2. **Create/Review Spec**
3. **Run Tests (Should Fail)**
```bash
yarn test:unit
# Verify test fails for the right reason
```
4. **Implement Minimal Code**
5. **Run Tests (Should Pass)**
```bash
yarn test:unit
# Verify test passes
```
6. **Refactor & Add More Tests**
- Improve implementation
- Add edge case tests
- Ensure all tests still pass
## 5. Browser SDK Specific Patterns
**Use established test utilities:**
[unit-test.mdc](mdc:.cursor/rules/unit-test.mdc)
**Follow co-location pattern:**
```
src/
├── domain/
│ ├── feature.ts ← Implementation
│ ├── feature.spec.ts ← Tests (co-located)
│ └── anotherFeature.ts
```
## 8. Error Prevention Rules
**❌ NEVER do this:**
- Write implementation without tests
- Skip edge case testing
- Leave failing tests
- Forget cleanup tasks
- Use real timers in tests
- Test multiple behaviors in one test
**✅ ALWAYS do this:**
- Write test first
- Use `registerCleanupTask` for cleanup
- Mock external dependencies
- Test both success and failure paths
- Use descriptive test names
- Follow existing patterns in codebase
Remember: **Tests are documentation**. Write them as if explaining the feature to a new team member.