main 5041353

runtime_config_test.go RawHistoryFolder

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			SaveModeLegendCollapsed: func(context.Context, bool) error {
32				return nil
33			},
34		},
35	}
36
37	if err := deps.Validate(); err != nil {
38		t.Fatalf("Validate() error = %v, want nil", err)
39	}
40}
41
42func TestAppRuntimeConfigReturnsProviderSnapshot(t *testing.T) {
43	provider := portmocks.NewMockRuntimeConfigProvider(t)
44	provider.EXPECT().
45		Current().
46		Return(entity.RuntimeConfigSnapshot{
47			UI: entity.RuntimeUIConfig{DefaultUIScale: 1.6},
48		}).
49		Once()
50	app := &App{deps: &Dependencies{RuntimeConfig: provider}}
51
52	got := app.runtimeConfigSnapshot()
53
54	if got.UI.DefaultUIScale != 1.6 {
55		t.Fatalf("DefaultUIScale=%v, want 1.6", got.UI.DefaultUIScale)
56	}
57}
58
59func TestAppRuntimeConfigStateStoresLatestSnapshot(t *testing.T) {
60	app := &App{}
61	setRuntimeConfigSnapshotForTest(app, entity.RuntimeConfigSnapshot{
62		UI: entity.RuntimeUIConfig{SidebarWidth: 340},
63	})
64
65	got := app.runtimeConfigSnapshot()
66	if got.UI.SidebarWidth != 340 {
67		t.Fatalf("SidebarWidth=%d, want 340", got.UI.SidebarWidth)
68	}
69}
70
71func TestConfigWatcherOnChangeUpdatesRuntimeConfigState(t *testing.T) {
72	ctx := context.Background()
73	provider := portmocks.NewMockRuntimeConfigProvider(t)
74	provider.EXPECT().Watch().Return(nil).Once()
75	var onChange func(entity.RuntimeConfigSnapshot)
76	provider.EXPECT().
77		OnChange(mock.Anything).
78		Run(func(fn func(entity.RuntimeConfigSnapshot)) {
79			onChange = fn
80		}).
81		Once()
82
83	initial := entity.RuntimeConfigSnapshot{
84		UI: entity.RuntimeUIConfig{
85			Workspace: entity.WorkspaceConfig{
86				BrowsingContexts: entity.BrowsingContextConfig{OpenInNewPane: true},
87			},
88		},
89	}
90	app := &App{
91		deps:           &Dependencies{RuntimeConfig: provider},
92		runtimeConfig:  runtimeConfigStateFromSnapshotForTest(initial),
93		contentCoord:   &content.Coordinator{},
94		browserWindows: map[string]*browserWindow{},
95		dispatchOnMainThread: func(label string, fn func()) syncdispatch.SyncDispatchResult {
96			if label != "ui.runtime_config_reload" {
97				t.Fatalf("dispatch label=%q, want ui.runtime_config_reload", label)
98			}
99			fn()
100			return syncdispatch.SyncDispatchResult{Label: label, Status: syncdispatch.SyncDispatchCompleted}
101		},
102	}
103	app.contentCoord.SetPopupConfig(nil, &initial.UI.Workspace.BrowsingContexts, nil)
104
105	app.initConfigWatcher(ctx)
106	if onChange == nil {
107		t.Fatal("runtime config OnChange callback was not registered")
108	}
109
110	onChange(entity.RuntimeConfigSnapshot{
111		UI: entity.RuntimeUIConfig{
112			SidebarWidth: 360,
113			Workspace: entity.WorkspaceConfig{
114				BrowsingContexts: entity.BrowsingContextConfig{OpenInNewPane: false, OAuthAutoClose: true},
115			},
116		},
117	})
118
119	got := app.runtimeConfigSnapshot()
120	if got.UI.SidebarWidth != 360 {
121		t.Fatalf("SidebarWidth=%d, want 360", got.UI.SidebarWidth)
122	}
123	if got.UI.Workspace.BrowsingContexts.OpenInNewPane {
124		t.Fatal("runtime config state did not observe updated popup OpenInNewPane")
125	}
126	if !got.UI.Workspace.BrowsingContexts.OAuthAutoClose {
127		t.Fatal("runtime config state did not observe updated popup OAuthAutoClose")
128	}
129}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close