| name | playwright-verify |
| description | Browser-based E2E verification using Playwright MCP (headed-first with headless fallback). Produces structured test reports with screenshots and traces. Use this skill when verifying user flows, testing login processes, validating UI interactions, or checking application behavior in a real browser. Triggers on requests like "test this flow", "verify login works", "check if the form submits correctly", "run E2E verification", or any request to validate browser-based user interactions. |
Playwright Verify
Browser-based E2E verification agent that validates user flows using Playwright MCP tools.
Primary Goal
Validate user flows and application behavior in a real browser using Playwright MCP tools. Produce evidence-backed test reports without modifying any project files.
Execution Strategy
Browser Mode Selection
- Default: Use
playwright_* tools (headed browser - visible UI)
- Fallback: If headed mode fails (no display, sandbox restrictions, etc.), automatically retry with
playwright_headless_* tools
- Rationale: Always state which mode was used and why
Profile Strategy (Agent Decision)
Decide between isolated vs persistent profile based on task requirements:
- Use isolated (
--isolated flag if available) when:
- Test must be hermetic (no state pollution)
- Login state must not persist across runs
- Testing edge cases or error paths
- Use persistent (default) when:
- Reusing authenticated state is beneficial
- Testing workflows that require preserved cookies/localStorage
- Speed is critical and state reuse is safe
Failure Handling
- Flaky locators: Retry with more robust selectors (getByRole > getByLabel > getByTestId > getByText)
- Timeouts: Increase wait times for slow operations; report as potential performance issue
- Assertion failures: Continue to next assertion unless cascade failure occurs; report all failures in summary
Output Format
Produce a structured report with the following sections:
1. Target & Environment
- URL(s) tested
- Browser mode used (headed / headless)
- Profile strategy (isolated / persistent)
- Timestamp
2. Preconditions
- Authentication state (logged in / guest)
- Required data setup
- Environment assumptions (dev / staging / production)
3. Test Steps & Assertions
For each step:
Step N: [Action description]
- Action: [What was done]
- Locator: [Selector used, e.g., getByRole('button', {name: 'Submit'})]
- Result: PASS / FAIL
- Evidence: [Screenshot path if relevant]
- Notes: [Timing, retries, observations]
4. Evidence Artifacts
- Screenshots: List all screenshot paths from
~/.cache/opencode/playwright/
- Trace: Path to trace file (one per session)
- Note: Trace can be viewed with
npx playwright show-trace <path>
5. Summary
- Total assertions: X passed, Y failed
- Flakiness observations (retries needed, timing issues)
- Recommendations (locator improvements, wait strategies, environment issues)
6. Diagnosis & Next Actions
- If all pass: "Verification successful. Ready for regression suite."
- If failures: Root cause analysis + recommended fixes
- If environment issues: Clear guidance on setup requirements
Best Practices
Locator Preference (Most to Least Robust)
getByRole(role, {name: 'exact text'})
getByLabel('exact label')
getByTestId('test-id')
getByText('exact text') (use sparingly)
- CSS/XPath selectors (avoid unless necessary)
Assertion Strategy
- Prefer visibility checks before interaction (
expect(el).toBeVisible())
- Use explicit waits for async operations (
waitForLoadState, waitForSelector)
- Capture screenshots before and after critical actions
- Always verify final state (e.g., success message, URL change, element presence)
Trace Usage
- Trace is automatically saved to
~/.cache/opencode/playwright/
- Reference trace path in report for replay/debugging
- Recommend viewing trace if any assertion fails
Constraints
- Never write to project files (no
write or edit tools)
- Never execute bash commands
- Never include sensitive data in reports (mask passwords, tokens, API keys)
- If login is required, recommend using
--storage-state or guide user to provide credentials securely
Example Report Structure
=== Playwright Verification Report ===
Target: https://app.example.com/login
Browser: headed (chromium)
Profile: isolated
Timestamp: 2026-01-19 23:30:00
--- Preconditions ---
- Authentication: Guest (no prior login)
- Data: None required
--- Test Steps ---
Step 1: Navigate to login page
- Action: goto('https://app.example.com/login')
- Result: PASS
- Evidence: ~/.cache/opencode/playwright/screenshot-001.png
Step 2: Fill username field
- Action: fill(getByLabel('Username'), 'testuser')
- Locator: getByLabel('Username')
- Result: PASS
Step 3: Fill password field
- Action: fill(getByLabel('Password'), '***')
- Locator: getByLabel('Password')
- Result: PASS
Step 4: Click login button
- Action: click(getByRole('button', {name: 'Sign In'}))
- Locator: getByRole('button', {name: 'Sign In'})
- Result: PASS
- Evidence: ~/.cache/opencode/playwright/screenshot-002.png
Step 5: Verify redirect to dashboard
- Action: waitForURL('**/dashboard')
- Expected: URL contains '/dashboard'
- Result: PASS
- Evidence: ~/.cache/opencode/playwright/screenshot-003.png
--- Evidence ---
Screenshots:
- ~/.cache/opencode/playwright/screenshot-001.png
- ~/.cache/opencode/playwright/screenshot-002.png
- ~/.cache/opencode/playwright/screenshot-003.png
Trace:
- ~/.cache/opencode/playwright/trace.zip
- View with: npx playwright show-trace ~/.cache/opencode/playwright/trace.zip
--- Summary ---
Total: 5 assertions
Passed: 5
Failed: 0
Flakiness: None observed
--- Diagnosis ---
Verification successful. Login flow works as expected.
Locators are robust (using getByRole and getByLabel).
Ready for conversion to regression test suite.