@su-record/vibe 2.0.10 → 2.1.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/.claude/agents/research/best-practices-agent.md +139 -0
- package/.claude/agents/research/codebase-patterns-agent.md +147 -0
- package/.claude/agents/research/framework-docs-agent.md +181 -0
- package/.claude/agents/research/security-advisory-agent.md +167 -0
- package/.claude/agents/review/architecture-reviewer.md +107 -0
- package/.claude/agents/review/complexity-reviewer.md +116 -0
- package/.claude/agents/review/data-integrity-reviewer.md +88 -0
- package/.claude/agents/review/git-history-reviewer.md +103 -0
- package/.claude/agents/review/performance-reviewer.md +86 -0
- package/.claude/agents/review/python-reviewer.md +152 -0
- package/.claude/agents/review/rails-reviewer.md +139 -0
- package/.claude/agents/review/react-reviewer.md +144 -0
- package/.claude/agents/review/security-reviewer.md +80 -0
- package/.claude/agents/review/simplicity-reviewer.md +140 -0
- package/.claude/agents/review/test-coverage-reviewer.md +116 -0
- package/.claude/agents/review/typescript-reviewer.md +127 -0
- package/.claude/commands/vibe.compound.md +261 -0
- package/.claude/commands/vibe.e2e.md +266 -0
- package/.claude/commands/vibe.review.md +324 -0
- package/.claude/commands/vibe.spec.md +48 -4
- package/.claude/settings.json +152 -152
- package/.claude/skills/git-worktree.md +178 -0
- package/.claude/skills/priority-todos.md +236 -0
- package/CLAUDE.md +150 -4
- package/README.md +128 -10
- package/package.json +1 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# TypeScript Reviewer Agent
|
|
2
|
+
|
|
3
|
+
TypeScript 코드 전문 리뷰 에이전트
|
|
4
|
+
|
|
5
|
+
## Role
|
|
6
|
+
|
|
7
|
+
- 타입 안전성 검증
|
|
8
|
+
- ESLint/Prettier 규칙 준수
|
|
9
|
+
- 모던 TS 패턴 제안
|
|
10
|
+
- React/Node.js 베스트 프랙티스
|
|
11
|
+
|
|
12
|
+
## Model
|
|
13
|
+
|
|
14
|
+
**Haiku** (inherit) - 빠른 병렬 실행
|
|
15
|
+
|
|
16
|
+
## Checklist
|
|
17
|
+
|
|
18
|
+
### Type Safety
|
|
19
|
+
- [ ] `any` 타입 사용 최소화?
|
|
20
|
+
- [ ] 타입 가드 적절히 사용?
|
|
21
|
+
- [ ] `unknown` 대신 `any`?
|
|
22
|
+
- [ ] 유니온 타입 narrowing?
|
|
23
|
+
- [ ] 제네릭 적절히 활용?
|
|
24
|
+
|
|
25
|
+
### Strict Mode
|
|
26
|
+
- [ ] strictNullChecks 준수?
|
|
27
|
+
- [ ] noImplicitAny 준수?
|
|
28
|
+
- [ ] optional chaining (?.) 활용?
|
|
29
|
+
- [ ] nullish coalescing (??) 활용?
|
|
30
|
+
|
|
31
|
+
### Modern Patterns
|
|
32
|
+
- [ ] const assertion (as const)?
|
|
33
|
+
- [ ] satisfies 연산자?
|
|
34
|
+
- [ ] Template literal types?
|
|
35
|
+
- [ ] Discriminated unions?
|
|
36
|
+
|
|
37
|
+
### Error Handling
|
|
38
|
+
- [ ] 에러 타입 정의?
|
|
39
|
+
- [ ] Result/Either 패턴?
|
|
40
|
+
- [ ] async 에러 처리?
|
|
41
|
+
- [ ] 사용자 친화적 에러 메시지?
|
|
42
|
+
|
|
43
|
+
### Imports/Exports
|
|
44
|
+
- [ ] 배럴 exports 사용?
|
|
45
|
+
- [ ] 순환 의존성 없음?
|
|
46
|
+
- [ ] 타입 전용 import (import type)?
|
|
47
|
+
- [ ] 사용하지 않는 import?
|
|
48
|
+
|
|
49
|
+
### Performance
|
|
50
|
+
- [ ] 불필요한 리렌더링?
|
|
51
|
+
- [ ] 메모이제이션 (useMemo, useCallback)?
|
|
52
|
+
- [ ] 번들 사이즈 영향?
|
|
53
|
+
- [ ] 동적 import 활용?
|
|
54
|
+
|
|
55
|
+
## Framework Specific
|
|
56
|
+
|
|
57
|
+
### React
|
|
58
|
+
- [ ] 훅 규칙 준수 (Rules of Hooks)?
|
|
59
|
+
- [ ] 의존성 배열 완전?
|
|
60
|
+
- [ ] key prop 적절?
|
|
61
|
+
- [ ] 컴포넌트 분리 적절?
|
|
62
|
+
- [ ] 상태 관리 적절?
|
|
63
|
+
|
|
64
|
+
### Node.js/Express
|
|
65
|
+
- [ ] async 에러 미들웨어?
|
|
66
|
+
- [ ] 입력 검증 (zod, joi)?
|
|
67
|
+
- [ ] 환경 변수 타입 안전?
|
|
68
|
+
- [ ] 로깅 적절?
|
|
69
|
+
|
|
70
|
+
### Next.js
|
|
71
|
+
- [ ] App Router 패턴?
|
|
72
|
+
- [ ] Server/Client 컴포넌트 구분?
|
|
73
|
+
- [ ] 메타데이터 설정?
|
|
74
|
+
- [ ] 이미지 최적화?
|
|
75
|
+
|
|
76
|
+
## Output Format
|
|
77
|
+
|
|
78
|
+
```markdown
|
|
79
|
+
## 📘 TypeScript Review
|
|
80
|
+
|
|
81
|
+
### 🔴 P1 Critical
|
|
82
|
+
1. **Unsafe Type Assertion**
|
|
83
|
+
- 📍 Location: src/api/user.ts:42
|
|
84
|
+
```typescript
|
|
85
|
+
// Bad
|
|
86
|
+
const user = data as User; // No runtime check
|
|
87
|
+
|
|
88
|
+
// Good
|
|
89
|
+
const user = userSchema.parse(data); // Runtime validation
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 🟡 P2 Important
|
|
93
|
+
2. **Missing Type Guard**
|
|
94
|
+
- 📍 Location: src/utils/parse.ts:23
|
|
95
|
+
```typescript
|
|
96
|
+
// Before
|
|
97
|
+
if (response.type === 'success') {
|
|
98
|
+
// response still has union type
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// After
|
|
102
|
+
function isSuccess(r: Response): r is SuccessResponse {
|
|
103
|
+
return r.type === 'success';
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 🔵 P3 Suggestions
|
|
108
|
+
3. **Use satisfies for Type Checking**
|
|
109
|
+
- 📍 Location: src/config/routes.ts:5
|
|
110
|
+
```typescript
|
|
111
|
+
// Before
|
|
112
|
+
const routes: Routes = { ... };
|
|
113
|
+
|
|
114
|
+
// After (preserves literal types)
|
|
115
|
+
const routes = { ... } satisfies Routes;
|
|
116
|
+
```
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Usage
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
Task(
|
|
123
|
+
model: "haiku",
|
|
124
|
+
subagent_type: "Explore",
|
|
125
|
+
prompt: "TypeScript review for [files]. Check type safety, React patterns."
|
|
126
|
+
)
|
|
127
|
+
```
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Auto-document solutions for knowledge compounding
|
|
3
|
+
argument-hint: "solution description (optional)"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /vibe.compound
|
|
7
|
+
|
|
8
|
+
**Knowledge Compounding** - Auto-document solved problems to boost future productivity
|
|
9
|
+
|
|
10
|
+
> "Each solution documented makes future problems easier to solve."
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
/vibe.compound # Auto-detect recent solutions
|
|
16
|
+
/vibe.compound "Redis cache invalidation" # Document specific solution
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Auto-Triggers
|
|
20
|
+
|
|
21
|
+
Automatically suggested when these patterns detected:
|
|
22
|
+
- "it's fixed", "fixed", "solved", "resolved"
|
|
23
|
+
- After PR merge
|
|
24
|
+
- After `/vibe.verify` passes
|
|
25
|
+
|
|
26
|
+
## Process
|
|
27
|
+
|
|
28
|
+
### Phase 1: Solution Extraction
|
|
29
|
+
|
|
30
|
+
Parallel agents analyze the solution:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
34
|
+
│ 🔍 PARALLEL SOLUTION ANALYSIS │
|
|
35
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
36
|
+
│ │
|
|
37
|
+
│ Task 1: problem-analyzer │
|
|
38
|
+
│ ├── Identify original problem │
|
|
39
|
+
│ ├── Symptoms and error messages │
|
|
40
|
+
│ └── Impact scope │
|
|
41
|
+
│ │
|
|
42
|
+
│ Task 2: solution-extractor │
|
|
43
|
+
│ ├── Applied fixes │
|
|
44
|
+
│ ├── Key code changes │
|
|
45
|
+
│ └── Configuration changes │
|
|
46
|
+
│ │
|
|
47
|
+
│ Task 3: root-cause-analyzer │
|
|
48
|
+
│ ├── Root cause identification │
|
|
49
|
+
│ ├── Why it happened │
|
|
50
|
+
│ └── Prevention methods │
|
|
51
|
+
│ │
|
|
52
|
+
│ Task 4: pattern-recognizer │
|
|
53
|
+
│ ├── Similar problem patterns │
|
|
54
|
+
│ ├── Related tech stack │
|
|
55
|
+
│ └── Search keywords │
|
|
56
|
+
│ │
|
|
57
|
+
│ Task 5: category-classifier │
|
|
58
|
+
│ ├── Category classification │
|
|
59
|
+
│ ├── Tag generation │
|
|
60
|
+
│ └── Related doc links │
|
|
61
|
+
│ │
|
|
62
|
+
│ Task 6: code-snippet-extractor │
|
|
63
|
+
│ ├── Before/After code │
|
|
64
|
+
│ ├── Key change highlights │
|
|
65
|
+
│ └── Copy-paste snippets │
|
|
66
|
+
│ │
|
|
67
|
+
│ Task 7: prevention-advisor │
|
|
68
|
+
│ ├── Prevention checklist │
|
|
69
|
+
│ ├── Suggested linter rules │
|
|
70
|
+
│ └── Test case suggestions │
|
|
71
|
+
│ │
|
|
72
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Phase 2: Category Classification
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
.vibe/solutions/
|
|
79
|
+
├── security/ # Security related
|
|
80
|
+
│ ├── sql-injection-prevention.md
|
|
81
|
+
│ └── xss-sanitization.md
|
|
82
|
+
├── performance/ # Performance optimization
|
|
83
|
+
│ ├── n1-query-fix.md
|
|
84
|
+
│ └── redis-cache-invalidation.md
|
|
85
|
+
├── database/ # Database related
|
|
86
|
+
│ ├── migration-rollback.md
|
|
87
|
+
│ └── deadlock-resolution.md
|
|
88
|
+
├── integration/ # External integrations
|
|
89
|
+
│ ├── stripe-webhook-retry.md
|
|
90
|
+
│ └── aws-s3-timeout.md
|
|
91
|
+
├── frontend/ # Frontend issues
|
|
92
|
+
│ ├── react-hydration-mismatch.md
|
|
93
|
+
│ └── infinite-scroll-memory.md
|
|
94
|
+
├── testing/ # Testing related
|
|
95
|
+
│ ├── flaky-test-fix.md
|
|
96
|
+
│ └── mock-timezone.md
|
|
97
|
+
└── deployment/ # Deployment issues
|
|
98
|
+
├── docker-layer-cache.md
|
|
99
|
+
└── k8s-rolling-update.md
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Phase 3: Document Generation
|
|
103
|
+
|
|
104
|
+
```markdown
|
|
105
|
+
# [Solution] Redis Cache Invalidation
|
|
106
|
+
|
|
107
|
+
## TL;DR
|
|
108
|
+
Added version suffix to Redis cache key to fix invalidation issue
|
|
109
|
+
|
|
110
|
+
## Problem
|
|
111
|
+
### Symptoms
|
|
112
|
+
- User profile shows stale data after update
|
|
113
|
+
- Refresh doesn't fix the issue
|
|
114
|
+
|
|
115
|
+
### Error/Logs
|
|
116
|
+
```
|
|
117
|
+
Cache hit: user:123 (stale data)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Impact Scope
|
|
121
|
+
- User profile page
|
|
122
|
+
- API: GET /api/users/:id
|
|
123
|
+
|
|
124
|
+
## Root Cause
|
|
125
|
+
Cache key only used user_id, not invalidated on update
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
# Before
|
|
129
|
+
cache_key = f"user:{user_id}" # No version
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Solution
|
|
133
|
+
### Key Change
|
|
134
|
+
Add updated_at timestamp to cache key
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
# After
|
|
138
|
+
cache_key = f"user:{user_id}:v{updated_at.timestamp()}"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Changed Files
|
|
142
|
+
- src/services/cache.py:42
|
|
143
|
+
- src/api/users.py:78
|
|
144
|
+
|
|
145
|
+
## Prevention
|
|
146
|
+
- [ ] Always include version/timestamp in cache keys
|
|
147
|
+
- [ ] Add cache invalidation tests
|
|
148
|
+
- [ ] Linter rule: cache_key pattern check
|
|
149
|
+
|
|
150
|
+
## Related
|
|
151
|
+
- Similar issue: #234 (Session cache)
|
|
152
|
+
- Docs: docs/caching-strategy.md
|
|
153
|
+
- Tags: #redis #cache #invalidation
|
|
154
|
+
|
|
155
|
+
## Metadata
|
|
156
|
+
- Resolved: 2026-01-11
|
|
157
|
+
- Time spent: 2 hours
|
|
158
|
+
- Difficulty: Medium
|
|
159
|
+
- Reusability: High
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Phase 4: Index Update
|
|
163
|
+
|
|
164
|
+
Auto-update `.vibe/solutions/index.md`:
|
|
165
|
+
|
|
166
|
+
```markdown
|
|
167
|
+
# Solution Index
|
|
168
|
+
|
|
169
|
+
## Recently Added
|
|
170
|
+
| Date | Category | Title | Tags |
|
|
171
|
+
|------|----------|-------|------|
|
|
172
|
+
| 2026-01-11 | performance | Redis cache invalidation | #redis #cache |
|
|
173
|
+
| 2026-01-10 | security | SQL Injection prevention | #sql #security |
|
|
174
|
+
|
|
175
|
+
## By Category
|
|
176
|
+
- **Security** (5 solutions)
|
|
177
|
+
- **Performance** (8 solutions)
|
|
178
|
+
- **Database** (4 solutions)
|
|
179
|
+
...
|
|
180
|
+
|
|
181
|
+
## Search Keywords
|
|
182
|
+
- redis → performance/redis-cache-invalidation.md
|
|
183
|
+
- n+1 → performance/n1-query-fix.md
|
|
184
|
+
- sql injection → security/sql-injection-prevention.md
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Auto-Suggestion
|
|
188
|
+
|
|
189
|
+
When similar problem detected:
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
193
|
+
│ 💡 Similar Solution Found! │
|
|
194
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
195
|
+
│ │
|
|
196
|
+
│ You're working on: "Cache not updating" │
|
|
197
|
+
│ │
|
|
198
|
+
│ Related solution (85% match): │
|
|
199
|
+
│ 📄 .vibe/solutions/performance/redis-cache-invalidation.md │
|
|
200
|
+
│ │
|
|
201
|
+
│ Key insight: Add version suffix to cache key │
|
|
202
|
+
│ │
|
|
203
|
+
│ Apply this solution? [Y/n] │
|
|
204
|
+
│ │
|
|
205
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Output
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
212
|
+
│ 📚 SOLUTION DOCUMENTED │
|
|
213
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
214
|
+
│ │
|
|
215
|
+
│ ✅ Created: .vibe/solutions/performance/redis-cache-invalid... │
|
|
216
|
+
│ │
|
|
217
|
+
│ 📊 Knowledge Base Stats: │
|
|
218
|
+
│ ├── Total Solutions: 42 │
|
|
219
|
+
│ ├── This Month: 8 │
|
|
220
|
+
│ └── Most Used Category: performance │
|
|
221
|
+
│ │
|
|
222
|
+
│ 🔗 Similar solutions linked: 2 │
|
|
223
|
+
│ 🏷️ Tags: #redis #cache #invalidation #performance │
|
|
224
|
+
│ │
|
|
225
|
+
│ 💡 Prevention rules added to .vibe/rules/ │
|
|
226
|
+
│ │
|
|
227
|
+
│ "This solution will help future you (or teammates) save hours" │
|
|
228
|
+
│ │
|
|
229
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Integration with Memory
|
|
233
|
+
|
|
234
|
+
Auto-invoke `vibe_save_memory`:
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"type": "solution",
|
|
239
|
+
"category": "performance",
|
|
240
|
+
"title": "Redis cache invalidation",
|
|
241
|
+
"keywords": ["redis", "cache", "invalidation"],
|
|
242
|
+
"file": ".vibe/solutions/performance/redis-cache-invalidation.md"
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Workflow Integration
|
|
247
|
+
|
|
248
|
+
```
|
|
249
|
+
/vibe.spec → /vibe.run → /vibe.verify → /vibe.compound
|
|
250
|
+
│
|
|
251
|
+
▼
|
|
252
|
+
.vibe/solutions/
|
|
253
|
+
│
|
|
254
|
+
▼
|
|
255
|
+
Future problem?
|
|
256
|
+
Auto-suggest!
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
ARGUMENTS: $ARGUMENTS
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: End-to-end testing with Playwright automation
|
|
3
|
+
argument-hint: "test scenario or URL"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /vibe.e2e
|
|
7
|
+
|
|
8
|
+
**E2E Test Automation** - Playwright-based browser testing
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
/vibe.e2e # Run all E2E tests
|
|
14
|
+
/vibe.e2e "login flow" # Test specific scenario
|
|
15
|
+
/vibe.e2e http://localhost:3000/login # Test specific URL
|
|
16
|
+
/vibe.e2e --visual # Visual regression testing
|
|
17
|
+
/vibe.e2e --record # Record test video
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Core Features
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
24
|
+
│ 🎭 Playwright E2E Testing │
|
|
25
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
26
|
+
│ │
|
|
27
|
+
│ ✅ Screenshot Capture - Record UI state │
|
|
28
|
+
│ ✅ Console Error Collection - Detect JS errors │
|
|
29
|
+
│ ✅ Network Monitoring - Detect API failures │
|
|
30
|
+
│ ✅ Visual Regression - Compare screenshots │
|
|
31
|
+
│ ✅ Video Recording - Bug reproduction evidence │
|
|
32
|
+
│ ✅ Accessibility Check - Detect a11y violations │
|
|
33
|
+
│ │
|
|
34
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Process
|
|
38
|
+
|
|
39
|
+
### Phase 1: Environment Setup
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Check Playwright installation
|
|
43
|
+
npx playwright --version
|
|
44
|
+
|
|
45
|
+
# Install browsers if needed
|
|
46
|
+
npx playwright install chromium
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Phase 2: Test Scenario Analysis
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
📋 Scenario Detection
|
|
53
|
+
├── .vibe/features/{feature}.feature → Extract BDD scenarios
|
|
54
|
+
├── .vibe/specs/{feature}.md → Check acceptance criteria
|
|
55
|
+
└── Analyze existing e2e/*.spec.ts
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Phase 3: Test Execution
|
|
59
|
+
|
|
60
|
+
**Single Page Test:**
|
|
61
|
+
```typescript
|
|
62
|
+
// Auto-generated test
|
|
63
|
+
import { test, expect } from '@playwright/test';
|
|
64
|
+
|
|
65
|
+
test('login flow', async ({ page }) => {
|
|
66
|
+
// Navigate
|
|
67
|
+
await page.goto('http://localhost:3000/login');
|
|
68
|
+
|
|
69
|
+
// Screenshot: initial state
|
|
70
|
+
await page.screenshot({ path: 'screenshots/login-initial.png' });
|
|
71
|
+
|
|
72
|
+
// Fill form
|
|
73
|
+
await page.fill('[data-testid="email"]', 'test@example.com');
|
|
74
|
+
await page.fill('[data-testid="password"]', 'password123');
|
|
75
|
+
|
|
76
|
+
// Submit
|
|
77
|
+
await page.click('[data-testid="submit"]');
|
|
78
|
+
|
|
79
|
+
// Wait for navigation
|
|
80
|
+
await page.waitForURL('**/dashboard');
|
|
81
|
+
|
|
82
|
+
// Screenshot: success state
|
|
83
|
+
await page.screenshot({ path: 'screenshots/login-success.png' });
|
|
84
|
+
|
|
85
|
+
// Assertions
|
|
86
|
+
await expect(page.locator('h1')).toContainText('Dashboard');
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Console Error Collection:**
|
|
91
|
+
```typescript
|
|
92
|
+
test.beforeEach(async ({ page }) => {
|
|
93
|
+
// Collect console errors
|
|
94
|
+
page.on('console', msg => {
|
|
95
|
+
if (msg.type() === 'error') {
|
|
96
|
+
console.log(`Console Error: ${msg.text()}`);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Collect network failures
|
|
101
|
+
page.on('requestfailed', request => {
|
|
102
|
+
console.log(`Request failed: ${request.url()}`);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Phase 4: Visual Regression (--visual)
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
111
|
+
│ 👁️ Visual Regression Test │
|
|
112
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
113
|
+
│ │
|
|
114
|
+
│ Comparing screenshots: │
|
|
115
|
+
│ │
|
|
116
|
+
│ ├── login-page.png │
|
|
117
|
+
│ │ ├── Baseline: .vibe/e2e/baseline/login-page.png │
|
|
118
|
+
│ │ ├── Current: .vibe/e2e/current/login-page.png │
|
|
119
|
+
│ │ └── Diff: ✅ 0.02% (threshold: 1%) │
|
|
120
|
+
│ │ │
|
|
121
|
+
│ ├── dashboard.png │
|
|
122
|
+
│ │ ├── Baseline: .vibe/e2e/baseline/dashboard.png │
|
|
123
|
+
│ │ ├── Current: .vibe/e2e/current/dashboard.png │
|
|
124
|
+
│ │ └── Diff: ❌ 5.3% (threshold: 1%) │
|
|
125
|
+
│ │ └── .vibe/e2e/diff/dashboard-diff.png │
|
|
126
|
+
│ │ │
|
|
127
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Phase 5: Accessibility Check
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
import { injectAxe, checkA11y } from 'axe-playwright';
|
|
134
|
+
|
|
135
|
+
test('accessibility check', async ({ page }) => {
|
|
136
|
+
await page.goto('/login');
|
|
137
|
+
await injectAxe(page);
|
|
138
|
+
await checkA11y(page, null, {
|
|
139
|
+
detailedReport: true,
|
|
140
|
+
detailedReportOptions: { html: true }
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Phase 6: Bug Reproduction (Optional)
|
|
146
|
+
|
|
147
|
+
Link with bug reports:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
/vibe.e2e --reproduce "User sees blank page after login"
|
|
151
|
+
|
|
152
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
153
|
+
│ 🐛 Bug Reproduction Mode │
|
|
154
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
155
|
+
│ │
|
|
156
|
+
│ Steps executed: │
|
|
157
|
+
│ 1. ✅ Navigate to /login │
|
|
158
|
+
│ 2. ✅ Enter credentials │
|
|
159
|
+
│ 3. ✅ Click login button │
|
|
160
|
+
│ 4. ❌ Dashboard shows blank │
|
|
161
|
+
│ │
|
|
162
|
+
│ Evidence collected: │
|
|
163
|
+
│ ├── 📸 screenshots/bug-step-1.png │
|
|
164
|
+
│ ├── 📸 screenshots/bug-step-2.png │
|
|
165
|
+
│ ├── 📸 screenshots/bug-step-3.png │
|
|
166
|
+
│ ├── 📸 screenshots/bug-step-4-FAIL.png │
|
|
167
|
+
│ ├── 🎥 videos/bug-reproduction.webm │
|
|
168
|
+
│ └── 📋 logs/console-errors.txt │
|
|
169
|
+
│ │
|
|
170
|
+
│ Console Errors Found: │
|
|
171
|
+
│ └── TypeError: Cannot read property 'user' of undefined │
|
|
172
|
+
│ at Dashboard.tsx:42 │
|
|
173
|
+
│ │
|
|
174
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Output
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
181
|
+
│ 🎭 E2E TEST RESULTS │
|
|
182
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
183
|
+
│ │
|
|
184
|
+
│ Test Suite: Login Flow │
|
|
185
|
+
│ Duration: 12.3s │
|
|
186
|
+
│ Browser: Chromium 120 │
|
|
187
|
+
│ │
|
|
188
|
+
│ Results: │
|
|
189
|
+
│ ├── ✅ Passed: 8 │
|
|
190
|
+
│ ├── ❌ Failed: 1 │
|
|
191
|
+
│ └── ⏭️ Skipped: 0 │
|
|
192
|
+
│ │
|
|
193
|
+
│ Failed Tests: │
|
|
194
|
+
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
|
|
195
|
+
│ ❌ "should show error for invalid password" │
|
|
196
|
+
│ Expected: "Invalid password" message │
|
|
197
|
+
│ Actual: No error message displayed │
|
|
198
|
+
│ 📸 Screenshot: .vibe/e2e/failures/invalid-password.png │
|
|
199
|
+
│ │
|
|
200
|
+
│ Console Errors: 2 │
|
|
201
|
+
│ ├── TypeError at Dashboard.tsx:42 │
|
|
202
|
+
│ └── 404 at /api/user/preferences │
|
|
203
|
+
│ │
|
|
204
|
+
│ Accessibility Issues: 3 │
|
|
205
|
+
│ ├── [serious] Form input missing label │
|
|
206
|
+
│ ├── [moderate] Color contrast insufficient │
|
|
207
|
+
│ └── [minor] Missing skip link │
|
|
208
|
+
│ │
|
|
209
|
+
│ Artifacts: │
|
|
210
|
+
│ ├── 📸 Screenshots: .vibe/e2e/screenshots/ │
|
|
211
|
+
│ ├── 🎥 Video: .vibe/e2e/videos/ │
|
|
212
|
+
│ └── 📋 Report: .vibe/e2e/report.html │
|
|
213
|
+
│ │
|
|
214
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Configuration
|
|
218
|
+
|
|
219
|
+
`.vibe/e2e/config.json`:
|
|
220
|
+
|
|
221
|
+
```json
|
|
222
|
+
{
|
|
223
|
+
"baseURL": "http://localhost:3000",
|
|
224
|
+
"browsers": ["chromium"],
|
|
225
|
+
"viewport": { "width": 1280, "height": 720 },
|
|
226
|
+
"video": "retain-on-failure",
|
|
227
|
+
"screenshot": "only-on-failure",
|
|
228
|
+
"trace": "retain-on-failure",
|
|
229
|
+
"visualRegression": {
|
|
230
|
+
"enabled": true,
|
|
231
|
+
"threshold": 0.01
|
|
232
|
+
},
|
|
233
|
+
"accessibility": {
|
|
234
|
+
"enabled": true,
|
|
235
|
+
"rules": ["wcag2aa"]
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Integration with Review
|
|
241
|
+
|
|
242
|
+
Auto-suggest after `/vibe.review`:
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
246
|
+
│ 💡 E2E Test Recommended │
|
|
247
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
248
|
+
│ │
|
|
249
|
+
│ UI changes detected in this PR: │
|
|
250
|
+
│ - src/components/LoginForm.tsx │
|
|
251
|
+
│ - src/pages/Dashboard.tsx │
|
|
252
|
+
│ │
|
|
253
|
+
│ Run E2E tests? /vibe.e2e "login flow" │
|
|
254
|
+
│ │
|
|
255
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Related Commands
|
|
259
|
+
|
|
260
|
+
- `/vibe.review` - Code review
|
|
261
|
+
- `/vibe.verify` - SPEC verification
|
|
262
|
+
- `/vibe.compound` - Document test results
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
ARGUMENTS: $ARGUMENTS
|