Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 77 additions & 1 deletion skills/playwright-skill/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: playwright-skill
description: Complete browser automation with Playwright. Auto-detects dev servers, writes clean test scripts to /tmp. Test pages, fill forms, take screenshots, check responsive design, validate UX, test login flows, check links, automate any browser task. Use when user wants to test websites, automate browser interactions, validate web functionality, or perform any browser-based testing.
description: Complete browser automation with Playwright. Auto-detects dev servers, writes clean test scripts to /tmp. Test pages, fill forms, take screenshots, record videos, check responsive design, validate UX, test login flows, check links, automate any browser task. Use when user wants to test websites, automate browser interactions, validate web functionality, or perform any browser-based testing.
---

**IMPORTANT - Path Resolution:**
Expand Down Expand Up @@ -276,6 +276,82 @@ const TARGET_URL = 'http://localhost:3001'; // Auto-detected
})();
```

### Record Session and Extract Frames for Analysis

Record a browser session as video, then extract frames for Claude to analyze. Useful for debugging visual issues, verifying animations, or reviewing user flows.

```javascript
// /tmp/playwright-test-record-analyze.js
const { chromium } = require('playwright');
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');

const TARGET_URL = 'http://localhost:3001'; // Auto-detected
const VIDEO_DIR = '/tmp/playwright-videos';
const FRAMES_DIR = '/tmp/playwright-frames';

(async () => {
// Ensure output directories exist
fs.mkdirSync(VIDEO_DIR, { recursive: true });
fs.mkdirSync(FRAMES_DIR, { recursive: true });

const browser = await chromium.launch({ headless: false, slowMo: 100 });

// Create context with video recording enabled
const context = await browser.newContext({
recordVideo: {
dir: VIDEO_DIR,
size: { width: 1280, height: 720 }
}
});

const page = await context.newPage();

// === Your automation here ===
await page.goto(TARGET_URL);
await page.waitForTimeout(2000);
// Add more interactions as needed
// ============================

// Close page and context to finalize video
await page.close();
await context.close();
await browser.close();

// Find the recorded video file
const videoFiles = fs.readdirSync(VIDEO_DIR).filter(f => f.endsWith('.webm'));
if (videoFiles.length === 0) {
console.error('No video file found');
process.exit(1);
}

const videoPath = path.join(VIDEO_DIR, videoFiles[videoFiles.length - 1]);
console.log(`Video saved: ${videoPath}`);

// Extract frames using ffmpeg (2 frames per second)
const framePattern = path.join(FRAMES_DIR, 'frame-%03d.png');
try {
execSync(`ffmpeg -y -i "${videoPath}" -vf "fps=2" "${framePattern}"`, { stdio: 'inherit' });
console.log(`Frames extracted to: ${FRAMES_DIR}`);

// List extracted frames for analysis
const frames = fs.readdirSync(FRAMES_DIR).filter(f => f.endsWith('.png')).sort();
console.log('\nExtracted frames for analysis:');
frames.forEach(f => console.log(` /tmp/playwright-frames/${f}`));
} catch (e) {
console.error('ffmpeg not found. Install with: brew install ffmpeg (macOS) or apt install ffmpeg (Linux)');
console.log('Video available at:', videoPath);
}
})();
```

**Notes:**

- Adjust `fps=2` to extract more/fewer frames (e.g., `fps=1` for 1 per second, `fps=0.5` for every 2 seconds)
- Claude can analyze extracted frames using the Read tool on the PNG files
- Requires ffmpeg: `brew install ffmpeg` (macOS) or `apt install ffmpeg` (Linux)

## Inline Execution (Simple Tasks)

For quick one-off tasks, you can execute code inline without creating files:
Expand Down