dev-test-playwright
This skill should be used when testing web applications with Playwright MCP, running headless E2E tests, cross-browser testing, CI/CD test automation, or when dev-test routes to Playwright-based browser testing.
Best use case
dev-test-playwright is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
This skill should be used when testing web applications with Playwright MCP, running headless E2E tests, cross-browser testing, CI/CD test automation, or when dev-test routes to Playwright-based browser testing.
Teams using dev-test-playwright should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/dev-test-playwright/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How dev-test-playwright Compares
| Feature / Agent | dev-test-playwright | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
This skill should be used when testing web applications with Playwright MCP, running headless E2E tests, cross-browser testing, CI/CD test automation, or when dev-test routes to Playwright-based browser testing.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
SKILL.md Source
**Announce:** "I'm using dev-test-playwright for headless browser automation."
<EXTREMELY-IMPORTANT>
## Gate Reminder
Before taking screenshots or running E2E tests, you MUST complete all 6 gates from dev-tdd:
```
GATE 1: BUILD
GATE 2: LAUNCH (with file-based logging)
GATE 3: WAIT
GATE 4: CHECK PROCESS
GATE 5: READ LOGS ← MANDATORY, CANNOT SKIP
GATE 6: VERIFY LOGS
THEN: E2E tests/screenshots
```
**You loaded dev-tdd earlier. Follow the gates now.**
</EXTREMELY-IMPORTANT>
## Contents
- [Tool Availability Gate](#tool-availability-gate)
- [When to Use Playwright MCP](#when-to-use-playwright-mcp)
- [MCP Tools Overview](#mcp-tools-overview)
- [Navigation](#navigation)
- [Element Interaction](#element-interaction)
- [Verification](#verification)
- [Form Handling](#form-handling)
- [Advanced Patterns](#advanced-patterns)
- [Complete E2E Examples](#complete-e2e-examples)
# Playwright MCP Browser Automation
<EXTREMELY-IMPORTANT>
## Tool Availability Gate
**Verify Playwright MCP tools are available before proceeding.**
Check for these MCP functions:
- `mcp__playwright__browser_navigate`
- `mcp__playwright__browser_snapshot`
- `mcp__playwright__browser_click`
**If MCP tools are not available:**
```
STOP: Cannot proceed with Playwright automation.
Missing: Playwright MCP server
The Playwright MCP server must be configured and running.
Check your Claude Code MCP configuration.
Reply when configured and I'll continue testing.
```
**This gate is non-negotiable. Missing tools = full stop.**
</EXTREMELY-IMPORTANT>
<EXTREMELY-IMPORTANT>
## When to Use Playwright MCP
**USE Playwright MCP when you need:**
- Headless browser automation (CI/CD)
- Cross-browser testing (Chromium, Firefox, WebKit)
- Test isolation (fresh browser state per test)
- Standard E2E test suite automation
- Network mocking/interception
- Parallel test execution
**DO NOT use Playwright MCP when:**
- Debugging console messages (use Chrome MCP)
- Inspecting network requests/responses (use Chrome MCP)
- Executing custom JavaScript in page (use Chrome MCP)
- Recording GIFs of interactions (use Chrome MCP)
- Interactive debugging with real browser (use Chrome MCP)
**For debugging, discover and read the Chrome MCP skill:**
Read `${CLAUDE_SKILL_DIR}/../../skills/dev-test-chrome/SKILL.md` and follow its instructions.
### Playwright Facts
- Playwright MCP cannot read console messages or network requests, and that capability cannot be bolted on later — if console/network debugging may be needed, start with Chrome MCP. Chrome MCP in turn requires a visible browser, so headless CI/CD requires Playwright. Choosing by familiarity instead of by these constraints (see Capability Comparison below) produces a test that cannot observe what it claims to verify.
### Capability Comparison
| Capability | Playwright MCP | Chrome MCP |
|------------|---------------|------------|
| Navigate/click/type | ✅ | ✅ |
| Accessibility tree | ✅ `browser_snapshot` | ✅ `read_page` |
| Screenshots | ✅ | ✅ |
| **Headless mode** | ✅ | ❌ |
| **Cross-browser** | ✅ | ❌ |
| Console messages | ❌ | ✅ |
| Network requests | ❌ | ✅ |
| JavaScript execution | ❌ | ✅ |
| GIF recording | ❌ | ✅ |
</EXTREMELY-IMPORTANT>
## MCP Tools Overview
| Tool | Purpose |
|------|---------|
| `browser_navigate` | Navigate to URL |
| `browser_snapshot` | Get accessibility tree (page state) |
| `browser_click` | Click elements |
| `browser_type` | Type into inputs |
| `browser_select_option` | Select dropdown options |
| `browser_hover` | Hover over elements |
| `browser_wait_for` | Wait for conditions |
| `browser_take_screenshot` | Visual capture |
| `browser_press` | Press keys |
## Navigation
### Basic Navigation
```
mcp__playwright__browser_navigate(url="https://example.com")
```
### Wait for Page Load
```
mcp__playwright__browser_navigate(url="https://example.com")
mcp__playwright__browser_wait_for(state="networkidle")
```
### Get Current State
```
mcp__playwright__browser_snapshot()
```
The snapshot returns the **accessibility tree** - a structured representation of all interactive elements on the page.
## Element Interaction
### Clicking Elements
```
# By visible text
mcp__playwright__browser_click(element="Submit button")
# By ref (from snapshot)
mcp__playwright__browser_click(ref="button[type=submit]")
# By role and name
mcp__playwright__browser_click(element="Login", role="button")
```
### Typing Text
```
# Into focused element
mcp__playwright__browser_type(text="hello world")
# Into specific element
mcp__playwright__browser_click(element="Email input")
mcp__playwright__browser_type(text="user@example.com")
# Clear and type
mcp__playwright__browser_click(element="Search box")
mcp__playwright__browser_type(text="new search", clear=true)
```
### Keyboard Shortcuts
```
# Press Enter
mcp__playwright__browser_press(key="Enter")
# Keyboard shortcuts
mcp__playwright__browser_press(key="Control+a")
mcp__playwright__browser_press(key="Control+c")
```
## Verification
<EXTREMELY-IMPORTANT>
### The Iron Law of Verification
**EVERY action must be VERIFIED. Taking action is not enough.**
After clicking, typing, or navigating, you MUST:
1. Wait for the expected result
2. Take a snapshot to verify state
3. Document the verification in LEARNINGS.md
| Action | Verification |
|--------|--------------|
| Click submit | `wait_for(text="Success")` + snapshot |
| Navigate | `wait_for(state="networkidle")` + snapshot |
| Fill form | Snapshot shows filled values |
| Login | Snapshot shows dashboard/logged-in state |
**"I clicked it" is not verification. Prove the click worked.**
</EXTREMELY-IMPORTANT>
### Snapshot Verification
```
# 1. Perform action
mcp__playwright__browser_click(element="Submit")
# 2. Wait for result
mcp__playwright__browser_wait_for(text="Success")
# 3. Take snapshot to verify
mcp__playwright__browser_snapshot()
# Check snapshot contains expected elements
```
### Wait Conditions
```
# Wait for text to appear
mcp__playwright__browser_wait_for(text="Welcome back")
# Wait for element
mcp__playwright__browser_wait_for(selector="#success-message")
# Wait for network idle
mcp__playwright__browser_wait_for(state="networkidle")
# Wait for navigation
mcp__playwright__browser_wait_for(state="load")
```
### Screenshots
```
# Full page
mcp__playwright__browser_take_screenshot(path="/tmp/screenshot.png", fullPage=true)
# Viewport only
mcp__playwright__browser_take_screenshot(path="/tmp/viewport.png")
# Specific element
mcp__playwright__browser_take_screenshot(
path="/tmp/element.png",
selector="#main-content"
)
```
## Form Handling
### Text Inputs
```
mcp__playwright__browser_click(element="Username")
mcp__playwright__browser_type(text="john_doe")
mcp__playwright__browser_click(element="Password")
mcp__playwright__browser_type(text="secret123")
```
### Dropdowns
```
mcp__playwright__browser_select_option(
element="Country dropdown",
value="US"
)
# Or by label
mcp__playwright__browser_select_option(
element="Country",
label="United States"
)
```
### Checkboxes and Radio Buttons
```
# Check checkbox
mcp__playwright__browser_click(element="Accept terms checkbox")
# Verify checked state (via snapshot)
mcp__playwright__browser_snapshot()
# Look for checked="true" in accessibility tree
```
### File Upload
```
mcp__playwright__browser_set_input_files(
selector="input[type=file]",
files=["/path/to/file.pdf"]
)
```
## Advanced Patterns
### Multi-Step Form
```
# Step 1
mcp__playwright__browser_click(element="Name input")
mcp__playwright__browser_type(text="John Doe")
mcp__playwright__browser_click(element="Next button")
mcp__playwright__browser_wait_for(text="Step 2")
# Step 2
mcp__playwright__browser_click(element="Email input")
mcp__playwright__browser_type(text="john@example.com")
mcp__playwright__browser_click(element="Next button")
mcp__playwright__browser_wait_for(text="Step 3")
# Step 3 - Submit
mcp__playwright__browser_click(element="Submit button")
mcp__playwright__browser_wait_for(text="Success")
```
### Handling Modals
```
# Click to open modal
mcp__playwright__browser_click(element="Open Dialog")
mcp__playwright__browser_wait_for(text="Dialog Title")
# Interact with modal
mcp__playwright__browser_click(element="Confirm button")
mcp__playwright__browser_wait_for(state="hidden", selector=".modal")
```
### Iframes
```
# Switch to iframe
mcp__playwright__browser_frame(name="payment-iframe")
# Interact within iframe
mcp__playwright__browser_click(element="Card number")
mcp__playwright__browser_type(text="4111111111111111")
# Switch back to main
mcp__playwright__browser_main_frame()
```
### Hover and Tooltips
```
mcp__playwright__browser_hover(element="Help icon")
mcp__playwright__browser_wait_for(text="This is the tooltip text")
mcp__playwright__browser_snapshot()
```
## Complete E2E Examples
### Login Flow
```
# 1. Navigate to login page
mcp__playwright__browser_navigate(url="https://app.example.com/login")
mcp__playwright__browser_wait_for(state="networkidle")
# 2. Take initial snapshot
mcp__playwright__browser_snapshot()
# Verify: Login form is visible
# 3. Fill credentials
mcp__playwright__browser_click(element="Email")
mcp__playwright__browser_type(text="user@example.com")
mcp__playwright__browser_click(element="Password")
mcp__playwright__browser_type(text="password123")
# 4. Submit
mcp__playwright__browser_click(element="Sign In")
mcp__playwright__browser_wait_for(text="Dashboard")
# 5. Verify success
mcp__playwright__browser_snapshot()
# Verify: Dashboard is visible, user name shown
# 6. Screenshot for evidence
mcp__playwright__browser_take_screenshot(path="/tmp/login_success.png")
```
### E-Commerce Checkout
```
# 1. Navigate to product
mcp__playwright__browser_navigate(url="https://shop.example.com/product/123")
mcp__playwright__browser_wait_for(state="networkidle")
# 2. Add to cart
mcp__playwright__browser_click(element="Add to Cart")
mcp__playwright__browser_wait_for(text="Added to cart")
# 3. Go to cart
mcp__playwright__browser_click(element="Cart icon")
mcp__playwright__browser_wait_for(text="Your Cart")
# 4. Verify cart
mcp__playwright__browser_snapshot()
# Verify: Product in cart, correct price
# 5. Proceed to checkout
mcp__playwright__browser_click(element="Checkout")
mcp__playwright__browser_wait_for(text="Shipping Address")
# 6. Fill shipping
mcp__playwright__browser_click(element="Address")
mcp__playwright__browser_type(text="123 Main St")
mcp__playwright__browser_click(element="City")
mcp__playwright__browser_type(text="New York")
mcp__playwright__browser_select_option(element="State", value="NY")
mcp__playwright__browser_click(element="Zip")
mcp__playwright__browser_type(text="10001")
# 7. Continue to payment
mcp__playwright__browser_click(element="Continue to Payment")
mcp__playwright__browser_wait_for(text="Payment Method")
# 8. Verify order summary
mcp__playwright__browser_snapshot()
# Verify: Correct items, shipping address, total
mcp__playwright__browser_take_screenshot(path="/tmp/checkout_complete.png")
```
### Search and Filter
```
# 1. Navigate
mcp__playwright__browser_navigate(url="https://search.example.com")
# 2. Search
mcp__playwright__browser_click(element="Search box")
mcp__playwright__browser_type(text="laptop")
mcp__playwright__browser_press(key="Enter")
mcp__playwright__browser_wait_for(text="results")
# 3. Apply filter
mcp__playwright__browser_click(element="Price filter")
mcp__playwright__browser_click(element="Under $1000")
mcp__playwright__browser_wait_for(state="networkidle")
# 4. Verify filtered results
mcp__playwright__browser_snapshot()
# Verify: Results shown, filter applied
# 5. Click first result
mcp__playwright__browser_click(element="First product link")
mcp__playwright__browser_wait_for(text="Product Details")
mcp__playwright__browser_take_screenshot(path="/tmp/search_result.png")
```
## Error Handling
### Retry Pattern
```
# Attempt action with retry
for attempt in range(3):
try:
mcp__playwright__browser_click(element="Flaky Button")
mcp__playwright__browser_wait_for(text="Success", timeout=5000)
break # Success
except:
if attempt == 2:
raise # Give up after 3 attempts
time.sleep(1) # Wait before retry
```
### Timeout Handling
```
# Set explicit timeout
mcp__playwright__browser_wait_for(
text="Slow loading content",
timeout=30000 # 30 seconds
)
```
## Limitations
<EXTREMELY-IMPORTANT>
### What Playwright MCP Cannot Do
| Need | Why Playwright Fails | Use Instead |
|------|---------------------|-------------|
| Read console.log | No console access | Chrome MCP `read_console_messages` |
| Inspect API responses | No network access | Chrome MCP `read_network_requests` |
| Execute page JavaScript | No JS execution | Chrome MCP `javascript_tool` |
| Record GIF | No recording capability | Chrome MCP `gif_creator` |
**If you need debugging capabilities, switch to Chrome MCP.**
</EXTREMELY-IMPORTANT>
## Integration
This skill is referenced by `dev-test` for Playwright browser automation.
Related skills:
- Read `${CLAUDE_SKILL_DIR}/../../skills/dev-test-chrome/SKILL.md` and follow its instructions.
- Read `${CLAUDE_SKILL_DIR}/../../skills/dev-tdd/SKILL.md` and follow its instructions.
- Chrome MCP skill - debugging (console/network)
- TDD skill - TDD protocolRelated Skills
typst-test-slide
This skill should be used when the user asks to 'test a slide', 'isolate a slide', 'debug a slide', 'preview a single slide', 'test this slide', 'render one slide', or when you need to visually verify a single Typst slide from a presentation in isolation. Provides the exact file setup pattern to avoid access-denied and import errors.
dev-test
This skill should be used when the user needs to 'debug web applications', 'test UI interactions', 'capture screenshots or network requests', 'test desktop automation', or needs to select between testing tools. Routes to platform-specific E2E testing skills: Chrome MCP for debugging, Playwright for CI/CD, Hammerspoon for macOS, Linux for X11/Wayland.
dev-test-linux
This skill should be used when the user asks to "test Linux desktop apps", "automate GTK/Qt applications", "test with ydotool", "test with xdotool", "verify Linux UI interactions", "capture screenshots on Linux", "control D-Bus services", "test Wayland applications", "test X11 applications", or needs Linux desktop E2E testing. Provides comprehensive guidance for Linux automation with ydotool (Wayland), xdotool (X11), grim, and D-Bus.
dev-test-hammerspoon
This skill should be used when the user asks to "debug macOS app", "test native app", "automate macOS workflow", "test native macOS application", or needs desktop automation for testing macOS applications with Hammerspoon. Use for application launch/control, window management, keyboard/mouse simulation, and visual verification.
dev-test-gaps
This skill should be used when validating test coverage against requirements, after implementation tasks complete (Phase 5.5 of /dev workflow). Invoked automatically by dev-implement before review phase.
dev-test-electron
This skill should be used when the user asks to "test Electron app", "automate Electron desktop app", "debug Electron renderer", "test VS Code extension", "E2E test Electron", or needs Chrome DevTools Protocol automation for Electron applications. Use for renderer process debugging, main process control, native menu automation, and file dialog testing.
dev-test-chrome
This skill should be used when testing web applications with Chrome MCP tools, debugging console errors, monitoring network requests, executing JavaScript in browser, recording GIF test evidence, or when dev-test routes to Chrome-based browser testing.
writing
This skill should be used when the user asks to 'write a paper', 'start a writing project', 'draft an article', 'write about', 'brainstorm writing topics', 'gather sources for a paper', 'what should I write about', or needs the writing workflow entry point for any writing task.
writing-validate
Validate draft sections cover all PRECIS claims before review.
writing-setup
Internal skill for creating PRECIS.md, OUTLINE.md, and ACTIVE_WORKFLOW.md. Called after brainstorm sources are gathered.
writing-revise
This skill should be used when the user asks to 'revise writing', 'fix review issues', 'polish draft', 'apply review feedback', 'complete writing workflow', or after /writing-review produces REVIEW.md with issues to fix.
writing-review
Internal skill for hierarchical document review. Called by writing-validate after claim validation passes.