mirror of
https://github.com/chenhg5/cc-connect.git
synced 2026-07-03 12:28:10 +08:00
* feat(core): implement shared workspace routing and binding fallback * fix(core): allow shared workspace commands for users * fix(core): scope workspace bindings by platform
152 lines
5.6 KiB
Go
152 lines
5.6 KiB
Go
package core
|
|
|
|
import (
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestWorkspaceBindingManager_SaveLoad(t *testing.T) {
|
|
dir := t.TempDir()
|
|
storePath := filepath.Join(dir, "bindings.json")
|
|
channelKey := workspaceChannelKey("slack", "C123")
|
|
|
|
mgr := NewWorkspaceBindingManager(storePath)
|
|
mgr.Bind("project:claude", channelKey, "my-channel", "/home/user/workspace/my-channel")
|
|
|
|
b := mgr.Lookup("project:claude", channelKey)
|
|
if b == nil {
|
|
t.Fatal("expected binding, got nil")
|
|
}
|
|
if b.ChannelName != "my-channel" {
|
|
t.Errorf("expected channel name 'my-channel', got %q", b.ChannelName)
|
|
}
|
|
if b.Workspace != "/home/user/workspace/my-channel" {
|
|
t.Errorf("expected workspace path, got %q", b.Workspace)
|
|
}
|
|
|
|
// Reload from disk
|
|
mgr2 := NewWorkspaceBindingManager(storePath)
|
|
b2 := mgr2.Lookup("project:claude", channelKey)
|
|
if b2 == nil {
|
|
t.Fatal("expected binding after reload, got nil")
|
|
}
|
|
if b2.Workspace != "/home/user/workspace/my-channel" {
|
|
t.Errorf("expected workspace path after reload, got %q", b2.Workspace)
|
|
}
|
|
}
|
|
|
|
func TestWorkspaceBindingManager_Unbind(t *testing.T) {
|
|
dir := t.TempDir()
|
|
storePath := filepath.Join(dir, "bindings.json")
|
|
channelKey := workspaceChannelKey("slack", "C123")
|
|
|
|
mgr := NewWorkspaceBindingManager(storePath)
|
|
mgr.Bind("project:claude", channelKey, "chan", "/path")
|
|
mgr.Unbind("project:claude", channelKey)
|
|
|
|
if b := mgr.Lookup("project:claude", channelKey); b != nil {
|
|
t.Error("expected nil after unbind")
|
|
}
|
|
}
|
|
|
|
func TestWorkspaceBindingManager_ListByProject(t *testing.T) {
|
|
dir := t.TempDir()
|
|
mgr := NewWorkspaceBindingManager(filepath.Join(dir, "bindings.json"))
|
|
mgr.Bind("project:claude", workspaceChannelKey("slack", "C1"), "chan1", "/path1")
|
|
mgr.Bind("project:claude", workspaceChannelKey("slack", "C2"), "chan2", "/path2")
|
|
mgr.Bind("project:other", workspaceChannelKey("slack", "C3"), "chan3", "/path3")
|
|
|
|
list := mgr.ListByProject("project:claude")
|
|
if len(list) != 2 {
|
|
t.Errorf("expected 2 bindings, got %d", len(list))
|
|
}
|
|
}
|
|
|
|
func TestWorkspaceBindingManager_LookupEffective(t *testing.T) {
|
|
dir := t.TempDir()
|
|
mgr := NewWorkspaceBindingManager(filepath.Join(dir, "bindings.json"))
|
|
channelKey := workspaceChannelKey("slack", "C1")
|
|
|
|
mgr.Bind(sharedWorkspaceBindingsKey, channelKey, "shared-chan", "/shared")
|
|
mgr.Bind("project:claude", channelKey, "local-chan", "/local")
|
|
|
|
if b, key := mgr.LookupEffective("project:claude", channelKey); b == nil || key != "project:claude" || b.Workspace != "/local" {
|
|
t.Fatalf("expected local override, got binding=%v key=%q", b, key)
|
|
}
|
|
|
|
if b, key := mgr.LookupEffective("project:other", channelKey); b == nil || key != sharedWorkspaceBindingsKey || b.Workspace != "/shared" {
|
|
t.Fatalf("expected shared fallback, got binding=%v key=%q", b, key)
|
|
}
|
|
|
|
if b, key := mgr.LookupEffective("project:none", "missing"); b != nil || key != "" {
|
|
t.Fatalf("expected nil binding, got binding=%v key=%q", b, key)
|
|
}
|
|
}
|
|
|
|
func TestWorkspaceBindingManager_LoadSharedFromDisk(t *testing.T) {
|
|
dir := t.TempDir()
|
|
storePath := filepath.Join(dir, "bindings.json")
|
|
channelKey := workspaceChannelKey("slack", "C1")
|
|
|
|
mgr := NewWorkspaceBindingManager(storePath)
|
|
mgr.Bind(sharedWorkspaceBindingsKey, channelKey, "shared-chan", "/shared")
|
|
|
|
reloaded := NewWorkspaceBindingManager(storePath)
|
|
if b, key := reloaded.LookupEffective("project:other", channelKey); b == nil || key != sharedWorkspaceBindingsKey || b.Workspace != "/shared" {
|
|
t.Fatalf("expected shared binding after reload, got binding=%v key=%q", b, key)
|
|
}
|
|
}
|
|
|
|
func TestWorkspaceBindingManager_RefreshesExternalChanges(t *testing.T) {
|
|
dir := t.TempDir()
|
|
storePath := filepath.Join(dir, "bindings.json")
|
|
channelKey := workspaceChannelKey("slack", "C1")
|
|
|
|
mgrA := NewWorkspaceBindingManager(storePath)
|
|
mgrB := NewWorkspaceBindingManager(storePath)
|
|
|
|
mgrA.Bind(sharedWorkspaceBindingsKey, channelKey, "shared-chan", "/shared")
|
|
|
|
if b, key := mgrB.LookupEffective("project:other", channelKey); b == nil || key != sharedWorkspaceBindingsKey || b.Workspace != "/shared" {
|
|
t.Fatalf("expected shared binding from external update, got binding=%v key=%q", b, key)
|
|
}
|
|
|
|
mgrB.Bind("project:other", channelKey, "local-chan", "/local")
|
|
|
|
if b, key := mgrA.LookupEffective("project:other", channelKey); b == nil || key != "project:other" || b.Workspace != "/local" {
|
|
t.Fatalf("expected local override from external update, got binding=%v key=%q", b, key)
|
|
}
|
|
|
|
mgrA.Unbind(sharedWorkspaceBindingsKey, channelKey)
|
|
|
|
if b, key := mgrB.LookupEffective("project:none", channelKey); b != nil || key != "" {
|
|
t.Fatalf("expected shared binding removal to propagate, got binding=%v key=%q", b, key)
|
|
}
|
|
}
|
|
|
|
func TestWorkspaceBindingManager_LegacyFallbackForScopedLookup(t *testing.T) {
|
|
dir := t.TempDir()
|
|
mgr := NewWorkspaceBindingManager(filepath.Join(dir, "bindings.json"))
|
|
|
|
mgr.Bind(sharedWorkspaceBindingsKey, "C1", "legacy-chan", "/shared")
|
|
|
|
if b, key := mgr.LookupEffective("project:other", workspaceChannelKey("slack", "C1")); b == nil || key != sharedWorkspaceBindingsKey || b.Workspace != "/shared" {
|
|
t.Fatalf("expected legacy shared binding to be found by scoped lookup, got binding=%v key=%q", b, key)
|
|
}
|
|
}
|
|
|
|
func TestWorkspaceBindingManager_UnbindScopedRemovesLegacyBinding(t *testing.T) {
|
|
dir := t.TempDir()
|
|
mgr := NewWorkspaceBindingManager(filepath.Join(dir, "bindings.json"))
|
|
|
|
mgr.Bind("project:claude", "C1", "legacy-chan", "/shared")
|
|
mgr.Unbind("project:claude", workspaceChannelKey("slack", "C1"))
|
|
|
|
if b := mgr.Lookup("project:claude", workspaceChannelKey("slack", "C1")); b != nil {
|
|
t.Fatalf("expected scoped unbind to remove legacy binding, got %+v", b)
|
|
}
|
|
if b := mgr.Lookup("project:claude", "C1"); b != nil {
|
|
t.Fatalf("expected legacy binding to be removed, got %+v", b)
|
|
}
|
|
}
|