详细分析 ▾
运行时依赖
版本
Initial release – brings Playwright-powered browser automation to any project. - Auto-detects running localhost dev servers before starting tests. - Writes Playwright test scripts to /tmp to avoid cluttering project files. - Supports common browser tasks: UI testing, form automation, screenshots, responsive checks, login flow validation, broken link checks, and more. - Always opens the browser visibly for debugging unless headless mode is requested. - URLs are parameterized and configurable at the top of each script. - Clear step-by-step workflow and robust usage documentation included.
安装命令 点击复制
技能文档
IMPORTANT - Path Resolution:
This skill can be installed in different locations (plugin system, manual installation, global, or project-specific). Before executing any commands, determine the skill directory based on where you loaded this SKILL.md file, and use that path in all commands below. Replace $SKILL_DIR with the actual discovered path.
Common installation paths:
- 插件 system:
~/.claude/plugins/marketplaces/playwright-skill/skills/playwright-skill - Manual global:
~/.claude/skills/playwright-skill - Project-specific:
/.claude/skills/playwright-skill
# Playwright Browser Automation
General-purpose browser automation skill. I'll write custom Playwright code for any automation task you request and execute it via the universal executor.
CRITICAL WORKFLOW - 关注 these steps 在...中 order:
- Auto-detect dev servers - 对于 localhost testing, ALWAYS run server detection 第一个:
cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(servers => console.log(JSON.stringify(servers)))"
- 如果 1 server found: 使用 automatically, inform 用户 - 如果 multiple servers found: Ask 用户 哪个 one 到 test - 如果 否 servers found: Ask 对于 URL 或 offer 到 help 开始 dev server
- 写入 scripts 到 /tmp - NEVER 写入 test files 到 skill directory; always 使用
/tmp/playwright-test-.js
- 使用 visible browser 由 默认 - Always 使用
headless: 假unless 用户 specifically requests headless mode
- Parameterize URLs - Always 使 URLs configurable 通过 environment 变量 或 常量 在 top 的 script
如何 Works
- 您 describe 什么 您 want 到 test/automate
- I auto-detect running dev servers (或 ask 对于 URL 如果 testing external site)
- I 写入 custom Playwright code 在...中
/tmp/playwright-test-.js(won't clutter project) - I execute 通过:
cd $SKILL_DIR && 节点 run.js /tmp/playwright-test-.js - Results displayed 在...中 real-时间, browser window visible 对于 debugging
- Test files auto-cleaned 从 /tmp 由 OS
Setup (第一个 时间)
cd $SKILL_DIR
npm run setup
This installs Playwright and Chromium browser. Only needed once.
Execution Pattern
Step 1: Detect dev servers (对于 localhost testing)
cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(s => console.log(JSON.stringify(s)))"
Step 2: 写入 test script 到 /tmp 带有 URL parameter
// /tmp/playwright-test-page.js
const { chromium } = require('playwright');// Parameterized URL (detected or user-provided)
const TARGET_URL = 'http://localhost:3001'; // <-- Auto-detected or from user
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto(TARGET_URL);
console.log('Page loaded:', await page.title());
await page.screenshot({ path: '/tmp/screenshot.png', fullPage: true });
console.log('📸 Screenshot saved to /tmp/screenshot.png');
await browser.close();
})();
Step 3: Execute 从 skill directory
cd $SKILL_DIR && node run.js /tmp/playwright-test-page.js
Common Patterns
Test Page (Multiple Viewports)
// /tmp/playwright-test-responsive.js
const { chromium } = require('playwright');const TARGET_URL = 'http://localhost:3001'; // Auto-detected
(async () => {
const browser = await chromium.launch({ headless: false, slowMo: 100 });
const page = await browser.newPage();
// Desktop test
await page.setViewportSize({ width: 1920, height: 1080 });
await page.goto(TARGET_URL);
console.log('Desktop - Title:', await page.title());
await page.screenshot({ path: '/tmp/desktop.png', fullPage: true });
// Mobile test
await page.setViewportSize({ width: 375, height: 667 });
await page.screenshot({ path: '/tmp/mobile.png', fullPage: true });
await browser.close();
})();
Test 登录 Flow
// /tmp/playwright-test-login.js
const { chromium } = require('playwright');const TARGET_URL = 'http://localhost:3001'; // Auto-detected
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto(${TARGET_URL}/login);
await page.fill('input[name="email"]', 'test@example.com');
await page.fill('input[name="password"]', 'password123');
await page.click('button[type="submit"]');
// Wait for redirect
await page.waitForURL('/dashboard');
console.log('✅ Login successful, redirected to dashboard');
await browser.close();
})();
Fill 和 Submit 表单
// /tmp/playwright-test-form.js
const { chromium } = require('playwright');const TARGET_URL = 'http://localhost:3001'; // Auto-detected
(async () => {
const browser = await chromium.launch({ headless: false, slowMo: 50 });
const page = await browser.newPage();
await page.goto(${TARGET_URL}/contact);
await page.fill('input[name="name"]', 'John Doe');
await page.fill('input[name="email"]', 'john@example.com');
await page.fill('textarea[name="message"]', 'Test message');
await page.click('button[type="submit"]');
// Verify submission
await page.waitForSelector('.success-message');
console.log('✅ Form submitted successfully');
await browser.close();
})();
Check 对于 Broken Links
const { chromium } = require('playwright');(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('http://localhost:3000');
const links = await page.locator('a[href^="http"]').all();
const results = { working: 0, broken: [] };
for (const link of links) {
const href = await link.getAttribute('href');
try {
const response = await page.request.head(href);
if (response.ok()) {
results.working++;
} else {
results.broken.push({ url: href, status: response.status() });
}
} catch (e) {
results.broken.push({ url: href, error: e.message });
}
}
console.log(✅ Working links: ${results.working});
console.log(❌ Broken links:, results.broken);
await browser.close();
})();
Take Screenshot 带有 错误 Handling
const { chromium } = require('playwright');(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
await page.goto('http://localhost:3000', {
waitUntil: 'networkidle',
timeout: 10000,
});
await page.screenshot({
path: '/tmp/screenshot.png',
fullPage: true,
});
console.log('📸 Screenshot saved to /tmp/screenshot.png');
} catch (error) {
console.error('❌ Error:', error.message);
} finally {
await browser.close();
}
})();
Test Responsive Design
// /tmp/playwright-test-responsive-full.js
const { chromium } = require('playwright');const TARGET_URL = 'http://localhost:3001'; // Auto-detected
(async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
const viewports = [
{ name: 'Desktop', width: 1920, height: 1080 },
{ name: 'Tablet', width: 768, height: 1024 },
{ name: 'Mobile', width: 375, height: 667 },
];
for (const viewport of viewports) {
console.log(
Testing ${viewport.name} (${viewport.width}x${viewport.height}),
);
await page.setViewportSize({
width: viewport.width,
height: viewport.height,
});
await page.goto(TARGET_URL);
await page.waitForTimeout(1000);
await page.screenshot({
path: /tmp/${viewport.name.toLowerCase()}.png,
fullPage: true,
});
}
console.log('✅ All viewports tested');
await browser.close();
})();
Inline Execution (Simple Tasks)
For quick one-off tasks, you can execute code inline without creating files:
# Take a quick screenshot
cd $SKILL_DIR && node run.js "
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto('http://localhost:3001');
await page.screenshot({ path: '/tmp/quick-screenshot.png', fullPage: true });
console.log('Screenshot saved');
await browser.close();
"
当...时 到 使用 inline vs files:
- Inline: Quick one-off tasks (screenshot, check 如果 元素 exists, 获取 page title)
- Files: Complex tests, responsive design checks, anything 用户 might want 到 re-run
可用 Helpers
Optional utility functions in lib/helpers.js:
const helpers = require('./lib/helpers');// Detect running dev servers (CRITICAL - use this first!)
const servers = await helpers.detectDevServers();
console.log('Found servers:', servers);
// Safe click with retry
await helpers.safeClick(page, 'button.submit', { retries: 3 });
// Safe type with clear
await helpers.safeType(page, '#username', 'testuser');
// Take timestamped screenshot
await helpers.takeScreenshot(page, 'test-result');
// Handle cookie banners
await helpers.handleCookieBanner(page);
// Extract table data
const data = await helpers.extractTableData(page, 'table.results');
See lib/helpers.js for full list.
Custom HTTP Headers
Configure custom headers for all HTTP requests via environment variables. Useful for:
- Identifying automated traffic 到 backend
- Getting LLM-optimized responses (e.g., plain text errors 代替 的 styled HTML)
- Adding authentication tokens globally
Configuration
Single 页头 (common case):
PW_HEADER_NAME=X-Automated-By PW_HEADER_VALUE=playwright-skill \
cd $SKILL_DIR && node run.js /tmp/my-script.js
Multiple headers (JSON 格式):
PW_EXTRA_HEADERS='{"X-Automated-By":"playwright-skill","X-Debug":"true"}' \
cd $SKILL_DIR && node run.js /tmp/my-script.js
如何 Works
Headers are automatically applied when using helpers.createContext():
const context = await helpers.createContext(browser);
const page = await context.newPage();
// All requests from this page include your custom headers
For scripts using raw Playwright API, use the injected getContextOptionsWithHeaders():
const context = await browser.newContext(
getContextOptionsWithHeaders({ viewport: { width: 1920, height: 1080 } }),
);
Advanced Usage
For comprehensive Playwright API documentation, see API_REFERENCE.md:
- Selectors & Locators best practices
- Network interception & API mocking
- Authentication & 会话 management
- Visual regression testing
- Mobile device emulation
- Performance testing
- Debugging techniques
- CI/CD integration
Tips
- CRITICAL: Detect servers 第一个 - Always run
detectDevServers()之前 writing test code 对于 localhost testing - Custom headers - 使用
PW_HEADER_NAME/PW_HEADER_VALUEenv vars 到 identify automated traffic 到 backend - 使用 /tmp 对于 test files - 写入 到
/tmp/playwright-test-.js, never 到 skill directory 或 用户's project - Parameterize URLs - Put detected/provided URL 在...中
TARGET_URL常量 在 top 的 every script - 默认: Visible browser - Always 使用
headless: 假unless 用户 explicitly asks 对于 headless mode - Headless mode - 仅 使用
headless: 真当...时 用户 specifically requests "headless" 或 "background" execution - Slow down: 使用
slowMo: 100到 使 actions visible 和 easier 到 关注 - Wait strategies: 使用
waitForURL,waitForSelector,waitForLoadState代替 的 fixed timeouts - 错误 handling: Always 使用 try-catch 对于 robust automation
- Console 输出: 使用
console.log()到 track progress 和 show 什么's happening
Troubleshooting
Playwright 不 installed:
cd $SKILL_DIR && npm run setup
模块 不 found:
Ensure running from skill directory via run.js wrapper
Browser doesn't 打开:
Check headless: false and ensure display available
元素 不 found:
Add wait: await page.waitForSelector('.element', { timeout: 10000 })
示例 Usage
User: "Test if the marketing page looks good"Claude: I'll test the marketing page across multiple viewports. Let me first detect running servers...
[Runs: detectDevServers()]
[Output: Found server on port 3001]
I found your dev server running on http://localhost:3001
[Writes custom automation script to /tmp/playwright-test-marketing.js with URL parameterized]
[Runs: cd $SKILL_DIR && node run.js /tmp/playwright-test-marketing.js]
[Shows results with screenshots from /tmp/]
User: "Check if login redirects correctly"Claude: I'll test the login flow. First, let me check for running servers...
[Runs: detectDevServers()]
[Output: Found servers on ports 3000 and 3001]
I found 2 dev servers. Which one should I test?
- http://localhost:3000
- http://localhost:3001
User: "Use 3001"
[Writes login automation to /tmp/playwright-test-login.js]
[Runs: cd $SKILL_DIR && node run.js /tmp/playwright-test-login.js]
[Reports: ✅ Login successful, redirected to /dashboard]
Notes
- 每个 automation custom-written 对于 specific 请求
- 不 limited 到 pre-built scripts - 任何 browser task possible
- Auto-detects running dev servers 到 eliminate hardcoded URLs
- Test scripts written 到
/tmp对于 automatic cleanup (否 clutter) - Code executes reliably 带有 proper 模块 resolution 通过
run.js - Progressive disclosure - API_REFERENCE.md loaded 仅 当...时 advanced features needed
免费技能或插件可能存在安全风险,如需更匹配、更安全的方案,建议联系付费定制