1package usecase
2
3import (
4 "context"
5 "errors"
6 "math"
7 "testing"
8
9 "github.com/bnema/dumber/internal/application/port"
10 "github.com/bnema/dumber/internal/domain/entity"
11 "github.com/stretchr/testify/require"
12)
13
14type fakeWebView struct {
15 loaded string
16 loadErr error
17}
18
19func (f *fakeWebView) LoadURI(_ context.Context, uri string) error {
20 if f.loadErr != nil {
21 return f.loadErr
22 }
23 f.loaded = uri
24 return nil
25}
26func (*fakeWebView) LoadHTML(context.Context, string, string) error { return nil }
27func (*fakeWebView) Reload(context.Context) error { return nil }
28func (*fakeWebView) ReloadBypassCache(context.Context) error { return nil }
29func (*fakeWebView) Stop(context.Context) error { return nil }
30func (*fakeWebView) GoBack(context.Context) error { return nil }
31func (*fakeWebView) GoForward(context.Context) error { return nil }
32func (*fakeWebView) ID() port.WebViewID { return 1 }
33func (*fakeWebView) State() port.WebViewState { return port.WebViewState{} }
34func (f *fakeWebView) URI() string { return f.loaded }
35func (*fakeWebView) Title() string { return "" }
36func (*fakeWebView) IsLoading() bool { return false }
37func (*fakeWebView) EstimatedProgress() float64 { return 1 }
38func (*fakeWebView) CanGoBack() bool { return false }
39func (*fakeWebView) CanGoForward() bool { return false }
40func (*fakeWebView) SetZoomLevel(context.Context, float64) error { return nil }
41func (*fakeWebView) GetZoomLevel() float64 { return 1 }
42func (*fakeWebView) GetFindController() port.FindController { return nil }
43func (*fakeWebView) SetCallbacks(*port.WebViewCallbacks) {}
44func (*fakeWebView) RunJavaScript(context.Context, string) {}
45func (*fakeWebView) SetBackgroundColor(float64, float64, float64, float64) {
46}
47func (*fakeWebView) ResetBackgroundToDefault() {}
48func (*fakeWebView) Favicon() port.Texture { return nil }
49func (*fakeWebView) Generation() uint64 { return 0 }
50func (*fakeWebView) IsFullscreen() bool { return false }
51func (*fakeWebView) IsPlayingAudio() bool { return false }
52func (*fakeWebView) IsDestroyed() bool { return false }
53func (*fakeWebView) Destroy() {}
54
55func TestNavigateUseCase_ExecuteLoadsURLAndReturnsDefaultZoom(t *testing.T) {
56 ctx := context.Background()
57 wv := &fakeWebView{}
58 uc := NewNavigateUseCase(entity.ZoomDefault)
59
60 out, err := uc.Execute(ctx, NavigateInput{URL: "https://example.com", PaneID: "pane-1", WebView: wv})
61
62 require.NoError(t, err)
63 require.Equal(t, "https://example.com", wv.loaded)
64 require.InDelta(t, entity.ZoomDefault, out.AppliedZoom, 0.0001)
65}
66
67func TestNavigateUseCase_ExecuteUsesConfiguredOrFallbackZoom(t *testing.T) {
68 tests := []struct {
69 name string
70 configuredZoom float64
71 wantZoom float64
72 }{
73 {name: "zero falls back", configuredZoom: 0, wantZoom: entity.ZoomDefault},
74 {name: "negative falls back", configuredZoom: -0.5, wantZoom: entity.ZoomDefault},
75 {name: "NaN falls back", configuredZoom: math.NaN(), wantZoom: entity.ZoomDefault},
76 {name: "positive infinity falls back", configuredZoom: math.Inf(1), wantZoom: entity.ZoomDefault},
77 {name: "positive is preserved", configuredZoom: 1.25, wantZoom: 1.25},
78 }
79
80 for _, tt := range tests {
81 t.Run(tt.name, func(t *testing.T) {
82 ctx := context.Background()
83 wv := &fakeWebView{}
84 uc := NewNavigateUseCase(tt.configuredZoom)
85
86 out, err := uc.Execute(ctx, NavigateInput{URL: "https://example.com", PaneID: "pane-1", WebView: wv})
87
88 require.NoError(t, err)
89 require.Equal(t, "https://example.com", wv.loaded)
90 require.InDelta(t, tt.wantZoom, out.AppliedZoom, 0.0001)
91 })
92 }
93}
94
95func TestNavigateUseCase_ExecuteReturnsLoadError(t *testing.T) {
96 ctx := context.Background()
97 loadErr := errors.New("load failed")
98 wv := &fakeWebView{loadErr: loadErr}
99 uc := NewNavigateUseCase(entity.ZoomDefault)
100
101 out, err := uc.Execute(ctx, NavigateInput{URL: "https://example.com", PaneID: "pane-1", WebView: wv})
102
103 require.Nil(t, out)
104 require.ErrorIs(t, err, loadErr)
105 require.Contains(t, err.Error(), "failed to load URL")
106}