m16-widgets.sh
raw
#!/usr/bin/env bash
# M16 widgets test under quibble, driving components/Settings.gdc:
# 1. Enter activates the focused button (the focus invariant focuses the
# first button at mount) — "all on",
# 2. Tab moves focus to the next button; Enter activates it — "all off",
# 3. a pointer click toggles a checkbox (and focuses it),
# 4. Space toggles the now-focused checkbox back,
# 5. idle renders zero frames (buttons and checkboxes request no timers).
set -euo pipefail
cd "$(dirname "$0")/.."
cargo build -p guiduck --example m16_demo
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 240 --height 150 \
target/debug/examples/m16_demo \
>"$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; }
qc() { quibblectl --socket "$sock" "$@" >/dev/null; }
shot() { quibblectl --socket "$sock" screenshot -o "$workdir/$1" >/dev/null; }
last() { grep '^options: ' "$workdir/out.log" | tail -1; }
fail=0
KEY_TAB=15; KEY_ENTER=28; KEY_SPACE=57
key() {
quibblectl --socket "$sock" key "$1" press >/dev/null
quibblectl --socket "$sock" key "$1" release >/dev/null
}
# Widget centers (from tests/m16_widgets.rs::print_settings_layout at 240x150).
ALLON_X=42; ALLON_Y=24
WIFI_X=78; WIFI_Y=54
shot s0.png
# 1: Enter activates the focused button. The focus invariant focused the
# first focusable (the "all on" button) at mount.
key $KEY_ENTER
sleep 0.3
shot s1.png
v=$(last)
if [ "$v" = "options: wifi=on bluetooth=on airplane=on" ] && ! cmp -s "$workdir/s0.png" "$workdir/s1.png"; then
echo "Enter activated the focused button: $v"
else
echo "FAIL: Enter activate; got '$v'" >&2; fail=1
fi
# 2: Tab moves focus to the next button; Enter activates "all off".
key $KEY_TAB
key $KEY_ENTER
sleep 0.3
shot s2.png
v=$(last)
if [ "$v" = "options: wifi=off bluetooth=off airplane=off" ] && ! cmp -s "$workdir/s1.png" "$workdir/s2.png"; then
echo "Tab+Enter activated the second button: $v"
else
echo "FAIL: Tab+Enter; got '$v'" >&2; fail=1
fi
# 3: a pointer click toggles a checkbox (and focuses it).
qc pointer-move $WIFI_X $WIFI_Y
qc click
sleep 0.3
shot s3.png
v=$(last)
if [ "$v" = "options: wifi=on bluetooth=off airplane=off" ] && ! cmp -s "$workdir/s2.png" "$workdir/s3.png"; then
echo "click toggled the checkbox: $v"
else
echo "FAIL: checkbox click; got '$v'" >&2; fail=1
fi
# 4: Space toggles the now-focused checkbox back off.
key $KEY_SPACE
sleep 0.3
v=$(last)
if [ "$v" = "options: wifi=off bluetooth=off airplane=off" ]; then
echo "Space toggled the focused checkbox: $v"
else
echo "FAIL: Space toggle; got '$v'" >&2; fail=1
fi
# 5: idle renders zero frames (no timers; buttons/checkboxes never blink).
q0=$(frames); sleep 3; q1=$(frames)
echo "idle frames: $q0 -> $q1"
[ "$q0" = "$q1" ] || { echo "FAIL: rendering while idle" >&2; fail=1; }
cp "$workdir/s3.png" target/m16-widgets.png 2>/dev/null || true
[ "$fail" -eq 0 ] && echo "M16 widgets test PASSED"
exit $fail