1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
package main
import (
"bytes"
"errors"
"strings"
"testing"
"codeberg.org/snonux/hexai/internal/tmuxedit"
)
func TestBuildOptions_AllEmpty(t *testing.T) {
opts := buildOptions("", "", "")
if opts.ConfigPath != "" || opts.Agent != "" || opts.Pane != "" {
t.Fatalf("expected all empty, got %+v", opts)
}
}
func TestBuildOptions_TrimsWhitespace(t *testing.T) {
opts := buildOptions(" /tmp/cfg.toml ", " claude ", " %5 ")
if opts.ConfigPath != "/tmp/cfg.toml" {
t.Fatalf("expected trimmed config path, got %q", opts.ConfigPath)
}
if opts.Agent != "claude" {
t.Fatalf("expected trimmed agent, got %q", opts.Agent)
}
if opts.Pane != "%5" {
t.Fatalf("expected trimmed pane, got %q", opts.Pane)
}
}
func TestRunTmuxEdit_Success(t *testing.T) {
old := runTmuxEdit
t.Cleanup(func() { runTmuxEdit = old })
var gotOpts tmuxedit.Options
runTmuxEdit = func(opts tmuxedit.Options) error {
gotOpts = opts
return nil
}
opts := buildOptions("/tmp/cfg.toml", "cursor", "%3")
if err := runTmuxEdit(opts); err != nil {
t.Fatalf("runTmuxEdit: %v", err)
}
if gotOpts.ConfigPath != "/tmp/cfg.toml" || gotOpts.Agent != "cursor" || gotOpts.Pane != "%3" {
t.Fatalf("unexpected opts: %+v", gotOpts)
}
}
func TestRunTmuxEdit_Error(t *testing.T) {
old := runTmuxEdit
t.Cleanup(func() { runTmuxEdit = old })
wantErr := errors.New("tmux not found")
runTmuxEdit = func(_ tmuxedit.Options) error { return wantErr }
if err := runTmuxEdit(tmuxedit.Options{}); !errors.Is(err, wantErr) {
t.Fatalf("expected error, got: %v", err)
}
}
// runMain happy path: flags parse, runTmuxEdit returns nil, exit code 0.
// We capture the resolved Options to confirm flags map onto fields correctly.
func TestRunMain_FlagsForwardedToTmuxedit(t *testing.T) {
old := runTmuxEdit
t.Cleanup(func() { runTmuxEdit = old })
var got tmuxedit.Options
runTmuxEdit = func(opts tmuxedit.Options) error {
got = opts
return nil
}
var stderr bytes.Buffer
code := runMain([]string{"-config", " /tmp/cfg.toml ", "-agent", "claude", "-pane", "%9"}, &stderr)
if code != 0 {
t.Fatalf("runMain code = %d, want 0", code)
}
if got.ConfigPath != "/tmp/cfg.toml" || got.Agent != "claude" || got.Pane != "%9" {
t.Fatalf("unexpected opts: %+v", got)
}
if stderr.Len() != 0 {
t.Fatalf("stderr should be empty on success, got %q", stderr.String())
}
}
// runMain reports tmuxedit.Run failures by writing to stderr and returning 1
// — the production exit code that the shipped binary uses.
func TestRunMain_RunErrorReturnsOne(t *testing.T) {
old := runTmuxEdit
t.Cleanup(func() { runTmuxEdit = old })
runTmuxEdit = func(tmuxedit.Options) error { return errors.New("boom") }
var stderr bytes.Buffer
code := runMain(nil, &stderr)
if code != 1 {
t.Fatalf("runMain code = %d, want 1", code)
}
if !strings.Contains(stderr.String(), "boom") {
t.Fatalf("stderr missing error: %q", stderr.String())
}
}
// Unknown flags must yield exit 2 (the convention used by stdlib `flag` when
// ExitOnError aborts) without ever invoking runTmuxEdit.
func TestRunMain_BadFlagReturnsTwo(t *testing.T) {
old := runTmuxEdit
t.Cleanup(func() { runTmuxEdit = old })
called := false
runTmuxEdit = func(tmuxedit.Options) error {
called = true
return nil
}
var stderr bytes.Buffer
code := runMain([]string{"--no-such-flag"}, &stderr)
if code != 2 {
t.Fatalf("runMain code = %d, want 2", code)
}
if called {
t.Fatal("runTmuxEdit must not be called on flag-parse failure")
}
}
|