@@ -267,6 +267,13 @@ func TestGetJourney_Success_WithContent(t *testing.T) {
267267 assert .Contains (t , bodyStr , "Bridge Timelapse" )
268268 assert .Contains (t , bodyStr , "photo-1" )
269269 assert .Contains (t , bodyStr , "video-1" )
270+
271+ // Verify section headers appear
272+ assert .Contains (t , bodyStr , "Unknown Date" ) // for video-1 without CapturedAt
273+
274+ // Verify date section appears (capturedAt was yesterday)
275+ yesterday := time .Now ().Add (- 24 * time .Hour ).UTC ().Format ("2006-01-02" )
276+ assert .Contains (t , bodyStr , yesterday )
270277}
271278
272279func TestGetJourney_Success_NoContent (t * testing.T ) {
@@ -402,3 +409,127 @@ func TestGetJourney_EmptyID(t *testing.T) {
402409 // Assertions - should return error
403410 assert .NotEqual (t , http .StatusOK , resp .StatusCode )
404411}
412+
413+ // Helper for tests
414+ func ptrTime (t time.Time ) * time.Time {
415+ return & t
416+ }
417+
418+ func TestGroupContentByDate (t * testing.T ) {
419+ tests := []struct {
420+ name string
421+ contents []Content
422+ want []ContentSection
423+ }{
424+ {
425+ name : "empty content" ,
426+ contents : []Content {},
427+ want : []ContentSection {},
428+ },
429+ {
430+ name : "all content without CapturedAt" ,
431+ contents : []Content {
432+ {ID : "1" , Title : "Photo 1" , UploadedAt : time .Date (2025 , 1 , 15 , 10 , 0 , 0 , 0 , time .UTC )},
433+ {ID : "2" , Title : "Photo 2" , UploadedAt : time .Date (2025 , 1 , 15 , 11 , 0 , 0 , 0 , time .UTC )},
434+ },
435+ want : []ContentSection {
436+ {
437+ DateKey : "Unknown" ,
438+ DisplayDate : "Unknown Date" ,
439+ SortOrder : - 9223372036854775807 ,
440+ Contents : []Content {
441+ {ID : "1" , Title : "Photo 1" , UploadedAt : time .Date (2025 , 1 , 15 , 10 , 0 , 0 , 0 , time .UTC )},
442+ {ID : "2" , Title : "Photo 2" , UploadedAt : time .Date (2025 , 1 , 15 , 11 , 0 , 0 , 0 , time .UTC )},
443+ },
444+ },
445+ },
446+ },
447+ {
448+ name : "content grouped by two different dates" ,
449+ contents : []Content {
450+ {ID : "1" , CapturedAt : ptrTime (time .Date (2025 , 1 , 15 , 10 , 30 , 0 , 0 , time .UTC ))},
451+ {ID : "2" , CapturedAt : ptrTime (time .Date (2025 , 1 , 15 , 14 , 0 , 0 , 0 , time .UTC ))},
452+ {ID : "3" , CapturedAt : ptrTime (time .Date (2025 , 1 , 16 , 9 , 0 , 0 , 0 , time .UTC ))},
453+ },
454+ want : []ContentSection {
455+ {
456+ DateKey : "2025-01-16" ,
457+ DisplayDate : "2025-01-16" ,
458+ Contents : []Content {{ID : "3" , CapturedAt : ptrTime (time .Date (2025 , 1 , 16 , 9 , 0 , 0 , 0 , time .UTC ))}},
459+ },
460+ {
461+ DateKey : "2025-01-15" ,
462+ DisplayDate : "2025-01-15" ,
463+ Contents : []Content {
464+ {ID : "1" , CapturedAt : ptrTime (time .Date (2025 , 1 , 15 , 10 , 30 , 0 , 0 , time .UTC ))},
465+ {ID : "2" , CapturedAt : ptrTime (time .Date (2025 , 1 , 15 , 14 , 0 , 0 , 0 , time .UTC ))},
466+ },
467+ },
468+ },
469+ },
470+ {
471+ name : "mixed: unknown date appears first" ,
472+ contents : []Content {
473+ {ID : "1" , CapturedAt : ptrTime (time .Date (2025 , 1 , 15 , 10 , 0 , 0 , 0 , time .UTC ))},
474+ {ID : "2" , CapturedAt : nil , UploadedAt : time .Date (2025 , 1 , 15 , 12 , 0 , 0 , 0 , time .UTC )},
475+ {ID : "3" , CapturedAt : ptrTime (time .Date (2025 , 1 , 16 , 10 , 0 , 0 , 0 , time .UTC ))},
476+ },
477+ want : []ContentSection {
478+ {
479+ DateKey : "Unknown" ,
480+ DisplayDate : "Unknown Date" ,
481+ SortOrder : - 9223372036854775807 ,
482+ Contents : []Content {{ID : "2" , CapturedAt : nil , UploadedAt : time .Date (2025 , 1 , 15 , 12 , 0 , 0 , 0 , time .UTC )}},
483+ },
484+ {
485+ DateKey : "2025-01-16" ,
486+ DisplayDate : "2025-01-16" ,
487+ Contents : []Content {{ID : "3" , CapturedAt : ptrTime (time .Date (2025 , 1 , 16 , 10 , 0 , 0 , 0 , time .UTC ))}},
488+ },
489+ {
490+ DateKey : "2025-01-15" ,
491+ DisplayDate : "2025-01-15" ,
492+ Contents : []Content {{ID : "1" , CapturedAt : ptrTime (time .Date (2025 , 1 , 15 , 10 , 0 , 0 , 0 , time .UTC ))}},
493+ },
494+ },
495+ },
496+ {
497+ name : "within section sorting: earliest to latest" ,
498+ contents : []Content {
499+ {ID : "1" , CapturedAt : ptrTime (time .Date (2025 , 1 , 15 , 14 , 0 , 0 , 0 , time .UTC ))},
500+ {ID : "2" , CapturedAt : ptrTime (time .Date (2025 , 1 , 15 , 9 , 0 , 0 , 0 , time .UTC ))},
501+ {ID : "3" , CapturedAt : ptrTime (time .Date (2025 , 1 , 15 , 12 , 0 , 0 , 0 , time .UTC ))},
502+ },
503+ want : []ContentSection {
504+ {
505+ DateKey : "2025-01-15" ,
506+ DisplayDate : "2025-01-15" ,
507+ Contents : []Content {
508+ {ID : "2" , CapturedAt : ptrTime (time .Date (2025 , 1 , 15 , 9 , 0 , 0 , 0 , time .UTC ))}, // 9:00
509+ {ID : "3" , CapturedAt : ptrTime (time .Date (2025 , 1 , 15 , 12 , 0 , 0 , 0 , time .UTC ))}, // 12:00
510+ {ID : "1" , CapturedAt : ptrTime (time .Date (2025 , 1 , 15 , 14 , 0 , 0 , 0 , time .UTC ))}, // 14:00
511+ },
512+ },
513+ },
514+ },
515+ }
516+
517+ for _ , tt := range tests {
518+ t .Run (tt .name , func (t * testing.T ) {
519+ got := groupContentByDate (tt .contents )
520+
521+ assert .Equal (t , len (tt .want ), len (got ), "section count mismatch" )
522+
523+ for i := range tt .want {
524+ assert .Equal (t , tt .want [i ].DateKey , got [i ].DateKey , "DateKey mismatch at section %d" , i )
525+ assert .Equal (t , tt .want [i ].DisplayDate , got [i ].DisplayDate , "DisplayDate mismatch at section %d" , i )
526+ assert .Equal (t , len (tt .want [i ].Contents ), len (got [i ].Contents ), "Contents count mismatch at section %d" , i )
527+
528+ // Verify content IDs in correct order
529+ for j := range tt .want [i ].Contents {
530+ assert .Equal (t , tt .want [i ].Contents [j ].ID , got [i ].Contents [j ].ID , "Content ID mismatch at section %d, item %d" , i , j )
531+ }
532+ }
533+ })
534+ }
535+ }
0 commit comments