browser-test
Skill16 starsChanged 3 months agoApache-2.0View on GitHub
Verify a cockpit UI/frontend change in a real browser with Playwright — screenshots, mobile viewport, reproduce a visual bug. Use when asked to visually confirm a UI change, screenshot the running app, or reproduce a rendering/layout bug. Covers cockpit-specific setup the generic run/verify skills miss: isolated dev server on a spare port, password auth, and the service-worker / NODE_ENV / .next caches that otherwise serve stale code.
- Deletes or force-pushes
7 other projects use a version of this.
Adopted by
Most recently taken up by
- leek/agent-skillstheir own version, first seen Nov 2, 2026
- pionxzh/chatgpt-exportertheir own version, first seen Nov 1, 2026
- langwatch/langwatchtheir own version, first seen Oct 8, 2026
- TheophilusChinomona/idevtheir own version, first seen Jun 12, 2026
- jpoindexter/theft-kittheir own version, first seen May 20, 2026
- alexiolan/craft-skillstheir own version, first seen Apr 16, 2026
Other versions7 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 7
- langwatch/langwatch★ 5ksame name
- pionxzh/chatgpt-exporter★ 2.9ksame name
- alexiolan/craft-skills★ 17same name
- leek/agent-skills★ 5same name
- jpoindexter/theft-kit★ 1same name
- TheophilusChinomona/idev★ 0same name
- wzc-miyasaki/agent-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository7 other files it gives its agents.
- accept-issueSkill
- implement-issueSkill
- integration-testSkill
- publish-releaseSkill
- refine-issueSkill
- regen-cli-commandsSkill
- review-issueSkill
The file
We split this skill into the rules it gives an agent
4 rules. 0 are common, 2 are distinctive, and 2 are very specific to this project.
0
Common
Most of the 6 edited versions we read keep these.
2
Distinctive
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 7
Run an isolated cockpit dev server and drive it with the Playwright MCP.
- Distinctive: line 16
Never test against the live instance (port 3001, runs from a packaged tarball).
- Distinctive: line 69
If you do hit the blank page on a reused port, just reload once — the dev cleanup script already unregistered the SW on the first load.
- Very specific: line 78
After it, navigate again. Confirm you're on current code: read a class or text you just changed off the live DOM via browser_evaluate and …
“Common” is measured: kept by at least 6 in 10 of the 6 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Browser-test a cockpit UI change with Playwright
Run an isolated cockpit dev server and drive it with the Playwright MCP. Use this over the generic run/verify skills: cockpit has three caches that will serve you stale code and burn a lot of time if you don't handle them up front.
When to use
- Visually confirm a UI / layout / CSS change renders correctly.
- Reproduce a rendering bug, especially on mobile.
- Screenshot a page or dialog at a given viewport.
1. Start an isolated dev server
Never test against the live instance (port 3001, runs from a packaged tarball). Spin up your own on a spare port with a throwaway config dir.
Three things bite you, all handled below:
- The shell exports
NODE_ENV=production, so plaintsx server.tsruns Next in production mode (serves the prebuilt.next, ignores your source). ForceNODE_ENV=development. - A separate
COCKPIT_CONFIG_DIRkeeps the test server off~/.cockpit— no job-scheduler or lock collisions, and a fresh auth state. - Foreground
sleepis blocked in this environment; poll readiness withcurl --retry.
rm -rf /tmp/cockpit-verify && mkdir -p /tmp/cockpit-verify
cd /home/dev/repos/cockpit
NODE_ENV=development COCKPIT_CONFIG_DIR=/tmp/cockpit-verify PORT=3010 \
nohup npx tsx server.ts > /tmp/cockpit-verify.log 2>&1 &
curl -s -o /dev/null -w "%{http_code}" --retry 120 --retry-delay 1 \
--retry-all-errors --retry-connrefused --max-time 12 http://localhost:3010/loginFirst load compiles on demand (~10-30s); the retry covers it. If it never returns 200, read /tmp/cockpit-verify.log.
2. Authenticate
A fresh config has no password, so /login renders the setup screen. Set one and you get a valid signed session cookie.
The COCKPIT_TOKEN bypass alone does NOT work: validateSession returns false when no password is stored, before it checks the token. Set a password.
Load the Playwright tools first:
ToolSearch → select:mcp__playwright__browser_navigate,mcp__playwright__browser_resize,mcp__playwright__browser_evaluate,mcp__playwright__browser_take_screenshot
Then browser_navigate to http://localhost:3010/login and submit the setup form via browser_evaluate (React inputs need the native value setter + an input event, so a plain .value = won't register):
() => {
const set = (el, v) => {
const d = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el), "value");
d.set.call(el, v);
el.dispatchEvent(new Event("input", { bubbles: true }));
};
const ps = document.querySelectorAll("input[type=password]");
set(ps[0], "verify123");
if (ps[1]) set(ps[1], "verify123");
[...document.querySelectorAll("button")].find((b) => /set password|login/i.test(b.textContent || ""))?.click();
}You land on /, authenticated.
3. The service worker — now auto-handled in dev (was the #1 time sink)
cockpit's PWA service worker (sw.js, cache cockpit-shell-v2) is cache-first for /_next/static. That is correct in production (content-hashed URLs) but poison in dev: turbopack dev chunk URLs are stable while their contents change across edits and server restarts, so the SW serves a stale chunk against a fresh shell. As of the layout.tsx fix, the SW is no longer registered in development, and a dev page actively unregisters any leftover SW and clears its caches on load. So a fresh spare port is clean, and a port previously poisoned by an old SW self-heals.
The symptom this caused (worth recognising — it cost hours): a blank page where every /_next/static/*.js chunk loads 200, React never mounts (document.body.innerText empty, only a <div hidden><!--$--><!--/$--></div> placeholder), and the console shows only HMR-websocket failures. That is a stale SW serving mismatched cached chunks, not a code bug.
Why it bit the MCP but not the ui-reviewer: SW scope is per origin including port. The ui-reviewer uses a fresh spare port (and a fresh browser profile) each run, so its origin never has a prior SW. The MCP reuses a small set of ports/profile, so a port that hosted an earlier server still carries that origin's stale SW. Two consequences:
- Prefer a unique, not-recently-used port per run (and vary it if you hit a blank page).
- If you do hit the blank page on a reused port, just reload once — the dev cleanup script already unregistered the SW on the first load; the reload lands clean. Belt-and-braces manual clear (rarely needed now):
async () => {
for (const r of await navigator.serviceWorker.getRegistrations()) await r.unregister();
for (const n of await caches.keys()) await caches.delete(n);
}After it, navigate again. Confirm you're on current code: read a class or text you just changed off the live DOM via browser_evaluate and compare to source. A quick tell that no SW is interfering: navigator.serviceWorker.controller === null.
4. Drive the UI
browser_resizeto a mobile size to reproduce mobile bugs — e.g.393×600, or360×440for a worst case. Real phones show less height than100vhimplies (browser chrome), so test shorter than you think.- Click via
browser_evaluate(find by text,.click()) — more reliable than ref-basedbrowser_click:() => [...document.querySelectorAll("button")].find((b) => (b.textContent || "").trim() === "New Session")?.click() - Verify with geometry, not just the screenshot. Read
getBoundingClientRect()for the element andwindow.innerHeight, and assert containment/visibility (e.g.rect.bottom <= innerHeight, element inside its scroll container).getBoundingClientRectreturns geometric position even for clipped content, so pair it with abrowser_take_screenshot+ Read the PNG to confirm what's actually visible.
5. Iterate after a source edit
HMR does NOT pick up edits here: Next infers the workspace root as the parent /home/dev/repos (multiple lockfiles), which breaks file watching for src/. After each edit:
- Kill the server,
rm -rf .next, restart (step 1). - Re-run the service-worker clear (step 3) and reload.
Skip either and you keep seeing stale code.
6. Teardown
kill $(lsof -ti:3010) 2>/dev/null || true # kill by PORT only
rm -rf /tmp/cockpit-verify /tmp/cockpit-verify.log
rm -f /home/dev/repos/cockpit/*.png # screenshots browser_take_screenshot saved into the repo rootKill by port, not pkill -f "tsx server.ts" — that pattern matches every cockpit dev server (sibling worktrees, the implement-issue review server, the ui-reviewer's server) and will take them all down. Leave .next (gitignored). The live instance on 3001 is untouched throughout.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

