package main import ( "testing" "time" ) var i3barTestNow = time.Date(2026, 3, 24, 12, 0, 0, 0, time.UTC) func TestFormatI3BarBlocks_MixedStates(t *testing.T) { waiting := i3barTestNow.Add(-3 * time.Minute) sessions := []SessionInfo{ {Cwd: "/home/pierre/Code/auth", Workspace: "3", State: "Needs Input", WaitType: "question", WaitingSince: &waiting}, {Cwd: "/home/pierre/Code/portal", Workspace: "2", State: "Working"}, {Cwd: "/home/pierre/Code/neia", Workspace: "5", State: "Idle"}, } blocks := formatI3BarBlocks(sessions, i3barTestNow) if len(blocks) != 3 { t.Fatalf("expected 3 blocks, got %d", len(blocks)) } if blocks[0].FullText != "3-auth[? 3m]" || blocks[0].Color != "#ff0000" { t.Errorf("block 0: %q %q", blocks[0].FullText, blocks[0].Color) } if blocks[1].FullText != "2-portal[W]" || blocks[1].Color != "#00ff00" { t.Errorf("block 1: %q %q", blocks[1].FullText, blocks[1].Color) } if blocks[2].FullText != "5-neia[I]" || blocks[2].Color != "#888888" { t.Errorf("block 2: %q %q", blocks[2].FullText, blocks[2].Color) } } func TestFormatI3BarBlocks_PermissionMarker(t *testing.T) { waiting := i3barTestNow.Add(-30 * time.Second) sessions := []SessionInfo{ {Cwd: "/a/proj", Workspace: "1", State: "Needs Input", WaitType: "permission", WaitingSince: &waiting}, } blocks := formatI3BarBlocks(sessions, i3barTestNow) if blocks[0].FullText != "1-proj[⚡ 30s]" { t.Errorf("full_text = %q, want %q", blocks[0].FullText, "1-proj[⚡ 30s]") } } func TestFormatI3BarBlocks_NeedsInputNoWaitType(t *testing.T) { sessions := []SessionInfo{ {Cwd: "/a/proj", State: "Needs Input"}, } blocks := formatI3BarBlocks(sessions, i3barTestNow) if blocks[0].FullText != "proj[!]" { t.Errorf("full_text = %q, want %q", blocks[0].FullText, "proj[!]") } } func TestFormatI3BarBlocks_AllWorking(t *testing.T) { sessions := []SessionInfo{ {Cwd: "/a/b/one", State: "Working"}, {Cwd: "/a/b/two", State: "Working"}, } blocks := formatI3BarBlocks(sessions, i3barTestNow) if len(blocks) != 2 { t.Fatalf("expected 2 blocks, got %d", len(blocks)) } if blocks[0].FullText != "one[W]" || blocks[0].Color != "#00ff00" { t.Errorf("block 0: %q %q", blocks[0].FullText, blocks[0].Color) } } func TestFormatI3BarBlocks_NoSessions(t *testing.T) { blocks := formatI3BarBlocks(nil, i3barTestNow) if len(blocks) != 1 || blocks[0].FullText != "vmux: no sessions" { t.Errorf("full_text = %q", blocks[0].FullText) } } func TestFormatI3BarBlocks_PerSessionColor(t *testing.T) { sessions := []SessionInfo{ {Cwd: "/a/x", State: "Working"}, {Cwd: "/a/y", State: "Needs Input"}, {Cwd: "/a/z", State: "Idle"}, } blocks := formatI3BarBlocks(sessions, i3barTestNow) if blocks[0].Color != "#00ff00" { t.Errorf("Working color = %q, want #00ff00", blocks[0].Color) } if blocks[1].Color != "#ff0000" { t.Errorf("Needs Input color = %q, want #ff0000", blocks[1].Color) } if blocks[2].Color != "#888888" { t.Errorf("Idle color = %q, want #888888", blocks[2].Color) } } func TestFormatI3BarBlocks_UsesLabel(t *testing.T) { sessions := []SessionInfo{ {Cwd: "/home/pierre/Code/auth-service", Label: "auth", State: "Working"}, } blocks := formatI3BarBlocks(sessions, i3barTestNow) if blocks[0].FullText != "auth[W]" { t.Errorf("full_text = %q, want %q", blocks[0].FullText, "auth[W]") } } func TestFormatI3BarBlocks_WorkspacePrefix(t *testing.T) { sessions := []SessionInfo{ {Cwd: "/home/pierre/Code/vibe/vmux", Workspace: "10", State: "Working"}, } blocks := formatI3BarBlocks(sessions, i3barTestNow) if blocks[0].FullText != "10-vmux[W]" { t.Errorf("full_text = %q, want %q", blocks[0].FullText, "10-vmux[W]") } } func TestFormatI3BarBlocks_LongWaitDuration(t *testing.T) { waiting := i3barTestNow.Add(-75 * time.Minute) sessions := []SessionInfo{ {Cwd: "/a/proj", Workspace: "2", State: "Needs Input", WaitType: "question", WaitingSince: &waiting}, } blocks := formatI3BarBlocks(sessions, i3barTestNow) if blocks[0].FullText != "2-proj[? 1h15m]" { t.Errorf("full_text = %q, want %q", blocks[0].FullText, "2-proj[? 1h15m]") } } func TestShortDuration(t *testing.T) { tests := []struct { d time.Duration want string }{ {10 * time.Second, "10s"}, {59 * time.Second, "59s"}, {1 * time.Minute, "1m"}, {5 * time.Minute, "5m"}, {65 * time.Minute, "1h5m"}, {120 * time.Minute, "2h0m"}, } for _, tt := range tests { got := shortDuration(tt.d) if got != tt.want { t.Errorf("shortDuration(%v) = %q, want %q", tt.d, got, tt.want) } } } func TestWaitTypeMarker(t *testing.T) { if waitTypeMarker("permission") != "⚡" { t.Error("permission should be ⚡") } if waitTypeMarker("question") != "?" { t.Error("question should be ?") } if waitTypeMarker("") != "!" { t.Error("empty should be !") } }