v0.27.2 5960dd8

keybindings_test.go RawHistoryFolder

1package usecase_test
2
3import (
4	"context"
5	"errors"
6	"testing"
7
8	"github.com/stretchr/testify/assert"
9	"github.com/stretchr/testify/mock"
10	"github.com/stretchr/testify/require"
11
12	"github.com/bnema/dumber/internal/application/port"
13	"github.com/bnema/dumber/internal/application/port/mocks"
14	"github.com/bnema/dumber/internal/application/usecase"
15)
16
17func TestGetKeybindingsUseCase_Execute(t *testing.T) {
18	t.Run("returns keybindings from provider", func(t *testing.T) {
19		// Arrange
20		mockProvider := mocks.NewMockKeybindingsProvider(t)
21		expected := port.KeybindingsConfig{
22			Groups: []port.KeybindingGroup{
23				{
24					Mode:        "global",
25					DisplayName: "Global Shortcuts",
26					Bindings: []port.KeybindingEntry{
27						{Action: "close_pane", Keys: []string{"ctrl+w"}},
28					},
29				},
30			},
31		}
32		mockProvider.EXPECT().GetKeybindings(mock.Anything).Return(expected, nil)
33
34		uc := usecase.NewGetKeybindingsUseCase(mockProvider)
35
36		// Act
37		result, err := uc.Execute(context.Background())
38
39		// Assert
40		require.NoError(t, err)
41		assert.Equal(t, expected, result)
42		mock.AssertExpectationsForObjects(t, mockProvider)
43	})
44
45	t.Run("returns error when provider fails", func(t *testing.T) {
46		// Arrange
47		mockProvider := mocks.NewMockKeybindingsProvider(t)
48		mockProvider.EXPECT().GetKeybindings(mock.Anything).Return(port.KeybindingsConfig{}, errors.New("provider error"))
49
50		uc := usecase.NewGetKeybindingsUseCase(mockProvider)
51
52		// Act
53		_, err := uc.Execute(context.Background())
54
55		// Assert
56		require.Error(t, err)
57		assert.Contains(t, err.Error(), "provider error")
58		mock.AssertExpectationsForObjects(t, mockProvider)
59	})
60
61	t.Run("returns error when provider is nil", func(t *testing.T) {
62		// Arrange
63		uc := usecase.NewGetKeybindingsUseCase(nil)
64
65		// Act
66		_, err := uc.Execute(context.Background())
67
68		// Assert
69		require.Error(t, err)
70		assert.Contains(t, err.Error(), "provider is nil")
71	})
72}
73
74func TestSetKeybindingUseCase_Execute(t *testing.T) {
75	t.Run("successfully sets keybinding", func(t *testing.T) {
76		// Arrange
77		mockProvider := mocks.NewMockKeybindingsProvider(t)
78		mockSaver := mocks.NewMockKeybindingsSaver(t)
79		req := port.SetKeybindingRequest{
80			Mode:   "pane",
81			Action: "split-right",
82			Keys:   []string{"r"},
83		}
84		mockProvider.EXPECT().CheckConflicts(mock.Anything, req.Mode, req.Action, req.Keys).Return(nil, nil)
85		mockSaver.EXPECT().SetKeybinding(mock.Anything, req).Return(nil)
86
87		uc := usecase.NewSetKeybindingUseCase(mockProvider, mockSaver)
88
89		// Act
90		resp, err := uc.Execute(context.Background(), req)
91
92		// Assert
93		require.NoError(t, err)
94		assert.Empty(t, resp.Conflicts)
95		mock.AssertExpectationsForObjects(t, mockProvider, mockSaver)
96	})
97
98	t.Run("returns conflicts when detected", func(t *testing.T) {
99		// Arrange
100		mockProvider := mocks.NewMockKeybindingsProvider(t)
101		mockSaver := mocks.NewMockKeybindingsSaver(t)
102		req := port.SetKeybindingRequest{
103			Mode:   "pane",
104			Action: "split-right",
105			Keys:   []string{"r"},
106		}
107		conflicts := []port.KeybindingConflict{
108			{ConflictingAction: "other-action", ConflictingMode: "pane", Key: "r"},
109		}
110		mockProvider.EXPECT().CheckConflicts(mock.Anything, req.Mode, req.Action, req.Keys).Return(conflicts, nil)
111		mockSaver.EXPECT().SetKeybinding(mock.Anything, req).Return(nil)
112
113		uc := usecase.NewSetKeybindingUseCase(mockProvider, mockSaver)
114
115		// Act
116		resp, err := uc.Execute(context.Background(), req)
117
118		// Assert
119		require.NoError(t, err)
120		assert.Equal(t, conflicts, resp.Conflicts)
121		mock.AssertExpectationsForObjects(t, mockProvider, mockSaver)
122	})
123
124	t.Run("returns error when saver fails", func(t *testing.T) {
125		// Arrange
126		mockProvider := mocks.NewMockKeybindingsProvider(t)
127		mockSaver := mocks.NewMockKeybindingsSaver(t)
128		req := port.SetKeybindingRequest{
129			Mode:   "pane",
130			Action: "split-right",
131			Keys:   []string{"r"},
132		}
133		mockProvider.EXPECT().CheckConflicts(mock.Anything, req.Mode, req.Action, req.Keys).Return(nil, nil)
134		mockSaver.EXPECT().SetKeybinding(mock.Anything, req).Return(errors.New("save error"))
135
136		uc := usecase.NewSetKeybindingUseCase(mockProvider, mockSaver)
137
138		// Act
139		_, err := uc.Execute(context.Background(), req)
140
141		// Assert
142		require.Error(t, err)
143		assert.Contains(t, err.Error(), "save error")
144		mock.AssertExpectationsForObjects(t, mockProvider, mockSaver)
145	})
146
147	t.Run("returns error when saver is nil", func(t *testing.T) {
148		// Arrange
149		uc := usecase.NewSetKeybindingUseCase(nil, nil)
150		req := port.SetKeybindingRequest{
151			Mode:   "pane",
152			Action: "split-right",
153			Keys:   []string{"r"},
154		}
155
156		// Act
157		_, err := uc.Execute(context.Background(), req)
158
159		// Assert
160		require.Error(t, err)
161		assert.Contains(t, err.Error(), "saver is nil")
162	})
163
164	t.Run("returns error when mode is empty", func(t *testing.T) {
165		// Arrange
166		mockProvider := mocks.NewMockKeybindingsProvider(t)
167		mockSaver := mocks.NewMockKeybindingsSaver(t)
168		req := port.SetKeybindingRequest{
169			Mode:   "",
170			Action: "split-right",
171			Keys:   []string{"r"},
172		}
173
174		uc := usecase.NewSetKeybindingUseCase(mockProvider, mockSaver)
175
176		// Act
177		_, err := uc.Execute(context.Background(), req)
178
179		// Assert
180		require.Error(t, err)
181		assert.Contains(t, err.Error(), "mode is required")
182	})
183
184	t.Run("returns error when action is empty", func(t *testing.T) {
185		// Arrange
186		mockProvider := mocks.NewMockKeybindingsProvider(t)
187		mockSaver := mocks.NewMockKeybindingsSaver(t)
188		req := port.SetKeybindingRequest{
189			Mode:   "pane",
190			Action: "",
191			Keys:   []string{"r"},
192		}
193
194		uc := usecase.NewSetKeybindingUseCase(mockProvider, mockSaver)
195
196		// Act
197		_, err := uc.Execute(context.Background(), req)
198
199		// Assert
200		require.Error(t, err)
201		assert.Contains(t, err.Error(), "action is required")
202	})
203
204	t.Run("returns error for invalid mode", func(t *testing.T) {
205		// Arrange
206		mockProvider := mocks.NewMockKeybindingsProvider(t)
207		mockSaver := mocks.NewMockKeybindingsSaver(t)
208		req := port.SetKeybindingRequest{
209			Mode:   "invalid",
210			Action: "split-right",
211			Keys:   []string{"r"},
212		}
213
214		uc := usecase.NewSetKeybindingUseCase(mockProvider, mockSaver)
215
216		// Act
217		_, err := uc.Execute(context.Background(), req)
218
219		// Assert
220		require.Error(t, err)
221		assert.Contains(t, err.Error(), "invalid mode")
222	})
223}
224
225func TestResetKeybindingUseCase_Execute(t *testing.T) {
226	t.Run("successfully resets keybinding", func(t *testing.T) {
227		// Arrange
228		mockSaver := mocks.NewMockKeybindingsSaver(t)
229		req := port.ResetKeybindingRequest{
230			Mode:   "pane",
231			Action: "split-right",
232		}
233		mockSaver.EXPECT().ResetKeybinding(mock.Anything, req).Return(nil)
234
235		uc := usecase.NewResetKeybindingUseCase(mockSaver)
236
237		// Act
238		err := uc.Execute(context.Background(), req)
239
240		// Assert
241		require.NoError(t, err)
242		mock.AssertExpectationsForObjects(t, mockSaver)
243	})
244
245	t.Run("returns error when saver fails", func(t *testing.T) {
246		// Arrange
247		mockSaver := mocks.NewMockKeybindingsSaver(t)
248		req := port.ResetKeybindingRequest{
249			Mode:   "pane",
250			Action: "split-right",
251		}
252		mockSaver.EXPECT().ResetKeybinding(mock.Anything, req).Return(errors.New("reset error"))
253
254		uc := usecase.NewResetKeybindingUseCase(mockSaver)
255
256		// Act
257		err := uc.Execute(context.Background(), req)
258
259		// Assert
260		require.Error(t, err)
261		assert.Contains(t, err.Error(), "reset error")
262		mock.AssertExpectationsForObjects(t, mockSaver)
263	})
264
265	t.Run("returns error when saver is nil", func(t *testing.T) {
266		// Arrange
267		uc := usecase.NewResetKeybindingUseCase(nil)
268		req := port.ResetKeybindingRequest{
269			Mode:   "pane",
270			Action: "split-right",
271		}
272
273		// Act
274		err := uc.Execute(context.Background(), req)
275
276		// Assert
277		require.Error(t, err)
278		assert.Contains(t, err.Error(), "saver is nil")
279	})
280
281	t.Run("returns error when mode is empty", func(t *testing.T) {
282		// Arrange
283		mockSaver := mocks.NewMockKeybindingsSaver(t)
284		req := port.ResetKeybindingRequest{
285			Mode:   "",
286			Action: "split-right",
287		}
288
289		uc := usecase.NewResetKeybindingUseCase(mockSaver)
290
291		// Act
292		err := uc.Execute(context.Background(), req)
293
294		// Assert
295		require.Error(t, err)
296		assert.Contains(t, err.Error(), "mode is required")
297	})
298}
299
300func TestResetAllKeybindingsUseCase_Execute(t *testing.T) {
301	t.Run("successfully resets all keybindings", func(t *testing.T) {
302		// Arrange
303		mockSaver := mocks.NewMockKeybindingsSaver(t)
304		mockSaver.EXPECT().ResetAllKeybindings(mock.Anything).Return(nil)
305
306		uc := usecase.NewResetAllKeybindingsUseCase(mockSaver)
307
308		// Act
309		err := uc.Execute(context.Background())
310
311		// Assert
312		require.NoError(t, err)
313		mock.AssertExpectationsForObjects(t, mockSaver)
314	})
315
316	t.Run("returns error when saver fails", func(t *testing.T) {
317		// Arrange
318		mockSaver := mocks.NewMockKeybindingsSaver(t)
319		mockSaver.EXPECT().ResetAllKeybindings(mock.Anything).Return(errors.New("reset all error"))
320
321		uc := usecase.NewResetAllKeybindingsUseCase(mockSaver)
322
323		// Act
324		err := uc.Execute(context.Background())
325
326		// Assert
327		require.Error(t, err)
328		assert.Contains(t, err.Error(), "reset all error")
329		mock.AssertExpectationsForObjects(t, mockSaver)
330	})
331
332	t.Run("returns error when saver is nil", func(t *testing.T) {
333		// Arrange
334		uc := usecase.NewResetAllKeybindingsUseCase(nil)
335
336		// Act
337		err := uc.Execute(context.Background())
338
339		// Assert
340		require.Error(t, err)
341		assert.Contains(t, err.Error(), "saver is nil")
342	})
343}

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