navigation_webview_targeted_test.go RawHistoryFolder
1package coordinator
2
3import (
4 "context"
5 "testing"
6
7 "github.com/bnema/dumber/internal/application/port"
8 "github.com/bnema/dumber/internal/application/port/mocks"
9 "github.com/bnema/dumber/internal/application/usecase"
10 "github.com/bnema/dumber/internal/domain/entity"
11)
12
13type mockScrollableWebView struct {
14 *mocks.MockWebView
15 *mocks.MockPageScrollable
16}
17
18type mockDevToolsWebView struct {
19 *mocks.MockWebView
20 *mocks.MockDevToolsOpener
21}
22
23type mockPrinterWebView struct {
24 *mocks.MockWebView
25 *mocks.MockPrinter
26}
27
28// TestNavigationCoordinator_WebViewTargetedActionsUseProvidedWebView verifies that
29// the explicit WebView-targeted navigation methods call the correct methods on the
30// provided WebView rather than resolving through the content coordinator.
31func TestNavigationCoordinator_WebViewTargetedActionsUseProvidedWebView(t *testing.T) {
32 ctx := context.Background()
33
34 t.Run("NavigateWebView with nil webview returns error", func(t *testing.T) {
35 testNavigateWebViewNilWebView(t, ctx)
36 })
37 t.Run("NavigateWebView targets provided webview", func(t *testing.T) {
38 testNavigateWebViewTargetsProvidedWebView(t, ctx)
39 })
40 t.Run("ReloadWebView with nil webview returns error", func(t *testing.T) {
41 testReloadWebViewNilWebView(t, ctx)
42 })
43 t.Run("ReloadWebView bypassCache=false calls Reload once", func(t *testing.T) {
44 testReloadWebViewCallsReload(t, ctx)
45 })
46 t.Run("ReloadWebView bypassCache=true calls ReloadBypassCache once", func(t *testing.T) {
47 testReloadWebViewCallsReloadBypassCache(t, ctx)
48 })
49 t.Run("StopWebView with nil webview returns error", func(t *testing.T) {
50 testStopWebViewNilWebView(t, ctx)
51 })
52 t.Run("StopWebView calls Stop once", func(t *testing.T) {
53 testStopWebViewCallsStop(t, ctx)
54 })
55 t.Run("GoBackWebView with nil webview returns error", func(t *testing.T) {
56 testGoBackWebViewNilWebView(t, ctx)
57 })
58 t.Run("GoBackWebView calls GoBack once", func(t *testing.T) {
59 testGoBackWebViewCallsGoBack(t, ctx)
60 })
61 t.Run("GoForwardWebView with nil webview returns error", func(t *testing.T) {
62 testGoForwardWebViewNilWebView(t, ctx)
63 })
64 t.Run("GoForwardWebView calls GoForward once", func(t *testing.T) {
65 testGoForwardWebViewCallsGoForward(t, ctx)
66 })
67 t.Run("OpenDevToolsWebView with nil webview returns error", func(t *testing.T) {
68 testOpenDevToolsWebViewNilWebView(t, ctx)
69 })
70 t.Run("OpenDevToolsWebView unsupported capability returns error", func(t *testing.T) {
71 testOpenDevToolsWebViewUnsupportedCapability(t, ctx)
72 })
73 t.Run("OpenDevToolsWebView calls OpenDevTools once", func(t *testing.T) {
74 testOpenDevToolsWebViewTargetsProvidedWebView(t, ctx)
75 })
76 t.Run("PrintWebView with nil webview returns error", func(t *testing.T) {
77 testPrintWebViewNilWebView(t, ctx)
78 })
79 t.Run("PrintWebView unsupported capability returns error", func(t *testing.T) {
80 testPrintWebViewUnsupportedCapability(t, ctx)
81 })
82 t.Run("PrintWebView calls PrintPage once", func(t *testing.T) {
83 testPrintWebViewTargetsProvidedWebView(t, ctx)
84 })
85 t.Run("ScrollWebView with nil webview returns error", func(t *testing.T) {
86 testScrollWebViewNilWebView(t, ctx)
87 })
88 t.Run("ScrollWebView delegates each scroll command through usecase", func(t *testing.T) {
89 testScrollWebViewDelegatesEachCommand(t, ctx)
90 })
91 t.Run("ScrollWebView usecase not set returns error", func(t *testing.T) {
92 testScrollWebViewUsecaseNotSet(t, ctx)
93 })
94}
95
96func testNavigateWebViewNilWebView(t *testing.T, ctx context.Context) {
97 t.Helper()
98 c := &NavigationCoordinator{}
99 err := c.NavigateWebView(ctx, "https://example.com", entity.PaneID("p1"), nil)
100 if err == nil {
101 t.Fatal("expected error for nil webview, got nil")
102 }
103}
104
105func testNavigateWebViewTargetsProvidedWebView(t *testing.T, ctx context.Context) {
106 t.Helper()
107 wv := mocks.NewMockWebView(t)
108 wv.EXPECT().LoadURI(ctx, "https://example.com").Return(nil).Once()
109 wv.EXPECT().ID().Return(port.WebViewID(42)).Once()
110 c := &NavigationCoordinator{}
111 err := c.NavigateWebView(ctx, "https://example.com", entity.PaneID("p1"), wv)
112 if err != nil {
113 t.Fatalf("unexpected error: %v", err)
114 }
115}
116
117func testReloadWebViewNilWebView(t *testing.T, ctx context.Context) {
118 t.Helper()
119 c := &NavigationCoordinator{}
120 err := c.ReloadWebView(ctx, nil, false)
121 if err == nil {
122 t.Fatal("expected error for nil webview, got nil")
123 }
124}
125
126func testReloadWebViewCallsReload(t *testing.T, ctx context.Context) {
127 t.Helper()
128 wv := mocks.NewMockWebView(t)
129 wv.EXPECT().ID().Return(port.WebViewID(1)).Once()
130 wv.EXPECT().Reload(ctx).Return(nil).Once()
131 c := &NavigationCoordinator{}
132 err := c.ReloadWebView(ctx, wv, false)
133 if err != nil {
134 t.Fatalf("unexpected error: %v", err)
135 }
136}
137
138func testReloadWebViewCallsReloadBypassCache(t *testing.T, ctx context.Context) {
139 t.Helper()
140 wv := mocks.NewMockWebView(t)
141 wv.EXPECT().ID().Return(port.WebViewID(1)).Once()
142 wv.EXPECT().ReloadBypassCache(ctx).Return(nil).Once()
143 c := &NavigationCoordinator{}
144 err := c.ReloadWebView(ctx, wv, true)
145 if err != nil {
146 t.Fatalf("unexpected error: %v", err)
147 }
148}
149
150func testStopWebViewNilWebView(t *testing.T, ctx context.Context) {
151 t.Helper()
152 c := &NavigationCoordinator{}
153 err := c.StopWebView(ctx, nil)
154 if err == nil {
155 t.Fatal("expected error for nil webview, got nil")
156 }
157}
158
159func testStopWebViewCallsStop(t *testing.T, ctx context.Context) {
160 t.Helper()
161 wv := mocks.NewMockWebView(t)
162 wv.EXPECT().ID().Return(port.WebViewID(1)).Once()
163 wv.EXPECT().Stop(ctx).Return(nil).Once()
164 c := &NavigationCoordinator{}
165 err := c.StopWebView(ctx, wv)
166 if err != nil {
167 t.Fatalf("unexpected error: %v", err)
168 }
169}
170
171func testGoBackWebViewNilWebView(t *testing.T, ctx context.Context) {
172 t.Helper()
173 c := &NavigationCoordinator{}
174 err := c.GoBackWebView(ctx, nil)
175 if err == nil {
176 t.Fatal("expected error for nil webview, got nil")
177 }
178}
179
180func testGoBackWebViewCallsGoBack(t *testing.T, ctx context.Context) {
181 t.Helper()
182 wv := mocks.NewMockWebView(t)
183 wv.EXPECT().ID().Return(port.WebViewID(1)).Once()
184 wv.EXPECT().GoBack(ctx).Return(nil).Once()
185 c := &NavigationCoordinator{}
186 err := c.GoBackWebView(ctx, wv)
187 if err != nil {
188 t.Fatalf("unexpected error: %v", err)
189 }
190}
191
192func testGoForwardWebViewNilWebView(t *testing.T, ctx context.Context) {
193 t.Helper()
194 c := &NavigationCoordinator{}
195 err := c.GoForwardWebView(ctx, nil)
196 if err == nil {
197 t.Fatal("expected error for nil webview, got nil")
198 }
199}
200
201func testGoForwardWebViewCallsGoForward(t *testing.T, ctx context.Context) {
202 t.Helper()
203 wv := mocks.NewMockWebView(t)
204 wv.EXPECT().ID().Return(port.WebViewID(1)).Once()
205 wv.EXPECT().GoForward(ctx).Return(nil).Once()
206 c := &NavigationCoordinator{}
207 err := c.GoForwardWebView(ctx, wv)
208 if err != nil {
209 t.Fatalf("unexpected error: %v", err)
210 }
211}
212
213func testOpenDevToolsWebViewNilWebView(t *testing.T, ctx context.Context) {
214 t.Helper()
215 c := &NavigationCoordinator{}
216 err := c.OpenDevToolsWebView(ctx, nil)
217 if err == nil {
218 t.Fatal("expected error for nil webview, got nil")
219 }
220}
221
222func testOpenDevToolsWebViewUnsupportedCapability(t *testing.T, ctx context.Context) {
223 t.Helper()
224 wv := mocks.NewMockWebView(t)
225 wv.EXPECT().ID().Return(port.WebViewID(1)).Once()
226 c := &NavigationCoordinator{}
227 err := c.OpenDevToolsWebView(ctx, wv)
228 if err == nil {
229 t.Fatal("expected unsupported devtools error, got nil")
230 }
231 if got, want := err.Error(), "webview does not support devtools"; got != want {
232 t.Fatalf("error = %q, want %q", got, want)
233 }
234}
235
236func testOpenDevToolsWebViewTargetsProvidedWebView(t *testing.T, ctx context.Context) {
237 t.Helper()
238 base := mocks.NewMockWebView(t)
239 opener := mocks.NewMockDevToolsOpener(t)
240 wv := &mockDevToolsWebView{MockWebView: base, MockDevToolsOpener: opener}
241 base.EXPECT().ID().Return(port.WebViewID(1)).Once()
242 opener.EXPECT().OpenDevTools().Return().Once()
243 c := &NavigationCoordinator{}
244 err := c.OpenDevToolsWebView(ctx, wv)
245 if err != nil {
246 t.Fatalf("unexpected error: %v", err)
247 }
248}
249
250func testPrintWebViewNilWebView(t *testing.T, ctx context.Context) {
251 t.Helper()
252 c := &NavigationCoordinator{}
253 err := c.PrintWebView(ctx, nil)
254 if err == nil {
255 t.Fatal("expected error for nil webview, got nil")
256 }
257}
258
259func testPrintWebViewUnsupportedCapability(t *testing.T, ctx context.Context) {
260 t.Helper()
261 wv := mocks.NewMockWebView(t)
262 wv.EXPECT().ID().Return(port.WebViewID(1)).Once()
263 c := &NavigationCoordinator{}
264 err := c.PrintWebView(ctx, wv)
265 if err == nil {
266 t.Fatal("expected unsupported printing error, got nil")
267 }
268 if got, want := err.Error(), "webview does not support printing"; got != want {
269 t.Fatalf("error = %q, want %q", got, want)
270 }
271}
272
273func testPrintWebViewTargetsProvidedWebView(t *testing.T, ctx context.Context) {
274 t.Helper()
275 base := mocks.NewMockWebView(t)
276 printer := mocks.NewMockPrinter(t)
277 wv := &mockPrinterWebView{MockWebView: base, MockPrinter: printer}
278 base.EXPECT().ID().Return(port.WebViewID(1)).Once()
279 printer.EXPECT().PrintPage().Return().Once()
280 c := &NavigationCoordinator{}
281 err := c.PrintWebView(ctx, wv)
282 if err != nil {
283 t.Fatalf("unexpected error: %v", err)
284 }
285}
286
287func testScrollWebViewNilWebView(t *testing.T, ctx context.Context) {
288 t.Helper()
289 c := &NavigationCoordinator{}
290 c.SetPageScrollUseCase(usecase.NewPageScrollUseCase())
291 err := c.ScrollWebView(ctx, nil, usecase.PageScrollDown)
292 if err == nil {
293 t.Fatal("expected error for nil webview, got nil")
294 }
295}
296
297func testScrollWebViewDelegatesEachCommand(t *testing.T, ctx context.Context) {
298 t.Helper()
299 commands := []struct {
300 cmd usecase.PageScrollCommand
301 dx int
302 dy int
303 }{
304 {usecase.PageScrollLeft, -80, 0},
305 {usecase.PageScrollRight, 80, 0},
306 {usecase.PageScrollUp, 0, -80},
307 {usecase.PageScrollDown, 0, 80},
308 {usecase.PageScrollUpFast, 0, -320},
309 {usecase.PageScrollDownFast, 0, 320},
310 }
311
312 for _, tc := range commands {
313 t.Run(tc.cmd.String(), func(t *testing.T) {
314 base := mocks.NewMockWebView(t)
315 scroller := mocks.NewMockPageScrollable(t)
316 wv := &mockScrollableWebView{MockWebView: base, MockPageScrollable: scroller}
317 base.EXPECT().ID().Return(port.WebViewID(42)).Once()
318 req := port.PageScrollRequest{Command: port.PageScrollCommand(tc.cmd), FallbackDX: tc.dx, FallbackDY: tc.dy}
319 scroller.EXPECT().ScrollPage(ctx, req).Return(nil).Once()
320
321 c := &NavigationCoordinator{}
322 c.SetPageScrollUseCase(usecase.NewPageScrollUseCase())
323 err := c.ScrollWebView(ctx, wv, tc.cmd)
324 if err != nil {
325 t.Fatalf("unexpected error for %s: %v", tc.cmd, err)
326 }
327 })
328 }
329}
330
331func testScrollWebViewUsecaseNotSet(t *testing.T, ctx context.Context) {
332 t.Helper()
333 base := mocks.NewMockWebView(t)
334 wv := &mockScrollableWebView{MockWebView: base, MockPageScrollable: mocks.NewMockPageScrollable(t)}
335 base.EXPECT().ID().Return(port.WebViewID(1)).Once()
336 c := &NavigationCoordinator{}
337 err := c.ScrollWebView(ctx, wv, usecase.PageScrollDown)
338 if err == nil {
339 t.Fatal("expected error for missing usecase, got nil")
340 }
341 if got, want := err.Error(), "page scroll usecase not set"; got != want {
342 t.Fatalf("error = %q, want %q", got, want)
343 }
344}