1package ui
2
3import (
4 "context"
5 "testing"
6
7 "github.com/stretchr/testify/mock"
8
9 "github.com/bnema/dumber/internal/application/dto"
10 "github.com/bnema/dumber/internal/application/port"
11 portmocks "github.com/bnema/dumber/internal/application/port/mocks"
12 "github.com/bnema/dumber/internal/domain/entity"
13 "github.com/bnema/dumber/internal/shared/syncdispatch"
14 "github.com/bnema/dumber/internal/ui/coordinator/content"
15)
16
17func TestDependenciesValidateAcceptsRuntimeConfigOnly(t *testing.T) {
18 runtimeConfig := portmocks.NewMockRuntimeConfigProvider(t)
19 engine := portmocks.NewMockEngine(t)
20 deps := &Dependencies{
21 Ctx: context.Background(),
22 RuntimeConfig: runtimeConfig,
23 Engine: engine,
24 HandlerDeps: port.HandlerDeps{
25 SaveConfig: func(context.Context, dto.WebUIConfig) error {
26 return nil
27 },
28 SaveOmniboxInitialBehavior: func(context.Context, entity.OmniboxInitialBehavior) error {
29 return nil
30 },
31 },
32 }
33
34 if err := deps.Validate(); err != nil {
35 t.Fatalf("Validate() error = %v, want nil", err)
36 }
37}
38
39func TestAppRuntimeConfigReturnsProviderSnapshot(t *testing.T) {
40 provider := portmocks.NewMockRuntimeConfigProvider(t)
41 provider.EXPECT().
42 Current().
43 Return(entity.RuntimeConfigSnapshot{
44 UI: entity.RuntimeUIConfig{DefaultUIScale: 1.6},
45 }).
46 Once()
47 app := &App{deps: &Dependencies{RuntimeConfig: provider}}
48
49 got := app.runtimeConfigSnapshot()
50
51 if got.UI.DefaultUIScale != 1.6 {
52 t.Fatalf("DefaultUIScale=%v, want 1.6", got.UI.DefaultUIScale)
53 }
54}
55
56func TestAppRuntimeConfigStateStoresLatestSnapshot(t *testing.T) {
57 app := &App{}
58 setRuntimeConfigSnapshotForTest(app, entity.RuntimeConfigSnapshot{
59 UI: entity.RuntimeUIConfig{SidebarWidth: 340},
60 })
61
62 got := app.runtimeConfigSnapshot()
63 if got.UI.SidebarWidth != 340 {
64 t.Fatalf("SidebarWidth=%d, want 340", got.UI.SidebarWidth)
65 }
66}
67
68func TestConfigWatcherOnChangeUpdatesRuntimeConfigState(t *testing.T) {
69 ctx := context.Background()
70 provider := portmocks.NewMockRuntimeConfigProvider(t)
71 provider.EXPECT().Watch().Return(nil).Once()
72 var onChange func(entity.RuntimeConfigSnapshot)
73 provider.EXPECT().
74 OnChange(mock.Anything).
75 Run(func(fn func(entity.RuntimeConfigSnapshot)) {
76 onChange = fn
77 }).
78 Once()
79
80 initial := entity.RuntimeConfigSnapshot{
81 UI: entity.RuntimeUIConfig{
82 Workspace: entity.WorkspaceConfig{
83 BrowsingContexts: entity.BrowsingContextConfig{OpenInNewPane: true},
84 },
85 },
86 }
87 app := &App{
88 deps: &Dependencies{RuntimeConfig: provider},
89 runtimeConfig: runtimeConfigStateFromSnapshotForTest(initial),
90 contentCoord: &content.Coordinator{},
91 browserWindows: map[string]*browserWindow{},
92 dispatchOnMainThread: func(label string, fn func()) syncdispatch.SyncDispatchResult {
93 if label != "ui.runtime_config_reload" {
94 t.Fatalf("dispatch label=%q, want ui.runtime_config_reload", label)
95 }
96 fn()
97 return syncdispatch.SyncDispatchResult{Label: label, Status: syncdispatch.SyncDispatchCompleted}
98 },
99 }
100 app.contentCoord.SetPopupConfig(nil, &initial.UI.Workspace.BrowsingContexts, nil)
101
102 app.initConfigWatcher(ctx)
103 if onChange == nil {
104 t.Fatal("runtime config OnChange callback was not registered")
105 }
106
107 onChange(entity.RuntimeConfigSnapshot{
108 UI: entity.RuntimeUIConfig{
109 SidebarWidth: 360,
110 Workspace: entity.WorkspaceConfig{
111 BrowsingContexts: entity.BrowsingContextConfig{OpenInNewPane: false, OAuthAutoClose: true},
112 },
113 },
114 })
115
116 got := app.runtimeConfigSnapshot()
117 if got.UI.SidebarWidth != 360 {
118 t.Fatalf("SidebarWidth=%d, want 360", got.UI.SidebarWidth)
119 }
120 if got.UI.Workspace.BrowsingContexts.OpenInNewPane {
121 t.Fatal("runtime config state did not observe updated popup OpenInNewPane")
122 }
123 if !got.UI.Workspace.BrowsingContexts.OAuthAutoClose {
124 t.Fatal("runtime config state did not observe updated popup OAuthAutoClose")
125 }
126}