diff --git a/i3bridge.go b/i3bridge.go new file mode 100644 index 0000000..dedb9fc --- /dev/null +++ b/i3bridge.go @@ -0,0 +1,21 @@ +package main + +import ( + i3 "go.i3wm.org/i3/v4" +) + +// I3Commander abstrait i3.RunCommand pour testabilite. +type I3Commander interface { + RunCommand(command string) ([]i3.CommandResult, error) +} + +// FuzzyMatch trouve la premiere session matchant query dans : label > branche > cwd. +// Case-insensitive. Retourne nil si aucun match. +func FuzzyMatch(query string, sessions []SessionInfo) *SessionInfo { + return nil +} + +// SwitchToWorkspace bascule vers le workspace indique via i3 IPC. +func SwitchToWorkspace(commander I3Commander, wsName string) error { + return nil +} diff --git a/i3bridge_test.go b/i3bridge_test.go new file mode 100644 index 0000000..3e8f7d6 --- /dev/null +++ b/i3bridge_test.go @@ -0,0 +1,147 @@ +package main + +import ( + "fmt" + "testing" + + i3 "go.i3wm.org/i3/v4" +) + +// --- Mock types --- + +type mockI3Commander struct { + lastCommand string + results []i3.CommandResult + err error +} + +func (m *mockI3Commander) RunCommand(command string) ([]i3.CommandResult, error) { + m.lastCommand = command + return m.results, m.err +} + +// --- FuzzyMatch tests --- + +func TestFuzzyMatchByLabel(t *testing.T) { + sessions := []SessionInfo{ + {SessionID: "s1", Label: "review MR !456", GitBranch: "main", Cwd: "/home/user/project"}, + {SessionID: "s2", Label: "auth work", GitBranch: "feat/other", Cwd: "/home/user/other"}, + } + + result := FuzzyMatch("review", sessions) + if result == nil { + t.Fatal("expected match, got nil") + } + if result.SessionID != "s1" { + t.Errorf("FuzzyMatch = session %q, want %q", result.SessionID, "s1") + } +} + +func TestFuzzyMatchByBranch(t *testing.T) { + sessions := []SessionInfo{ + {SessionID: "s1", Label: "", GitBranch: "feat/auth-flow", Cwd: "/home/user/project"}, + {SessionID: "s2", Label: "", GitBranch: "main", Cwd: "/home/user/other"}, + } + + result := FuzzyMatch("auth", sessions) + if result == nil { + t.Fatal("expected match, got nil") + } + if result.SessionID != "s1" { + t.Errorf("FuzzyMatch = session %q, want %q", result.SessionID, "s1") + } +} + +func TestFuzzyMatchByCwd(t *testing.T) { + sessions := []SessionInfo{ + {SessionID: "s1", Label: "", GitBranch: "main", Cwd: "/home/pierre/Code/vibe/vmux"}, + {SessionID: "s2", Label: "", GitBranch: "main", Cwd: "/home/pierre/Code/other"}, + } + + result := FuzzyMatch("vmux", sessions) + if result == nil { + t.Fatal("expected match, got nil") + } + if result.SessionID != "s1" { + t.Errorf("FuzzyMatch = session %q, want %q", result.SessionID, "s1") + } +} + +func TestFuzzyMatchPriority(t *testing.T) { + // Label match should win over branch match + sessions := []SessionInfo{ + {SessionID: "s1", Label: "auth", GitBranch: "main", Cwd: "/home/user/project"}, + {SessionID: "s2", Label: "", GitBranch: "auth", Cwd: "/home/user/other"}, + } + + result := FuzzyMatch("auth", sessions) + if result == nil { + t.Fatal("expected match, got nil") + } + if result.SessionID != "s1" { + t.Errorf("FuzzyMatch = session %q, want %q (label should win over branch)", result.SessionID, "s1") + } +} + +func TestFuzzyMatchNoResult(t *testing.T) { + sessions := []SessionInfo{ + {SessionID: "s1", Label: "review", GitBranch: "main", Cwd: "/home/user/project"}, + } + + result := FuzzyMatch("inexistant", sessions) + if result != nil { + t.Errorf("expected nil, got session %q", result.SessionID) + } +} + +func TestFuzzyMatchCaseInsensitive(t *testing.T) { + sessions := []SessionInfo{ + {SessionID: "s1", Label: "", GitBranch: "feat/auth-flow", Cwd: "/home/user/project"}, + } + + result := FuzzyMatch("AUTH", sessions) + if result == nil { + t.Fatal("expected case-insensitive match, got nil") + } + if result.SessionID != "s1" { + t.Errorf("FuzzyMatch = session %q, want %q", result.SessionID, "s1") + } +} + +// --- SwitchToWorkspace tests --- + +func TestSwitchToWorkspace(t *testing.T) { + mock := &mockI3Commander{ + results: []i3.CommandResult{{Success: true}}, + } + + err := SwitchToWorkspace(mock, "3") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if mock.lastCommand != "workspace number 3" { + t.Errorf("command = %q, want %q", mock.lastCommand, "workspace number 3") + } +} + +func TestSwitchToWorkspaceError(t *testing.T) { + mock := &mockI3Commander{ + results: []i3.CommandResult{{Success: false, Error: "no such workspace"}}, + } + + err := SwitchToWorkspace(mock, "99") + if err == nil { + t.Fatal("expected error, got nil") + } +} + +func TestSwitchToWorkspaceI3Error(t *testing.T) { + mock := &mockI3Commander{ + err: fmt.Errorf("i3 connection lost"), + } + + err := SwitchToWorkspace(mock, "1") + if err == nil { + t.Fatal("expected error, got nil") + } +}