//go:build !windows && linux package infra import ( "fmt" "os" "os/exec" "strings" "testing" "time" ) // tmuxAvailable reports whether the tmux binary is present. Tests skip when it // is not (CI without tmux). func tmuxAvailable(t *testing.T) { t.Helper() if _, err := exec.LookPath("tmux"); err != nil { t.Skipf("tmux no disponible en PATH: %v", err) } } // isolatedSocket returns a per-test isolated tmux socket name and registers a // cleanup that kills its server. All commands in a test run against // `tmux -L ...`, never the user's default server. func isolatedSocket(t *testing.T) string { t.Helper() socket := fmt.Sprintf("fleettest_%d_%d", os.Getpid(), time.Now().UnixNano()) t.Cleanup(func() { // best-effort: el server puede no existir si el test fallo antes de crearlo _ = exec.Command("tmux", "-L", socket, "kill-server").Run() }) return socket } // startConsoleSession crea una sesion con una window "console" cuyo // pane 0 corre `cat` (simula la TUI fleetview, un proceso que no termina). func startConsoleSession(t *testing.T, socket, session string) { t.Helper() cmd := exec.Command("tmux", "-L", socket, "new-session", "-d", "-s", session, "-n", "console", "cat") if out, err := cmd.CombinedOutput(); err != nil { t.Fatalf("new-session: %v (%s)", err, out) } } func TestTmuxNewClaudeWindow(t *testing.T) { tmuxAvailable(t) socket := isolatedSocket(t) session := "fleet" startConsoleSession(t, socket, session) cwd, err := os.Getwd() if err != nil { t.Fatalf("getwd: %v", err) } // El comando real ("claude ...") no esta disponible en el test, pero // new-window devuelve el window_id ANTES de que el comando pueda fallar: // tmux crea la window y reporta su id sincronamente. Validamos que el id // venga con la forma esperada (@N) y no vacio. windowID, err := TmuxNewClaudeWindow(socket, session, cwd) if err != nil { t.Fatalf("TmuxNewClaudeWindow: %v", err) } if windowID == "" { t.Fatal("window_id vacio") } if !strings.HasPrefix(windowID, "@") { t.Errorf("window_id %q no tiene la forma esperada @N", windowID) } } func TestTmuxNewClaudeWindowEmptyArgs(t *testing.T) { if _, err := TmuxNewClaudeWindow("", "fleet", "/tmp"); err == nil { t.Error("socket vacio deberia dar error") } if _, err := TmuxNewClaudeWindow("sock", "", "/tmp"); err == nil { t.Error("session vacia deberia dar error") } if _, err := TmuxNewClaudeWindow("sock", "fleet", ""); err == nil { t.Error("cwd vacio deberia dar error") } }