tmux-party/tests/87-log.bats
veg 6c48777553 fix: party log --stop closes only the pipes it opened
Start already skipped panes the host had piped for other purposes,
but --stop swept every pane, killing pipes party log never owned.
Record the pane ids we pipe in .log-panes inside the per-party dir
and close exactly those on --stop; the file dies with the dir.
2026-07-11 16:54:57 +00:00

99 lines
2.9 KiB
Bash

#!/usr/bin/env bats
#
# party log: pipe-pane transcript into the per-party dir. Needs a real
# tmux server (pipe-pane semantics can't be stubbed honestly), so setup
# pins TMUX_PARTY_GROUP to the caller's own primary group rather than
# gating on require_party_group like the other e2e suites: no group
# membership setup is needed, and no test here ever skips.
load 'helpers'
setup() {
setup_party_sandbox
export TMUX_PARTY_GROUP="$(id -gn)"
}
teardown() { teardown_party_sandbox; }
logfile() { printf '%s/party-%s:%s.d/log\n' "$PARTY_SOCKET_DIR" "$USER" "$1"; }
sock_of() { printf '%s/party-%s:%s.d/sock\n' "$PARTY_SOCKET_DIR" "$USER" "$1"; }
# Wait up to ~10s for $2 to appear in file $1. Integer sleeps only:
# fractional sleep is not portable across the matrix.
poll_for() {
for _ in 1 2 3 4 5 6 7 8 9 10; do
grep -q "$2" "$1" 2>/dev/null && return 0
sleep 1
done
return 1
}
@test "log without a hosted party fails" {
run "$PARTY_BIN" log
[ "$status" -eq 1 ]
[[ "$output" == *"do not host"* ]]
}
@test "log captures pane output; --stop ends capture" {
"$PARTY_BIN" host scribe
run "$PARTY_BIN" log
[ "$status" -eq 0 ]
[[ "$output" == *"Logging to"* ]]
tmux -S "$(sock_of scribe)" send-keys -t scribe 'echo marker-ONE' Enter
poll_for "$(logfile scribe)" marker-ONE
run "$PARTY_BIN" log --stop
[ "$status" -eq 0 ]
tmux -S "$(sock_of scribe)" send-keys -t scribe 'echo marker-TWO' Enter
sleep 2
! grep -q marker-TWO "$(logfile scribe)"
}
@test "log file is 0640 so group members can copy it" {
"$PARTY_BIN" host perms
"$PARTY_BIN" log
[ -n "$(find "$(logfile perms)" -prune -perm 0640 2>/dev/null)" ]
}
@test "re-running log attaches panes created after the first run" {
"$PARTY_BIN" host panes
"$PARTY_BIN" log
tmux -S "$(sock_of panes)" split-window -t panes
"$PARTY_BIN" log
tmux -S "$(sock_of panes)" send-keys -t panes.1 'echo marker-PANE2' Enter
poll_for "$(logfile panes)" marker-PANE2
}
@test "close rescues a non-empty transcript to HOME" {
export HOME="$PARTY_TMP/home"
mkdir -p "$HOME"
"$PARTY_BIN" host rescue
"$PARTY_BIN" log
tmux -S "$(sock_of rescue)" send-keys -t rescue 'echo marker-KEEP' Enter
poll_for "$(logfile rescue)" marker-KEEP
run "$PARTY_BIN" close rescue
[ "$status" -eq 0 ]
[[ "$output" == *"transcript saved to"* ]]
saved=$(ls "$HOME"/party-rescue-*.log)
grep -q marker-KEEP "$saved"
}
@test "log --stop leaves a manually piped pane alone" {
"$PARTY_BIN" host bystander
manual="$PARTY_TMP/manual-pipe.out"
tmux -S "$(sock_of bystander)" pipe-pane -t bystander "cat >> '$manual'"
"$PARTY_BIN" log
"$PARTY_BIN" log --stop
tmux -S "$(sock_of bystander)" send-keys -t bystander 'echo marker-MANUAL' Enter
poll_for "$manual" marker-MANUAL
}
@test "close without a transcript stays silent about rescue" {
export HOME="$PARTY_TMP/home"
mkdir -p "$HOME"
"$PARTY_BIN" host quiet
run "$PARTY_BIN" close quiet
[ "$status" -eq 0 ]
[[ "$output" != *"transcript"* ]]
}