qa-use
E2E testing and browser automation for AI-driven development workflows.
Critical Insight: Plugin Commands as Shortcuts
For AI Harnesses (codex, opencode, etc.):
Plugin commands (slash commands like
) are
convenience shortcuts that wrap CLI workflows. Harnesses with only the Bash tool can access ALL functionality via CLI commands documented below.
Pattern throughout this document:
- CLI Workflow: Step-by-step CLI commands (works for ALL harnesses)
- Plugin Shortcut: Optional slash command (convenience)
Core Workflow
1. Browser Control & Session Lifecycle
CLI Workflow:
bash
# Create browser session
qa-use browser create --viewport desktop
# For localhost testing
qa-use browser create --tunnel --no-headless
# Navigate
qa-use browser goto https://example.com
# Snapshot to get element refs (ALWAYS do this before interacting)
qa-use browser snapshot
# Interact by ref
qa-use browser click e3
qa-use browser fill e5 "text"
# Close
qa-use browser close
Plugin Shortcut:
/qa-use:explore https://example.com
(Wraps create + goto + snapshot with autonomous exploration)
Critical: Always run
before interacting. Never guess element refs.
Snapshot Diff Feature:
After each action (goto, click, fill, etc.), the browser automatically shows DOM changes:
- Summary: "5 elements added, 1 element modified"
- Added elements:
+ [e54] generic "Thanks for agreeing!"
(green)
- Modified elements:
~ [e18] checkbox "I agree..."
with (yellow)
- Removed elements: (red)
This helps you understand what changed after each action without manually inspecting the DOM.
2. Understanding Blocks
What are blocks?
Blocks are atomic recorded interactions from a browser session. They are:
- Automatically captured during any browser interaction (click, fill, goto, scroll, etc.)
- Stored server-side with the session
- Retrieved via
qa-use browser get-blocks
- The foundation for test generation
Why blocks matter:
- Record-once, replay-many: Interactive recording becomes automated test
- AI-friendly: Agents can analyze blocks to understand user intent
- Version control: Blocks stored with session enable test iteration
- Bridge CLI → Tests: Natural workflow from exploration to automation
How blocks work:
bash
# 1. Create session and interact
qa-use browser create --tunnel --no-headless
qa-use browser goto https://example.com
qa-use browser snapshot # Returns: [ref=e1] button
qa-use browser click e1 # Records as block
qa-use browser fill e5 "text" # Records as block
# 2. Retrieve blocks (JSON array)
qa-use browser get-blocks
# Returns:
# [
# {"type": "goto", "url": "...", "timestamp": "..."},
# {"type": "click", "ref": "e1", "timestamp": "..."},
# {"type": "fill", "ref": "e5", "value": "text", "timestamp": "..."}
# ]
# 3. Generate test YAML from blocks
qa-use browser generate-test -n "my_test" -o qa-tests/my_test.yaml
# 4. Run generated test
qa-use test run my_test
Plugin Shortcut:
/qa-use:record start my_test
# ... perform interactions ...
/qa-use:record stop
(Wraps the interactive workflow with AI-powered test generation)
3. Test Management
CLI Workflow:
bash
# Run test by name
qa-use test run login
# Run with autofix (AI self-healing)
qa-use test run login --autofix
# Validate syntax
qa-use test validate login
# Show test details
qa-use test info login
# List test runs
qa-use test runs --status failed
Plugin Shortcut:
/qa-use:test-run login --autofix
(Convenience shortcut for common test execution)
4. Test Sync Lifecycle
CLI Workflow:
bash
# Pull tests from cloud
qa-use test sync pull
# Push all local tests to cloud
qa-use test sync push --all
# Push specific test
qa-use test sync push --id <uuid>
# Force push (overwrite conflicts)
qa-use test sync push --force
# Compare local vs cloud
qa-use test diff login.yaml
No Plugin Shortcut - Use CLI commands directly
Essential Commands
Browser Session Management
| Command | Description |
|---|
| Create remote browser session |
qa-use browser create --tunnel
| Create local browser with API tunnel |
qa-use browser create --no-headless
| Show browser window (tunnel mode only) |
qa-use browser create --viewport <size>
| Set viewport: , , |
qa-use browser create --ws-url <url>
| Connect to existing WebSocket browser |
qa-use browser create --after-test-id <uuid>
| Run a test first, then become interactive |
qa-use browser create --var <key=value>
| Override app config variables (repeatable) |
| List active sessions |
| Show current session details (app_url, recording_url, etc.) |
| Close active session |
Sessions auto-persist in
. One active session = no
flag needed.
Navigation
| Command | Description |
|---|
qa-use browser goto <url>
| Navigate to URL |
| Go back |
| Go forward |
| Reload page |
Element Interaction
| Command | Description |
|---|
qa-use browser click <ref>
| Click element by ref |
qa-use browser click --text "Button"
| Click by semantic description |
qa-use browser fill <ref> "value"
| Fill input field |
qa-use browser type <ref> "text"
| Type with delays (for autocomplete) |
qa-use browser press <key>
| Press key (e.g., , ) |
qa-use browser check <ref>
| Check checkbox |
qa-use browser uncheck <ref>
| Uncheck checkbox |
qa-use browser select <ref> "option"
| Select dropdown option |
qa-use browser hover <ref>
| Hover over element |
qa-use browser scroll down 500
| Scroll by pixels |
qa-use browser scroll-into-view <ref>
| Scroll element into view |
qa-use browser drag <ref> --target <ref>
| Drag element to target |
qa-use browser mfa-totp [ref] <secret>
| Generate TOTP code (optionally fill) |
qa-use browser upload <ref> <file>...
| Upload file(s) to input |
Inspection & Snapshot Diff
| Command | Description |
|---|
| Get ARIA tree with element refs (shows snapshot diff after actions) |
| Get current URL |
qa-use browser screenshot
| Save screenshot.png |
qa-use browser screenshot file.png
| Save to custom path |
qa-use browser screenshot --base64
| Output base64 to stdout |
qa-use browser evaluate <expression>
| Execute JavaScript in browser context |
The snapshot-diff feature automatically displays DOM changes after each browser action:
- Added elements: Shown with prefix and green color
- Modified elements: Shown with prefix and yellow color, including attribute changes ()
- Removed elements: Shown with prefix and red color
Test Operations
| Command | Description |
|---|
| Run test by name |
| Run all tests |
qa-use test run <name> --tunnel
| Run with local browser tunnel |
qa-use test run <name> --autofix
| Enable AI self-healing |
qa-use test run <name> --update-local
| Persist AI fixes to file |
qa-use test run <name> --download
| Download assets to |
qa-use test run <name> --var key=value
| Override variable |
qa-use test validate <name>
| Validate test syntax |
| List available tests |
| Show test details (steps, tags, description) |
qa-use test info --id <uuid>
| Show cloud test details by ID |
| List test run history |
qa-use test runs --id <uuid>
| Filter runs by test ID |
qa-use test runs --status failed
| Filter runs by status |
| Initialize test directory |
| Pull tests from cloud |
qa-use test sync push --all
| Push all local tests to cloud |
qa-use test sync push --id <uuid>
| Push specific test |
qa-use test sync push --force
| Push tests, overwriting conflicts |
| Compare local vs cloud test |
qa-use test schema [path]
| View test definition schema |
Logs & Debugging
| Command | Description |
|---|
qa-use browser logs console
| View console logs from session |
qa-use browser logs console -s <id>
| View logs from specific/closed session |
qa-use browser logs network
| View network request logs |
qa-use browser logs network -s <id>
| View network logs from specific session |
Test Generation
| Command | Description |
|---|
qa-use browser generate-test
| Generate test YAML from recorded session |
qa-use browser generate-test -s <id>
| Generate from specific session |
qa-use browser generate-test -n <name>
| Specify test name |
qa-use browser generate-test -o <path>
| Specify output path |
qa-use browser get-blocks
| Get recorded interaction blocks (JSON) |
Waiting
| Command | Description |
|---|
| Fixed wait |
qa-use browser wait-for-selector ".class"
| Wait for selector |
qa-use browser wait-for-load
| Wait for page load |
Variable Overrides
Use
to override app config variables at runtime. Common variables:
| Variable | Description |
|---|
| Base URL for the app (e.g., preview deployment URL) |
| Login page URL |
| Username/email for authentication |
| Password for authentication |
Example with ephemeral preview URL:
bash
qa-use browser create --after-test-id <login-test-uuid> \
--var base_url=https://preview-123.example.com \
--var login_url=https://preview-123.example.com/auth/login
Common Patterns
Pattern 1: Feature Verification
CLI Workflow:
bash
# 1. Search for existing test
qa-use test list | grep "login"
# 2. Run test with autofix
qa-use test run login --autofix
# 3. Debug failures
qa-use browser logs console
Plugin Shortcut:
/qa-use:verify "login works with valid credentials"
(Wraps the above CLI workflow with AI-powered test discovery and analysis)
Pattern 2: Record & Generate Test
CLI Workflow:
bash
# 1. Create session
qa-use browser create --tunnel --no-headless
# 2. Navigate and interact
qa-use browser goto https://example.com
qa-use browser snapshot
qa-use browser click e1
qa-use browser fill e5 "test"
# 3. Generate test from blocks
qa-use browser get-blocks
qa-use browser generate-test -n "my_test"
# 4. Run test
qa-use test run my_test
Plugin Shortcut:
/qa-use:record start my_test
# ... perform interactions ...
/qa-use:record stop
Pattern 3: Authenticated Exploration
CLI Workflow:
bash
# Create session that runs login test first
qa-use browser create --after-test-id <login-test-uuid>
# Session now authenticated, explore
qa-use browser goto /dashboard
qa-use browser snapshot
Plugin Shortcut:
/qa-use:explore /dashboard
(Automatically handles auth detection and session creation)
Pattern 4: Edit Existing Test
CLI Workflow:
bash
# 1. Open test file in editor
vim qa-tests/login.yaml
# 2. Validate syntax
qa-use test validate login
# 3. Run to verify
qa-use test run login
Plugin Shortcut:
/qa-use:record edit login
(AI-assisted editing with validation)
Pattern 5: Understanding DOM Changes with Snapshot Diff
CLI Workflow:
bash
# Create session and navigate
qa-use browser create --tunnel --no-headless
qa-use browser goto https://evals.desplega.ai/checkboxes
# Output shows initial elements:
# Changes: 45 elements added
# + [e18] checkbox "I agree to the terms and conditions"
# + [e19] generic "I agree to the terms and conditions"
# Click checkbox
qa-use browser click e18
# Snapshot diff automatically shows:
# Changes: 5 elements added, 1 element modified
# + [e54] generic "Thanks for agreeing!"
# + [e55] link "Terms and Conditions"
# ~ [e18] checkbox "I agree to the terms and conditions"
# +attrs: active, checked
Why this matters:
- Instantly see what changed after each action
- Identify new elements that appeared (e.g., success messages, modals)
- Track attribute changes (checked, disabled, aria-expanded)
- Debug failed assertions by understanding actual DOM state changes
No Plugin Shortcut - Automatic feature in all browser commands
CI/CD Integration
Running Tests in CI
Environment Variables:
bash
export QA_USE_API_KEY="your-api-key"
export QA_USE_REGION="us" # Optional: "us" or "auto"
Basic Test Execution:
bash
# Run all tests
qa-use test run --all
# Run specific tag
qa-use test run --tag smoke
# Exit codes: 0 = pass, 1 = fail
GitHub Actions Example
yaml
name: QA Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install qa-use
run: npm install -g @desplega.ai/qa-use
- name: Run tests
run: qa-use test run --all
env:
QA_USE_API_KEY: ${{ secrets.QA_USE_API_KEY }}
Test Artifacts
Screenshots:
- Automatically saved on failure
- Location: (local) or cloud (remote)
Logs:
- Console logs:
qa-use browser logs console -s <session-id>
- Network logs:
qa-use browser logs network -s <session-id>
Advanced Topics
Localhost Testing (Tunnel Mode)
When to use tunnel mode:
Testing localhost (http://localhost:3000)?
├─ YES → Use --tunnel
│ └─ qa-use browser create --tunnel [--no-headless]
│ (Starts local Playwright, creates localtunnel, keeps running)
│
└─ NO (Public URL) → Use remote browser (default)
└─ qa-use browser create
(Uses desplega.ai cloud browser via WebSocket)
The flag is a binary choice:
- Local tunnel mode: Playwright on your machine + localtunnel
- Remote mode: WebSocket URL to cloud-hosted browser
For test execution:
bash
# Local app
qa-use test run my_test --tunnel [--headful]
# Public app
qa-use test run my_test
Plugin shortcuts handle tunnel detection automatically:
/qa-use:explore http://localhost:3000
/qa-use:record start local_test
See references/localhost-testing.md for troubleshooting.
Session Persistence
Sessions are stored in
and have:
- TTL: 30 minutes (default)
- Auto-resolve: One active session = no flag needed
- Cleanup: Automatic on timeout or explicit
Block Limitations
What's captured:
- goto, click, fill, type, check, uncheck, select, hover
- scroll, scroll-into-view, drag, upload, press
What's NOT captured:
- Assertions (must be added manually)
- Waits (inferred from timing, may need adjustment)
- Complex interactions (multi-drag, hover sequences)
Manual editing: Edit generated YAML to add assertions and refine selectors.
WebSocket Sessions
Sharing sessions across processes:
bash
# Process 1: Create session
qa-use browser create --tunnel
# Output: ws://localhost:12345/browser/abc123
# Process 2: Connect to session
qa-use browser goto https://example.com --ws-url ws://localhost:12345/browser/abc123
Deep-Dive References
| Document | Description |
|---|
| browser-commands.md | Complete browser CLI reference with all flags |
| test-format.md | Full test YAML specification |
| localhost-testing.md | Tunnel setup for local development |
| failure-debugging.md | Failure classification and diagnostics |
| ci.md | CI/CD integration patterns and examples |
Templates
| Template | Description |
|---|
| basic-test.yaml | Simple navigation and assertion |
| auth-flow.yaml | Login flow with credentials |
| form-test.yaml | Form submission with validation |
Test Format Overview
yaml
name: Login Test
description: Validates login functionality with valid credentials
tags:
- smoke
- auth
app_config: <app-config-id>
variables:
email: test@example.com
password: secret123
depends_on: setup-test # Optional
steps:
- action: goto
url: /login
- action: fill
target: email input
value: $email
- action: click
target: login button
- action: to_be_visible
target: dashboard
See references/test-format.md for complete specification.
Common Mistakes
| ❌ Wrong | ✅ Correct |
|---|
| |
| |
browser close <session-id>
| |
| Guessing element refs | Always first |
| Testing localhost without | Use flag |
| (subcommand, not flag) |
| (subcommand, not flag) |
npx Alternative
All commands use
assuming global install. For one-off use:
bash
npx @desplega.ai/qa-use browser <command>