一键导入
ce-test-browser
Run browser tests for pages affected by the current JJ change stack, a revision, or a PR.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Run browser tests for pages affected by the current JJ change stack, a revision, or a PR.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Babysits or watches an open GitHub PR until merge-ready, continuously reacting to new review comments and CI failures throughout the PR's life. Use when asked to 'babysit the PR', 'watch the PR', monitor, or keep an eye on a PR over time — not a one-shot request to resolve review comments or debug one CI failure (those are separate skills). GitHub only, including GitHub Enterprise.
Explore vague or ambitious ideas into a right-sized requirements-only unified plan. Use when the user wants to brainstorm, think through scope, decide what to build, or needs collaborative product framing before planning. Also use when the user must scope work in territory they say they do not know ("I know nothing about X but need to...") or asks for a blindspot pass — mapping the decision surface before questions begin. Not for executing already-specified work — direct implementation, debugging, or code review where no product scope is left to decide. Not for a decisive verdict on whether to adopt or switch to a specific external technology, library, or platform — brainstorming scopes what to build, not whether to commit to an outside option.
Structured code review for bugs, regressions, tests, and standards. Use before PRs or when asked for review; interactive mode can fix locally, while mode:agent reports only for pipeline callers.
Commit with JJ, push through `jj git` interoperability, and open or update a GitHub PR. Use when asked to ship/open a PR or only write, rewrite, or apply a PR description.
Create a JJ commit with a clear, repository-appropriate message. Use when the user asks to commit or save current working-copy changes.
Diagnosis loop for bugs and failing behavior. Use for errors, stack traces, regressions, failed tests, issue-tracker bugs, stuck investigations after failed fixes, or asks to debug/fix a bug.
| name | ce-test-browser |
| description | Run browser tests for pages affected by the current JJ change stack, a revision, or a PR. |
| argument-hint | [PR number, bookmark/revset, 'current', or --port PORT] |
Run end-to-end browser tests on pages affected by a PR or JJ revision using the best approved browser driver available in the active harness.
agent-browser, ask whether to run headed or headless.mode:pipeline): invoked by LFG or another automated runner. The run is unattended — never block on a question. Read references/pipeline-orchestration.md from this skill's directory and follow it; it overrides the free-port scan (step 4), dev-server startup (step 5), and visibility prompts (step 6). It still uses the preferred port that step 4 computes.Select the driver before the first browser action:
agent-browser. Read references/agent-browser-driver.md before running any command.Use one driver for the entire run. A selected host-native driver may fall back to agent-browser only if initialization fails before the first route is tested. After testing begins, do not mix driver sessions, element references, screenshots, or authentication state.
Apply the Browser Driver Policy above and record the selected driver. This also requires a JJ workspace containing the content to test. If the selected fallback is agent-browser, read references/agent-browser-driver.md and perform its installation check before continuing.
For every scope, first establish the JJ workspace and inspect its status:
jj root
jj status
Run subsequent project discovery from the workspace root printed by jj root. If jj root fails, stop and report that the current path is not in a JJ workspace. If jj status reports unresolved conflicts, stop and report them rather than testing conflicted content.
If PR number provided:
gh pr view [number] --json files -q '.files[].path'
If 'current' or empty:
jj log -r 'exactly(trunk(), 1)' --no-graph -T 'change_id.short() ++ "\n"'
jj log -r 'trunk() & root()' --count
jj diff --from 'trunk()' --to @ --name-only
@ is the current workspace's working-copy revision. JJ has no active bookmark; use @ for the content currently being tested. trunk() is JJ's configured default-remote trunk revision. The first command must resolve exactly one trunk revision, and the second must print 0. If trunk() is unresolved, ambiguous, or has fallen back to root(), stop and ask the user to configure or provide the intended base revision instead of treating every project file as changed.
If bookmark or revset provided:
jj log -r 'exactly(<bookmark-or-revset>, 1)' --no-graph -T 'change_id.short() ++ "\n"'
jj log -r 'exactly(trunk(), 1)' --no-graph -T 'change_id.short() ++ "\n"'
jj log -r 'trunk() & root()' --count
jj diff --from 'trunk()' --to '<bookmark-or-revset>' --name-only
Substitute the user-provided bookmark or revset literally; do not assume a current bookmark because JJ has no active bookmark concept. Require it to resolve to exactly one revision before passing it to --to. Apply the same trunk() checks as the current scope. A bookmark, change ID, or other single-revision revset is valid. If the changed-file list is empty, report that the selected scope has no net file changes from trunk() and stop.
The PR, bookmark, or revset selects the affected files and pages; browser actions always exercise the content in the current workspace at @. If the requested content is not present at @, stop and ask the user to open a JJ workspace at the intended revision rather than moving or rewriting the current workspace.
Map each changed file to the route(s) that render it, then build the list of URLs to test. The table below is a starting point of common patterns, not an exhaustive rule set — apply judgment for the project's actual layout:
| File Pattern | Route(s) |
|---|---|
app/views/users/* | /users, /users/:id, /users/new |
app/controllers/settings_controller.rb | /settings |
app/javascript/controllers/*_controller.js | Pages using that Stimulus controller |
app/components/*_component.rb | Pages rendering that component |
app/views/layouts/* | All pages (test homepage at minimum) |
app/assets/stylesheets/* | Visual regression on key pages |
app/helpers/*_helper.rb | Pages using that helper |
src/app/* (Next.js) | Corresponding routes |
src/components/* | Pages using those components |
Determine the preferred port using this priority:
--port 5000, use that directly..env are the trustworthy sources.--port flags..env, .env.local, .env.development for PORT=.3000.# If your in-context project instructions state the dev-server port, set EXPLICIT_PORT first.
PORT="${EXPLICIT_PORT:-}"
if [ -z "$PORT" ]; then
PORT=$(grep -Eo '\-\-port[= ]+[0-9]{4,5}' package.json 2>/dev/null | grep -Eo '[0-9]{4,5}' | head -1)
fi
if [ -z "$PORT" ]; then
PORT=$(grep -h '^PORT=' .env .env.local .env.development 2>/dev/null | tail -1 | cut -d= -f2)
fi
PORT="${PORT:-3000}"
echo "Preferred dev server port: $PORT"
Manual mode uses this preferred port as-is — the user controls their own server, so do not scan for alternatives. In pipeline mode, references/pipeline-orchestration.md takes the preferred port value printed here and scans upward to a genuinely free port.
Confirm the server is up before asking the headed/headless question — a manual run with no server stops here, so asking first would waste the question.
if lsof -i ":${PORT}" -sTCP:LISTEN -t >/dev/null 2>&1; then
echo "Server running on port ${PORT}";
else
echo "Server not running on port ${PORT}";
echo "Start your dev server, then re-run:";
echo " Rails: bin/dev or rails server -p ${PORT}";
echo " Node/Next.js: npm run dev";
echo " Custom port: run this skill again with --port <your-port>";
exit 0;
fi
In pipeline mode, do not stop here — references/pipeline-orchestration.md auto-starts the server in the background instead.
Visibility is independent from unattended execution:
Host-native integrated browser: keep its normal integrated surface visible and non-blocking so the user can watch progress when useful. Do not repeatedly steal focus as routes change. This applies in both manual and pipeline modes.
agent-browser fallback, pipeline mode: run headless without asking.
agent-browser fallback, manual mode: ask the user whether to run headed or headless using the platform's blocking question tool: AskUserQuestion in Claude Code (call ToolSearch with select:AskUserQuestion first if its schema isn't loaded), request_user_input in Codex, ask_question in Antigravity CLI (agy), ask_user in Pi (requires the pi-ask-user extension). Fall back to presenting options in chat only when no blocking tool exists in the harness or the call errors. Never silently skip the question:
Do you want to watch the browser tests run?
1. Headed (watch) - Opens a visible browser window
2. Headless (faster) - Runs without a visible window
Then use the selected driver to navigate to http://localhost:<port>, capture its rendered or interactive state, and confirm the root is served before iterating.
For each affected route, use the selected driver to navigate and capture fresh rendered or interactive state.
Verify key elements:
Test critical interactions: derive locators or element references from the selected driver's latest inspected state, perform the click/fill/press action, then inspect the resulting state. Do not guess selectors or reuse stale references.
Take screenshots: capture viewport and full-page evidence when the selected driver supports it. Materialize screenshots as local artifacts when a later workflow or report needs file paths; otherwise in-app evidence is sufficient.
Pause for human input when testing touches flows that require external interaction. Pipeline mode: do not pause — log each such flow as Skip with the reason and continue.
| Flow Type | What to Ask |
|---|---|
| OAuth | "Please sign in with [provider] and confirm it works" |
| "Check your inbox for the test email and confirm receipt" | |
| Payments | "Complete a test purchase in sandbox mode" |
| SMS | "Verify you received the SMS code" |
| External APIs | "Confirm the [service] integration is working" |
Ask the user (using the platform's question tool, or present numbered options and wait):
Human Verification Needed
This test touches [flow type]. Please:
1. [Action to take]
2. [What to verify]
Did it work correctly?
1. Yes - continue testing
2. No - describe the issue
When a test fails (pipeline mode: do not ask how to proceed — capture the error screenshot and repro steps, log the failure, and continue):
Document the failure:
Ask the user how to proceed:
Test Failed: [route]
Issue: [description]
Console errors: [if any]
How to proceed?
1. Fix now - debug and fix the failing test
2. Skip - continue testing other pages
If "Fix now": investigate, propose a fix, apply, re-run the failing test
If "Skip": log as skipped, continue
After all tests complete, present a summary:
## Browser Test Results
**Test Scope:** PR #[number] / `@` against `trunk()` / [bookmark or revset] against `trunk()`
**Server:** http://localhost:${PORT}
### Pages Tested: [count]
| Route | Status | Notes |
|-------|--------|-------|
| `/users` | Pass | |
| `/settings` | Pass | |
| `/dashboard` | Fail | Console error: [msg] |
| `/checkout` | Skip | Requires payment credentials |
### Console Errors: [count]
- [List any errors found]
### Human Verifications: [count]
- OAuth flow: Confirmed
- Email delivery: Confirmed
### Failures: [count]
- `/dashboard` - [issue description]
### Result: [PASS / FAIL / PARTIAL]
# Test the current JJ change stack through @ (auto-detects port)
/ce-test-browser
# Test specific PR
/ce-test-browser 847
# Test a specific JJ bookmark or single-revision revset
/ce-test-browser feature/new-dashboard
# Test on a specific port
/ce-test-browser --port 5000
When agent-browser is selected as the fallback, read references/agent-browser-driver.md from this skill's directory before running its commands. Host-native drivers follow their harness-provided instructions instead.