Announce: "I'm using dev-test-playwright for headless browser automation."
<EXTREMELY-IMPORTANT> ## Gate ReminderBefore 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
- •When to Use Playwright MCP
- •MCP Tools Overview
- •Navigation
- •Element Interaction
- •Verification
- •Form Handling
- •Advanced Patterns
- •Complete E2E Examples
Playwright MCP Browser Automation
<EXTREMELY-IMPORTANT> ## Tool Availability GateVerify 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 MCPUSE 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, use: Read("${CLAUDE_PLUGIN_ROOT}/lib/skills/dev-test-chrome/SKILL.md")
Rationalization Prevention
| Thought | Reality |
|---|---|
| "Playwright can do everything" | NO. It cannot read console or network requests. |
| "I don't need console debugging" | You will. Start with Chrome MCP if unsure. |
| "I'll add console checks later" | You can't with Playwright. Choose the right tool now. |
| "Headless mode doesn't matter" | YES IT DOES for CI/CD. |
| "Chrome MCP works for CI" | NO. It requires visible browser. |
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 | ❌ | ✅ |
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 VerificationEVERY action must be VERIFIED. Taking action is not enough.
After clicking, typing, or navigating, you MUST:
- •Wait for the expected result
- •Take a snapshot to verify state
- •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.
For debugging (console/network), use: Read("${CLAUDE_PLUGIN_ROOT}/lib/skills/dev-test-chrome/SKILL.md")
For TDD protocol, see: Skill(skill="workflows:dev-tdd")