specweave 0.23.12 → 0.23.16
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.md +55 -0
- package/dist/src/core/progress/error-logger.d.ts +58 -0
- package/dist/src/core/progress/error-logger.d.ts.map +1 -0
- package/dist/src/core/progress/error-logger.js +99 -0
- package/dist/src/core/progress/error-logger.js.map +1 -0
- package/dist/src/core/spec-detector.d.ts +5 -0
- package/dist/src/core/spec-detector.d.ts.map +1 -1
- package/dist/src/core/spec-detector.js +91 -33
- package/dist/src/core/spec-detector.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/hooks/docs-changed.sh +9 -1
- package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
- package/plugins/specweave/hooks/human-input-required.sh +9 -1
- package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
- package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
- package/plugins/specweave/hooks/post-increment-change.sh +6 -1
- package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
- package/plugins/specweave/hooks/post-increment-completion.sh +6 -1
- package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
- package/plugins/specweave/hooks/post-increment-planning.sh +6 -1
- package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
- package/plugins/specweave/hooks/post-increment-status-change.sh +6 -1
- package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
- package/plugins/specweave/hooks/post-metadata-change.sh +7 -1
- package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
- package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
- package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
- package/plugins/specweave/hooks/pre-implementation.sh +9 -1
- package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
- package/plugins/specweave/hooks/pre-task-completion.sh +9 -1
- package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
- package/plugins/specweave/hooks/pre-tool-use.sh +9 -1
- package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
- package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh +9 -2
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
- package/plugins/specweave-ado/hooks/post-task-completion.sh +9 -1
- package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-github/.claude-plugin/plugin.json +15 -1
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +16 -0
- package/plugins/specweave-github/hooks/post-task-completion.sh +62 -1
- package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
- package/plugins/specweave-jira/hooks/post-task-completion.sh +9 -1
- package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +48 -0
- package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
- package/plugins/specweave-alternatives/.claude-plugin/plugin.json +0 -21
- package/plugins/specweave-alternatives/skills/bmad-method-expert/SKILL.md +0 -626
- package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/analyze-project.js +0 -318
- package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/check-setup.js +0 -208
- package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/generate-template.js +0 -1149
- package/plugins/specweave-alternatives/skills/bmad-method-expert/scripts/validate-documents.js +0 -340
- package/plugins/specweave-alternatives/skills/spec-kit-expert/SKILL.md +0 -1010
- package/plugins/specweave-cost-optimizer/.claude-plugin/plugin.json +0 -20
- package/plugins/specweave-cost-optimizer/skills/cost-optimizer/SKILL.md +0 -190
- package/plugins/specweave-docs/.claude-plugin/plugin.json +0 -19
- package/plugins/specweave-docs/skills/docusaurus/SKILL.md +0 -613
- package/plugins/specweave-docs/skills/spec-driven-brainstorming/README.md +0 -264
- package/plugins/specweave-docs/skills/spec-driven-brainstorming/SKILL.md +0 -439
- package/plugins/specweave-docs/skills/spec-driven-debugging/README.md +0 -479
- package/plugins/specweave-docs/skills/spec-driven-debugging/SKILL.md +0 -652
- package/plugins/specweave-figma/.claude-plugin/.mcp.json +0 -12
- package/plugins/specweave-figma/.claude-plugin/plugin.json +0 -20
- package/plugins/specweave-figma/ARCHITECTURE.md +0 -453
- package/plugins/specweave-figma/README.md +0 -728
- package/plugins/specweave-figma/skills/figma-to-code/SKILL.md +0 -632
- package/plugins/specweave-figma/skills/figma-to-code/test-1-token-generation.yaml +0 -29
- package/plugins/specweave-figma/skills/figma-to-code/test-2-component-generation.yaml +0 -27
- package/plugins/specweave-figma/skills/figma-to-code/test-3-typescript-generation.yaml +0 -28
- package/plugins/specweave-frontend/.claude-plugin/plugin.json +0 -21
- package/plugins/specweave-frontend/skills/design-system-architect/SKILL.md +0 -107
- package/plugins/specweave-frontend/skills/frontend/SKILL.md +0 -177
- package/plugins/specweave-frontend/skills/nextjs/SKILL.md +0 -176
- package/plugins/specweave-testing/.claude-plugin/plugin.json +0 -20
- package/plugins/specweave-testing/skills/e2e-playwright/README.md +0 -506
- package/plugins/specweave-testing/skills/e2e-playwright/SKILL.md +0 -457
- package/plugins/specweave-testing/skills/e2e-playwright/execute.js +0 -373
- package/plugins/specweave-testing/skills/e2e-playwright/lib/utils.js +0 -514
- package/plugins/specweave-testing/skills/e2e-playwright/package.json +0 -33
- package/plugins/specweave-tooling/.claude-plugin/plugin.json +0 -19
- package/plugins/specweave-tooling/skills/skill-creator/LICENSE.txt +0 -202
- package/plugins/specweave-tooling/skills/skill-creator/SKILL.md +0 -209
- package/plugins/specweave-tooling/skills/skill-creator/scripts/init_skill.py +0 -303
- package/plugins/specweave-tooling/skills/skill-creator/scripts/package_skill.py +0 -110
- package/plugins/specweave-tooling/skills/skill-creator/scripts/quick_validate.py +0 -65
- package/plugins/specweave-tooling/skills/skill-router/SKILL.md +0 -479
- package/plugins/specweave-ui/.claude-plugin/plugin.json +0 -26
- package/plugins/specweave-ui/.mcp.json +0 -10
- package/plugins/specweave-ui/README.md +0 -492
- package/plugins/specweave-ui/skills/browser-automation/SKILL.md +0 -676
|
@@ -1,676 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: browser-automation
|
|
3
|
-
description: |
|
|
4
|
-
Browser automation and E2E testing using Playwright MCP (always available).
|
|
5
|
-
Auto-activates for: browser automation, web testing, E2E tests, Playwright, browser interaction,
|
|
6
|
-
scraping, testing flows, user journeys, accessibility testing, screenshot capture.
|
|
7
|
-
|
|
8
|
-
CRITICAL: ALWAYS use Playwright MCP (mcp__plugin_specweave-ui_playwright__*) as PRIMARY choice.
|
|
9
|
-
|
|
10
|
-
NOTE: Browserbase tools (mcp__plugin_specweave-ui_browserbase__*) are NOT loaded by default.
|
|
11
|
-
They require manual setup and are only for CI/CD or cloud scenarios.
|
|
12
|
-
allowed-tools:
|
|
13
|
-
- mcp__plugin_specweave-ui_playwright__*
|
|
14
|
-
- mcp__plugin_specweave-ui_browserbase__*
|
|
15
|
-
- Read
|
|
16
|
-
- Write
|
|
17
|
-
- Bash
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
# Browser Automation Skill
|
|
21
|
-
|
|
22
|
-
**Expert in browser automation and E2E testing using Playwright MCP and Browserbase.**
|
|
23
|
-
|
|
24
|
-
## Core Capabilities
|
|
25
|
-
|
|
26
|
-
### 1. Playwright MCP Integration (PRIMARY - Local Testing)
|
|
27
|
-
|
|
28
|
-
**✅ ALWAYS TRY PLAYWRIGHT MCP FIRST!**
|
|
29
|
-
|
|
30
|
-
Playwright MCP provides local, fast, reliable browser automation:
|
|
31
|
-
|
|
32
|
-
#### Available Tools (mcp__plugin_specweave-ui_playwright__*)
|
|
33
|
-
|
|
34
|
-
- **browser_goto** - Navigate to URLs
|
|
35
|
-
- **browser_click** - Click elements (by role, text, test ID)
|
|
36
|
-
- **browser_fill** - Fill form inputs
|
|
37
|
-
- **browser_press** - Keyboard interactions
|
|
38
|
-
- **browser_evaluate** - Execute JavaScript
|
|
39
|
-
- **browser_snapshot** - Get accessibility tree (for element selection)
|
|
40
|
-
- **browser_console_messages** - Retrieve console logs
|
|
41
|
-
- **browser_close** - Close browser session
|
|
42
|
-
|
|
43
|
-
#### Best Practices (Microsoft Playwright MCP Guidelines)
|
|
44
|
-
|
|
45
|
-
**Element Selection Strategy** (in priority order):
|
|
46
|
-
|
|
47
|
-
1. **getByRole** (PREFERRED) - Accessibility-first, semantic selection
|
|
48
|
-
```javascript
|
|
49
|
-
// Example: Click a button
|
|
50
|
-
browser_click({ ref: "button[name='submit']", element: "Submit button" })
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
2. **getByText** - Text content selection
|
|
54
|
-
```javascript
|
|
55
|
-
// Example: Find by visible text
|
|
56
|
-
browser_click({ ref: "text='Sign In'", element: "Sign In button" })
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
3. **getByTestId** - Test ID attributes (data-testid)
|
|
60
|
-
```javascript
|
|
61
|
-
// Example: Use test IDs
|
|
62
|
-
browser_click({ ref: "[data-testid='login-btn']", element: "Login button" })
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
4. **Avoid .locator** - Only use when absolutely necessary with justification comment
|
|
66
|
-
|
|
67
|
-
**Session Management**:
|
|
68
|
-
- Default: Persistent profile (retains login state)
|
|
69
|
-
- Use `--isolated` flag for fresh sessions
|
|
70
|
-
- Use `--storage-state` for pre-authenticated scenarios
|
|
71
|
-
|
|
72
|
-
**Configuration Options**:
|
|
73
|
-
```json
|
|
74
|
-
{
|
|
75
|
-
"playwright": {
|
|
76
|
-
"command": "npx",
|
|
77
|
-
"args": [
|
|
78
|
-
"@playwright/mcp@latest",
|
|
79
|
-
"--browser", "chromium", // or firefox, webkit, msedge
|
|
80
|
-
"--headless", // or omit for headed mode
|
|
81
|
-
"--timeout-action", "5000", // ms
|
|
82
|
-
"--timeout-navigation", "60000" // ms
|
|
83
|
-
]
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
#### Testing Workflow
|
|
89
|
-
|
|
90
|
-
**Step 1: Navigate**
|
|
91
|
-
```javascript
|
|
92
|
-
browser_goto({ url: "https://example.com" })
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
**Step 2: Get Snapshot (for element discovery)**
|
|
96
|
-
```javascript
|
|
97
|
-
browser_snapshot({ fullPage: true })
|
|
98
|
-
// Returns accessibility tree with element refs
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
**Step 3: Interact with Elements**
|
|
102
|
-
```javascript
|
|
103
|
-
// Click button (by role)
|
|
104
|
-
browser_click({
|
|
105
|
-
ref: "button[name='login']",
|
|
106
|
-
element: "Login button"
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
// Fill input (by role)
|
|
110
|
-
browser_fill({
|
|
111
|
-
ref: "input[name='email']",
|
|
112
|
-
text: "user@example.com"
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
// Press Enter
|
|
116
|
-
browser_press({
|
|
117
|
-
ref: "input[name='email']",
|
|
118
|
-
key: "Enter"
|
|
119
|
-
})
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
**Step 4: Verify Results**
|
|
123
|
-
```javascript
|
|
124
|
-
// Execute JavaScript to check state
|
|
125
|
-
browser_evaluate({
|
|
126
|
-
code: "document.querySelector('.success-message').textContent"
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
// Get console messages
|
|
130
|
-
browser_console_messages()
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
**Step 5: Clean Up**
|
|
134
|
-
```javascript
|
|
135
|
-
browser_close()
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### 2. Browserbase Integration (OPTIONAL - Cloud Testing)
|
|
139
|
-
|
|
140
|
-
**⚠️ NOT LOADED BY DEFAULT - Manual setup required!**
|
|
141
|
-
|
|
142
|
-
**Note**: Browserbase is NOT auto-loaded to save ~5,600 tokens per request. Enable only when needed for CI/CD or cloud scenarios.
|
|
143
|
-
|
|
144
|
-
Browserbase provides cloud-based browser automation:
|
|
145
|
-
|
|
146
|
-
#### When to Use Browserbase
|
|
147
|
-
|
|
148
|
-
- ✅ CI/CD pipelines without local browsers
|
|
149
|
-
- ✅ Parallel test execution (10x faster)
|
|
150
|
-
- ✅ Cross-browser testing at scale
|
|
151
|
-
- ❌ **NOT for local development** (use Playwright MCP!)
|
|
152
|
-
|
|
153
|
-
#### Available Tools (mcp__plugin_specweave-ui_browserbase__*)
|
|
154
|
-
|
|
155
|
-
**Note**: These tools are ONLY available after manual setup.
|
|
156
|
-
|
|
157
|
-
- **browserbase_session_create** - Create cloud session
|
|
158
|
-
- **browserbase_session_close** - Close session
|
|
159
|
-
- **browserbase_stagehand_navigate** - Navigate to URL
|
|
160
|
-
- **browserbase_stagehand_act** - Perform action (click, type, etc.)
|
|
161
|
-
- **browserbase_stagehand_extract** - Extract data from page
|
|
162
|
-
- **browserbase_stagehand_observe** - Find elements
|
|
163
|
-
- **browserbase_screenshot** - Capture screenshot
|
|
164
|
-
- **browserbase_stagehand_get_url** - Get current URL
|
|
165
|
-
- **browserbase_stagehand_agent** - Run autonomous task
|
|
166
|
-
|
|
167
|
-
#### Manual Setup (when needed)
|
|
168
|
-
|
|
169
|
-
1. Get API credentials from [Browserbase](https://www.browserbase.com/)
|
|
170
|
-
2. Set environment variables:
|
|
171
|
-
```bash
|
|
172
|
-
export BROWSERBASE_API_KEY="bb_xxx"
|
|
173
|
-
export BROWSERBASE_PROJECT_ID="proj_xxx"
|
|
174
|
-
```
|
|
175
|
-
3. Add to `.claude/settings.json`:
|
|
176
|
-
```json
|
|
177
|
-
{
|
|
178
|
-
"mcpServers": {
|
|
179
|
-
"browserbase": {
|
|
180
|
-
"command": "npx",
|
|
181
|
-
"args": ["-y", "@browserbasehq/mcp-server-browserbase"],
|
|
182
|
-
"env": {
|
|
183
|
-
"BROWSERBASE_API_KEY": "${BROWSERBASE_API_KEY}",
|
|
184
|
-
"BROWSERBASE_PROJECT_ID": "${BROWSERBASE_PROJECT_ID}"
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
```
|
|
190
|
-
4. Restart Claude Code
|
|
191
|
-
|
|
192
|
-
#### Testing Workflow (Browserbase)
|
|
193
|
-
|
|
194
|
-
**Step 1: Create Session**
|
|
195
|
-
```javascript
|
|
196
|
-
browserbase_session_create()
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
**Step 2: Navigate**
|
|
200
|
-
```javascript
|
|
201
|
-
browserbase_stagehand_navigate({ url: "https://example.com" })
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
**Step 3: Interact**
|
|
205
|
-
```javascript
|
|
206
|
-
// Click button (natural language)
|
|
207
|
-
browserbase_stagehand_act({
|
|
208
|
-
action: "Click the login button"
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
// Fill form (natural language)
|
|
212
|
-
browserbase_stagehand_act({
|
|
213
|
-
action: "Type 'user@example.com' into the email field"
|
|
214
|
-
})
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
**Step 4: Extract Data**
|
|
218
|
-
```javascript
|
|
219
|
-
browserbase_stagehand_extract({
|
|
220
|
-
instruction: "Extract all product names and prices"
|
|
221
|
-
})
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
**Step 5: Close Session**
|
|
225
|
-
```javascript
|
|
226
|
-
browserbase_session_close()
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### 3. E2E Test Writing Best Practices
|
|
230
|
-
|
|
231
|
-
#### Test Structure
|
|
232
|
-
|
|
233
|
-
```typescript
|
|
234
|
-
import { test, expect } from '@playwright/test';
|
|
235
|
-
|
|
236
|
-
test.describe('User Login Flow', () => {
|
|
237
|
-
test('should login successfully with valid credentials', async ({ page }) => {
|
|
238
|
-
// ✅ Use accessibility-first selectors
|
|
239
|
-
await page.goto('https://example.com/login');
|
|
240
|
-
|
|
241
|
-
// ✅ getByRole (PREFERRED)
|
|
242
|
-
await page.getByRole('textbox', { name: 'Email' }).fill('user@example.com');
|
|
243
|
-
await page.getByRole('textbox', { name: 'Password' }).fill('password123');
|
|
244
|
-
await page.getByRole('button', { name: 'Sign In' }).click();
|
|
245
|
-
|
|
246
|
-
// ✅ Verify outcome
|
|
247
|
-
await expect(page.getByText('Welcome back!')).toBeVisible();
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
test('should show error with invalid credentials', async ({ page }) => {
|
|
251
|
-
await page.goto('https://example.com/login');
|
|
252
|
-
|
|
253
|
-
// ✅ getByTestId for stable selectors
|
|
254
|
-
await page.getByTestId('email-input').fill('invalid@example.com');
|
|
255
|
-
await page.getByTestId('password-input').fill('wrong');
|
|
256
|
-
await page.getByTestId('login-button').click();
|
|
257
|
-
|
|
258
|
-
// ✅ Verify error message
|
|
259
|
-
await expect(page.getByText('Invalid credentials')).toBeVisible();
|
|
260
|
-
});
|
|
261
|
-
});
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
#### Selector Guidelines (Priority Order)
|
|
265
|
-
|
|
266
|
-
1. **getByRole** - Accessibility-first (BEST)
|
|
267
|
-
- `getByRole('button', { name: 'Submit' })`
|
|
268
|
-
- `getByRole('textbox', { name: 'Email' })`
|
|
269
|
-
- `getByRole('link', { name: 'Home' })`
|
|
270
|
-
|
|
271
|
-
2. **getByText** - Visible text (GOOD)
|
|
272
|
-
- `getByText('Sign In')`
|
|
273
|
-
- `getByText(/welcome/i)` (regex)
|
|
274
|
-
|
|
275
|
-
3. **getByTestId** - Test attributes (OK)
|
|
276
|
-
- `getByTestId('login-form')`
|
|
277
|
-
- Requires: `<form data-testid="login-form">`
|
|
278
|
-
|
|
279
|
-
4. **getByLabel** - Form labels (OK)
|
|
280
|
-
- `getByLabel('Email')`
|
|
281
|
-
|
|
282
|
-
5. **.locator** - CSS/XPath (AVOID)
|
|
283
|
-
- Only use with clear justification comment
|
|
284
|
-
- Example: `// JUSTIFICATION: Complex table structure requires XPath`
|
|
285
|
-
|
|
286
|
-
#### Test Organization
|
|
287
|
-
|
|
288
|
-
```typescript
|
|
289
|
-
// ✅ Use .serial for dependent tests
|
|
290
|
-
test.describe.serial('User Journey', () => {
|
|
291
|
-
test('step 1: register', async ({ page }) => {
|
|
292
|
-
// Registration flow
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
test('step 2: verify email', async ({ page }) => {
|
|
296
|
-
// Email verification (depends on step 1)
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
test('step 3: complete profile', async ({ page }) => {
|
|
300
|
-
// Profile completion (depends on step 2)
|
|
301
|
-
});
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
// ✅ Re-use auth state
|
|
305
|
-
test.use({ storageState: 'auth.json' });
|
|
306
|
-
|
|
307
|
-
test('authenticated action', async ({ page }) => {
|
|
308
|
-
// Already logged in via storageState
|
|
309
|
-
await page.goto('https://example.com/dashboard');
|
|
310
|
-
});
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
### 4. Common Patterns
|
|
314
|
-
|
|
315
|
-
#### Pattern: Form Submission
|
|
316
|
-
```javascript
|
|
317
|
-
// Playwright MCP
|
|
318
|
-
browser_goto({ url: "https://example.com/contact" })
|
|
319
|
-
browser_fill({ ref: "input[name='email']", text: "user@example.com" })
|
|
320
|
-
browser_fill({ ref: "textarea[name='message']", text: "Hello!" })
|
|
321
|
-
browser_click({ ref: "button[type='submit']", element: "Submit button" })
|
|
322
|
-
|
|
323
|
-
// Browserbase (fallback)
|
|
324
|
-
browserbase_stagehand_act({ action: "Fill email with user@example.com" })
|
|
325
|
-
browserbase_stagehand_act({ action: "Fill message with Hello!" })
|
|
326
|
-
browserbase_stagehand_act({ action: "Click the Submit button" })
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
#### Pattern: Data Extraction
|
|
330
|
-
```javascript
|
|
331
|
-
// Playwright MCP
|
|
332
|
-
browser_snapshot() // Get page structure
|
|
333
|
-
browser_evaluate({
|
|
334
|
-
code: `
|
|
335
|
-
Array.from(document.querySelectorAll('.product')).map(el => ({
|
|
336
|
-
name: el.querySelector('.name').textContent,
|
|
337
|
-
price: el.querySelector('.price').textContent
|
|
338
|
-
}))
|
|
339
|
-
`
|
|
340
|
-
})
|
|
341
|
-
|
|
342
|
-
// Browserbase (fallback)
|
|
343
|
-
browserbase_stagehand_extract({
|
|
344
|
-
instruction: "Extract all product names and prices from the page"
|
|
345
|
-
})
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
#### Pattern: Screenshot Capture
|
|
349
|
-
```javascript
|
|
350
|
-
// Playwright MCP
|
|
351
|
-
browser_evaluate({
|
|
352
|
-
code: `
|
|
353
|
-
const canvas = await page.screenshot({ fullPage: true });
|
|
354
|
-
canvas.toDataURL('image/png')
|
|
355
|
-
`
|
|
356
|
-
})
|
|
357
|
-
|
|
358
|
-
// Browserbase (fallback)
|
|
359
|
-
browserbase_screenshot({ name: "page-capture" })
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
### 5. Debugging E2E Tests
|
|
363
|
-
|
|
364
|
-
#### Test Output Analysis
|
|
365
|
-
|
|
366
|
-
When tests fail, check `test-output/` for:
|
|
367
|
-
- **Error context** (.md files) - What went wrong
|
|
368
|
-
- **Screenshots** (.png files) - End state visualization
|
|
369
|
-
- **Traces** (.zip files) - Full execution trace
|
|
370
|
-
|
|
371
|
-
#### Common Issues
|
|
372
|
-
|
|
373
|
-
**Issue: Element not found**
|
|
374
|
-
```javascript
|
|
375
|
-
// ❌ BAD: Fragile selector
|
|
376
|
-
await page.locator('.btn-primary').click()
|
|
377
|
-
|
|
378
|
-
// ✅ GOOD: Accessibility-first
|
|
379
|
-
await page.getByRole('button', { name: 'Submit' }).click()
|
|
380
|
-
```
|
|
381
|
-
|
|
382
|
-
**Issue: Timing issues**
|
|
383
|
-
```javascript
|
|
384
|
-
// ❌ BAD: Arbitrary wait
|
|
385
|
-
await page.waitForTimeout(5000)
|
|
386
|
-
|
|
387
|
-
// ✅ GOOD: Wait for specific condition
|
|
388
|
-
await page.waitForSelector('[data-testid="success-message"]')
|
|
389
|
-
await expect(page.getByText('Success')).toBeVisible()
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
**Issue: Flaky tests**
|
|
393
|
-
```javascript
|
|
394
|
-
// ✅ Use test-only API endpoints
|
|
395
|
-
await request.post('/api/test/seed', { data: testData })
|
|
396
|
-
|
|
397
|
-
// ✅ Re-use auth storage state
|
|
398
|
-
test.use({ storageState: 'auth.json' })
|
|
399
|
-
|
|
400
|
-
// ✅ Explicit waits
|
|
401
|
-
await page.waitForLoadState('networkidle')
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
## Decision Tree: Which Tool to Use?
|
|
405
|
-
|
|
406
|
-
```
|
|
407
|
-
Are you running locally (dev machine or VM)?
|
|
408
|
-
├─ YES → Use Playwright MCP (PRIMARY)
|
|
409
|
-
│ ├─ Tools: mcp__plugin_specweave-ui_playwright__*
|
|
410
|
-
│ ├─ Fast, reliable, local execution
|
|
411
|
-
│ └─ No API keys needed
|
|
412
|
-
│
|
|
413
|
-
└─ NO → Running in CI/CD or need cloud infrastructure?
|
|
414
|
-
└─ YES → Use Browserbase (FALLBACK)
|
|
415
|
-
├─ Tools: mcp__plugin_specweave-ui_browserbase__*
|
|
416
|
-
├─ Requires: BROWSERBASE_API_KEY, BROWSERBASE_PROJECT_ID
|
|
417
|
-
└─ Benefits: Parallel execution, no browser install
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
## Configuration Files
|
|
421
|
-
|
|
422
|
-
### .mcp.json (Plugin-Level - Auto-Loaded)
|
|
423
|
-
```json
|
|
424
|
-
{
|
|
425
|
-
"mcpServers": {
|
|
426
|
-
"playwright": {
|
|
427
|
-
"command": "npx",
|
|
428
|
-
"args": ["-y", "@playwright/mcp@latest"],
|
|
429
|
-
"description": "Local Playwright - PRIMARY",
|
|
430
|
-
"optional": false
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
**Note**: Browserbase is NOT in `.mcp.json` (not auto-loaded). To enable Browserbase, add it to your project's `.claude/settings.json` as shown in the "Manual Setup" section above.
|
|
437
|
-
|
|
438
|
-
### playwright.config.ts (Project-Level)
|
|
439
|
-
```typescript
|
|
440
|
-
import { defineConfig } from '@playwright/test';
|
|
441
|
-
|
|
442
|
-
export default defineConfig({
|
|
443
|
-
testDir: './tests/e2e',
|
|
444
|
-
timeout: 30000,
|
|
445
|
-
expect: {
|
|
446
|
-
timeout: 5000
|
|
447
|
-
},
|
|
448
|
-
use: {
|
|
449
|
-
// ✅ Accessibility-first testing
|
|
450
|
-
actionTimeout: 5000,
|
|
451
|
-
navigationTimeout: 60000,
|
|
452
|
-
|
|
453
|
-
// ✅ Screenshots on failure
|
|
454
|
-
screenshot: 'only-on-failure',
|
|
455
|
-
|
|
456
|
-
// ✅ Traces for debugging
|
|
457
|
-
trace: 'retain-on-failure',
|
|
458
|
-
},
|
|
459
|
-
projects: [
|
|
460
|
-
{
|
|
461
|
-
name: 'chromium',
|
|
462
|
-
use: { browserName: 'chromium' }
|
|
463
|
-
},
|
|
464
|
-
{
|
|
465
|
-
name: 'firefox',
|
|
466
|
-
use: { browserName: 'firefox' }
|
|
467
|
-
},
|
|
468
|
-
{
|
|
469
|
-
name: 'webkit',
|
|
470
|
-
use: { browserName: 'webkit' }
|
|
471
|
-
}
|
|
472
|
-
]
|
|
473
|
-
});
|
|
474
|
-
```
|
|
475
|
-
|
|
476
|
-
## Quick Reference
|
|
477
|
-
|
|
478
|
-
### Playwright MCP Commands
|
|
479
|
-
```bash
|
|
480
|
-
# Install MCP server
|
|
481
|
-
npx @playwright/mcp@latest
|
|
482
|
-
|
|
483
|
-
# Run with options
|
|
484
|
-
npx @playwright/mcp@latest --browser chromium --headless
|
|
485
|
-
|
|
486
|
-
# Run with config
|
|
487
|
-
npx @playwright/mcp@latest --config playwright-mcp.json
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
### Browserbase Setup
|
|
491
|
-
```bash
|
|
492
|
-
# Get API keys
|
|
493
|
-
# 1. Sign up at https://www.browserbase.com/
|
|
494
|
-
# 2. Create project
|
|
495
|
-
# 3. Get API key and project ID
|
|
496
|
-
|
|
497
|
-
# Set environment
|
|
498
|
-
export BROWSERBASE_API_KEY="bb_xxx"
|
|
499
|
-
export BROWSERBASE_PROJECT_ID="proj_xxx"
|
|
500
|
-
|
|
501
|
-
# Test connection
|
|
502
|
-
npx -y @browserbasehq/mcp-server-browserbase
|
|
503
|
-
```
|
|
504
|
-
|
|
505
|
-
## Examples
|
|
506
|
-
|
|
507
|
-
### Example 1: Login Flow (Playwright MCP)
|
|
508
|
-
```javascript
|
|
509
|
-
// Step 1: Navigate
|
|
510
|
-
browser_goto({ url: "https://app.example.com/login" })
|
|
511
|
-
|
|
512
|
-
// Step 2: Fill form
|
|
513
|
-
browser_fill({ ref: "input[name='email']", text: "user@example.com" })
|
|
514
|
-
browser_fill({ ref: "input[name='password']", text: "secure123" })
|
|
515
|
-
|
|
516
|
-
// Step 3: Submit
|
|
517
|
-
browser_click({ ref: "button[type='submit']", element: "Login button" })
|
|
518
|
-
|
|
519
|
-
// Step 4: Verify
|
|
520
|
-
browser_evaluate({ code: "document.querySelector('.welcome').textContent" })
|
|
521
|
-
// Returns: "Welcome back, User!"
|
|
522
|
-
```
|
|
523
|
-
|
|
524
|
-
### Example 2: E2E Test Generation
|
|
525
|
-
```typescript
|
|
526
|
-
import { test, expect } from '@playwright/test';
|
|
527
|
-
|
|
528
|
-
test('complete user registration flow', async ({ page }) => {
|
|
529
|
-
// Navigate
|
|
530
|
-
await page.goto('https://app.example.com/signup');
|
|
531
|
-
|
|
532
|
-
// ✅ MUST use getByRole (accessibility-first)
|
|
533
|
-
await page.getByRole('textbox', { name: 'Email' })
|
|
534
|
-
.fill('newuser@example.com');
|
|
535
|
-
await page.getByRole('textbox', { name: 'Password' })
|
|
536
|
-
.fill('secure123');
|
|
537
|
-
await page.getByRole('textbox', { name: 'Confirm Password' })
|
|
538
|
-
.fill('secure123');
|
|
539
|
-
|
|
540
|
-
// ✅ MUST use getByRole for button
|
|
541
|
-
await page.getByRole('button', { name: 'Create Account' }).click();
|
|
542
|
-
|
|
543
|
-
// ✅ Verify success
|
|
544
|
-
await expect(page.getByText('Account created successfully'))
|
|
545
|
-
.toBeVisible();
|
|
546
|
-
});
|
|
547
|
-
```
|
|
548
|
-
|
|
549
|
-
### Example 3: Data Extraction (Browserbase Fallback)
|
|
550
|
-
```javascript
|
|
551
|
-
// Create session
|
|
552
|
-
browserbase_session_create()
|
|
553
|
-
|
|
554
|
-
// Navigate
|
|
555
|
-
browserbase_stagehand_navigate({ url: "https://products.example.com" })
|
|
556
|
-
|
|
557
|
-
// Extract products
|
|
558
|
-
browserbase_stagehand_extract({
|
|
559
|
-
instruction: "Extract all product names, prices, and availability status"
|
|
560
|
-
})
|
|
561
|
-
// Returns: [
|
|
562
|
-
// { name: "Product A", price: "$99", available: true },
|
|
563
|
-
// { name: "Product B", price: "$149", available: false }
|
|
564
|
-
// ]
|
|
565
|
-
|
|
566
|
-
// Close session
|
|
567
|
-
browserbase_session_close()
|
|
568
|
-
```
|
|
569
|
-
|
|
570
|
-
## Troubleshooting
|
|
571
|
-
|
|
572
|
-
### Playwright MCP Issues
|
|
573
|
-
|
|
574
|
-
**Issue: MCP server not found**
|
|
575
|
-
```bash
|
|
576
|
-
# Install globally
|
|
577
|
-
npm install -g @playwright/mcp
|
|
578
|
-
|
|
579
|
-
# Or use npx (recommended)
|
|
580
|
-
npx @playwright/mcp@latest
|
|
581
|
-
```
|
|
582
|
-
|
|
583
|
-
**Issue: Browser not installed**
|
|
584
|
-
```bash
|
|
585
|
-
# Install Playwright browsers
|
|
586
|
-
npx playwright install chromium
|
|
587
|
-
```
|
|
588
|
-
|
|
589
|
-
**Issue: Timeout errors**
|
|
590
|
-
```json
|
|
591
|
-
{
|
|
592
|
-
"args": [
|
|
593
|
-
"@playwright/mcp@latest",
|
|
594
|
-
"--timeout-action", "10000",
|
|
595
|
-
"--timeout-navigation", "120000"
|
|
596
|
-
]
|
|
597
|
-
}
|
|
598
|
-
```
|
|
599
|
-
|
|
600
|
-
### Browserbase Issues
|
|
601
|
-
|
|
602
|
-
**Issue: Authentication failed**
|
|
603
|
-
```bash
|
|
604
|
-
# Check environment variables
|
|
605
|
-
echo $BROWSERBASE_API_KEY
|
|
606
|
-
echo $BROWSERBASE_PROJECT_ID
|
|
607
|
-
|
|
608
|
-
# Re-set if missing
|
|
609
|
-
export BROWSERBASE_API_KEY="bb_xxx"
|
|
610
|
-
export BROWSERBASE_PROJECT_ID="proj_xxx"
|
|
611
|
-
```
|
|
612
|
-
|
|
613
|
-
**Issue: Session creation timeout**
|
|
614
|
-
- Check Browserbase dashboard for quota limits
|
|
615
|
-
- Verify API key has correct permissions
|
|
616
|
-
- Try reducing parallel session count
|
|
617
|
-
|
|
618
|
-
## Verification Steps
|
|
619
|
-
|
|
620
|
-
### Quick Check: Is Playwright MCP Connected?
|
|
621
|
-
|
|
622
|
-
```bash
|
|
623
|
-
# Check MCP server status
|
|
624
|
-
claude mcp list
|
|
625
|
-
|
|
626
|
-
# Should show:
|
|
627
|
-
# plugin:specweave-ui:playwright - ✓ Connected
|
|
628
|
-
```
|
|
629
|
-
|
|
630
|
-
### Test Playwright MCP (5-Second Test)
|
|
631
|
-
|
|
632
|
-
```javascript
|
|
633
|
-
// 1. Navigate
|
|
634
|
-
mcp__plugin_specweave-ui_playwright__browser_goto({ url: "https://example.com" })
|
|
635
|
-
|
|
636
|
-
// 2. Get title
|
|
637
|
-
mcp__plugin_specweave-ui_playwright__browser_evaluate({ code: "document.title" })
|
|
638
|
-
// Expected: "Example Domain"
|
|
639
|
-
|
|
640
|
-
// 3. Close
|
|
641
|
-
mcp__plugin_specweave-ui_playwright__browser_close()
|
|
642
|
-
```
|
|
643
|
-
|
|
644
|
-
✅ **If this works**: Playwright MCP is properly configured!
|
|
645
|
-
|
|
646
|
-
❌ **If this fails**: See troubleshooting section below.
|
|
647
|
-
|
|
648
|
-
### Common Setup Issue: Missing `-y` Flag
|
|
649
|
-
|
|
650
|
-
**Problem**: Playwright MCP shows as not connected in `claude mcp list`
|
|
651
|
-
|
|
652
|
-
**Solution**: Check `.mcp.json` has the `-y` flag:
|
|
653
|
-
|
|
654
|
-
```json
|
|
655
|
-
{
|
|
656
|
-
"playwright": {
|
|
657
|
-
"args": ["-y", "@playwright/mcp@latest"] // ✅ Has -y
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
```
|
|
661
|
-
|
|
662
|
-
Without `-y`, npx waits for user confirmation and MCP connection hangs!
|
|
663
|
-
|
|
664
|
-
**After fixing**: Restart Claude Code for changes to take effect.
|
|
665
|
-
|
|
666
|
-
## Resources
|
|
667
|
-
|
|
668
|
-
- **Playwright MCP**: https://github.com/microsoft/playwright-mcp
|
|
669
|
-
- **Browserbase**: https://www.browserbase.com/docs
|
|
670
|
-
- **Playwright Docs**: https://playwright.dev/
|
|
671
|
-
- **E2E Best Practices**: https://playwright.dev/docs/best-practices
|
|
672
|
-
- **Verification Guide**: See `.specweave/increments/0029-cicd-failure-detection-auto-fix/reports/MCP-PLAYWRIGHT-VERIFICATION-GUIDE.md`
|
|
673
|
-
|
|
674
|
-
---
|
|
675
|
-
|
|
676
|
-
**Remember**: ALWAYS try Playwright MCP first! Only use Browserbase as fallback for cloud/CI scenarios.
|