Co-Pilot
Updated a month ago

playwright-skill

Llackeyjb
1.3k
lackeyjb/playwright-skill/skills/playwright-skill
74
Agent Score

💡 Summary

An AI agent skill that writes and executes custom Playwright scripts for browser automation and testing, with auto-detection of local dev servers.

🎯 Target Audience

Frontend developers needing automated UI testsQA engineers automating regression checksDevOps engineers validating deploymentsProduct managers testing user flows

🤖 AI Roast:It's a competent but unremarkable wrapper for Playwright that feels like it's mostly reading the manual back to you.

Security AnalysisMedium Risk

The skill executes arbitrary Node.js code and has filesystem access to /tmp. The auto-detection of dev servers involves network scanning. Mitigation: Run the skill in a sandboxed environment, restrict network access to intended targets only, and never run with elevated privileges.


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.

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:

  • Plugin system: ~/.claude/plugins/marketplaces/playwright-skill/skills/playwright-skill
  • Manual global: ~/.claude/skills/playwright-skill
  • Project-specific: <project>/.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 - Follow these steps in order:

  1. Auto-detect dev servers - For localhost testing, ALWAYS run server detection FIRST:

    cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(servers => console.log(JSON.stringify(servers)))"
    • If 1 server found: Use it automatically, inform user
    • If multiple servers found: Ask user which one to test
    • If no servers found: Ask for URL or offer to help start dev server
  2. Write scripts to /tmp - NEVER write test files to skill directory; always use /tmp/playwright-test-*.js

  3. Use visible browser by default - Always use headless: false unless user specifically requests headless mode

  4. Parameterize URLs - Always make URLs configurable via environment variable or constant at top of script

How It Works

  1. You describe what you want to test/automate
  2. I auto-detect running dev servers (or ask for URL if testing external site)
  3. I write custom Playwright code in /tmp/playwright-test-*.js (won't clutter your project)
  4. I execute it via: cd $SKILL_DIR && node run.js /tmp/playwright-test-*.js
  5. Results displayed in real-time, browser window visible for debugging
  6. Test files auto-cleaned from /tmp by your OS

Setup (First Time)

cd $SKILL_DIR npm run setup

This installs Playwright and Chromium browser. Only needed once.

Execution Pattern

Step 1: Detect dev servers (for localhost testing)

cd $SKILL_DIR && node -e "require('./lib/helpers').detectDevServers().then(s => console.log(JSON.stringify(s)))"

Step 2: Write test script to /tmp with 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 from skill directory

cd $SKILL_DIR && node run.js /tmp/playwright-test-page.js

Common Patterns

Test a 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 Login 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 and Submit Form

// /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 for 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 with Error 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(); "

When to use inline vs files:

  • Inline: Quick one-off tasks (screenshot, check if element exists, get page title)
  • Files: Complex tests, responsive design checks, anything user might want to re-run

Available 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 to your backend
  • Getting LLM-optimized responses (e.g., plain text errors instead of styled HTML)
  • Adding authentication tokens globally

Configuration

Single header (common case):

PW_HEADER_NAME=X-Aut
5-Dim Analysis
Clarity8/10
Novelty5/10
Utility9/10
Completeness8/10
Maintainability7/10
Pros & Cons

Pros

  • Automates script generation for common testing patterns
  • Includes helpful utilities like dev server detection
  • Emphasizes clean execution patterns and temporary file usage
  • Provides clear examples for various use cases

Cons

  • Adds an abstraction layer over direct Playwright use
  • Limited novelty as a wrapper for an existing library
  • Potential path resolution complexity in README
  • Relies on correct environment setup by the user

Related Skills

pytorch

S
toolCode Lib
92/ 100

“It's the Swiss Army knife of deep learning, but good luck figuring out which of the 47 installation methods is the one that won't break your system.”

agno

S
toolCode Lib
90/ 100

“It promises to be the Kubernetes for agents, but let's see if developers have the patience to learn yet another orchestration layer.”

nuxt-skills

S
toolCo-Pilot
90/ 100

“It's essentially a well-organized cheat sheet that turns your AI assistant into a Nuxt framework parrot.”

Disclaimer: This content is sourced from GitHub open source projects for display and rating purposes only.

Copyright belongs to the original author lackeyjb.