| name | qa-smoke-test |
| description | Run automated QA tests on desktop apps or websites. Smoke tests, visual regression, UI validation, accessibility checks, end-to-end flows. Use when: "test this app", "smoke test", "check if login works", "validate the UI", "visual regression", "verify button is clickable", "test flow", "QA check", "accessibility audit".
|
| allowed-tools | ["mcp__sh__screenshot_file","mcp__sh__screenshot","mcp__sh__ocr","mcp__sh__ui_tree","mcp__sh__ui_find","mcp__sh__browser_dom","mcp__sh__browser_page_info","mcp__sh__browser_js","mcp__sh__browser_wait","mcp__sh__browser_navigate","mcp__sh__wait_for_state","mcp__sh__locate_with_fallback","mcp__sh__read_with_fallback","mcp__sh__apps","mcp__sh__windows","mcp__sh__focus","mcp__sh__memory_record_learning","mcp__sh__memory_record_error","mcp__sh__memory_errors","mcp__sh__memory_query_patterns"] |
QA Smoke Testing & UI Validation
You are running automated quality assurance tests using ScreenHand's inspection and interaction tools.
Intelligence Wrapper
Every tool call returns automatic hints. Watch for:
[HINT] โ known selectors for the app/site under test
[WARNING] โ this tool has failed before, here's the fix
[STRATEGY] โ suggested next step based on past test sequences
Test Plan Structure
Before any action, define the test plan:
Test Plan: {App/Site Name}
===========================
1. [CHECK_NAME]: {assertion}
2. [CHECK_NAME]: {assertion}
...
Each assertion must be verifiable: "element X exists", "text Y is visible", "page loads under 3s", "button Z is clickable".
Phase 1: Baseline Capture
- Take initial
screenshot_file โ this is the "before" state.
- For web:
browser_page_info โ capture URL, title, initial text.
- For native apps:
apps โ verify the app is running, get pid
windows โ identify target window, get windowId
ui_tree(pid) โ capture the element hierarchy
- For canvas/custom-drawn UIs:
ocr โ screenshot + text extraction with bounding boxes. Use when ui_tree returns empty.
- Check verified patterns:
memory_query_patterns(scope="{app_name}") โ known working selectors.
- Record the baseline for comparison.
Phase 2: Execute Test Checks
Element Existence
locate_with_fallback(text="Submit Button")
โ PASS if element found with bounds
โ FAIL if "not found"
Uses the fallback chain: AX โ CDP โ OCR. Most thorough detection.
Text Presence
wait_for_state(condition="text_appears", text="Welcome back")
โ PASS if text found within timeout
โ FAIL if timeout exceeded
Element Interactivity (Web)
const btn = document.querySelector('button.submit');
const style = getComputedStyle(btn);
return JSON.stringify({
exists: !!btn,
visible: style.display !== 'none' && style.visibility !== 'hidden',
enabled: !btn.disabled,
clickable: btn.offsetWidth > 0 && btn.offsetHeight > 0
});
Use browser_js with this check.
Element Interactivity (Native)
ui_find(text="Submit")
โ Check AXEnabled attribute in result
โ PASS if enabled=true
โ FAIL if enabled=false or not found
Page Load Performance (Web)
const timing = performance.getEntriesByType('navigation')[0];
return JSON.stringify({
loadTime: timing.loadEventEnd - timing.startTime,
domReady: timing.domContentLoadedEventEnd - timing.startTime,
ttfb: timing.responseStart - timing.requestStart
});
Accessibility Audit (Web)
const issues = [];
document.querySelectorAll('img:not([alt])').forEach(img =>
issues.push({type: 'missing-alt', element: img.src}));
document.querySelectorAll('button').forEach(btn => {
if (!btn.textContent.trim() && !btn.getAttribute('aria-label'))
issues.push({type: 'empty-button', element: btn.outerHTML.slice(0, 100)});
});
document.querySelectorAll('input:not([type=hidden])').forEach(input => {
if (!input.getAttribute('aria-label') && !document.querySelector(`label[for="${input.id}"]`))
issues.push({type: 'unlabeled-input', element: input.name || input.type});
});
document.querySelectorAll('a, button, input, select, textarea').forEach((el, i) => {
if (el.tabIndex < 0) issues.push({type: 'negative-tabindex', element: el.tagName});
});
return JSON.stringify(issues);
Visual Regression
- Take
screenshot_file at each step
- Compare OCR text from
screenshot between baseline and current state
- Flag any text that appeared or disappeared unexpectedly
Phase 3: End-to-End Flow Testing
For user flow testing (e.g., "test the login flow"):
- Define the flow steps
- Execute each step using the automate-app or browser tools
- After EACH step, verify the expected state
- Record PASS/FAIL per step
- Take
screenshot_file at each step for evidence
Phase 4: Test Report
Produce a structured report:
Test Report: {App/Site Name}
============================
Date: {date}
Total: {N} checks
Passed: {P} โ
Failed: {F} โ
Skipped: {S} -
Results:
โ [element_exists] Submit button is present
โ [text_visible] Welcome message appears
โ [interactivity] Save button is disabled (expected: enabled)
โ [performance] Page loads in 1.2s (threshold: 3s)
โ [a11y] 3 images missing alt text
Screenshots:
- baseline: /path/to/screenshot1.png
- after_login: /path/to/screenshot2.png
Failed Check Details:
[interactivity] Save button:
Expected: enabled=true
Actual: enabled=false, aria-disabled="true"
Suggestion: Check if form validation is blocking the button
Learning from Results
After each test run:
memory_record_learning(scope="qa/{app}", method="{tool}", pattern="{what worked}", confidence=0.9) for each passing check
memory_record_error(tool="{tool}", error="{what failed}", resolution="{suggested fix}") for each failing check
- Check
memory_errors(tool="{tool}") to see if failures match known patterns
$ARGUMENTS