m8-echo.sh raw

#!/usr/bin/env bash
# M8 data-driven text-input test under quibble:
#   1. typing works immediately — `:autofocus` granted focus, no click,
#   2. each edit raises `:on-change` through compiled logic and out the
#      `changed` output (asserted on stdout),
#   3. the echo label re-renders reactively (screenshots differ),
#   4. idle renders only the caret-blink cadence.
set -euo pipefail
cd "$(dirname "$0")/.."

cargo build -p guiduck --example m8_echo

workdir=$(mktemp -d)
sock="$workdir/quibble.sock"
cleanup() {
    quibblectl --socket "$sock" quit >/dev/null 2>&1 || true
    rm -rf "$workdir"
}
trap cleanup EXIT

GUIDUCK_BACKEND=software GUIDUCK_TRACE_FRAMES=1 \
    quibble --socket "$sock" --width 480 --height 360 \
    target/debug/examples/m8_echo \
    >"$workdir/out.log" 2>"$workdir/err.log" &
for _ in $(seq 1 50); do
    quibblectl --socket "$sock" ping >/dev/null 2>&1 && break
    sleep 0.2
done
quibblectl --socket "$sock" wait-window --timeout-ms 30000 >/dev/null
sleep 1

frames() { grep -c '^guiduck-frame' "$workdir/err.log" || true; }
fail=0

quibblectl --socket "$sock" screenshot -o "$workdir/before.png" >/dev/null

# 1+2: type with no click first — autofocus is the point.
quibblectl --socket "$sock" type "duck" >/dev/null
sleep 0.5
last=$(grep '^changed=' "$workdir/out.log" | tail -1)
if [ "$last" = "changed=duck" ]; then
    echo "autofocus + on-change: ok ($last)"
else
    echo "FAIL: expected changed=duck, got '$last'" >&2; fail=1
fi
count=$(grep -c '^changed=' "$workdir/out.log")
if [ "$count" = "4" ]; then
    echo "per-edit events: 4 changes for 4 keys"
else
    echo "FAIL: expected 4 change events, got $count" >&2; fail=1
fi

# 3: the bound label repainted.
quibblectl --socket "$sock" screenshot -o "$workdir/after.png" >/dev/null
if cmp -s "$workdir/before.png" "$workdir/after.png"; then
    echo "FAIL: echo label did not update" >&2; fail=1
else
    echo "reactive label: pixels changed"
fi

# 4: idle with a focused text input = the caret blink cadence, and
# nothing more. ~5-6 toggles in 3s at the 530ms interval; a count outside
# [3, 9] means the blink stalled or something renders beyond it.
q0=$(frames); sleep 3; q1=$(frames)
d=$((q1 - q0))
echo "idle frames: $q0 -> $q1 (blink cadence: $d)"
{ [ "$d" -ge 3 ] && [ "$d" -le 9 ]; } || { echo "FAIL: expected caret-blink cadence while idle, got $d frames" >&2; fail=1; }

[ "$fail" -eq 0 ] && echo "M8 echo test PASSED"
exit $fail