v0.21.0 73bf644

restore_session_test.go RawHistoryFolder

1package usecase_test
2
3import (
4	"errors"
5	"testing"
6	"time"
7
8	"github.com/bnema/dumber/internal/application/usecase"
9	"github.com/bnema/dumber/internal/domain/entity"
10	repomocks "github.com/bnema/dumber/internal/domain/repository/mocks"
11	"github.com/stretchr/testify/assert"
12	"github.com/stretchr/testify/require"
13)
14
15func TestRestoreSessionUseCase_Execute_ReturnsState(t *testing.T) {
16	ctx := testContext()
17
18	stateRepo := repomocks.NewMockSessionStateRepository(t)
19	sessionRepo := repomocks.NewMockSessionRepository(t)
20
21	sessionID := entity.SessionID("20251224_120000_restore")
22
23	expectedState := &entity.SessionState{
24		Version:   entity.SessionStateVersion,
25		SessionID: sessionID,
26		Tabs: []entity.TabSnapshot{
27			{
28				ID:   "tab-1",
29				Name: "Test Tab",
30				Workspace: entity.WorkspaceSnapshot{
31					Root: &entity.PaneNodeSnapshot{
32						Pane: &entity.PaneSnapshot{
33							ID:    "pane-1",
34							URI:   "https://example.com",
35							Title: "Example",
36						},
37					},
38				},
39			},
40		},
41		SavedAt: time.Now(),
42	}
43
44	stateRepo.EXPECT().GetSnapshot(ctx, sessionID).Return(expectedState, nil)
45
46	uc := usecase.NewRestoreSessionUseCase(stateRepo, sessionRepo)
47
48	output, err := uc.Execute(ctx, usecase.RestoreInput{SessionID: sessionID})
49	require.NoError(t, err)
50	require.NotNil(t, output)
51	assert.Equal(t, expectedState, output.State)
52}
53
54func TestRestoreSessionUseCase_Execute_RequiresSessionID(t *testing.T) {
55	ctx := testContext()
56
57	stateRepo := repomocks.NewMockSessionStateRepository(t)
58	sessionRepo := repomocks.NewMockSessionRepository(t)
59
60	uc := usecase.NewRestoreSessionUseCase(stateRepo, sessionRepo)
61
62	_, err := uc.Execute(ctx, usecase.RestoreInput{SessionID: ""})
63	require.Error(t, err)
64	assert.Contains(t, err.Error(), "session id required")
65}
66
67func TestRestoreSessionUseCase_Execute_SessionNotFound(t *testing.T) {
68	ctx := testContext()
69
70	stateRepo := repomocks.NewMockSessionStateRepository(t)
71	sessionRepo := repomocks.NewMockSessionRepository(t)
72
73	sessionID := entity.SessionID("20251224_120000_notfound")
74
75	stateRepo.EXPECT().GetSnapshot(ctx, sessionID).Return(nil, nil)
76
77	uc := usecase.NewRestoreSessionUseCase(stateRepo, sessionRepo)
78
79	_, err := uc.Execute(ctx, usecase.RestoreInput{SessionID: sessionID})
80	require.Error(t, err)
81	assert.ErrorIs(t, err, usecase.ErrSessionNotFound)
82}
83
84func TestRestoreSessionUseCase_Execute_VersionMismatch(t *testing.T) {
85	ctx := testContext()
86
87	stateRepo := repomocks.NewMockSessionStateRepository(t)
88	sessionRepo := repomocks.NewMockSessionRepository(t)
89
90	sessionID := entity.SessionID("20251224_120000_version")
91
92	// Return a state with a future version
93	futureState := &entity.SessionState{
94		Version:   entity.SessionStateVersion + 1,
95		SessionID: sessionID,
96		Tabs:      []entity.TabSnapshot{},
97		SavedAt:   time.Now(),
98	}
99
100	stateRepo.EXPECT().GetSnapshot(ctx, sessionID).Return(futureState, nil)
101
102	uc := usecase.NewRestoreSessionUseCase(stateRepo, sessionRepo)
103
104	_, err := uc.Execute(ctx, usecase.RestoreInput{SessionID: sessionID})
105	require.Error(t, err)
106	assert.ErrorIs(t, err, usecase.ErrVersionMismatch)
107}
108
109func TestRestoreSessionUseCase_Execute_GetSnapshotError(t *testing.T) {
110	ctx := testContext()
111
112	stateRepo := repomocks.NewMockSessionStateRepository(t)
113	sessionRepo := repomocks.NewMockSessionRepository(t)
114
115	sessionID := entity.SessionID("20251224_120000_error")
116
117	stateRepo.EXPECT().GetSnapshot(ctx, sessionID).Return(nil, errors.New("db error"))
118
119	uc := usecase.NewRestoreSessionUseCase(stateRepo, sessionRepo)
120
121	_, err := uc.Execute(ctx, usecase.RestoreInput{SessionID: sessionID})
122	require.Error(t, err)
123	assert.Contains(t, err.Error(), "get session snapshot")
124}
125
126func TestRestoreSessionUseCase_DeleteSnapshot(t *testing.T) {
127	ctx := testContext()
128
129	stateRepo := repomocks.NewMockSessionStateRepository(t)
130	sessionRepo := repomocks.NewMockSessionRepository(t)
131
132	sessionID := entity.SessionID("20251224_120000_delete")
133
134	stateRepo.EXPECT().DeleteSnapshot(ctx, sessionID).Return(nil)
135
136	uc := usecase.NewRestoreSessionUseCase(stateRepo, sessionRepo)
137
138	err := uc.DeleteSnapshot(ctx, sessionID)
139	require.NoError(t, err)
140}

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