package tui
// These tests catch cancellation blocked by a descendant's inherited stdout.
// The daemon E2E suite cannot drive the TUI's local clipboard subprocesses.
import (
"context"
"errors"
"os"
"os/exec"
"strconv"
"strings"
"testing"
"time"
)
func TestClipboardCancellationClosesDescendantStdout(t *testing.T) {
shell, err := exec.LookPath("sh")
if err != nil {
t.Skip("requires sh")
}
for _, parent := range []string{"wait", "exit 0"} {
t.Run(parent, func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
defer cancel()
start := time.Now()
out, err := execClipboardCommand(ctx, shell, "-c", `sleep 2 & printf '%s\n' "$!"; `+parent)
elapsed := time.Since(start)
// Kill the fixture's descendant promptly even when an assertion fails.
pid, parseErr := strconv.Atoi(strings.TrimSpace(string(out)))
if parseErr != nil {
t.Fatalf("descendant did not report its PID: %q: %v", out, parseErr)
}
process, findErr := os.FindProcess(pid)
if findErr != nil {
t.Fatal(findErr)
}
_ = process.Kill()
if !errors.Is(err, context.DeadlineExceeded) {
t.Fatalf("expected deadline error, got %v", err)
}
if elapsed >= time.Second {
t.Fatalf("cancellation took %s with a 50 ms deadline", elapsed)
}
})
}
}