You have a budget of N steps (each chrome-devtools MCP tool call = 1 step). Count your steps as you go. When you reach N, stop immediately and report:
- STEP_PASS/STEP_FAIL for every test you completed
- STEP_SKIP|<test-id>|budget reached for every test you didn't get to
Drive the browser ONLY through the chrome-devtools MCP tools (mcp__chrome-devtools__*).
You own the browser exclusively for this run — no other agent is using it. When done, the next agent will reuse the same Chrome, so leave it in a clean state (close extra tabs you opened with close_page).
Do not retry or continue after hitting the budget.
Run only these tests: [numbered list from the merged plan]
Do not explore beyond the assigned tests.
Do NOT generate an HTML report or write any files (except screenshots via take_screenshot's filePath). Return only step markers and your findings as text.
# 1. BEFORE: capture state
mcp__chrome-devtools__take_snapshot
# Record: what elements exist, their text, their uids
# 2. ACT: perform the interaction (uid comes from the snapshot above)
mcp__chrome-devtools__click { uid: "12" }
# 3. AFTER: capture new state
mcp__chrome-devtools__take_snapshot
# Compare: what changed? What appeared? What disappeared?
# 4. ASSERT: emit marker based on comparison
# If dialog appeared: STEP_PASS|modal-open|dialog "Confirm" appeared at uid=20
# If nothing changed:
mcp__chrome-devtools__take_screenshot { filePath: ".context/ui-test-screenshots/modal-open.png" }
# STEP_FAIL|modal-open|expected dialog to appear → snapshot unchanged|.context/ui-test-screenshots/modal-open.png
# Check what branch is currently checked out
git branch --show-current
# If it's not the PR branch, switch to it
git fetch origin <branch> && git checkout <branch>
# Install deps — the lockfile may differ between branches
yarn install # or npm install / pnpm install
如果开发服务器之前是在另一个分支上跑的,checkout 之后要重启它。
找出正在运行的开发服务器:
for port in 3000 3001 5173 4200 8080 8000 5000; do
s=$(curl -s -o /dev/null -w "%{http_code}""http://localhost:$port" 2>/dev/null)
if [ "$s" != "000" ]; thenecho"Dev server on port $port (HTTP $s)"; fidone
Test Plan (based on git diff)
=============================
Changed: src/components/SignupForm.tsx (added email validation)
1. [happy] Valid email submits successfully
URL: http://localhost:3000/signup
Steps: fill valid email → submit → verify success message appears
2. [adversarial] Invalid email shows error
Steps: fill "not-an-email" → submit → verify error message appears
3. [adversarial] Empty form submission
Steps: click submit without filling anything → verify error, no crash
4. [adversarial] XSS in email field
Steps: fill "<script>alert(1)</script>" → submit → verify sanitized/rejected
5. [adversarial] Rapid double-submit
Steps: click submit twice quickly → verify no duplicate submission
6. [adversarial] Keyboard-only flow
Steps: Tab to email → type → Tab to submit → Enter → verify success
阶段 5:执行测试
mkdir -p .context/ui-test-screenshots
# Open the app (localhost or deployed). Use an isolated context for a clean run.
mcp__chrome-devtools__new_page { url: "http://localhost:3000", isolatedContext: "ui-test" }
每个测试都遵循前后对比模式:
# Navigate
mcp__chrome-devtools__navigate_page { type: "url", url: "http://localhost:3000/path" }
mcp__chrome-devtools__wait_for { text: "<text that proves the page is ready>" } # optional
# BEFORE snapshot
mcp__chrome-devtools__take_snapshot
# Note the current state: elements, uids, text
# ACT (uids come from the snapshot above)
mcp__chrome-devtools__click { uid: "<uid>" }
# or: mcp__chrome-devtools__fill { uid: "<uid>", value: "..." }
# or: mcp__chrome-devtools__fill_form { ... } # several fields at once
# or: mcp__chrome-devtools__type_text { text: "..." }
# or: mcp__chrome-devtools__press_key { key: "Enter" }
# AFTER snapshot
mcp__chrome-devtools__take_snapshot
# Compare against BEFORE: what changed?
# ASSERT with marker
# STEP_PASS|step-id|evidence OR STEP_FAIL|step-id|expected → actual
阶段 6:汇报结果
## UI Test Results
### STEP_PASS|valid-email-submit|status "Thanks!" appeared at uid=42 after submit
- URL: http://localhost:3000/signup
- Before: form with email input uid=3, submit button uid=7
- Action: filled "user@test.com", clicked uid=7
- After: form replaced by status element with "Thanks! We'll be in touch."
### STEP_FAIL|double-submit|expected single submission → form submitted twice|.context/ui-test-screenshots/double-submit.png
- URL: http://localhost:3000/signup
- Before: form with submit button uid=7
- Action: clicked uid=7 twice rapidly
- After: two success toasts appeared, suggesting duplicate submission
- Screenshot: .context/ui-test-screenshots/double-submit.png
- Suggestion: disable submit button after first click, or debounce the handler
---
**Summary: 4/6 passed, 2 failed**
Failed: double-submit, xss-sanitization
Screenshots saved to `.context/ui-test-screenshots/` — open any failed step's screenshot to see the broken state.
<!-- Failed test card (open by default) --><divclass="section"><h2>Failures <spanclass="count">{{FAIL_COUNT}}</span></h2><detailsclass="test-card fail"open><summary><spanclass="badge fail">FAIL</span><spanclass="step-id">step-id-here</span><spanclass="evidence">expected → actual</span></summary><divclass="body"><dl><dt>URL</dt><dd>http://localhost:3000/path</dd><dt>Action</dt><dd>What was done</dd><dt>Expected</dt><dd>What should have happened</dd><dt>Actual</dt><dd>What happened instead</dd></dl><divclass="suggestion">Fix: description of suggested fix</div><divclass="screenshot"><imgsrc="data:image/png;base64,..."alt="Screenshot of failure"><divclass="caption">step-id.png — captured at moment of failure</div></div></div></details></div><!-- Passed test card (collapsed by default) --><divclass="section"><h2>Passed <spanclass="count">{{PASS_COUNT}}</span></h2><detailsclass="test-card pass"><summary><spanclass="badge pass">PASS</span><spanclass="step-id">step-id-here</span><spanclass="evidence">evidence summary</span></summary><divclass="body"><dl><dt>URL</dt><dd>http://localhost:3000/path</dd><dt>Evidence</dt><dd>What was observed</dd></dl></div></details></div>
把截图以 base64 嵌入,使 HTML 完全自包含:
# Convert screenshot to base64 data URIbase64 -i .context/ui-test-screenshots/step-id.png | tr -d '\n'# Use as: src="data:image/png;base64,<output>"
# Write the generated HTMLcat > .context/ui-test-report.html << 'REPORT_EOF'
<!DOCTYPE html>
...generated report...
REPORT_EOF
# Open it for the reviewer
open .context/ui-test-report.html # macOS# xdg-open .context/ui-test-report.html # Linux
告诉用户:Report saved to .context/ui-test-report.html,并主动提出帮他打开。