From dm-work
QA web applications using Chrome DevTools MCP. Use when testing running apps, verifying acceptance criteria against a live UI, checking for console errors, evaluating UI behavior, or running regression checks. Requires the chrome-devtools MCP server to be connected. Complements dm-work:review (code-level) with runtime verification.
How this skill is triggered — by the user, by Claude, or both
Slash command
/dm-work:browser-qaThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Test running web applications by actually navigating, clicking, and asserting — not just reading code.
Test running web applications by actually navigating, clicking, and asserting — not just reading code.
This skill covers standard web applications testable via Chrome DevTools. It is NOT suitable for:
When the evaluator encounters projects outside browser-qa's scope, it should mark runtime criteria as UNTESTABLE and note the recommended verification method.
Find testable criteria from (in priority order):
bd show <id> → check the design field for acceptance criteriadocs/ or history/ for the spec that spawned this worknavigate_page(url: "http://localhost:<port>/<path>")
take_snapshot()
The snapshot returns a text representation of the page's accessibility tree. Each interactive element has a UID you can target with click, fill, etc.
Always snapshot before interacting — UIDs are ephemeral and change on navigation.
For each acceptance criterion, drive the corresponding user flow.
Navigate and verify content:
navigate_page(url: "<target URL>")
wait_for(text: ["<expected content>"])
take_snapshot() # confirm element is present in a11y tree
Fill and submit a form:
take_snapshot() # get current UIDs
fill(uid: "<input-uid>", value: "<test value>") # type into field
click(uid: "<submit-uid>", includeSnapshot: true) # submit + get new state
wait_for(text: ["<success indicator>"]) # wait for result
Multi-field forms (more efficient):
fill_form(elements: [
{ uid: "<email-uid>", value: "[email protected]" },
{ uid: "<name-uid>", value: "Test User" },
{ uid: "<role-uid>", value: "admin" }
])
click(uid: "<save-uid>", includeSnapshot: true)
Keyboard interaction:
press_key(key: "Enter") # submit
press_key(key: "Escape") # dismiss modal
press_key(key: "Tab") # focus next
press_key(key: "Control+A") # select all
Drag and drop:
drag(from_uid: "<source>", to_uid: "<target>", includeSnapshot: true)
After each flow step, verify using the cheapest sufficient method:
Text/element presence (cheapest — prefer this):
take_snapshot()
# Scan the a11y tree for expected text, roles, states
Visual verification (use when layout/styling matters):
take_screenshot()
# Review for correct layout, colors, typography, spacing
Console errors (always check):
list_console_messages(types: ["error"])
# Should be empty. Warnings are informational, errors are failures.
Network request success:
list_network_requests(resourceTypes: ["fetch", "xhr"])
# Verify status codes (200, 201, 204). Flag 4xx/5xx.
Custom JS assertions (for state that isn't visible in the a11y tree):
evaluate_script(expression: "document.querySelector('.toast.success') !== null")
evaluate_script(expression: "window.__APP_STATE__.user.role === 'admin'")
Beyond the specific acceptance criteria, check for collateral damage:
list_console_messages(types: ["error"]) on every page visitedlist_network_requests()emulate(viewport: "375x667,mobile,touch") then re-check key elementsemulate(colorScheme: "dark") then screenshotlighthouse_audit(mode: "snapshot") for quick a11y scoreStructure the report as pass/fail per acceptance criterion:
## QA Report: <bead-id or description>
### Acceptance Criteria Results
| # | Criterion | Result | Notes |
|---|-----------|--------|-------|
| 1 | User can navigate to /settings | PASS | |
| 2 | Form validates email client-side | PASS | Shows red border + message |
| 3 | Save button disabled during submit | FAIL | Button stays enabled |
| 4 | Success toast after save | PASS | |
| 5 | No console errors | PASS | 0 errors |
### Regression Checks
- Console errors: 0
- Network failures: 0
- Mobile responsive: PASS
- Lighthouse accessibility: 92
### Verdict: FAIL (1/5 criteria failed)
Failing criteria:
- #3: Save button not disabled during form submission. The button remains
clickable, allowing duplicate submissions.
Integration with beads: If a criterion fails, create a linked bead:
bd create --title="Save button not disabled during submission" --type=bug --priority=2 --deps discovered-from:<parent-bead>
| Tool | Purpose | When to use |
|---|---|---|
navigate_page | Go to URL, back/forward/reload | Start of each flow |
take_snapshot | A11y tree with element UIDs | Before any interaction; for text/structure assertions |
take_screenshot | Visual capture (PNG) | Layout/styling verification; design quality checks |
click | Click element by UID | Buttons, links, toggles |
fill | Input/textarea/select by UID | Single form fields |
fill_form | Multiple fields at once | Multi-field forms (more efficient) |
type_text | Raw keystrokes (no targeting) | When you need to type into the focused element |
press_key | Key/combo (Enter, Escape, Ctrl+A) | Submit, dismiss, shortcuts |
wait_for | Wait for text to appear | After navigation or async operations |
drag | Drag element to element | Drag-and-drop UIs |
list_console_messages | Console output (filter by type) | Error checking — always run |
list_network_requests | Network activity (filter by type) | API call verification |
get_network_request | Single request details + body | Deep API response inspection |
get_console_message | Single console message details | Investigating specific errors |
lighthouse_audit | A11y, SEO, best practices scores | Quick accessibility check |
evaluate_script | Run JS in page context | Custom assertions on app state |
emulate | Viewport, dark mode, network, geo | Responsive/a11y/offline testing |
upload_file | File input interaction | Upload flows |
take_snapshot over take_screenshot — text is far cheaper than images in contexttake_screenshot only when you need to verify visual appearance (layout, colors, styling)wait_for before asserting — async UI needs time to settle after interactionslist_console_messages(types: ["error"]) is the cheapest smoke test — run it on every pagewait_for expected content after navigation — don't assume instant renderincludeSnapshot: true on click/fill to get the post-action state in one call instead of twofilePath) when running multiple checks to avoid bloating contextlighthouse_audit(mode: "snapshot") is faster than mode: "navigation" (no reload)Cheapest possible verification — use when you just need to know the page works:
navigate_page(url: "<url>")
wait_for(text: ["<any expected text>"])
list_console_messages(types: ["error"]) # should be empty
navigate_page(url: "<form page>")
take_snapshot()
fill_form(elements: [<fields>])
click(uid: "<submit>", includeSnapshot: true)
wait_for(text: ["<success message>"])
list_console_messages(types: ["error"])
list_network_requests(resourceTypes: ["fetch"]) # verify API call
navigate_page(url: "<page>")
wait_for(text: ["<loaded indicator>"])
take_screenshot(filePath: "qa-screenshots/desktop.png")
emulate(viewport: "375x667,mobile,touch")
take_screenshot(filePath: "qa-screenshots/mobile.png")
emulate(colorScheme: "dark")
take_screenshot(filePath: "qa-screenshots/dark-mobile.png")
navigate_page(url: "<page>")
take_screenshot(fullPage: true, filePath: "qa-screenshots/full-page.png")
# Review screenshot for AI slop patterns:
# - Generic purple/blue gradients over white cards
# - Template-default typography and spacing
# - Identical component styling across unrelated sections
# - Over-reliance on rounded corners + drop shadows + blur
# - No distinct identity or mood — looks like every other AI-generated site
npx claudepluginhub rbergman/dark-matter-marketplace --plugin dm-workTests and debugs browser apps using Chrome DevTools MCP to inspect DOM, capture console errors, analyze network requests, profile performance, and verify visuals.
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.
Automates browser testing for web apps using Playwright MCP: navigate pages, click/fill elements, take screenshots, verify UI/console logs, debug frontend issues, validate responsive design.