Help us improve
Share bugs, ideas, or general feedback.
From chrome-test-runner
Knowledge base for QA testing web applications in Chrome using the Claude in Chrome browser tools. Auto-loaded when conversations involve testing, QA, stress testing, bug finding, or browser-based test execution.
npx claudepluginhub victor-qin/chrome-test-runner-plugin --plugin chrome-test-runnerHow this skill is triggered — by the user, by Claude, or both
Slash command
/chrome-test-runner:chrome-testingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
These are the tools available when Claude Code is connected to Chrome (`claude --chrome`):
Automates Chrome browser testing via MCP tools: debugging console errors, monitoring network requests, executing JavaScript, recording GIF evidence. Requires visible browser, not for CI/CD.
Drives a real Chrome session against a running web app to find bugs, UX issues, a11y problems, and perf regressions. Outputs structured findings JSON for downstream triage.
Tests and debugs browser apps using Chrome DevTools MCP to inspect DOM, capture console errors, analyze network requests, profile performance, and verify visuals.
Share bugs, ideas, or general feedback.
These are the tools available when Claude Code is connected to Chrome (claude --chrome):
| Tool | What it captures | Key params |
|---|---|---|
read_network_requests | All HTTP/fetch/XHR requests with method, URL, status, timing | clear: true to flush, urlPattern to filter |
read_console_messages | console.log/warn/error/info with timestamps | clear: true to flush, onlyErrors: true, pattern: "regex" |
javascript_tool | Execute arbitrary JS to inspect page state | tabId, text (JS code) |
computer: screenshot | Current viewport capture | tabId |
gif_creator | Record animated GIF of interactions | start/stop/export |
read_page | Accessibility tree / DOM structure | filter: "interactive" for just buttons/inputs |
Always use this flush-capture cycle for clean per-step data:
1. read_network_requests(clear: true) ← flush old data
2. read_console_messages(clear: true) ← flush old data
3. [perform your action]
4. computer: wait 1-2 seconds
5. read_network_requests() ← capture fresh data for this step
6. read_console_messages() ← capture fresh data for this step
document.querySelectorAll('*').length — compare early vs lateUncaught TypeError / Uncaught ReferenceErrorUnhandled Promise rejectionCannot update a component while rendering a different componentEach child in a list should have a unique "key" prop (if data-dependent)CORS policy errorsError: in redcomponentWillMount / componentWillReceiveProps deprecationfindDOMNode is deprecatedCan't perform a React state update on an unmounted componentDownload the React DevTools/favicon.ico)| Metric | Good | Concerning | Bad |
|---|---|---|---|
| Error rate | < 1% | 1-5% | > 5% |
| Avg response | < 200ms | 200ms-1s | > 1s |
| Payload per request | < 100KB | 100KB-1MB | > 1MB |
| Duplicate requests | 0 | 1-2 | 3+ identical |
// Performance navigation timing
JSON.stringify(performance.getEntriesByType('navigation')[0], null, 2)
// Count DOM nodes (tracks memory pressure)
document.querySelectorAll('*').length
// Find all event listeners (estimate via element count with handlers)
document.querySelectorAll('[onclick],[onchange],[onsubmit],[onkeydown],[onkeyup]').length
// Check for leaked intervals/timeouts (inject early, read later)
window.__intervals = window.__intervals || 0;
const origSetInterval = window.setInterval;
window.setInterval = (...args) => { window.__intervals++; return origSetInterval(...args); };
window.__intervals
// Get all failed resource loads
performance.getEntriesByType('resource')
.filter(r => r.responseStatus >= 400 || r.responseStatus === 0)
.map(r => ({ url: r.name, status: r.responseStatus, type: r.initiatorType }))