#!/usr/bin/env bash # test-features.sh — drive a headless hack-house clergy via `tmux send-keys` and # assert each feature by scraping the rendered TUI with `tmux capture-pane`. # # It boots a --no-tls server, opens an OWNER pane and a MEMBER (bob) pane in a # detached tmux session, fires deterministic keystrokes, and greps the captured # screen for the state markers the UI paints (DRIVING, scrollback, chat ↑, …). # # ./test-features.sh # run the suite, leave the session up to inspect # ./test-features.sh --kill # tear the session + server down # PORT=4199 PW=test-bless ./test-features.sh # # While it runs you can watch live in another terminal: # tmux attach -t hh-autotest set -uo pipefail HERE="$(cd "$(dirname "$0")" && pwd)" # .../hh ROOT="$(cd "$HERE/.." && pwd)" # repo root PY="$ROOT/.venv/bin/python" BIN="$HERE/target/debug/hack-house" SESSION="${SESSION:-hh-autotest}" HOST="${HOST:-127.0.0.1}" PORT="${PORT:-4199}" PW="${PW:-test-bless}" SRV_LOG="/tmp/hh-${SESSION}-server.log" SRV_PIDFILE="/tmp/hh-${SESSION}-server.pid" is_up() { curl -s --max-time 2 "http://$HOST:$PORT/health" 2>/dev/null | grep -q '"status":"ok"'; } stop_server() { if [[ -f "$SRV_PIDFILE" ]]; then kill "$(cat "$SRV_PIDFILE")" 2>/dev/null && echo "stopped server (pid $(cat "$SRV_PIDFILE"))" rm -f "$SRV_PIDFILE" fi } if [[ "${1:-}" == "--kill" || "${1:-}" == "--teardown" ]]; then tmux kill-session -t "$SESSION" 2>/dev/null && echo "killed tmux $SESSION" || echo "no tmux session" stop_server exit 0 fi # ─── result tracking ────────────────────────────────────────────────────────── PASS=0; FAIL=0 declare -a RESULTS=() cap() { tmux capture-pane -pt "$1" 2>/dev/null; } # want