SuperAPI AI Directory

browser-ui-harness

Design & creation

View repository

Updated 10-15 19:57

About this skill

Browser UI harness best practices

Generic patterns for human-readable browser journeys driven by a CLI (typically agent-browser). Distilled from production-style smoke harnesses: a runner owns infrastructure; cases own product steps.

Install this skill:

# Global
npx skills add ArchAstro/astroshots --skill browser-ui-harness -g -y

# This project only
cd /path/to/your/project
npx skills add ArchAstro/astroshots --skill browser-ui-harness -y

Pair with:

npx skills add ArchAstro/astroshots --skill agent-browser -g -y
npx skills add ArchAstro/astroshots --skill astroshots-review -g -y

Goals of a good harness

Goal Practice
Prove a product journey Steps a human would recognize (“signed in”, “modal open”)
Stay debuggable Screenshots + interactive snapshots + a Markdown report
Stay repeatable Stable fixtures + run-unique names for created data
Fail loudly with evidence On timeout/assert fail, capture page + console + errors
Keep cases thin No env discovery or browser lifecycle inside case files
Support live review Write frames under .astroshot/<feature>/ for Astroshots

Unit/component tests (Playwright fixtures, Astroshot fixtures, etc.) stay separate. This skill is for end-to-end journeys against a running app.


Architecture: runner vs cases

test-harness/browser/          # name as you like
  run.sh                       # runner: env, session, login, helpers, cleanup
  cases/
    install-wizard.sh          # case: CASE_DESCRIPTION + run_case()
    checkout.sh

Runner owns

  • Discovering base URLs / ports from this project’s config (never hardcode)
  • Health checks (“is the app up?”)
  • Creating an isolated named agent-browser session
  • Auth bootstrap if needed (prefer real UI login when that is the product)
  • Helpers: wait, assert, capture, step logging
  • Artifact directories + Markdown report
  • Cleanup of browser session and run-created resources
  • Optional: refuse non-loopback URLs when the harness mutates local-only data

Case owns

#!/usr/bin/env bash
CASE_DESCRIPTION="One sentence: what this journey proves."

run_case() {
  smoke_step "Open the pricing page"
  smoke_browser open "$APP_BASE_URL/pricing"
  smoke_wait_text "Plans" 20
  smoke_capture "pricing" "Plan cards are visible."

  smoke_step "Start checkout"
  smoke_click_text "Get started"
  smoke_wait_text "Checkout" 15
  smoke_assert_url '/checkout'
  smoke_capture "checkout" "Checkout form is ready."
}

Rule: setup and evidence mechanics live in run.sh; product clicks and assertions live in cases.


Session and isolation

REPO="$(basename "$(git rev-parse --show-toplevel)")"
CASE_NAME="install-wizard"
RUN_ID="${CASE_NAME}-$(date -u +%Y%m%dT%H%M%SZ)-$$"
SESSION="${SESSION:-ui-${REPO}-${RUN_ID}}"
  • One session per run; pass it into every agent-browser call.
  • Close the session on exit unless HOLD=1 (leave open for human inspection).
  • Prefer a fresh session for smoke (no leftover cookies) unless the case is explicitly about resume/persistence.

Helper contract (implement in the runner)

Name them as you like; keep the semantics:

Helper Behavior
smoke_browser … agent-browser --session "$SESSION" "$@" + log
smoke_step "…" Numbered section in report + log
smoke_wait_js "label" 'expr' [seconds] Poll until true or fail with evidence
smoke_wait_text "…" Wait until body text includes string
smoke_assert_text / smoke_assert_url Hard fail if missing
smoke_click_text "…" Click visible button/link by text (prefer dialog scope when open)
smoke_capture "slug" "what it proves" Screenshot + optional a11y snapshot + report lines
smoke_fail "…" Diagnostics then non-zero exit

Waits

  • Bound every wait (default 10–20s). Infinite waits are bugs.
  • Prefer product signals (heading text, URL, enabled button) over fixed sleep.
  • Short settle (wait 300–500) only after known animations before a screenshot.

Assertions

  • Assert outcomes (“All set.” visible, URL under /networks/) not implementation details.
  • On failure: full-page screenshot, snapshot, console, errors into the artifact dir.

