omnibox_navigation_state_test.go RawHistoryFolder
1package component
2
3import (
4 "testing"
5
6 "github.com/bnema/puregotk/v4/gdk"
7)
8
9func TestShouldPreferTypedURLNavigation(t *testing.T) {
10 tests := []struct {
11 name string
12 input string
13 want bool
14 }{
15 {name: "domain", input: "x.com", want: true},
16 {name: "domain with path", input: "github.com/bnema", want: true},
17 {name: "http url", input: "http://example.com", want: true},
18 {name: "localhost", input: "localhost", want: true},
19 {name: "ipv4", input: "127.0.0.1", want: true},
20 {name: "ipv4 with port", input: "192.168.1.1:8080", want: true},
21 {name: "ipv6 bracketed", input: "[::1]", want: true},
22 {name: "http ipv6 bracketed", input: "http://[::1]", want: true},
23 {name: "search query", input: "hello world", want: false},
24 {name: "empty", input: "", want: false},
25 }
26
27 for _, tt := range tests {
28 t.Run(tt.name, func(t *testing.T) {
29 if got := shouldPreferTypedURLNavigation(tt.input); got != tt.want {
30 t.Fatalf("shouldPreferTypedURLNavigation(%q) = %v, want %v", tt.input, got, tt.want)
31 }
32 })
33 }
34}
35
36func TestResetSearchSessionState(t *testing.T) {
37 o := &Omnibox{}
38 o.lastQuery = "github"
39
40 o.resetSearchSessionState()
41
42 if o.lastQuery != "" {
43 t.Fatalf("lastQuery should be reset, got %q", o.lastQuery)
44 }
45}
46
47func TestIsDeletionKey(t *testing.T) {
48 tests := []struct {
49 name string
50 key uint
51 want bool
52 }{
53 {name: "backspace is deletion", key: uint(gdk.KEY_BackSpace), want: true},
54 {name: "delete is deletion", key: uint(gdk.KEY_Delete), want: true},
55 {name: "typing key is not deletion", key: uint(gdk.KEY_g), want: false},
56 {name: "arrow key is not deletion", key: uint(gdk.KEY_Left), want: false},
57 }
58
59 for _, tt := range tests {
60 t.Run(tt.name, func(t *testing.T) {
61 if got := isDeletionKey(tt.key); got != tt.want {
62 t.Fatalf("isDeletionKey(%d) = %v, want %v", tt.key, got, tt.want)
63 }
64 })
65 }
66}
67
68func TestEffectiveSearchQuery(t *testing.T) {
69 tests := []struct {
70 name string
71 entryText string
72 realInput string
73 hasGhost bool
74 want string
75 }{
76 {name: "uses typed input when ghost visible", entryText: "dumber.bnema.dev", realInput: "dumb", hasGhost: true, want: "dumb"},
77 {name: "falls back to entry when no ghost", entryText: "dumb", realInput: "dumb", hasGhost: false, want: "dumb"},
78 {name: "uses entry when real input unavailable", entryText: "dumb", realInput: "", hasGhost: true, want: "dumb"},
79 }
80
81 for _, tt := range tests {
82 t.Run(tt.name, func(t *testing.T) {
83 if got := effectiveSearchQuery(tt.entryText, tt.realInput, tt.hasGhost); got != tt.want {
84 t.Fatalf("effectiveSearchQuery(%q, %q, %v) = %q, want %q", tt.entryText, tt.realInput, tt.hasGhost, got, tt.want)
85 }
86 })
87 }
88}
89
90func TestUpdateGhostFromSelectionUsesRealInputWhenGhostVisible(t *testing.T) {
91 entryText := "github.com/bnema/dumber"
92 realInput := "upl"
93
94 got := effectiveSearchQuery(entryText, realInput, true)
95 if got != realInput {
96 t.Fatalf("effectiveSearchQuery should prefer real input when ghost is visible, got %q want %q", got, realInput)
97 }
98}
99
100func TestResolveTargetURLForSelection(t *testing.T) {
101 suggestions := []Suggestion{
102 {URL: "https://github.com/bnema/dumber"},
103 {URL: "https://github.com/bnema/dumber/pulls"},
104 }
105 favorites := []Favorite{
106 {URL: "https://dumber.bnema.dev"},
107 }
108
109 tests := []struct {
110 name string
111 mode ViewMode
112 index int
113 wantURL string
114 }{
115 {name: "history index", mode: ViewModeHistory, index: 1, wantURL: "https://github.com/bnema/dumber/pulls"},
116 {name: "favorites index", mode: ViewModeFavorites, index: 0, wantURL: "https://dumber.bnema.dev"},
117 {name: "invalid index", mode: ViewModeHistory, index: 99, wantURL: ""},
118 }
119
120 for _, tt := range tests {
121 t.Run(tt.name, func(t *testing.T) {
122 got := resolveTargetURLForSelection(tt.mode, tt.index, suggestions, favorites)
123 if got != tt.wantURL {
124 t.Fatalf("resolveTargetURLForSelection(%s, %d) = %q, want %q", tt.mode, tt.index, got, tt.wantURL)
125 }
126 })
127 }
128}
129
130func TestSelectedTargetURL(t *testing.T) {
131 suggestions := []Suggestion{
132 {URL: "https://github.com/bnema/dumber"},
133 }
134 favorites := []Favorite{
135 {URL: "https://dumber.bnema.dev"},
136 }
137
138 tests := []struct {
139 name string
140 mode ViewMode
141 index int
142 wantURL string
143 wantBool bool
144 }{
145 {name: "negative index is not explicit selection", mode: ViewModeHistory, index: -1, wantURL: "", wantBool: false},
146 {name: "history selection is explicit", mode: ViewModeHistory, index: 0, wantURL: "https://github.com/bnema/dumber", wantBool: true},
147 {name: "favorites selection is explicit", mode: ViewModeFavorites, index: 0, wantURL: "https://dumber.bnema.dev", wantBool: true},
148 }
149
150 for _, tt := range tests {
151 t.Run(tt.name, func(t *testing.T) {
152 gotURL, gotBool := selectedTargetURL(tt.mode, tt.index, suggestions, favorites)
153 if gotURL != tt.wantURL || gotBool != tt.wantBool {
154 t.Fatalf("selectedTargetURL(%s, %d) = (%q, %v), want (%q, %v)", tt.mode, tt.index, gotURL, gotBool, tt.wantURL, tt.wantBool)
155 }
156 })
157 }
158}
159
160func TestVisibleGhostSuggestion(t *testing.T) {
161 suggestions := []Suggestion{
162 {URL: "https://github.com/bnema/dumber"},
163 {URL: "https://gitlab.com/team/project"},
164 }
165
166 tests := []struct {
167 name string
168 input string
169 selectedURL string
170 hasExplicitSelection bool
171 wantFull string
172 wantSuffix string
173 wantOK bool
174 }{
175 {
176 name: "top visible candidate drives ghost without selection",
177 input: "git",
178 wantFull: "github.com",
179 wantSuffix: "hub.com",
180 wantOK: true,
181 },
182 {
183 name: "explicit selection wins over top candidate",
184 input: "git",
185 selectedURL: "https://gitlab.com/team/project",
186 hasExplicitSelection: true,
187 wantFull: "gitlab.com/team/project",
188 wantSuffix: "lab.com/team/project",
189 wantOK: true,
190 },
191 {
192 name: "no visible prefix match means no ghost",
193 input: "xyz",
194 wantFull: "",
195 wantSuffix: "",
196 wantOK: false,
197 },
198 }
199
200 for _, tt := range tests {
201 t.Run(tt.name, func(t *testing.T) {
202 gotFull, gotSuffix, gotOK := visibleGhostSuggestion(
203 tt.input,
204 tt.selectedURL,
205 tt.hasExplicitSelection,
206 ViewModeHistory,
207 suggestions,
208 nil,
209 )
210 if gotFull != tt.wantFull || gotSuffix != tt.wantSuffix || gotOK != tt.wantOK {
211 t.Fatalf(
212 "visibleGhostSuggestion(%q) = (%q, %q, %v), want (%q, %q, %v)",
213 tt.input,
214 gotFull,
215 gotSuffix,
216 gotOK,
217 tt.wantFull,
218 tt.wantSuffix,
219 tt.wantOK,
220 )
221 }
222 })
223 }
224}
225
226func TestShouldPromoteHoverSelection(t *testing.T) {
227 tests := []struct {
228 name string
229 realInput string
230 hasGhostText bool
231 hasNavigated bool
232 want bool
233 }{
234 {
235 name: "initial open allows hover selection",
236 want: true,
237 },
238 {
239 name: "typed input keeps hover from stealing authority",
240 realInput: "git",
241 want: false,
242 },
243 {
244 name: "visible ghost keeps hover from stealing authority",
245 hasGhostText: true,
246 want: false,
247 },
248 {
249 name: "keyboard navigation keeps hover from stealing authority",
250 hasNavigated: true,
251 want: false,
252 },
253 }
254
255 for _, tt := range tests {
256 t.Run(tt.name, func(t *testing.T) {
257 got := shouldPromoteHoverSelection(tt.realInput, tt.hasGhostText, tt.hasNavigated)
258 if got != tt.want {
259 t.Fatalf(
260 "shouldPromoteHoverSelection(%q, %v, %v) = %v, want %v",
261 tt.realInput,
262 tt.hasGhostText,
263 tt.hasNavigated,
264 got,
265 tt.want,
266 )
267 }
268 })
269 }
270}