@@ -8,182 +8,6 @@ import (
88 "github.com/tduyng/codeme/core"
99)
1010
11- func TestSessionManager_GroupSessions (t * testing.T ) {
12- baseTime := time .Date (2025 , 1 , 15 , 10 , 0 , 0 , 0 , time .UTC )
13-
14- tests := []struct {
15- name string
16- activities []core.Activity
17- expectedSessions int
18- timeout time.Duration
19- minDuration time.Duration
20- checkFirstSession func (t * testing.T , s core.Session )
21- }{
22- {
23- name : "empty activities" ,
24- activities : []core.Activity {},
25- expectedSessions : 0 ,
26- },
27- {
28- name : "single activity" ,
29- activities : []core.Activity {
30- {
31- ID : "1" ,
32- Timestamp : baseTime ,
33- Duration : 120 ,
34- Language : "go" ,
35- Project : "test" ,
36- },
37- },
38- expectedSessions : 1 ,
39- checkFirstSession : func (t * testing.T , s core.Session ) {
40- require .Equal (t , "1" , s .ID )
41- require .Contains (t , s .Projects , "test" )
42- require .Contains (t , s .Languages , "go" )
43- },
44- },
45- {
46- name : "two activities same session" ,
47- activities : []core.Activity {
48- {ID : "1" , Timestamp : baseTime , Duration : 120 , Language : "go" , Project : "p1" },
49- {ID : "2" , Timestamp : baseTime .Add (5 * time .Minute ), Duration : 120 , Language : "go" , Project : "p1" },
50- },
51- expectedSessions : 1 ,
52- checkFirstSession : func (t * testing.T , s core.Session ) {
53- require .Greater (t , s .Duration , 0.0 )
54- },
55- },
56- {
57- name : "timeout creates new session" ,
58- activities : []core.Activity {
59- {ID : "1" , Timestamp : baseTime , Duration : 120 , Language : "go" , Project : "p1" },
60- {ID : "2" , Timestamp : baseTime .Add (30 * time .Minute ), Duration : 120 , Language : "go" , Project : "p1" },
61- },
62- expectedSessions : 2 ,
63- timeout : 15 * time .Minute ,
64- },
65- {
66- name : "mixed languages" ,
67- activities : []core.Activity {
68- {ID : "1" , Timestamp : baseTime , Duration : 120 , Language : "go" , Project : "p1" },
69- {ID : "2" , Timestamp : baseTime .Add (2 * time .Minute ), Duration : 120 , Language : "typescript" , Project : "p1" },
70- {ID : "3" , Timestamp : baseTime .Add (4 * time .Minute ), Duration : 120 , Language : "python" , Project : "p1" },
71- },
72- expectedSessions : 1 ,
73- checkFirstSession : func (t * testing.T , s core.Session ) {
74- require .Len (t , s .Languages , 3 )
75- require .Contains (t , s .Languages , "go" )
76- require .Contains (t , s .Languages , "typescript" )
77- require .Contains (t , s .Languages , "python" )
78- },
79- },
80- {
81- name : "mixed projects" ,
82- activities : []core.Activity {
83- {ID : "1" , Timestamp : baseTime , Duration : 120 , Language : "go" , Project : "p1" },
84- {ID : "2" , Timestamp : baseTime .Add (2 * time .Minute ), Duration : 120 , Language : "go" , Project : "p2" },
85- },
86- expectedSessions : 1 ,
87- checkFirstSession : func (t * testing.T , s core.Session ) {
88- require .Len (t , s .Projects , 2 )
89- require .Contains (t , s .Projects , "p1" )
90- require .Contains (t , s .Projects , "p2" )
91- },
92- },
93- {
94- name : "exactly at timeout boundary" ,
95- activities : []core.Activity {
96- {ID : "1" , Timestamp : baseTime , Duration : 120 , Language : "go" , Project : "p1" },
97- {ID : "2" , Timestamp : baseTime .Add (15 * time .Minute ), Duration : 120 , Language : "go" , Project : "p1" },
98- },
99- expectedSessions : 1 ,
100- timeout : 15 * time .Minute ,
101- },
102- {
103- name : "just over timeout" ,
104- activities : []core.Activity {
105- {ID : "1" , Timestamp : baseTime , Duration : 120 , Language : "go" , Project : "p1" },
106- {ID : "2" , Timestamp : baseTime .Add (15 * time .Minute + time .Second ), Duration : 120 , Language : "go" , Project : "p1" },
107- },
108- expectedSessions : 2 ,
109- timeout : 15 * time .Minute ,
110- },
111- {
112- name : "invalid language filtered" ,
113- activities : []core.Activity {
114- {ID : "1" , Timestamp : baseTime , Duration : 120 , Language : "" , Project : "p1" },
115- {ID : "2" , Timestamp : baseTime .Add (2 * time .Minute ), Duration : 120 , Language : "unknown" , Project : "p1" },
116- },
117- expectedSessions : 1 ,
118- checkFirstSession : func (t * testing.T , s core.Session ) {
119- require .Len (t , s .Languages , 0 )
120- },
121- },
122- {
123- name : "unsorted activities" ,
124- activities : func () []core.Activity {
125- // Activities are now expected to be sorted by timestamp
126- // (guaranteed from DB query in production)
127- return []core.Activity {
128- {ID : "1" , Timestamp : baseTime , Duration : 120 , Language : "go" , Project : "p1" },
129- {ID : "2" , Timestamp : baseTime .Add (5 * time .Minute ), Duration : 120 , Language : "go" , Project : "p1" },
130- {ID : "3" , Timestamp : baseTime .Add (10 * time .Minute ), Duration : 120 , Language : "go" , Project : "p1" },
131- }
132- }(),
133- expectedSessions : 1 ,
134- checkFirstSession : func (t * testing.T , s core.Session ) {
135- require .Equal (t , "1" , s .ID )
136- },
137- },
138- }
139-
140- for _ , tt := range tests {
141- t .Run (tt .name , func (t * testing.T ) {
142- timeout := tt .timeout
143- if timeout == 0 {
144- timeout = 15 * time .Minute
145- }
146- minDuration := tt .minDuration
147- if minDuration == 0 {
148- minDuration = 1 * time .Minute
149- }
150-
151- sm := NewSessionManager (timeout , minDuration )
152- sessions := sm .GroupSessions (tt .activities )
153-
154- require .Len (t , sessions , tt .expectedSessions )
155-
156- if tt .expectedSessions > 0 && tt .checkFirstSession != nil {
157- tt .checkFirstSession (t , sessions [0 ])
158- }
159- })
160- }
161- }
162-
163- func TestSessionManager_BreakCalculation (t * testing.T ) {
164- baseTime := time .Date (2025 , 1 , 15 , 10 , 0 , 0 , 0 , time .UTC )
165-
166- activities := []core.Activity {
167- {ID : "1" , Timestamp : baseTime , Duration : 120 , Language : "go" , Project : "p1" },
168- {ID : "2" , Timestamp : baseTime .Add (30 * time .Minute ), Duration : 120 , Language : "go" , Project : "p1" },
169- {ID : "3" , Timestamp : baseTime .Add (90 * time .Minute ), Duration : 120 , Language : "go" , Project : "p1" },
170- }
171-
172- sm := NewSessionManager (15 * time .Minute , 1 * time .Minute )
173- sessions := sm .GroupSessions (activities )
174-
175- require .Len (t , sessions , 3 )
176-
177- // First session should have break to second
178- require .Greater (t , sessions [0 ].BreakAfter , 0.0 )
179-
180- // Second session should have break to third
181- require .Greater (t , sessions [1 ].BreakAfter , 0.0 )
182-
183- // Last session has no break
184- require .Equal (t , 0.0 , sessions [2 ].BreakAfter )
185- }
186-
18711func TestConvertSessionsToAPI (t * testing.T ) {
18812 baseTime := time .Date (2025 , 1 , 15 , 10 , 0 , 0 , 0 , time .UTC )
18913
@@ -222,48 +46,3 @@ func TestConvertSessionsToAPI(t *testing.T) {
22246 require .Equal (t , "2" , apiSessions [1 ].ID )
22347 require .True (t , apiSessions [1 ].IsActive )
22448}
225-
226- func TestSessionManager_EdgeCases (t * testing.T ) {
227- t .Run ("same timestamp activities" , func (t * testing.T ) {
228- baseTime := time .Date (2025 , 1 , 15 , 10 , 0 , 0 , 0 , time .UTC )
229-
230- activities := []core.Activity {
231- {ID : "1" , Timestamp : baseTime , Duration : 120 , Language : "go" , Project : "p1" },
232- {ID : "2" , Timestamp : baseTime , Duration : 120 , Language : "go" , Project : "p1" },
233- }
234-
235- sm := NewSessionManager (15 * time .Minute , 1 * time .Minute )
236- sessions := sm .GroupSessions (activities )
237-
238- require .Len (t , sessions , 1 )
239- })
240-
241- t .Run ("zero duration activities" , func (t * testing.T ) {
242- baseTime := time .Date (2025 , 1 , 15 , 10 , 0 , 0 , 0 , time .UTC )
243-
244- activities := []core.Activity {
245- {ID : "1" , Timestamp : baseTime , Duration : 0 , Language : "go" , Project : "p1" },
246- }
247-
248- sm := NewSessionManager (15 * time .Minute , 1 * time .Minute )
249- sessions := sm .GroupSessions (activities )
250-
251- // Single activity gets idleCap duration (120s), which passes minDuration
252- require .Len (t , sessions , 1 )
253- })
254-
255- t .Run ("cross-day session" , func (t * testing.T ) {
256- day1 := time .Date (2025 , 1 , 15 , 23 , 50 , 0 , 0 , time .UTC )
257- day2 := time .Date (2025 , 1 , 16 , 0 , 5 , 0 , 0 , time .UTC )
258-
259- activities := []core.Activity {
260- {ID : "1" , Timestamp : day1 , Duration : 600 , Language : "go" , Project : "p1" },
261- {ID : "2" , Timestamp : day2 , Duration : 600 , Language : "go" , Project : "p1" },
262- }
263-
264- sm := NewSessionManager (15 * time .Minute , 1 * time .Minute )
265- sessions := sm .GroupSessions (activities )
266-
267- require .Len (t , sessions , 1 )
268- })
269- }
0 commit comments