1package domain
2
3import "testing"
4
5func TestOrdinalTabSelectorPreservesUnnamedTabs(t *testing.T) {
6 tests := []struct {
7 name string
8 selector TabSelector
9 tabs []TabSelectorTab
10 want int
11 }{
12 {name: "unnamed middle tab", selector: NewOrdinalTabSelector(1, "", 3), tabs: []TabSelectorTab{{Name: "first"}, {Name: ""}, {Name: "trailing"}}, want: 1},
13 }
14 for _, test := range tests {
15 t.Run(test.name, func(t *testing.T) {
16 index, ok := test.selector.Resolve(test.tabs)
17 if !ok || index != test.want {
18 t.Fatalf("Resolve() = %d, %t, want %d, true", index, ok, test.want)
19 }
20 })
21 }
22}
23
24func TestRemoteSessionTargetResolveTab(t *testing.T) {
25 base := RemoteSessionTarget{Endpoint: "host", DisplayOrigin: "host", LifecycleID: SessionLifecycleID{1}, SessionName: "work"}
26 tests := []struct {
27 name string
28 target RemoteSessionTarget
29 tabs []TabSelectorTab
30 want int
31 ok bool
32 }{
33 {name: "down without metadata", target: RemoteSessionTarget{Endpoint: base.Endpoint, DisplayOrigin: base.DisplayOrigin, LifecycleID: base.LifecycleID, SessionName: base.SessionName, Stopped: true}, ok: true},
34 {name: "down fresh default tab", target: RemoteSessionTarget{Endpoint: base.Endpoint, DisplayOrigin: base.DisplayOrigin, LifecycleID: base.LifecycleID, SessionName: base.SessionName, Stopped: true}, tabs: []TabSelectorTab{{ID: "fresh"}}, ok: true},
35 {name: "down without selector rejects ambiguity", target: RemoteSessionTarget{Endpoint: base.Endpoint, DisplayOrigin: base.DisplayOrigin, LifecycleID: base.LifecycleID, SessionName: base.SessionName, Stopped: true}, tabs: []TabSelectorTab{{ID: "one"}, {ID: "two"}}},
36 {name: "down stable selector", target: RemoteSessionTarget{Endpoint: base.Endpoint, DisplayOrigin: base.DisplayOrigin, LifecycleID: base.LifecycleID, SessionName: base.SessionName, Stopped: true, StoppedTab: NewStableTabSelector("two")}, tabs: []TabSelectorTab{{ID: "one"}, {ID: "two"}}, want: 1, ok: true},
37 {name: "down invalid selector", target: RemoteSessionTarget{Endpoint: base.Endpoint, DisplayOrigin: base.DisplayOrigin, LifecycleID: base.LifecycleID, SessionName: base.SessionName, Stopped: true, StoppedTab: TabSelector{Kind: TabSelectorByStableID, Ordinal: 1}}, tabs: []TabSelectorTab{{ID: "one"}}},
38 {name: "live stable tab", target: RemoteSessionTarget{Endpoint: base.Endpoint, DisplayOrigin: base.DisplayOrigin, LifecycleID: base.LifecycleID, SessionName: base.SessionName, LiveTabID: "two"}, tabs: []TabSelectorTab{{ID: "one"}, {ID: "two"}}, want: 1, ok: true},
39 {name: "live missing tab", target: RemoteSessionTarget{Endpoint: base.Endpoint, DisplayOrigin: base.DisplayOrigin, LifecycleID: base.LifecycleID, SessionName: base.SessionName, LiveTabID: "missing"}, tabs: []TabSelectorTab{{ID: "one"}, {ID: "two"}}, want: -1},
40 {name: "live duplicate tab rejected", target: RemoteSessionTarget{Endpoint: base.Endpoint, DisplayOrigin: base.DisplayOrigin, LifecycleID: base.LifecycleID, SessionName: base.SessionName, LiveTabID: "two"}, tabs: []TabSelectorTab{{ID: "two"}, {ID: "two"}}},
41 }
42 for _, test := range tests {
43 t.Run(test.name, func(t *testing.T) {
44 got, ok := test.target.ResolveTab(test.tabs)
45 if got != test.want || ok != test.ok {
46 t.Fatalf("ResolveTab() = %d, %t, want %d, %t", got, ok, test.want, test.ok)
47 }
48 })
49 }
50}
51
52func TestValidateTabStableIDRejectsUnsafeIdentity(t *testing.T) {
53 tests := []struct {
54 name string
55 id TabStableID
56 }{
57 {name: "empty", id: ""},
58 {name: "space", id: "tab id"},
59 {name: "newline", id: "tab\n1"},
60 }
61 for _, test := range tests {
62 t.Run(test.name, func(t *testing.T) {
63 if err := ValidateTabStableID(test.id); err == nil {
64 t.Fatalf("ValidateTabStableID(%q) = nil, want error", test.id)
65 }
66 })
67 }
68}