一键导入
test-e2e
Run E2E Playwright testing workflow for web applications
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Run E2E Playwright testing workflow for web applications
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | test-e2e |
| description | Run E2E Playwright testing workflow for web applications |
| user_invocable | true |
| usage | /workflow:test-e2e <url> [--framework=<framework>] [--auth=<strategy>] [--depth=<n>] [--output=<dir>] [--config-only] [--format=<format>] |
| arguments | [{"name":"url","required":true,"description":"Base URL of the web application to test (e.g., http://localhost:8080)"},{"name":"framework","required":false,"description":"Framework type: symfony, laravel, vue, react, next, generic (auto-detected if omitted)"},{"name":"auth","required":false,"description":"Auth strategy: none, form, token, cookie (default: none)"},{"name":"depth","required":false,"description":"Exploration depth limit (default: 3)"},{"name":"output","required":false,"description":"Test output directory (default: tests/e2e or e2e)"},{"name":"config-only","required":false,"description":"Only generate config files, skip exploration and test generation"},{"name":"format","required":false,"description":"State file format: org, md (default: org)"}] |
Orchestrate end-to-end test generation for web applications using browser automation.
E2E agents select a browser driver at runtime per resources/e2e/browser-driver.md. The selection order is:
mcp__playwright__browser_*mcp__chrome-devtools__*mcp__tpmcp-ux_capture__*ignoreHTTPSErrors: true (used when no MCP is present or when self-signed TLS blocks the MCP)The workflow adapts to whatever driver is available. The Playwright MCP is no longer hard-required for live exploration.
Generated test specs are always Playwright (@playwright/test, run via npx playwright test) — that is the artifact format. @playwright/test as a dev dependency is still installed so specs can be executed, but the live MCP browser is not mandatory.
Beyond this standalone /workflow:test-e2e command, e2e_validation is a mandatory gate in swarm and epic dev workflows whenever the change is FE-facing. FE-facing detection is performed by lib/fe-detect-cli.js and triggers when the change set touches routes, components, templates, styles, assets, or FE config files. On a non-FE change the gate status is set to skipped. The gate is enforced by the stop-guard and task-completed-gate hooks via the phase order, so an FE-facing workflow cannot reach completion without passing e2e_validation.
This workflow runs in fully autonomous agentic mode. Do NOT ask for permission on non-destructive operations.
REQUIRED: The project MUST have
Bash(*)in its permissions allow list. Without this, bash commands will prompt for permission and break autonomous execution.
~ in Tool CallsThe Write, Read, Glob, and Edit tools do NOT expand ~. You MUST run echo $HOME first and use the absolute path in ALL tool calls.
DO WITHOUT ASKING:
npm install --save-dev @playwright/test)npx playwright install chromium)npx playwright test)ASK BEFORE:
git commit - User reviews and commitsgit push - User pushes when readyrm) - Confirm before removalALWAYS BLOCKED:
rm -rf on directoriesgit push --forceProceed autonomously through all phases. Only pause for:
/workflow:test-e2e <url> [options]
# Test local Symfony app
/workflow:test-e2e http://localhost:8080 --framework=symfony --auth=form
# Test React app with default settings
/workflow:test-e2e http://localhost:3000
# Just generate config, no tests
/workflow:test-e2e http://localhost:8080 --config-only
# Deep exploration
/workflow:test-e2e http://localhost:8080 --depth=5
# Custom output directory
/workflow:test-e2e http://localhost:4200 --output=e2e/specs --framework=vue
Setup --> Exploration --> Generation --> Validation --> Quality Gate --> Completion
| | | | | |
| e2e-explorer e2e-generator e2e-reviewer quality-gate completion-guard
| (driver- (app map -> (run tests, (lint, type (final check)
| agnostic) test specs) check quality) check)
v
Install deps,
detect framework,
generate config
You are the supervisor agent for the E2E testing workflow. You coordinate all phases, spawn subagents, and maintain state.
Follow these steps in order:
echo $HOME
Store the result (e.g., /home/user). Use this for ALL file paths.
Ensure workflow directories exist (use ABSOLUTE paths):
$HOME_PATH/.claude-workflows/active/.gitkeep
$HOME_PATH/.claude-workflows/completed/.gitkeep
--framework=<val> (default: auto-detect)--auth=<val> (default: none)--depth=<n> (default: 3)--output=<dir> (default: auto-detect based on framework)--config-only (boolean flag)--format=<val> (default: org)Before anything else, validate and test the target URL:
URL scheme validation (MANDATORY):
Only http:// and https:// URLs are accepted. Reject file://, ftp://, javascript:, data:, and any other scheme.
# Validate URL scheme
URL_SCHEME=$(echo "<url>" | grep -oP '^[a-z]+(?=://)')
if [ "$URL_SCHEME" != "http" ] && [ "$URL_SCHEME" != "https" ]; then
echo "ERROR: Only http:// and https:// URLs are supported"
# Stop and inform user
fi
# Check reachability
curl -sS -o /dev/null -w "%{http_code}" --max-time 10 <url>
Check the project directory for framework indicators:
| File/Pattern | Framework |
|---|---|
symfony.lock or config/packages/ | symfony |
artisan or app/Http/Kernel.php | laravel |
vue.config.js or vite.config.ts with vue plugin | vue |
next.config.* | next |
package.json scripts with react-scripts | react |
| None of the above | generic |
If auto-detected, confirm with user: "Detected framework: {framework}. Correct?"
Default test directory based on framework:
| Framework | Default Output Dir |
|---|---|
| symfony | tests/E2e |
| laravel | tests/E2e |
| vue | e2e |
| react | e2e |
| next | e2e |
| generic | tests/e2e |
Generate workflow ID: YYYYMMDD-<random> (e.g., 20260213-abc123)
Create state file using the template from the plugin:
<PLUGIN_DIR>/templates/e2e-testing.<format>{{WORKFLOW_ID}} -> generated ID{{TITLE}} -> URL + framework description{{DESCRIPTION}} -> full task description{{DATE}} -> current date{{TIMESTAMP}} -> ISO timestamp{{BRANCH}} -> current branch{{BASE_BRANCH}} -> main/master{{STATE_FILE}} -> path to .state.json{{TESTS_ENABLED}} -> "true"{{BASE_URL}} -> target URL{{FRAMEWORK}} -> detected/specified framework{{AUTH_STRATEGY}} -> auth flag value{{DEPTH}} -> depth limit{{OUTPUT_DIR}} -> resolved output directoryPLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/workflow}"
ACTIVE_DIR=$(node "$PLUGIN_ROOT/lib/active-dir-cli.js")
REPO_KEY=$(node "$PLUGIN_ROOT/lib/repo-key-cli.js")
REPO_ROOT=$(node -e "console.log(require('$PLUGIN_ROOT/lib/repo-key').getRepoRoot())")
$ACTIVE_DIR/<id>.<format> (inside the repo bucket — never the flat active/ root)Create JSON state sidecar:
{
"$schema": "1.0.0",
"workflow_id": "<id>",
"repo_key": "<REPO_KEY>",
"repo_root": "<REPO_ROOT>",
"org_file": "<ACTIVE_DIR>/<id>.<format>",
"workflow": {
"type": "e2e-testing",
"description": "<description>",
"branch": "<branch>"
},
"config": {
"tests_enabled": true,
"base_url": "<url>",
"framework": "<framework>",
"auth_strategy": "<auth>",
"depth": <depth>,
"output_dir": "<output_dir>"
},
"phase": {
"current": "setup",
"completed": [],
"remaining": ["e2e_exploration", "e2e_generation", "e2e_validation", "quality_gate", "completion_guard"]
},
"gates": {
"setup": { "status": "pending", "iteration": 0 },
"e2e_exploration": { "status": "pending", "iteration": 0 },
"e2e_generation": { "status": "pending", "iteration": 0 },
"e2e_validation": { "status": "pending", "iteration": 0 },
"quality_gate": { "status": "pending", "iteration": 0 },
"completion_guard": { "status": "pending", "iteration": 0 }
},
"agent_log": [],
"updated_at": "<timestamp>"
}
Write to: $ACTIVE_DIR/<id>.state.json (inside the repo bucket — never the flat active/ root)
Verify both files by reading them back.
After creating the state files, bind this session to the workflow so hooks only affect this workflow.
First, get the OS temp directory:
node -e "console.log(require('os').tmpdir())"
Store this as $TMPDIR_PATH.
$TMPDIR_PATH/workflow-session-marker-*.json and read the most recent file to get the session_id$TMPDIR_PATH/workflow-binding-{session_id}.json with:
{
"session_id": "<session_id>",
"workflow_path": "<ACTIVE_DIR>/<id>.state.json",
"workflow_id": "<generated-id>",
"bound_at": "<ISO timestamp>"
}
If no session marker is found, skip this step (backward compatible — hooks will fall back to most recent workflow).
Show summary:
E2E Testing Workflow
URL: <url>
Framework: <framework>
Auth: <auth>
Depth: <depth>
Output: <output_dir>
State: ~/.claude-workflows/active/<id>.<format>
Ready to begin Phase 0: Setup?
The supervisor handles setup directly. This phase installs dependencies and configures Playwright.
# Check in priority order
if [ -f pnpm-lock.yaml ]; then echo "pnpm"
elif [ -f yarn.lock ]; then echo "yarn"
elif [ -f package-lock.json ] || [ -f package.json ]; then echo "npm"
else echo "npm" # default
fi
# Check if already installed
npx playwright --version 2>/dev/null
# If not installed:
<pkg_manager> install --save-dev @playwright/test
npx playwright install chromium
Only install chromium by default. Users can add firefox/webkit later.
Read the config template from the plugin:
<PLUGIN_DIR>/resources/e2e/playwright.config.ts.template
Replace placeholders:
{{OUTPUT_DIR}} -> resolved output directory{{BASE_URL}} -> target URL{{WEBSERVER_CONFIG}} -> look up framework in <PLUGIN_DIR>/resources/e2e/webserver-configs.jsonIf webserver-configs.json has a config for the framework, add:
webServer: {
command: '<command>',
url: '<url>',
reuseExistingServer: true,
},
If framework config is null (generic), omit the webServer block.
Port validation: If substituting {{PORT}} in webserver configs, validate that the value is a numeric integer between 1024 and 65535. Reject any non-numeric port values.
Write playwright.config.ts to the project root.
mkdir -p <output_dir>
MANDATORY: Update .gitignore to prevent accidental commit of auth state and test artifacts:
Check if .gitignore exists. If so, append these entries (if not already present):
# Playwright E2E
.auth/
auth.json
test-results/
playwright-report/
blob-report/
If .gitignore does not exist, create it with these entries.
Select the browser driver per resources/e2e/browser-driver.md:
mcp__playwright__browser_*)mcp__chrome-devtools__*)mcp__tpmcp-ux_capture__*)ignoreHTTPSErrors: trueState the chosen driver (e.g. DRIVER: playwright-mcp) in the setup summary. Attempt a navigate to <url> using the selected driver. If the URL is unreachable, report the connection error. A missing Playwright MCP is not a blocking error — the workflow continues with the next available driver.
If auth strategy is specified:
For --auth=form:
<PLUGIN_DIR>/resources/e2e/global-setup.ts.template{{LOGIN_URL}} -> URL where the login form is{{EMAIL_LABEL}} -> detected email/username label{{PASSWORD_LABEL}} -> detected password label{{SUBMIT_TEXT}} -> detected submit button text{{POST_LOGIN_URL}} -> detected redirect URL after login{{AUTH_STATE_FILE}} -> <output_dir>/.auth/state.jsonglobal-setup.ts to the output directoryauth-fixture.ts.template to the output directory./.creds file first (it's gitignored — test creds usually live there; never commit it or echo its contents into logs/commits/PRs). Only ask the user if .creds is missing or lacks the needed account. Expose them as E2E_USER / E2E_PASS env vars — never hardcode credentials in test files.For --auth=token:
./.creds first; only ask the user if it's absent. Token env var name default: E2E_TOKEN.For --auth=cookie:
E2E_SESSION_COOKIE)If --config-only flag was passed:
Mark setup phase as complete. Update state file and JSON sidecar.
Spawn the e2e-explorer agent to map the application.
Task(
subagent_type="workflow:e2e-explorer",
prompt="""
## Task
Explore the web application at {base_url} and generate an app map.
## Context
Workflow ID: {workflow_id}
Output path: {output_dir}/app-map.json
Max depth: {depth}
Auth strategy: {auth_strategy}
Framework: {framework}
## Instructions
### 1. Connection Check
- Select a browser driver per resources/e2e/browser-driver.md; state which driver is used
- Navigate to {base_url} using that driver
- If connection refused/timeout: report error and stop
- Capture initial accessibility snapshot
### 2. Auth Handling
{auth_instructions_based_on_strategy}
### 3. Exploration
- Use BFS traversal up to depth {depth}
- For each page: navigate then take accessibility snapshot (using the selected driver's action mapping)
- Record all interactive elements (links, buttons, forms, inputs)
- Track which pages require authentication
- Detect SPA routing (URL changes from clicks vs full navigations)
### 4. Output
Write app map JSON to: {output_dir}/app-map.json
App map structure:
{
"base_url": "...",
"framework": "...",
"explored_at": "ISO timestamp",
"pages": [
{
"url": "/path",
"title": "Page Title",
"requires_auth": false,
"links": [{"text": "...", "href": "..."}],
"forms": [{"action": "...", "fields": [...]}],
"buttons": [{"text": "...", "role": "..."}],
"navigation": [{"text": "...", "href": "..."}],
"headings": ["..."],
"dynamic_content": ["..."]
}
],
"navigation_graph": {
"/": ["/about", "/login"],
"/about": ["/", "/contact"]
},
"auth": {
"login_url": "/login",
"login_fields": ["email", "password"],
"protected_urls": ["/dashboard", "/profile"]
},
"summary": {
"total_pages": N,
"total_forms": N,
"total_buttons": N,
"auth_required_pages": N
}
}
Report completion with summary statistics.
"""
)
After explorer completes:
Spawn the e2e-generator agent to create test files from the app map.
Task(
subagent_type="workflow:e2e-generator",
prompt="""
## Task
Generate Playwright E2E test suite from app map.
## Context
Workflow ID: {workflow_id}
App map: {output_dir}/app-map.json
Test directory: {output_dir}
Framework: {framework}
Auth strategy: {auth_strategy}
## Instructions
### 1. Read App Map
Read and parse {output_dir}/app-map.json
### 2. Plan Test Suites
Group tests by feature:
- navigation.spec.ts - Navigation structure and routing
- auth.spec.ts - Login/logout (if auth detected)
- <page-name>.spec.ts - Per-page feature tests
- forms.spec.ts - Form validation and submission
- accessibility.spec.ts - A11y checks
### 3. Selector Priority (MANDATORY)
Use this priority for all selectors:
1. getByRole('button', { name: '...' })
2. getByLabel('...')
3. getByPlaceholder('...')
4. getByText('...')
5. getByTestId('...')
NEVER use:
- CSS selectors (.class, #id)
- XPath
- Auto-generated class names
- page.locator() with CSS unless no accessible alternative exists
### 4. Test Patterns
Each test file must:
- Import from @playwright/test (or auth fixture if auth needed)
- Use test.describe() for grouping
- Use meaningful test names: test('should <action> when <condition>')
- Include at least one assertion per test
- Use page.waitForURL() instead of hard waits
- Use expect(...).toBeVisible() for element presence
### 5. Auth Tests
If auth is configured:
- Import { test, expect } from the auth fixture
- Tests that need auth use the authenticated fixture
- Tests for public pages use standard @playwright/test import
### 6. Write Files
Write all test files to {output_dir}/
Each file must compile with tsc --noEmit.
### 7. Report
List all generated files with line counts and features covered.
"""
)
After generator completes:
npx tsc --noEmit on test files (quick syntax check)This is the main review gate. The e2e-reviewer runs tests and checks quality.
iteration = 0
max_iterations = 3
while iteration < max_iterations:
Task(
subagent_type="workflow:e2e-reviewer",
prompt="""
## Task
Review E2E Playwright tests in {output_dir}
## Context
Workflow ID: {workflow_id}
Review iteration: {iteration + 1} of {max_iterations}
Previous issues: {previous_issues if iteration > 0 else "None (first review)"}
Base URL: {base_url}
## Instructions
### 1. Run Tests
Execute: npx playwright test --reporter=list
### 2. Static Analysis
For each test file:
- Check selector quality (getByRole preferred)
- Check for anti-patterns (waitForTimeout, sleep, CSS selectors)
- Check test isolation (no shared state between tests)
- Check assertions are meaningful
- Check error handling
### 3. Flakiness Check
Run tests 2 more times and compare results for determinism.
### 4. Verdict
Return structured verdict:
VERDICT: PASS or FAIL
If FAIL, list issues:
- [ISSUE-1] <severity>: <description> in <file>:<line>
- [ISSUE-2] ...
If PASS:
- Total tests: N
- All passing: yes/no
- Flakiness detected: yes/no
- Selector quality: good/acceptable/poor
"""
)
if verdict == "PASS":
# Update state: e2e_validation passed
break
else:
iteration += 1
if iteration < max_iterations:
# Send issues back to generator for fixes
Task(
subagent_type="workflow:e2e-generator",
prompt="""
## Review Issues to Fix (MANDATORY)
{numbered_issues_from_review}
## Fix Protocol
1. Address EVERY issue by ID
2. Read the file, understand the problem, apply the fix
3. Self-verify by re-reading the fixed code
4. Report: [ISSUE-N] FIXED: <what changed>
5. If false positive: [ISSUE-N] DISPUTE: <justification>
"""
)
else:
# Max iterations reached
Report: "BLOCKING: Test validation failed after {max_iterations} iterations."
Ask user for intervention
PAUSE
After validation passes, run the quality gate.
Task(
subagent_type="workflow:quality-gate",
prompt="""
QUALITY GATE CHECK - E2E Testing
Project: {project_path}
Test directory: {output_dir}
Run checks:
1. TypeScript compilation: npx tsc --noEmit (on test files)
2. Lint: npx eslint {output_dir} (if eslint configured)
3. All E2E tests pass: npx playwright test
4. No security issues in test code (no hardcoded credentials, no eval)
Auto-fix up to 3 iterations.
Report: PASS or FAIL with details.
"""
)
If quality gate made changes, run a targeted review (e2e-reviewer on changed files only, max 2 iterations).
Final verification before marking the workflow complete.
Task(
subagent_type="workflow:completion-guard",
prompt="""
COMPLETION GUARD - E2E Testing Workflow
Original task: Generate E2E tests for {base_url}
Workflow ID: {workflow_id}
App map: {output_dir}/app-map.json
Verify:
1. App map exists and is valid JSON
2. Test files exist for discovered pages
3. All tests pass: npx playwright test
4. No TODO/FIXME in test files
5. playwright.config.ts is valid
6. Auth setup works (if configured)
7. Coverage: compare test files against app map pages
Return: APPROVED or REJECTED with specific issues.
"""
)
If rejected: fix issues -> re-run quality gate -> re-run completion guard (max 3 cycles).
When all phases pass:
Update state files:
Report to user:
E2E Testing Complete!
URL: <url>
Tests generated: N files, M test cases
All tests passing: yes
Coverage: N/M pages covered
Generated files:
- playwright.config.ts
- <output_dir>/navigation.spec.ts
- <output_dir>/auth.spec.ts
- ...
Run tests: npx playwright test
View report: npx playwright show-report
Ask about commit: "Should I commit these test files?"
Clean up temp files:
TMPDIR_PATH=$(node -e "console.log(require('os').tmpdir())")
rm -f "$TMPDIR_PATH/workflow-session-marker-${SESSION_ID}.json"
rm -f "$TMPDIR_PATH/workflow-binding-${SESSION_ID}.json"
rm -f "$TMPDIR_PATH/workflow-stop-${SESSION_ID}."*
rm -f "$TMPDIR_PATH/workflow-deny-${SESSION_ID}.json"
rm -f "$TMPDIR_PATH/workflow-complete-${SESSION_ID}-"*
${SESSION_ID} is the session_id from Step 5.5Archive state:
active/ to completed/| Error | Action |
|---|---|
| URL unreachable | Warn user, ask to proceed or abort |
| No browser driver available | Report which drivers were checked; local Playwright fallback is last resort |
| npm install fails | Report error, suggest manual install |
| Browser install fails | Report error, suggest npx playwright install --with-deps |
| Explorer finds no pages | Report, ask user to check URL and try again |
| Tests won't compile | Send back to generator with errors |
| All tests fail on first run | Check if app is running, then fix tests |
| Auth setup fails | Re-check ./.creds; if absent or insufficient, ask the user, then retry |
MANDATORY: Update the state file before and after each phase:
Templates and resources are in the plugin cache:
<PLUGIN_DIR>/templates/e2e-testing.org
<PLUGIN_DIR>/templates/e2e-testing.md
<PLUGIN_DIR>/resources/e2e/playwright.config.ts.template
<PLUGIN_DIR>/resources/e2e/global-setup.ts.template
<PLUGIN_DIR>/resources/e2e/auth-fixture.ts.template
<PLUGIN_DIR>/resources/e2e/webserver-configs.json
Where <PLUGIN_DIR> is the workflow plugin cache directory (find it via the plugin system).
Enable or disable the workflow usage status line
Interactive live testing of a running web application via Playwright MCP browser automation
Autonomous driver — outer loop that wakes on a schedule, resumes or advances the in-flight task for a repo, then pulls and launches the next queued task. Reconstructs all state from disk and the GitHub issue on every wake; never relies on session memory.
Assign or archive unscoped legacy workflow state files (created before repo-scoping) so they stop leaking into every repo's session.
Run verification loop on current changes