feat(02-03): main.go subcommands + display enrichi avec workspace, label, duree
- main.go dispatch list/switch/label/stop/daemon via client socket - DisplaySessionInfos affiche [ws:N], label entre guillemets, "depuis X min" - formatDuration pour duree relative humaine (< 1 min, 3 min, 1 h 5 min) - Daemon mode integre i3 + X11 avec degradation gracieuse - Tests complets pour tous les champs optionnels du display
This commit is contained in:
178
display_test.go
178
display_test.go
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDisplaySessions_WithSessions(t *testing.T) {
|
||||
@@ -113,3 +114,180 @@ func TestDisplaySessions_NoBranch(t *testing.T) {
|
||||
t.Errorf("no branch should mean no parentheses: %q", output)
|
||||
}
|
||||
}
|
||||
|
||||
// --- DisplaySessionInfos tests ---
|
||||
|
||||
func TestDisplayWithWorkspace(t *testing.T) {
|
||||
sessions := []SessionInfo{
|
||||
{
|
||||
PID: 100,
|
||||
SessionID: "sess-1",
|
||||
Cwd: "/home/pierre/Code/vibe/vmux",
|
||||
GitBranch: "feat-auth",
|
||||
State: "Working",
|
||||
Workspace: "3",
|
||||
},
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
DisplaySessionInfos(&buf, sessions, true, time.Now())
|
||||
output := buf.String()
|
||||
|
||||
if !strings.Contains(output, "[ws:3]") {
|
||||
t.Errorf("output should contain [ws:3]: %q", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisplayWithLabel(t *testing.T) {
|
||||
sessions := []SessionInfo{
|
||||
{
|
||||
PID: 100,
|
||||
SessionID: "sess-1",
|
||||
Cwd: "/home/user/project",
|
||||
State: "Working",
|
||||
Label: "review MR",
|
||||
},
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
DisplaySessionInfos(&buf, sessions, true, time.Now())
|
||||
output := buf.String()
|
||||
|
||||
if !strings.Contains(output, `"review MR"`) {
|
||||
t.Errorf("output should contain quoted label: %q", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisplayWithWaitingSince(t *testing.T) {
|
||||
threeMinAgo := time.Now().Add(-3 * time.Minute)
|
||||
sessions := []SessionInfo{
|
||||
{
|
||||
PID: 100,
|
||||
SessionID: "sess-1",
|
||||
Cwd: "/home/user/project",
|
||||
State: "Needs Input",
|
||||
WaitingSince: &threeMinAgo,
|
||||
},
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
now := time.Now()
|
||||
DisplaySessionInfos(&buf, sessions, true, now)
|
||||
output := buf.String()
|
||||
|
||||
if !strings.Contains(output, "depuis 3 min") {
|
||||
t.Errorf("output should contain waiting duration: %q", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisplayWithoutOptionalFields(t *testing.T) {
|
||||
sessions := []SessionInfo{
|
||||
{
|
||||
PID: 100,
|
||||
SessionID: "sess-1",
|
||||
Cwd: "/home/user/project",
|
||||
State: "Working",
|
||||
},
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
DisplaySessionInfos(&buf, sessions, true, time.Now())
|
||||
output := buf.String()
|
||||
|
||||
if strings.Contains(output, "[ws:") {
|
||||
t.Errorf("should not show workspace when empty: %q", output)
|
||||
}
|
||||
if strings.Contains(output, `"`) {
|
||||
t.Errorf("should not show quotes when no label: %q", output)
|
||||
}
|
||||
if strings.Contains(output, "depuis") {
|
||||
t.Errorf("should not show waiting when nil: %q", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisplaySessionInfosEmpty(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
DisplaySessionInfos(&buf, nil, false, time.Now())
|
||||
output := buf.String()
|
||||
|
||||
want := "No active Claude Code sessions found.\n"
|
||||
if output != want {
|
||||
t.Errorf("output = %q, want %q", output, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisplayWithPreview(t *testing.T) {
|
||||
sessions := []SessionInfo{
|
||||
{
|
||||
PID: 100,
|
||||
SessionID: "sess-1",
|
||||
Cwd: "/home/user/project",
|
||||
State: "Needs Input",
|
||||
Preview: "What should I do?",
|
||||
},
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
DisplaySessionInfos(&buf, sessions, true, time.Now())
|
||||
output := buf.String()
|
||||
|
||||
if !strings.Contains(output, "What should I do?") {
|
||||
t.Errorf("output should contain preview: %q", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatDuration(t *testing.T) {
|
||||
tests := []struct {
|
||||
d time.Duration
|
||||
want string
|
||||
}{
|
||||
{30 * time.Second, "< 1 min"},
|
||||
{3 * time.Minute, "3 min"},
|
||||
{65 * time.Minute, "1 h 5 min"},
|
||||
{2 * time.Hour, "2 h"},
|
||||
{2*time.Hour + 30*time.Minute, "2 h 30 min"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := formatDuration(tt.d)
|
||||
if got != tt.want {
|
||||
t.Errorf("formatDuration(%v) = %q, want %q", tt.d, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisplayFullLine(t *testing.T) {
|
||||
threeMinAgo := time.Now().Add(-3 * time.Minute)
|
||||
sessions := []SessionInfo{
|
||||
{
|
||||
PID: 100,
|
||||
SessionID: "sess-1",
|
||||
Cwd: "/home/pierre/Code/vibe/vmux",
|
||||
GitBranch: "feat/auth",
|
||||
State: "Needs Input",
|
||||
Workspace: "3",
|
||||
Label: "review MR !456",
|
||||
WaitingSince: &threeMinAgo,
|
||||
Preview: "preview line 1\npreview line 2",
|
||||
},
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
DisplaySessionInfos(&buf, sessions, true, time.Now())
|
||||
output := buf.String()
|
||||
|
||||
for _, want := range []string{
|
||||
"[Needs Input]",
|
||||
"/home/pierre/Code/vibe/vmux",
|
||||
"(feat/auth)",
|
||||
"[ws:3]",
|
||||
`"review MR !456"`,
|
||||
"(depuis 3 min)",
|
||||
"preview line 1",
|
||||
"preview line 2",
|
||||
} {
|
||||
if !strings.Contains(output, want) {
|
||||
t.Errorf("output missing %q in: %q", want, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user