1package usecase_test
2
3import (
4 "testing"
5 "time"
6
7 "github.com/bnema/dumber/internal/application/usecase"
8 "github.com/bnema/dumber/internal/domain/entity"
9 repomocks "github.com/bnema/dumber/internal/domain/repository/mocks"
10 "github.com/stretchr/testify/assert"
11 "github.com/stretchr/testify/require"
12)
13
14func TestListSessionsUseCase_Execute_ReturnsSessionsWithState(t *testing.T) {
15 ctx := testContext()
16
17 sessionRepo := repomocks.NewMockSessionRepository(t)
18 stateRepo := repomocks.NewMockSessionStateRepository(t)
19
20 endedAt := time.Now().Add(-time.Hour)
21 sessions := []*entity.Session{
22 {
23 ID: "20251224_120000_abc1",
24 Type: entity.SessionTypeBrowser,
25 StartedAt: time.Now().Add(-2 * time.Hour),
26 EndedAt: &endedAt,
27 },
28 {
29 ID: "20251224_130000_def2",
30 Type: entity.SessionTypeBrowser,
31 StartedAt: time.Now().Add(-time.Hour),
32 EndedAt: nil, // Active
33 },
34 }
35
36 states := []*entity.SessionState{
37 {
38 SessionID: "20251224_120000_abc1",
39 SavedAt: time.Now().Add(-time.Hour),
40 Tabs: []entity.TabSnapshot{
41 {ID: "tab1"},
42 {ID: "tab2"},
43 },
44 },
45 }
46
47 sessionRepo.EXPECT().GetRecent(ctx, 50).Return(sessions, nil)
48 stateRepo.EXPECT().GetAllSnapshots(ctx).Return(states, nil)
49
50 uc := usecase.NewListSessionsUseCase(sessionRepo, stateRepo)
51
52 output, err := uc.Execute(ctx, "", 50)
53 require.NoError(t, err)
54 require.NotNil(t, output)
55 require.Len(t, output.Sessions, 2)
56
57 // Active session should be first (or current, but we have no current)
58 // The sorting puts active sessions before inactive
59 activeSession := output.Sessions[0]
60 assert.True(t, activeSession.IsActive)
61
62 // Check session with state has tab count
63 var sessionWithState *entity.SessionInfo
64 for i := range output.Sessions {
65 if output.Sessions[i].Session.ID == "20251224_120000_abc1" {
66 sessionWithState = &output.Sessions[i]
67 break
68 }
69 }
70 require.NotNil(t, sessionWithState)
71 assert.Equal(t, 2, sessionWithState.TabCount)
72}
73
74func TestListSessionsUseCase_GetPurgeableSessions_ReturnsOnlyInactive(t *testing.T) {
75 ctx := testContext()
76
77 sessionRepo := repomocks.NewMockSessionRepository(t)
78 stateRepo := repomocks.NewMockSessionStateRepository(t)
79
80 endedAt := time.Now().Add(-time.Hour)
81 sessions := []*entity.Session{
82 {
83 ID: "20251224_120000_inactive1",
84 Type: entity.SessionTypeBrowser,
85 StartedAt: time.Now().Add(-3 * time.Hour),
86 EndedAt: &endedAt, // Ended - purgeable
87 },
88 {
89 ID: "20251224_130000_active1",
90 Type: entity.SessionTypeBrowser,
91 StartedAt: time.Now().Add(-time.Hour),
92 EndedAt: nil, // Active - NOT purgeable
93 },
94 {
95 ID: "20251224_140000_inactive2",
96 Type: entity.SessionTypeBrowser,
97 StartedAt: time.Now().Add(-2 * time.Hour),
98 EndedAt: &endedAt, // Ended - purgeable
99 },
100 }
101
102 sessionRepo.EXPECT().GetRecent(ctx, 1000).Return(sessions, nil)
103 stateRepo.EXPECT().GetAllSnapshots(ctx).Return(nil, nil)
104 stateRepo.EXPECT().GetTotalSnapshotsSize(ctx).Return(int64(12345), nil)
105
106 uc := usecase.NewListSessionsUseCase(sessionRepo, stateRepo)
107
108 output, err := uc.GetPurgeableSessions(ctx)
109 require.NoError(t, err)
110 require.NotNil(t, output)
111
112 // Should only have 2 inactive sessions, not the active one
113 require.Len(t, output.Sessions, 2)
114 assert.Equal(t, int64(12345), output.TotalSize)
115
116 // Verify all returned sessions are inactive
117 for _, s := range output.Sessions {
118 assert.False(t, s.Info.IsActive, "session %s should not be active", s.Info.Session.ID)
119 assert.True(t, s.Selected, "sessions should be selected by default")
120 }
121}
122
123func TestListSessionsUseCase_GetPurgeableSessions_EmptyWhenAllActive(t *testing.T) {
124 ctx := testContext()
125
126 sessionRepo := repomocks.NewMockSessionRepository(t)
127 stateRepo := repomocks.NewMockSessionStateRepository(t)
128
129 sessions := []*entity.Session{
130 {
131 ID: "20251224_130000_active1",
132 Type: entity.SessionTypeBrowser,
133 StartedAt: time.Now().Add(-time.Hour),
134 EndedAt: nil, // Active
135 },
136 }
137
138 sessionRepo.EXPECT().GetRecent(ctx, 1000).Return(sessions, nil)
139 stateRepo.EXPECT().GetAllSnapshots(ctx).Return(nil, nil)
140 stateRepo.EXPECT().GetTotalSnapshotsSize(ctx).Return(int64(0), nil)
141
142 uc := usecase.NewListSessionsUseCase(sessionRepo, stateRepo)
143
144 output, err := uc.GetPurgeableSessions(ctx)
145 require.NoError(t, err)
146 require.NotNil(t, output)
147 require.Empty(t, output.Sessions)
148}
149
150func TestListSessionsUseCase_GetPurgeableSessions_HandlesGetSizeError(t *testing.T) {
151 ctx := testContext()
152
153 sessionRepo := repomocks.NewMockSessionRepository(t)
154 stateRepo := repomocks.NewMockSessionStateRepository(t)
155
156 endedAt := time.Now().Add(-time.Hour)
157 sessions := []*entity.Session{
158 {
159 ID: "20251224_120000_inactive1",
160 Type: entity.SessionTypeBrowser,
161 StartedAt: time.Now().Add(-2 * time.Hour),
162 EndedAt: &endedAt,
163 },
164 }
165
166 sessionRepo.EXPECT().GetRecent(ctx, 1000).Return(sessions, nil)
167 stateRepo.EXPECT().GetAllSnapshots(ctx).Return(nil, nil)
168 stateRepo.EXPECT().GetTotalSnapshotsSize(ctx).Return(int64(0), assert.AnError)
169
170 uc := usecase.NewListSessionsUseCase(sessionRepo, stateRepo)
171
172 output, err := uc.GetPurgeableSessions(ctx)
173 // Should succeed even if size query fails
174 require.NoError(t, err)
175 require.NotNil(t, output)
176 require.Len(t, output.Sessions, 1)
177 assert.Equal(t, int64(0), output.TotalSize) // Size defaults to 0 on error
178}