Captures

Each capture should answer: what does this frame prove?

smoke_capture "destination-default" \
  "Destination and ACL choices are presented before install."

Also dual-write for live review when Astroshots is in play:

Resolve the capture command in this order (the runner skeleton in references/runner-skeleton.sh does this):

  1. ASTROSHOT_CAPTURE, when set to an executable (explicit override).
  2. archdev shots capture, when archdev shots doctor exits 0 (native support is installed and enabled).
  3. astroshot-capture on PATH (the helper from the astroshots-review skill).

If none resolve, the dual-write is skipped and the harness still runs.

# CAPTURE is the resolved command, e.g. `archdev shots capture` or astroshot-capture
$CAPTURE --feature "$CASE_NAME" --slug "$slug" \
  --description "$description" \
  --status running \
  --from-agent-browser "$SESSION"
# at end:
$CAPTURE --feature "$CASE_NAME" --status pass --finalize

archdev shots capture and astroshot-capture take the same flags. In a script, keep the command in an array (CAPTURE_CMD=(archdev shots capture)) and call "${CAPTURE_CMD[@]}".

Layout (see astroshots-review skill):

$REPO_ROOT/.astroshot/<feature>/
  manifest.json
  0001-slug.png

Data and repeatability

Do Don't
Stable catalog/fixture resources the product always has Depend on yesterday’s manual UI state
Run-unique names for anything you create (Smoke ${RUN_ID}) Fixed names that collide on re-run
Clean up run-created rows (best effort in trap) Leave infinite garbage in shared local DBs
Keep secrets out of argv and logs Echo magic links, tokens, or passwords

Safety for local harnesses

If the harness hits local-only setup endpoints or mutates a shared DB:

  • Default to loopback base URLs only.
  • Require an explicit escape hatch for remote targets (ALLOW_REMOTE=1).
  • Document that the harness writes data and what it cleans up.

Report shape

Write a single report.md as you go:

# Browser smoke report

- Case: `install-wizard`
- Run: `install-wizard-20260724T…`
- App: `http://localhost:3000`
- Session: `ui-…`

## 01. Sign in
- Fresh session authenticated.
- Screenshot: `screenshots/01-signed-in.png`

## Result
PASS

Humans should understand the run without reading the shell log.


Runner skeleton (outline)

#!/usr/bin/env bash
set -euo pipefail
# 1. parse case name, resolve APP_BASE_URL from env/files
# 2. health check or exit with clear error
# 3. mkdir artifacts; start report header
# 4. trap cleanup → diagnostics on fail; close session unless HOLD=1
# 5. source cases/$case.sh; require run_case
# 6. optional login_with_real_ui
# 7. run_case
# 8. append PASS; exit 0

Keep run.sh under a few hundred lines by pushing product detail into cases.


How this relates to other tools

Tool Role
agent-browser Drive one browser session (see agent-browser skill)
Playwright test runner Large suites, parallel specs, CI gates
@archastro/astroshot react from npmjs Isolated React docs PNGs without a full stack
@archastro/astroshot ink from npmjs Isolated Ink terminal PNGs without a PTY
@archastro/astroshot pty from npmjs Real Ratatui or arbitrary terminal-process PNGs
@archastro/astroshot movie --source browser Continuous browser journey with poster+video manifest
Astroshots Live human review of harness frames

Use a Bash agent-browser harness when you want a readable journey + evidence agents and humans can both follow. Use Playwright when you need matrix scale and strict CI parallelism.


Checklist before you call a harness “done”

  • Runner discovers URLs; cases do not hardcode ports
  • Named session; closed on exit (or documented HOLD)
  • Bounded waits + product-level asserts
  • Failures dump screenshot + snapshot + console
  • Captures include “what this proves”
  • Run-unique data + cleanup
  • Report.md written
  • Optional: .astroshot/<case>/ dual-write for live review

Related

  • screenshot skill — documentation asset planning and visual review
  • agent-browser skill — CLI loop, snapshot, screenshots
  • astroshots-review skill — .astroshot/ layout, astroshot-capture, and the archdev shots equivalents
  • astroshot skill — deterministic React, Ink, and PTY stills plus journey movies
  • CLI deep dive: agent-browser skills get core --full