@su-record/vibe 2.7.6 → 2.7.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/dist/cli/commands/init.d.ts +10 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +78 -2
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +17 -2
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/postinstall/codex-agents.d.ts +12 -0
- package/dist/cli/postinstall/codex-agents.d.ts.map +1 -0
- package/dist/cli/postinstall/codex-agents.js +51 -0
- package/dist/cli/postinstall/codex-agents.js.map +1 -0
- package/dist/cli/postinstall/codex-instruction.d.ts +10 -0
- package/dist/cli/postinstall/codex-instruction.d.ts.map +1 -0
- package/dist/cli/postinstall/codex-instruction.js +56 -0
- package/dist/cli/postinstall/codex-instruction.js.map +1 -0
- package/dist/cli/postinstall/constants.d.ts.map +1 -1
- package/dist/cli/postinstall/constants.js +1 -0
- package/dist/cli/postinstall/constants.js.map +1 -1
- package/dist/cli/postinstall/gemini-agents.d.ts +12 -0
- package/dist/cli/postinstall/gemini-agents.d.ts.map +1 -0
- package/dist/cli/postinstall/gemini-agents.js +80 -0
- package/dist/cli/postinstall/gemini-agents.js.map +1 -0
- package/dist/cli/postinstall/gemini-instruction.d.ts +10 -0
- package/dist/cli/postinstall/gemini-instruction.d.ts.map +1 -0
- package/dist/cli/postinstall/gemini-instruction.js +59 -0
- package/dist/cli/postinstall/gemini-instruction.js.map +1 -0
- package/dist/cli/postinstall/index.d.ts +4 -0
- package/dist/cli/postinstall/index.d.ts.map +1 -1
- package/dist/cli/postinstall/index.js +4 -0
- package/dist/cli/postinstall/index.js.map +1 -1
- package/dist/cli/postinstall/main.d.ts.map +1 -1
- package/dist/cli/postinstall/main.js +34 -1
- package/dist/cli/postinstall/main.js.map +1 -1
- package/dist/cli/postinstall.d.ts +1 -1
- package/dist/cli/postinstall.d.ts.map +1 -1
- package/dist/cli/postinstall.js +1 -1
- package/dist/cli/postinstall.js.map +1 -1
- package/dist/cli/setup/ProjectSetup.d.ts +15 -0
- package/dist/cli/setup/ProjectSetup.d.ts.map +1 -1
- package/dist/cli/setup/ProjectSetup.js +159 -0
- package/dist/cli/setup/ProjectSetup.js.map +1 -1
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +1 -1
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/utils/cli-detector.d.ts +25 -0
- package/dist/cli/utils/cli-detector.d.ts.map +1 -0
- package/dist/cli/utils/cli-detector.js +55 -0
- package/dist/cli/utils/cli-detector.js.map +1 -0
- package/hooks/gemini-hooks.json +73 -0
- package/package.json +1 -1
- package/skills/agents-md/SKILL.md +120 -0
- package/skills/brand-assets/SKILL.md +8 -0
- package/skills/characterization-test/SKILL.md +4 -0
- package/skills/commerce-patterns/SKILL.md +36 -338
- package/skills/commit-push-pr/SKILL.md +21 -64
- package/skills/core-capabilities/SKILL.md +26 -142
- package/skills/e2e-commerce/SKILL.md +37 -284
- package/skills/frontend-design/SKILL.md +12 -31
- package/skills/git-worktree/SKILL.md +34 -146
- package/skills/handoff/SKILL.md +8 -0
- package/skills/parallel-research/SKILL.md +7 -0
- package/skills/priority-todos/SKILL.md +34 -213
- package/skills/seo-checklist/SKILL.md +38 -225
- package/skills/tool-fallback/SKILL.md +53 -143
- package/skills/typescript-advanced-types/SKILL.md +30 -685
- package/skills/ui-ux-pro-max/SKILL.md +40 -220
- package/skills/vercel-react-best-practices/SKILL.md +38 -283
- package/skills/video-production/SKILL.md +35 -206
|
@@ -5,94 +5,53 @@ triggers: [commit, push, PR, pull request, merge]
|
|
|
5
5
|
priority: 70
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Commit-Push-PR
|
|
9
|
-
|
|
10
|
-
Commit current changes, push to the remote branch, and create a GitHub PR.
|
|
8
|
+
# Commit-Push-PR
|
|
11
9
|
|
|
12
10
|
## Pre-checks
|
|
13
11
|
|
|
14
12
|
```bash
|
|
15
|
-
#
|
|
16
|
-
git
|
|
17
|
-
git
|
|
18
|
-
git log --oneline -5
|
|
13
|
+
git status # What's changed
|
|
14
|
+
git diff --stat # Review changes
|
|
15
|
+
git log --oneline -5 # Recent commits for style
|
|
19
16
|
```
|
|
20
17
|
|
|
21
18
|
## Workflow
|
|
22
19
|
|
|
23
20
|
1. Review and stage changed files
|
|
24
|
-
2. Write commit message (Conventional Commits
|
|
21
|
+
2. Write commit message (Conventional Commits)
|
|
25
22
|
3. Push to remote branch
|
|
26
23
|
4. Create PR with `gh pr create`
|
|
27
|
-
5. Write PR title/body
|
|
28
24
|
|
|
29
25
|
## Commit Message Format
|
|
30
26
|
|
|
31
27
|
```
|
|
32
28
|
[type] title (under 50 chars)
|
|
33
29
|
|
|
34
|
-
body (optional, 72 char
|
|
35
|
-
- What was changed
|
|
36
|
-
- Why it was changed
|
|
37
|
-
|
|
38
|
-
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### Type List
|
|
42
|
-
|
|
43
|
-
| Type | Description |
|
|
44
|
-
|------|-------------|
|
|
45
|
-
| `feat` | New feature |
|
|
46
|
-
| `fix` | Bug fix |
|
|
47
|
-
| `docs` | Documentation changes |
|
|
48
|
-
| `style` | Formatting (no code changes) |
|
|
49
|
-
| `refactor` | Refactoring |
|
|
50
|
-
| `test` | Add/modify tests |
|
|
51
|
-
| `chore` | Build, config changes |
|
|
52
|
-
| `perf` | Performance improvement |
|
|
53
|
-
|
|
54
|
-
## Co-Authored-By Rule
|
|
55
|
-
|
|
56
|
-
Always add for AI-generated/modified code:
|
|
30
|
+
body (optional, 72 char wrap)
|
|
57
31
|
|
|
58
|
-
```
|
|
59
32
|
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
60
33
|
```
|
|
61
34
|
|
|
62
|
-
|
|
35
|
+
Types: `feat` | `fix` | `docs` | `style` | `refactor` | `test` | `chore` | `perf`
|
|
63
36
|
|
|
64
|
-
|
|
37
|
+
## Security Checks (CRITICAL)
|
|
65
38
|
|
|
66
39
|
```bash
|
|
67
|
-
#
|
|
40
|
+
# Before committing — detect sensitive files
|
|
68
41
|
git diff --cached --name-only | grep -E '\.(env|pem|key)$|credentials|secret'
|
|
69
42
|
```
|
|
70
43
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
| File Pattern | Reason |
|
|
74
|
-
|-------------|--------|
|
|
75
|
-
| `.env`, `.env.local` | Environment variables (contains secrets) |
|
|
76
|
-
| `*.pem`, `*.key` | Certificates/keys |
|
|
77
|
-
| `credentials.json` | Authentication info |
|
|
78
|
-
| `service-account.json` | Service account |
|
|
79
|
-
|
|
80
|
-
> If any of these files are staged, immediately warn and abort the commit.
|
|
81
|
-
|
|
82
|
-
## Branch Protection Rules
|
|
44
|
+
**Never commit:** `.env`, `.env.local`, `*.pem`, `*.key`, `credentials.json`, `service-account.json`
|
|
83
45
|
|
|
84
|
-
|
|
46
|
+
> If sensitive files are staged, **immediately warn and abort**.
|
|
85
47
|
|
|
86
|
-
|
|
87
|
-
# Check current branch
|
|
88
|
-
git branch --show-current
|
|
89
|
-
```
|
|
48
|
+
## Branch Protection
|
|
90
49
|
|
|
91
50
|
- **No direct commits/pushes to main/master**
|
|
92
|
-
- If on main
|
|
93
|
-
- **Never** `--force` push
|
|
51
|
+
- If on main: create a new branch first
|
|
52
|
+
- **Never** `--force` push to main/master
|
|
94
53
|
|
|
95
|
-
## PR
|
|
54
|
+
## PR Format
|
|
96
55
|
|
|
97
56
|
```bash
|
|
98
57
|
gh pr create \
|
|
@@ -107,12 +66,10 @@ gh pr create \
|
|
|
107
66
|
- Test methods and results"
|
|
108
67
|
```
|
|
109
68
|
|
|
110
|
-
##
|
|
111
|
-
|
|
112
|
-
This skill follows rules from `.claude/vibe/rules/standards/git-workflow.md`:
|
|
113
|
-
|
|
114
|
-
- Conventional Commits format
|
|
115
|
-
- PR checklist compliance
|
|
116
|
-
- Prohibited actions (force push, .env commits, etc.)
|
|
69
|
+
## Done Criteria (K4)
|
|
117
70
|
|
|
118
|
-
|
|
71
|
+
- [ ] No sensitive files in commit
|
|
72
|
+
- [ ] Commit message follows Conventional Commits
|
|
73
|
+
- [ ] Co-Authored-By line included
|
|
74
|
+
- [ ] Not pushing directly to main/master
|
|
75
|
+
- [ ] PR created with clear description
|
|
@@ -4,161 +4,45 @@ description: "Core framework capabilities overview. Auto-activates when working
|
|
|
4
4
|
triggers: [core, capabilities, features, workflow, framework guide]
|
|
5
5
|
priority: 50
|
|
6
6
|
---
|
|
7
|
-
# Core Capabilities
|
|
8
|
-
|
|
9
|
-
Complete guide to core's scenario-driven development framework.
|
|
10
|
-
|
|
11
|
-
## Core Workflow
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
/vibe.spec → /vibe.run → /vibe.verify → /vibe.review
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Slash Commands
|
|
18
|
-
|
|
19
|
-
| Command | Purpose |
|
|
20
|
-
|---------|---------|
|
|
21
|
-
| `/vibe.spec "feature"` | Create SPEC with PTCF structure + 8 parallel research |
|
|
22
|
-
| `/vibe.spec "feature" split` | Create multiple SPECs for large scope features |
|
|
23
|
-
| `/vibe.run "feature"` | Implement based on SPEC |
|
|
24
|
-
| `/vibe.run "feature" ultrawork` | Maximum performance mode |
|
|
25
|
-
| `/vibe.verify "feature"` | BDD scenario verification |
|
|
26
|
-
| `/vibe.review` | Parallel code review (13+ agents) |
|
|
27
|
-
| `/vibe.analyze` | Project analysis |
|
|
28
|
-
| `/vibe.reason "problem"` | Systematic reasoning |
|
|
29
|
-
| `/vibe.utils --e2e` | Playwright E2E testing |
|
|
30
|
-
| `/vibe.utils --diagram` | Generate diagrams |
|
|
31
|
-
| `/vibe.utils --ui "description"` | UI preview |
|
|
32
|
-
| `/vibe.utils --continue` | Session restore (load previous context) |
|
|
33
|
-
| `/vibe.utils --compound` | Document solutions |
|
|
34
|
-
|
|
35
|
-
## Built-in Tools
|
|
36
|
-
|
|
37
|
-
### Semantic Code Analysis
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
node -e "import('{{VIBE_PATH_URL}}/node_modules/@su-record/vibe/dist/tools/index.js').then(t => t.TOOL_NAME({...}))"
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
| Tool | Purpose |
|
|
44
|
-
|------|---------|
|
|
45
|
-
| `findSymbol` | Find symbol definitions |
|
|
46
|
-
| `findReferences` | Find all references |
|
|
47
|
-
| `analyzeComplexity` | Code complexity analysis |
|
|
48
|
-
| `validateCodeQuality` | Quality validation |
|
|
49
|
-
|
|
50
|
-
### Memory Management
|
|
51
7
|
|
|
52
|
-
|
|
53
|
-
|------|---------|
|
|
54
|
-
| `startSession` | Start session (restore previous context) |
|
|
55
|
-
| `autoSaveContext` | Save current state |
|
|
56
|
-
| `saveMemory` | Save important decisions |
|
|
57
|
-
| `recallMemory` | Recall saved memory |
|
|
58
|
-
| `listMemories` | List saved memories |
|
|
59
|
-
|
|
60
|
-
## Orchestrator
|
|
61
|
-
|
|
62
|
-
### Background Agents
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
node -e "import('{{VIBE_PATH_URL}}/node_modules/@su-record/vibe/dist/infra/orchestrator/index.js').then(o =>
|
|
66
|
-
o.launchBackgroundAgent({ prompt: '...', agentName: '...' })
|
|
67
|
-
)"
|
|
68
|
-
```
|
|
8
|
+
# Core Capabilities
|
|
69
9
|
|
|
70
|
-
##
|
|
10
|
+
## Pre-check (K1)
|
|
71
11
|
|
|
72
|
-
|
|
12
|
+
> Need to call VIBE tools directly or understand orchestrator patterns? For slash commands and workflow, check CLAUDE.md first — it covers `/vibe.spec`, `/vibe.run`, `/vibe.review`, etc.
|
|
73
13
|
|
|
74
|
-
|
|
75
|
-
/vibe.spec "feature"
|
|
76
|
-
↓
|
|
77
|
-
[Claude] Draft SPEC
|
|
78
|
-
↓
|
|
79
|
-
[Parallel Research] 8 parallel tasks:
|
|
80
|
-
- 4x Bash: GPT/Gemini (best practices + security)
|
|
81
|
-
- 4x Task: Claude agents (docs, patterns, advisories)
|
|
82
|
-
↓
|
|
83
|
-
[SPEC Review] GPT + Gemini parallel review
|
|
84
|
-
↓
|
|
85
|
-
[Claude] Finalize SPEC
|
|
86
|
-
```
|
|
14
|
+
## Direct Tool Invocation (Not in CLAUDE.md)
|
|
87
15
|
|
|
88
|
-
|
|
89
|
-
|-------|--------|-------- |
|
|
90
|
-
| Research | `llm-orchestrate.js` via Bash | GPT best practices, GPT security, Gemini best practices, Gemini security |
|
|
91
|
-
| Research | Task tool (Claude agents) | framework-docs, codebase-patterns, best-practices, security-advisory |
|
|
92
|
-
| SPEC Review | `llm-orchestrate.js` via Bash | SPEC quality validation |
|
|
93
|
-
| Docs | context7 MCP | Latest library documentation |
|
|
16
|
+
Call built-in tools without slash commands:
|
|
94
17
|
|
|
95
|
-
**Setup:**
|
|
96
18
|
```bash
|
|
97
|
-
|
|
98
|
-
vibe
|
|
99
|
-
vibe
|
|
100
|
-
```
|
|
19
|
+
# Semantic code analysis
|
|
20
|
+
node -e "import('{{VIBE_PATH_URL}}/node_modules/@su-record/vibe/dist/tools/index.js').then(t => t.findSymbol({symbol: 'UserService'}))"
|
|
21
|
+
node -e "import('{{VIBE_PATH_URL}}/node_modules/@su-record/vibe/dist/tools/index.js').then(t => t.analyzeComplexity({filePath: 'src/service.ts'}))"
|
|
101
22
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
Add `ultrawork` or `ulw` for maximum performance:
|
|
105
|
-
|
|
106
|
-
- Parallel subagent exploration (3+ concurrent)
|
|
107
|
-
- Background agents preparing next phase
|
|
108
|
-
- Phase pipelining (no wait between phases)
|
|
109
|
-
- Boulder Loop (auto-progress until complete)
|
|
110
|
-
- Auto-retry on errors (max 3 times)
|
|
111
|
-
- Auto-compress at 70%+ context
|
|
112
|
-
|
|
113
|
-
## Review Agents (13+)
|
|
114
|
-
|
|
115
|
-
| Category | Agents |
|
|
116
|
-
|----------|--------|
|
|
117
|
-
| Security | security-reviewer, data-integrity-reviewer |
|
|
118
|
-
| Performance | performance-reviewer, complexity-reviewer |
|
|
119
|
-
| Architecture | architecture-reviewer, simplicity-reviewer |
|
|
120
|
-
| Language | python, typescript, rails, react reviewers |
|
|
121
|
-
| Context | git-history, test-coverage reviewers |
|
|
122
|
-
|
|
123
|
-
## Project Structure
|
|
23
|
+
# Background agent via orchestrator
|
|
24
|
+
node -e "import('{{VIBE_PATH_URL}}/node_modules/@su-record/vibe/dist/infra/orchestrator/index.js').then(o => o.launchBackgroundAgent({prompt: '...', agentName: '...'}))"
|
|
124
25
|
|
|
26
|
+
# Parallel research
|
|
27
|
+
node -e "import('{{VIBE_PATH_URL}}/node_modules/@su-record/vibe/dist/infra/orchestrator/index.js').then(o => o.research('topic', ['React']).then(r => console.log(r.content[0].text)))"
|
|
125
28
|
```
|
|
126
|
-
# Global (~/.claude/)
|
|
127
|
-
~/.claude/
|
|
128
|
-
├── commands/ # Slash commands
|
|
129
|
-
├── agents/ # Sub-agents
|
|
130
|
-
├── skills/ # Auto-activated guides
|
|
131
|
-
└── core/
|
|
132
|
-
├── rules/ # Coding rules
|
|
133
|
-
├── languages/ # Language guides
|
|
134
|
-
└── templates/ # Templates
|
|
135
|
-
|
|
136
|
-
# Global (%APPDATA%/vibe/ or ~/.config/vibe/)
|
|
137
|
-
core/
|
|
138
|
-
├── hooks/scripts/ # Hook scripts (llm-orchestrate.js)
|
|
139
|
-
├── gpt.json # GPT credentials
|
|
140
|
-
└── gemini.json # Gemini credentials
|
|
141
29
|
|
|
142
|
-
|
|
143
|
-
.claude/
|
|
144
|
-
├── settings.local.json # Hooks config (personal, gitignored)
|
|
145
|
-
└── core/
|
|
146
|
-
├── specs/ # SPEC documents
|
|
147
|
-
├── features/ # BDD scenarios
|
|
148
|
-
├── config.json # Project config
|
|
149
|
-
└── constitution.md # Project rules
|
|
150
|
-
```
|
|
30
|
+
## Available Tools
|
|
151
31
|
|
|
152
|
-
|
|
32
|
+
| Category | Tools |
|
|
33
|
+
|----------|-------|
|
|
34
|
+
| Code Analysis | `findSymbol`, `findReferences`, `analyzeComplexity`, `validateCodeQuality` |
|
|
35
|
+
| Memory | `startSession`, `autoSaveContext`, `saveMemory`, `recallMemory`, `listMemories` |
|
|
153
36
|
|
|
154
|
-
|
|
155
|
-
- 70/80/90%: Auto-save checkpoints
|
|
156
|
-
- Context overflow: Use `saveMemory` → `/new`
|
|
37
|
+
## Context Thresholds
|
|
157
38
|
|
|
158
|
-
|
|
39
|
+
| Threshold | Action |
|
|
40
|
+
|-----------|--------|
|
|
41
|
+
| 70% | `autoSaveContext` checkpoint |
|
|
42
|
+
| 80% | Warning + save |
|
|
43
|
+
| 90% | Critical — `saveMemory` → `/new` → `/vibe.utils --continue` |
|
|
159
44
|
|
|
160
|
-
|
|
45
|
+
## Done Criteria (K4)
|
|
161
46
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
3. Apply coding rules from `~/.claude/vibe/rules/` (global)
|
|
47
|
+
- [ ] Tool call executed successfully (non-empty result)
|
|
48
|
+
- [ ] Context saved before reaching 90% threshold
|
|
@@ -4,301 +4,54 @@ description: "E2E test scenarios for commerce checkout and payment flows"
|
|
|
4
4
|
triggers: [e2e commerce, checkout test, payment test, order flow test]
|
|
5
5
|
priority: 65
|
|
6
6
|
---
|
|
7
|
-
# E2E Commerce Test Scenarios
|
|
8
|
-
|
|
9
|
-
Playwright-based E2E testing for commerce checkout flows.
|
|
10
|
-
|
|
11
|
-
## When to Use
|
|
12
|
-
|
|
13
|
-
- After implementing checkout/payment features
|
|
14
|
-
- Before production deployment
|
|
15
|
-
- CI/CD pipeline quality gate
|
|
16
|
-
- Regression testing after changes
|
|
17
|
-
|
|
18
|
-
## Test Scenarios
|
|
19
|
-
|
|
20
|
-
### 1. Happy Path - Complete Checkout
|
|
21
|
-
|
|
22
|
-
```typescript
|
|
23
|
-
// tests/e2e/checkout.spec.ts
|
|
24
|
-
import { test, expect } from '@playwright/test';
|
|
25
|
-
|
|
26
|
-
test.describe('Checkout Flow', () => {
|
|
27
|
-
test('complete purchase - happy path', async ({ page }) => {
|
|
28
|
-
// 1. Add to cart
|
|
29
|
-
await page.goto('/products/test-product');
|
|
30
|
-
await page.click('[data-testid="add-to-cart"]');
|
|
31
|
-
await expect(page.locator('[data-testid="cart-count"]')).toHaveText('1');
|
|
32
|
-
|
|
33
|
-
// 2. Go to cart
|
|
34
|
-
await page.click('[data-testid="cart-icon"]');
|
|
35
|
-
await expect(page).toHaveURL('/cart');
|
|
36
|
-
|
|
37
|
-
// 3. Proceed to checkout
|
|
38
|
-
await page.click('[data-testid="checkout-button"]');
|
|
39
|
-
await expect(page).toHaveURL('/checkout');
|
|
40
|
-
|
|
41
|
-
// 4. Fill shipping info
|
|
42
|
-
await page.fill('[name="name"]', 'Test User');
|
|
43
|
-
await page.fill('[name="phone"]', '010-1234-5678');
|
|
44
|
-
await page.fill('[name="address"]', 'Test Address 123');
|
|
45
|
-
|
|
46
|
-
// 5. Select payment method
|
|
47
|
-
await page.click('[data-testid="payment-card"]');
|
|
48
|
-
|
|
49
|
-
// 6. Complete payment (sandbox/mock)
|
|
50
|
-
await page.click('[data-testid="pay-button"]');
|
|
51
|
-
|
|
52
|
-
// 7. Verify order complete
|
|
53
|
-
await expect(page).toHaveURL(/\/orders\/\w+/);
|
|
54
|
-
await expect(page.locator('[data-testid="order-status"]')).toHaveText('결제 완료');
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### 2. Stock Validation
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
test('prevent checkout when out of stock', async ({ page }) => {
|
|
63
|
-
// Setup: Product with stock = 1, another user reserves it
|
|
64
|
-
await page.goto('/products/low-stock-product');
|
|
65
|
-
await page.click('[data-testid="add-to-cart"]');
|
|
66
|
-
await page.goto('/checkout');
|
|
67
|
-
|
|
68
|
-
// Simulate stock depletion during checkout
|
|
69
|
-
await page.evaluate(async () => {
|
|
70
|
-
await fetch('/api/test/deplete-stock', { method: 'POST' });
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
// Attempt payment
|
|
74
|
-
await page.click('[data-testid="pay-button"]');
|
|
75
|
-
|
|
76
|
-
// Should show out of stock error
|
|
77
|
-
await expect(page.locator('[data-testid="error-message"]'))
|
|
78
|
-
.toContainText('재고가 부족합니다');
|
|
79
|
-
});
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### 3. Payment Failure Handling
|
|
83
|
-
|
|
84
|
-
```typescript
|
|
85
|
-
test('handle payment failure gracefully', async ({ page }) => {
|
|
86
|
-
await page.goto('/products/test-product');
|
|
87
|
-
await page.click('[data-testid="add-to-cart"]');
|
|
88
|
-
await page.goto('/checkout');
|
|
89
|
-
|
|
90
|
-
// Fill form
|
|
91
|
-
await page.fill('[name="name"]', 'Test User');
|
|
92
|
-
await page.fill('[name="address"]', 'Test Address');
|
|
93
|
-
|
|
94
|
-
// Use test card that triggers failure
|
|
95
|
-
await page.fill('[name="card-number"]', '4000000000000002'); // Decline card
|
|
96
|
-
await page.click('[data-testid="pay-button"]');
|
|
97
|
-
|
|
98
|
-
// Verify error handling
|
|
99
|
-
await expect(page.locator('[data-testid="payment-error"]'))
|
|
100
|
-
.toContainText('결제가 거절되었습니다');
|
|
101
|
-
|
|
102
|
-
// Stock should be released
|
|
103
|
-
await page.goto('/products/test-product');
|
|
104
|
-
await expect(page.locator('[data-testid="stock-status"]'))
|
|
105
|
-
.not.toContainText('품절');
|
|
106
|
-
});
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### 4. Duplicate Payment Prevention
|
|
110
7
|
|
|
111
|
-
|
|
112
|
-
test('prevent duplicate payment on double click', async ({ page }) => {
|
|
113
|
-
await page.goto('/checkout');
|
|
114
|
-
// Fill checkout form...
|
|
115
|
-
|
|
116
|
-
// Double click pay button rapidly
|
|
117
|
-
const payButton = page.locator('[data-testid="pay-button"]');
|
|
118
|
-
await Promise.all([
|
|
119
|
-
payButton.click(),
|
|
120
|
-
payButton.click(),
|
|
121
|
-
]);
|
|
122
|
-
|
|
123
|
-
// Wait for completion
|
|
124
|
-
await page.waitForURL(/\/orders\/\w+/);
|
|
125
|
-
|
|
126
|
-
// Verify only one order created
|
|
127
|
-
const orderId = page.url().split('/').pop();
|
|
128
|
-
const response = await page.request.get(`/api/orders?userId=test`);
|
|
129
|
-
const orders = await response.json();
|
|
130
|
-
|
|
131
|
-
expect(orders.filter(o => o.id === orderId)).toHaveLength(1);
|
|
132
|
-
});
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### 5. Coupon Application
|
|
136
|
-
|
|
137
|
-
```typescript
|
|
138
|
-
test('apply coupon and verify discount', async ({ page }) => {
|
|
139
|
-
await page.goto('/products/test-product'); // Price: 10,000
|
|
140
|
-
await page.click('[data-testid="add-to-cart"]');
|
|
141
|
-
await page.goto('/checkout');
|
|
142
|
-
|
|
143
|
-
// Original price
|
|
144
|
-
await expect(page.locator('[data-testid="total-price"]'))
|
|
145
|
-
.toHaveText('10,000원');
|
|
146
|
-
|
|
147
|
-
// Apply 10% coupon
|
|
148
|
-
await page.fill('[name="coupon"]', 'DISCOUNT10');
|
|
149
|
-
await page.click('[data-testid="apply-coupon"]');
|
|
150
|
-
|
|
151
|
-
// Verify discount applied
|
|
152
|
-
await expect(page.locator('[data-testid="discount-amount"]'))
|
|
153
|
-
.toHaveText('-1,000원');
|
|
154
|
-
await expect(page.locator('[data-testid="total-price"]'))
|
|
155
|
-
.toHaveText('9,000원');
|
|
156
|
-
});
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
### 6. Webhook Resilience
|
|
160
|
-
|
|
161
|
-
```typescript
|
|
162
|
-
test('order completes even with webhook delay', async ({ page, request }) => {
|
|
163
|
-
// Configure webhook delay in test environment
|
|
164
|
-
await request.post('/api/test/configure-webhook', {
|
|
165
|
-
data: { delay: 5000 } // 5 second delay
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
// Complete checkout
|
|
169
|
-
await page.goto('/checkout');
|
|
170
|
-
// ... fill form
|
|
171
|
-
await page.click('[data-testid="pay-button"]');
|
|
172
|
-
|
|
173
|
-
// Should show processing state
|
|
174
|
-
await expect(page.locator('[data-testid="order-status"]'))
|
|
175
|
-
.toHaveText('처리 중');
|
|
176
|
-
|
|
177
|
-
// Wait for webhook
|
|
178
|
-
await page.waitForSelector('[data-testid="order-status"]:has-text("결제 완료")', {
|
|
179
|
-
timeout: 10000
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
## CLI Usage
|
|
185
|
-
|
|
186
|
-
```bash
|
|
187
|
-
# Run all commerce e2e tests
|
|
188
|
-
/vibe.utils --e2e commerce
|
|
189
|
-
|
|
190
|
-
# Run specific scenario
|
|
191
|
-
/vibe.utils --e2e checkout-flow
|
|
192
|
-
|
|
193
|
-
# Run with visual recording
|
|
194
|
-
/vibe.utils --e2e commerce --record
|
|
195
|
-
|
|
196
|
-
# Run against staging
|
|
197
|
-
/vibe.utils --e2e commerce --env staging
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
## Test Environment Setup
|
|
201
|
-
|
|
202
|
-
### Mock PG Server
|
|
203
|
-
```typescript
|
|
204
|
-
// tests/mocks/pg-server.ts
|
|
205
|
-
import { setupServer } from 'msw/node';
|
|
206
|
-
import { http, HttpResponse } from 'msw';
|
|
207
|
-
|
|
208
|
-
export const pgMockServer = setupServer(
|
|
209
|
-
// Success response
|
|
210
|
-
http.post('/payments/authorize', () => {
|
|
211
|
-
return HttpResponse.json({
|
|
212
|
-
success: true,
|
|
213
|
-
transactionId: `txn_${Date.now()}`,
|
|
214
|
-
status: 'AUTHORIZED',
|
|
215
|
-
});
|
|
216
|
-
}),
|
|
217
|
-
|
|
218
|
-
// Failure simulation
|
|
219
|
-
http.post('/payments/authorize', ({ request }) => {
|
|
220
|
-
const body = request.json();
|
|
221
|
-
if (body.cardNumber === '4000000000000002') {
|
|
222
|
-
return HttpResponse.json({
|
|
223
|
-
success: false,
|
|
224
|
-
error: 'CARD_DECLINED',
|
|
225
|
-
}, { status: 400 });
|
|
226
|
-
}
|
|
227
|
-
}),
|
|
228
|
-
);
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### Database Seeding
|
|
232
|
-
```typescript
|
|
233
|
-
// tests/fixtures/commerce.ts
|
|
234
|
-
export async function seedCommerceData(db: Database) {
|
|
235
|
-
// Create test products
|
|
236
|
-
await db.products.createMany([
|
|
237
|
-
{ id: 'test-product', name: 'Test Product', price: 10000, stock: 100 },
|
|
238
|
-
{ id: 'low-stock', name: 'Low Stock', price: 5000, stock: 1 },
|
|
239
|
-
]);
|
|
8
|
+
# E2E Commerce Test Scenarios
|
|
240
9
|
|
|
241
|
-
|
|
242
|
-
await db.coupons.create({
|
|
243
|
-
code: 'DISCOUNT10',
|
|
244
|
-
discountPercent: 10,
|
|
245
|
-
expiresAt: addDays(new Date(), 30),
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
```
|
|
10
|
+
## Pre-check (K1)
|
|
249
11
|
|
|
250
|
-
|
|
12
|
+
> Are you testing a checkout/payment/order flow? If testing simple CRUD or non-transactional features, standard E2E patterns suffice — this skill is not needed.
|
|
251
13
|
|
|
252
|
-
|
|
253
|
-
# .github/workflows/e2e.yml
|
|
254
|
-
name: E2E Commerce Tests
|
|
14
|
+
## Must-Test Scenarios
|
|
255
15
|
|
|
256
|
-
|
|
257
|
-
pull_request:
|
|
258
|
-
paths:
|
|
259
|
-
- 'src/checkout/**'
|
|
260
|
-
- 'src/payment/**'
|
|
261
|
-
- 'src/cart/**'
|
|
16
|
+
### P0 — Blocks Deployment
|
|
262
17
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
18
|
+
| Scenario | What to Verify | Gotcha |
|
|
19
|
+
|----------|---------------|--------|
|
|
20
|
+
| **Happy path checkout** | Cart → Shipping → Payment → Order confirmation | Verify order status text, not just URL change |
|
|
21
|
+
| **Payment failure** | Error message shown, stock released | Check stock is RELEASED after failure, not just error displayed |
|
|
22
|
+
| **Duplicate payment** | Only 1 order created on double-click | `Promise.all([click(), click()])` then verify order count via API |
|
|
23
|
+
| **Out of stock** | Blocks checkout with clear message | Simulate stock depletion mid-checkout via test API |
|
|
268
24
|
|
|
269
|
-
|
|
270
|
-
run: npm ci
|
|
25
|
+
### P1 — Should Pass
|
|
271
26
|
|
|
272
|
-
|
|
273
|
-
|
|
27
|
+
| Scenario | What to Verify | Gotcha |
|
|
28
|
+
|----------|---------------|--------|
|
|
29
|
+
| **Coupon calculation** | Discount amount and total correct | Test percentage AND fixed amount coupons separately |
|
|
30
|
+
| **Webhook resilience** | Order completes even with delayed webhook | Configure 5s delay, verify processing→complete transition |
|
|
31
|
+
| **Cart merge on login** | Guest cart merged into user cart | User cart takes priority for duplicate items |
|
|
32
|
+
| **Partial refund** | Refunded amount correct, order updated | Verify remaining amount, not just refund event |
|
|
274
33
|
|
|
275
|
-
|
|
276
|
-
run: npx playwright test tests/e2e/commerce/
|
|
34
|
+
### P2 — Nice to Have
|
|
277
35
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
path: playwright-report/
|
|
284
|
-
```
|
|
36
|
+
| Scenario | What to Verify |
|
|
37
|
+
|----------|---------------|
|
|
38
|
+
| Multiple payment methods | Each method completes checkout |
|
|
39
|
+
| Guest checkout | Full flow without login |
|
|
40
|
+
| Order cancellation | Refund triggered, stock restored |
|
|
285
41
|
|
|
286
|
-
##
|
|
42
|
+
## Test Environment Gotchas
|
|
287
43
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
44
|
+
| Gotcha | Fix |
|
|
45
|
+
|--------|-----|
|
|
46
|
+
| Using real PG sandbox in CI | Use MSW (`setupServer`) for mock PG responses |
|
|
47
|
+
| Flaky tests from timing | Use `waitForSelector`/`waitForURL`, never `sleep` |
|
|
48
|
+
| Test data leaks between tests | Seed in `beforeAll`, clean in `afterAll` |
|
|
49
|
+
| Hardcoded test card numbers | Document: `4000000000000002` = decline |
|
|
293
50
|
|
|
294
|
-
|
|
295
|
-
- [ ] Coupon calculation correct
|
|
296
|
-
- [ ] Webhook retry handled
|
|
297
|
-
- [ ] Cart merge on login works
|
|
298
|
-
- [ ] Partial refund processed
|
|
51
|
+
## Done Criteria (K4)
|
|
299
52
|
|
|
300
|
-
|
|
301
|
-
- [ ]
|
|
302
|
-
- [ ]
|
|
303
|
-
- [ ]
|
|
304
|
-
- [ ]
|
|
53
|
+
- [ ] All P0 scenarios pass in CI
|
|
54
|
+
- [ ] P1 scenarios written and tracked
|
|
55
|
+
- [ ] Test data seeded/cleaned per suite
|
|
56
|
+
- [ ] No flaky tests (no arbitrary waits)
|
|
57
|
+
- [ ] Mock PG server configured for CI
|