Files
Classroom_Desktop/tests/test-classroom-window.sh
T
ekklesiaandClaude Opus 5 719b856040 refactor: share the sway helpers
classroom-dvd-session needs to ask sway whether VLC has taken the
screen, which is the same tree walking classroom-window already does.
One copy, in a module both import; classroom-window loses a third of its
length.

The state machine is worth protecting through a move like that, so its
regression test comes with it: the exact swaymsg commands for launch,
focus, minimise, restore, Super+M, Super+Shift+M, the scratchpad rescue
and sway not running at all.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-04 23:17:18 -05:00

148 lines
4.8 KiB
Bash
Executable File

#!/bin/bash
set -uo pipefail
# Tests the minimise/restore state machine against a mock sway IPC, by
# asserting the exact commands classroom-window sends.
#
# tests/test-classroom-window.sh
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SCRIPT="$ROOT/scripts/classroom-window"
WORK="$(mktemp -d)"
trap 'rm -rf "$WORK"' EXIT
passed=0
failed=0
check() {
local label="$1" expected="$2" actual="$3"
if [[ "$actual" == "$expected" ]]; then
echo " ok $label"
passed=$((passed + 1))
else
echo " FAIL $label"
echo " expected: ${expected//$'\n'/ | }"
echo " got: ${actual//$'\n'/ | }"
failed=$((failed + 1))
fi
}
mkdir -p "$WORK/bin"
cat > "$WORK/bin/swaymsg" <<'SHIM'
#!/usr/bin/env python3
import json, os, sys
args = sys.argv[1:]
state = json.load(open(os.environ["MOCK_TREE"]))
if args[:1] == ["-t"]:
print(json.dumps(state["tree" if args[1] == "get_tree" else "workspaces"]))
sys.exit(0)
with open(os.environ["MOCK_LOG"], "a") as log:
log.write(" ".join(a for a in args if a != "--") + "\n")
SHIM
chmod +x "$WORK/bin/swaymsg"
export PATH="$WORK/bin:$PATH"
export MOCK_LOG="$WORK/log"
export XDG_RUNTIME_DIR="$WORK/run"
tree() {
cat > "$WORK/tree.json"
export MOCK_TREE="$WORK/tree.json"
}
run() { : > "$MOCK_LOG"; python3 "$SCRIPT" "$@" >/dev/null 2>&1; cat "$MOCK_LOG"; }
# ------------------------------------------------ a focused Chrome window
tree <<'JSON'
{"tree":{"type":"root","id":1,"nodes":[
{"type":"output","id":2,"name":"HDMI-A-1","nodes":[
{"type":"workspace","id":3,"name":"1","nodes":[
{"type":"con","id":10,"pid":100,"app_id":"google-chrome","focused":true,
"fullscreen_mode":0,"nodes":[],"floating_nodes":[]}],"floating_nodes":[]},
{"type":"workspace","id":4,"name":"__ekklesia_hidden","nodes":[
{"type":"con","id":11,"pid":101,"app_id":null,
"window_properties":{"class":"vlc","instance":"vlc"},"focused":false,
"fullscreen_mode":1,"nodes":[],"floating_nodes":[]}],"floating_nodes":[]}
],"floating_nodes":[]}],"floating_nodes":[]},
"workspaces":[{"name":"1","focused":true,"visible":true},
{"name":"__ekklesia_hidden","focused":false,"visible":false}]}
JSON
echo "1. the browser button"
check "focused window is minimised, fullscreen dropped first" \
"[con_id=10] fullscreen disable
[con_id=10] move container to workspace __ekklesia_hidden" \
"$(run toggle --match google-chrome -- google-chrome)"
check "a minimised window comes back tiled, not floating" \
"[con_id=11] move container to workspace 1
[con_id=11] floating disable
[con_id=11] focus" \
"$(run toggle --match '(?i)vlc' -- vlc)"
echo
echo "2. keyboard"
check "Super+M minimises whatever is focused" \
"[con_id=10] fullscreen disable
[con_id=10] move container to workspace __ekklesia_hidden" \
"$(run minimize)"
check "Super+Shift+M restores from the hidden workspace" \
"[con_id=11] move container to workspace 1
[con_id=11] floating disable
[con_id=11] focus" \
"$(run restore-last)"
echo
echo "3. a running but unfocused window is focused, not minimised"
python3 - "$WORK/tree.json" <<'PY'
import json, sys
data = json.load(open(sys.argv[1]))
data["tree"]["nodes"][0]["nodes"][0]["nodes"][0]["focused"] = False
json.dump(data, open(sys.argv[1], "w"))
PY
check "focus only" "[con_id=10] focus" "$(run toggle --match google-chrome -- x)"
echo
echo "4. nothing running launches the application"
: > "$MOCK_LOG"
output="$(python3 "$SCRIPT" toggle --match firefox -- /bin/echo LAUNCHED 2>&1)"
sleep 0.3
check "launch instead of a sway command" "LAUNCHED" "$output"
check "no sway command sent" "" "$(cat "$MOCK_LOG")"
echo
echo "5. a window stranded in sway's own scratchpad is rescued"
tree <<'JSON'
{"tree":{"type":"root","id":1,"nodes":[
{"type":"output","id":90,"name":"__i3","nodes":[
{"type":"workspace","id":91,"name":"__i3_scratch","nodes":[],"floating_nodes":[
{"type":"floating_con","id":12,"pid":102,"app_id":"google-chrome",
"focused":false,"fullscreen_mode":0,"nodes":[],"floating_nodes":[]}]}],
"floating_nodes":[]},
{"type":"output","id":2,"name":"HDMI-A-1","nodes":[
{"type":"workspace","id":3,"name":"1","nodes":[],"floating_nodes":[]}],
"floating_nodes":[]}],"floating_nodes":[]},
"workspaces":[{"name":"1","focused":true,"visible":true},
{"name":"__i3_scratch","focused":false,"visible":false}]}
JSON
check "pulled back and forced out of floating" \
"[con_id=12] move container to workspace 1
[con_id=12] floating disable
[con_id=12] focus" \
"$(run toggle --match google-chrome -- x)"
echo
echo "6. sway not running is survivable"
export PATH="${PATH#"$WORK/bin:"}"
for action in list minimize restore-last; do
python3 "$SCRIPT" "$action" >/dev/null 2>&1
check "$action exits cleanly with no sway" "0" "$?"
done
echo
echo "passed: $passed failed: $failed"
[[ "$failed" -eq 0 ]]