2026-07-12 18:05:13 -04:00
package query
import (
"testing"
"time"
"github.com/AmanTahiliani/box-box/internal/store"
)
func contextService ( t * testing . T , now time . Time ) * Service {
t . Helper ( )
base := openTestService ( t )
return NewServiceWithClock ( base . store , func ( ) time . Time { return now } )
}
func addContextMeeting ( t * testing . T , svc * Service , key int , name , start , end string , cancelled bool ) {
t . Helper ( )
if err := svc . store . UpsertMeeting ( store . Meeting { MeetingKey : key , MeetingName : name , MeetingOfficialName : name , CircuitShortName : name , Year : 2026 , DateStart : start , DateEnd : end , IsCancelled : cancelled } ) ; err != nil {
t . Fatal ( err )
}
}
func addContextSession ( t * testing . T , svc * Service , key , meeting int , name , start , end string , cancelled bool ) {
t . Helper ( )
if err := svc . store . UpsertSession ( store . Session { SessionKey : key , MeetingKey : meeting , SessionName : name , SessionType : name , DateStart : start , DateEnd : end , IsCancelled : cancelled } ) ; err != nil {
t . Fatal ( err )
}
}
func completeContextSession ( t * testing . T , svc * Service , key , meeting int ) {
t . Helper ( )
if err := svc . store . UpsertSessionResult ( store . SessionResult { SessionKey : key , MeetingKey : meeting , DriverNumber : 1 , Position : 1 } ) ; err != nil {
t . Fatal ( err )
}
}
func TestResolveWeekendContextTemporalStates ( t * testing . T ) {
tests := [ ] struct {
name string
now string
seed func ( * testing . T , * Service )
evidence LiveEvidence
want TemporalState
} {
{ name : "no season" , now : "2026-06-01T12:00:00Z" , want : TemporalNoSeason } ,
{ name : "between weekends" , now : "2026-06-10T12:00:00Z" , seed : func ( t * testing . T , s * Service ) {
addContextMeeting ( t , s , 1 , "Monaco Grand Prix" , "2026-06-01T09:00:00Z" , "2026-06-02T16:00:00Z" , false )
addContextSession ( t , s , 11 , 1 , "Race" , "2026-06-02T14:00:00Z" , "2026-06-02T16:00:00Z" , false )
completeContextSession ( t , s , 11 , 1 )
addContextMeeting ( t , s , 2 , "Canada Grand Prix" , "2026-06-20T09:00:00Z" , "2026-06-22T16:00:00Z" , false )
addContextSession ( t , s , 21 , 2 , "Practice 1" , "2026-06-20T09:00:00Z" , "2026-06-20T10:00:00Z" , false )
addContextSession ( t , s , 22 , 2 , "Race" , "2026-06-22T14:00:00Z" , "2026-06-22T16:00:00Z" , false )
} , want : TemporalBetweenWeekends } ,
{ name : "pre session" , now : "2026-06-19T12:00:00Z" , seed : func ( t * testing . T , s * Service ) {
addContextMeeting ( t , s , 2 , "Canada Grand Prix" , "2026-06-20T09:00:00Z" , "2026-06-22T16:00:00Z" , false )
addContextSession ( t , s , 21 , 2 , "Practice 1" , "2026-06-20T09:00:00Z" , "2026-06-20T10:00:00Z" , false )
addContextSession ( t , s , 22 , 2 , "Race" , "2026-06-22T14:00:00Z" , "2026-06-22T16:00:00Z" , false )
} , want : TemporalPreSession } ,
{ name : "session live overrides schedule" , now : "2026-06-20T12:00:00Z" , seed : func ( t * testing . T , s * Service ) {
addContextMeeting ( t , s , 2 , "Canada Grand Prix" , "2026-06-20T09:00:00Z" , "2026-06-22T16:00:00Z" , false )
addContextSession ( t , s , 21 , 2 , "Practice 1" , "2026-06-20T09:00:00Z" , "2026-06-20T10:00:00Z" , false )
addContextSession ( t , s , 22 , 2 , "Race" , "2026-06-22T14:00:00Z" , "2026-06-22T16:00:00Z" , false )
} , evidence : LiveEvidence { Active : true , MeetingName : "Canadian Grand Prix" , CircuitName : "Canada Grand Prix" , SessionName : "Practice 1" , SessionType : "Practice 1" } , want : TemporalSessionLive } ,
{ name : "session settling" , now : "2026-06-20T11:00:00Z" , seed : func ( t * testing . T , s * Service ) {
addContextMeeting ( t , s , 2 , "Canada Grand Prix" , "2026-06-20T09:00:00Z" , "2026-06-22T16:00:00Z" , false )
addContextSession ( t , s , 21 , 2 , "Practice 1" , "2026-06-20T09:00:00Z" , "2026-06-20T10:00:00Z" , false )
addContextSession ( t , s , 22 , 2 , "Race" , "2026-06-22T14:00:00Z" , "2026-06-22T16:00:00Z" , false )
} , want : TemporalSessionSettling } ,
{ name : "between sessions" , now : "2026-06-20T11:00:00Z" , seed : func ( t * testing . T , s * Service ) {
addContextMeeting ( t , s , 2 , "Canada Grand Prix" , "2026-06-20T09:00:00Z" , "2026-06-22T16:00:00Z" , false )
addContextSession ( t , s , 21 , 2 , "Practice 1" , "2026-06-20T09:00:00Z" , "2026-06-20T10:00:00Z" , false )
completeContextSession ( t , s , 21 , 2 )
addContextSession ( t , s , 22 , 2 , "Race" , "2026-06-22T14:00:00Z" , "2026-06-22T16:00:00Z" , false )
} , want : TemporalBetweenSessions } ,
{ name : "post weekend" , now : "2026-06-22T18:00:00Z" , seed : func ( t * testing . T , s * Service ) {
addContextMeeting ( t , s , 2 , "Canada Grand Prix" , "2026-06-20T09:00:00Z" , "2026-06-22T16:00:00Z" , false )
addContextSession ( t , s , 22 , 2 , "Race" , "2026-06-22T14:00:00Z" , "2026-06-22T16:00:00Z" , false )
completeContextSession ( t , s , 22 , 2 )
} , want : TemporalPostWeekend } ,
{ name : "season complete" , now : "2026-06-30T12:00:00Z" , seed : func ( t * testing . T , s * Service ) {
addContextMeeting ( t , s , 2 , "Canada Grand Prix" , "2026-06-20T09:00:00Z" , "2026-06-22T16:00:00Z" , false )
addContextSession ( t , s , 22 , 2 , "Race" , "2026-06-22T14:00:00Z" , "2026-06-22T16:00:00Z" , false )
completeContextSession ( t , s , 22 , 2 )
} , want : TemporalSeasonComplete } ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , tt . now )
svc := contextService ( t , now )
if tt . seed != nil {
tt . seed ( t , svc )
}
got , err := svc . ResolveWeekendContext ( tt . evidence )
if err != nil {
t . Fatal ( err )
}
if got . TemporalState != tt . want {
t . Fatalf ( "state = %s, want %s; context=%+v" , got . TemporalState , tt . want , got )
}
} )
}
}
func TestResolveWeekendContextTruthRules ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-10T12:00:00Z" )
svc := contextService ( t , now )
addContextMeeting ( t , svc , 1 , "Pre-Season Testing" , "2026-02-01T00:00:00Z" , "2026-02-03T00:00:00Z" , false )
addContextSession ( t , svc , 10 , 1 , "Race" , "2026-02-03T10:00:00Z" , "2026-02-03T12:00:00Z" , false )
addContextMeeting ( t , svc , 2 , "Cancelled Grand Prix" , "2026-03-01T00:00:00Z" , "2026-03-03T00:00:00Z" , true )
addContextSession ( t , svc , 20 , 2 , "Race" , "2026-03-03T10:00:00Z" , "2026-03-03T12:00:00Z" , false )
addContextMeeting ( t , svc , 3 , "British Grand Prix" , "2026-07-01T00:00:00Z" , "2026-07-05T00:00:00Z" , false )
addContextSession ( t , svc , 30 , 3 , "Practice 1" , "2026-07-03T09:00:00Z" , "2026-07-03T10:00:00Z" , false )
addContextSession ( t , svc , 31 , 3 , "Sprint" , "2026-07-04T10:00:00Z" , "2026-07-04T11:00:00Z" , false )
addContextSession ( t , svc , 32 , 3 , "Race" , "2026-07-05T14:00:00Z" , "2026-07-05T16:00:00Z" , false )
completeContextSession ( t , svc , 32 , 3 )
addContextMeeting ( t , svc , 4 , "Belgian Grand Prix" , "2026-07-16T00:00:00Z" , "2026-07-18T00:00:00Z" , false )
addContextSession ( t , svc , 40 , 4 , "Practice 1" , "2026-07-17T09:00:00Z" , "2026-07-17T10:00:00Z" , false )
addContextSession ( t , svc , 41 , 4 , "Cancelled Practice" , "2026-07-18T09:00:00Z" , "2026-07-18T10:00:00Z" , true )
addContextSession ( t , svc , 42 , 4 , "Race" , "2026-07-19T14:00:00Z" , "2026-07-19T16:00:00Z" , false )
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . TotalChampionshipRounds != 2 || got . ChampionshipRound != 2 {
t . Fatalf ( "rounds = %d/%d, want 2/2" , got . ChampionshipRound , got . TotalChampionshipRounds )
}
if got . DefaultAnalysisSession == nil || got . DefaultAnalysisSession . Session . SessionKey != 32 {
t . Fatalf ( "default analysis = %+v, want completed race 32" , got . DefaultAnalysisSession )
}
if got . NextSession == nil || got . NextSession . Session . SessionKey != 40 {
t . Fatalf ( "next = %+v, want 40" , got . NextSession )
}
if got . NextMeeting . DateStart != "2026-07-17T09:00:00Z" || got . NextMeeting . DateEnd != "2026-07-19T16:00:00Z" {
t . Fatalf ( "display range = %s..%s" , got . NextMeeting . DateStart , got . NextMeeting . DateEnd )
}
}
func TestResolveWeekendContextPassedTimeDoesNotCompleteSession ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-05T18:00:00Z" )
svc := contextService ( t , now )
addContextMeeting ( t , svc , 1 , "British Grand Prix" , "2026-07-03T00:00:00Z" , "2026-07-05T16:00:00Z" , false )
addContextSession ( t , svc , 11 , 1 , "Race" , "2026-07-05T14:00:00Z" , "2026-07-05T16:00:00Z" , false )
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . PreviousCompletedSession != nil || got . DefaultAnalysisSession != nil {
t . Fatalf ( "passed schedule was treated complete: %+v" , got )
}
archive , err := svc . ResolveWeekendContext ( LiveEvidence { Final : true , MeetingName : "British Grand Prix" , CircuitName : "British Grand Prix" , SessionName : "Race" , SessionType : "Race" , ObservedAt : now } )
if err != nil {
t . Fatal ( err )
}
if archive . PreviousCompletedSession == nil || archive . PreviousCompletedSession . Availability . Archive != "available" {
t . Fatalf ( "final archive not used: %+v" , archive )
}
if archive . DefaultAnalysisSession != nil {
t . Fatal ( "archive without local analysis must not become default analysis" )
}
}
2026-07-26 09:14:37 -04:00
func TestResolveWeekendContextAvailabilityUsesTruthfulSources ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-05T18:00:00Z" )
svc := contextService ( t , now )
addContextMeeting ( t , svc , 1 , "British Grand Prix" , "2026-07-03T00:00:00Z" , "2026-07-05T16:00:00Z" , false )
addContextSession ( t , svc , 11 , 1 , "Race" , "2026-07-05T14:00:00Z" , "2026-07-05T16:00:00Z" , false )
// Results without laps/stints/positions are meaningful but incomplete local
// analysis, so they must not be labelled universally fresh.
completeContextSession ( t , svc , 11 , 1 )
addContextMeeting ( t , svc , 2 , "Belgian Grand Prix" , "2026-07-17T00:00:00Z" , "2026-07-19T16:00:00Z" , false )
addContextSession ( t , svc , 21 , 2 , "Practice 1" , "2026-07-17T09:00:00Z" , "2026-07-17T10:00:00Z" , false )
addContextSession ( t , svc , 22 , 2 , "Race" , "2026-07-19T14:00:00Z" , "2026-07-19T16:00:00Z" , false )
local , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got := local . PreviousCompletedSession . Availability ; got . Source != "local" || got . Freshness != "partial" || got . LocalAnalysis != "partial" {
t . Fatalf ( "partial local availability = %+v" , got )
}
if got := local . NextSession . Availability ; got . Source != "local" || got . Freshness != "local" {
t . Fatalf ( "future local availability = %+v" , got )
}
liveContext , err := svc . ResolveWeekendContext ( LiveEvidence { Active : true , MeetingName : "Belgian Grand Prix" , CircuitName : "Belgian Grand Prix" , SessionName : "Practice 1" , SessionType : "Practice 1" , ObservedAt : now } )
if err != nil {
t . Fatal ( err )
}
if got := liveContext . ActiveSession . Availability ; got . Source != "mixed" || got . Freshness != "live" || got . LiveSession != "active" {
t . Fatalf ( "FIA + local availability = %+v" , got )
}
archiveContext , err := svc . ResolveWeekendContext ( LiveEvidence { Final : true , MeetingName : "British Grand Prix" , CircuitName : "British Grand Prix" , SessionName : "Race" , SessionType : "Race" , ObservedAt : now } )
if err != nil {
t . Fatal ( err )
}
if got := archiveContext . PreviousCompletedSession . Availability ; got . Source != "mixed" || got . Freshness != "archive" || got . Archive != "available" {
t . Fatalf ( "FIA archive + local availability = %+v" , got )
}
synthetic , err := svc . ResolveWeekendContext ( LiveEvidence { Active : true , MeetingName : "Unscheduled Grand Prix" , SessionName : "Race" , SessionType : "Race" , ObservedAt : now } )
if err != nil {
t . Fatal ( err )
}
if got := synthetic . ActiveSession . Availability ; got . Source != "fia" || got . Freshness != "live" || got . Schedule != "unavailable" {
t . Fatalf ( "synthetic FIA availability = %+v" , got )
}
}
2026-07-12 18:05:13 -04:00
func TestResolveWeekendContextNeverUsesFutureAnalysis ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-01T12:00:00Z" )
svc := contextService ( t , now )
addContextMeeting ( t , svc , 1 , "British Grand Prix" , "2026-07-03T00:00:00Z" , "2026-07-05T16:00:00Z" , false )
addContextSession ( t , svc , 11 , 1 , "Race" , "2026-07-05T14:00:00Z" , "2026-07-05T16:00:00Z" , false )
completeContextSession ( t , svc , 11 , 1 ) // bad/preloaded data must not make a future session canonical
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . PreviousCompletedSession != nil || got . DefaultAnalysisSession != nil {
t . Fatalf ( "future analysis selected: %+v" , got )
}
}
2026-07-26 09:11:03 -04:00
// Regression for the v0.4.0 release blocker (#90). Production held a run
// British race (11326) and an unrun Belgian race (11334) two weekends apart.
// Analysis must resolve to the race that actually happened, even when the
// later meeting carries preloaded rows.
func TestResolveWeekendContextPrefersRunRaceOverLaterUnrunRace ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-13T12:00:00Z" )
svc := contextService ( t , now )
addContextMeeting ( t , svc , 1289 , "British Grand Prix" , "2026-07-03T11:30:00Z" , "2026-07-05T16:00:00Z" , false )
addContextSession ( t , svc , 11326 , 1289 , "Race" , "2026-07-05T14:00:00Z" , "2026-07-05T16:00:00Z" , false )
completeContextSession ( t , svc , 11326 , 1289 )
addContextMeeting ( t , svc , 1290 , "Belgian Grand Prix" , "2026-07-17T11:30:00Z" , "2026-07-19T15:00:00Z" , false )
addContextSession ( t , svc , 11334 , 1290 , "Race" , "2026-07-19T13:00:00Z" , "2026-07-19T15:00:00Z" , false )
completeContextSession ( t , svc , 11334 , 1290 )
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . DefaultAnalysisSession == nil {
t . Fatal ( "no analysis session resolved" )
}
if key := got . DefaultAnalysisSession . Session . SessionKey ; key != 11326 {
t . Fatalf ( "analysis session = %d, want 11326 (British); 11334 is the unrun Belgian race" , key )
}
if got . PreviousCompletedSession == nil || got . PreviousCompletedSession . Session . SessionKey != 11326 {
t . Fatalf ( "previous completed = %+v, want 11326" , got . PreviousCompletedSession )
}
if got . NextSession == nil || got . NextSession . Session . SessionKey != 11334 {
t . Fatalf ( "next session = %+v, want 11334" , got . NextSession )
}
}
2026-07-12 18:05:13 -04:00
func TestResolveWeekendContextSprintWeekendHandoff ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-04T12:00:00Z" )
svc := contextService ( t , now )
addContextMeeting ( t , svc , 1 , "British Grand Prix" , "2026-07-03T09:00:00Z" , "2026-07-05T16:00:00Z" , false )
addContextSession ( t , svc , 11 , 1 , "Sprint" , "2026-07-04T10:00:00Z" , "2026-07-04T11:00:00Z" , false )
addContextSession ( t , svc , 12 , 1 , "Race" , "2026-07-05T14:00:00Z" , "2026-07-05T16:00:00Z" , false )
completeContextSession ( t , svc , 11 , 1 )
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . TemporalState != TemporalBetweenSessions || got . PreviousCompletedSession . Session . SessionKey != 11 || got . NextSession . Session . SessionKey != 12 {
t . Fatalf ( "sprint handoff = %+v" , got )
}
if got . TotalChampionshipRounds != 1 {
t . Fatalf ( "sprint created extra championship round: %d" , got . TotalChampionshipRounds )
}
}
func TestResolveWeekendContextBoundaryTimestamps ( t * testing . T ) {
t . Run ( "pre-session window is inclusive" , func ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-01T09:00:00Z" )
svc := contextService ( t , now )
addContextMeeting ( t , svc , 1 , "British Grand Prix" , "2026-07-03T09:00:00Z" , "2026-07-05T16:00:00Z" , false )
addContextSession ( t , svc , 11 , 1 , "Practice 1" , "2026-07-03T09:00:00Z" , "2026-07-03T10:00:00Z" , false )
addContextSession ( t , svc , 12 , 1 , "Race" , "2026-07-05T14:00:00Z" , "2026-07-05T16:00:00Z" , false )
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . TemporalState != TemporalPreSession {
t . Fatalf ( "state = %s" , got . TemporalState )
}
} )
t . Run ( "scheduled end enters settling" , func ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-03T10:00:00Z" )
svc := contextService ( t , now )
addContextMeeting ( t , svc , 1 , "British Grand Prix" , "2026-07-03T09:00:00Z" , "2026-07-05T16:00:00Z" , false )
addContextSession ( t , svc , 11 , 1 , "Practice 1" , "2026-07-03T09:00:00Z" , "2026-07-03T10:00:00Z" , false )
addContextSession ( t , svc , 12 , 1 , "Race" , "2026-07-05T14:00:00Z" , "2026-07-05T16:00:00Z" , false )
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . TemporalState != TemporalSessionSettling {
t . Fatalf ( "state = %s" , got . TemporalState )
}
} )
t . Run ( "post-weekend window is inclusive" , func ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-07T16:00:00Z" )
svc := contextService ( t , now )
addContextMeeting ( t , svc , 1 , "British Grand Prix" , "2026-07-03T09:00:00Z" , "2026-07-05T16:00:00Z" , false )
addContextSession ( t , svc , 12 , 1 , "Race" , "2026-07-05T14:00:00Z" , "2026-07-05T16:00:00Z" , false )
completeContextSession ( t , svc , 12 , 1 )
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . TemporalState != TemporalPostWeekend {
t . Fatalf ( "state = %s" , got . TemporalState )
}
} )
}
func TestResolveWeekendContextPartialFutureSchedule ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-01T12:00:00Z" )
svc := contextService ( t , now )
addContextMeeting ( t , svc , 1 , "British Grand Prix" , "2026-07-03T09:00:00Z" , "" , false )
addContextSession ( t , svc , 11 , 1 , "Practice 1" , "" , "" , false )
addContextSession ( t , svc , 12 , 1 , "Race" , "2026-07-05T14:00:00Z" , "" , false )
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . NextSession == nil || got . NextSession . Session . SessionKey != 12 {
t . Fatalf ( "partial schedule next = %+v" , got . NextSession )
}
if got . FocusMeeting == nil || got . FocusMeeting . DateStart != "2026-07-05T14:00:00Z" || got . FocusMeeting . DateEnd != "2026-07-05T14:00:00Z" {
t . Fatalf ( "partial display range = %+v" , got . FocusMeeting )
}
}
2026-07-12 18:15:14 -04:00
func TestResolveWeekendContextActiveSessionIsNotCompletedOrDefault ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-05T15:00:00Z" )
svc := contextService ( t , now )
addContextMeeting ( t , svc , 1 , "British Grand Prix" , "2026-07-03T09:00:00Z" , "2026-07-05T16:00:00Z" , false )
addContextSession ( t , svc , 10 , 1 , "Qualifying" , "2026-07-04T14:00:00Z" , "2026-07-04T15:00:00Z" , false )
completeContextSession ( t , svc , 10 , 1 )
addContextSession ( t , svc , 11 , 1 , "Race" , "2026-07-05T14:00:00Z" , "2026-07-05T16:00:00Z" , false )
completeContextSession ( t , svc , 11 , 1 )
got , err := svc . ResolveWeekendContext ( LiveEvidence { Active : true , MeetingName : "British Grand Prix" , CircuitName : "British Grand Prix" , SessionName : "Race" , SessionType : "Race" , ObservedAt : now } )
if err != nil {
t . Fatal ( err )
}
if got . ActiveSession == nil || got . ActiveSession . Session . SessionKey != 11 {
t . Fatalf ( "active = %+v" , got . ActiveSession )
}
if got . PreviousCompletedSession == nil || got . PreviousCompletedSession . Session . SessionKey != 10 {
t . Fatalf ( "previous = %+v, want earlier completed session" , got . PreviousCompletedSession )
}
if got . DefaultAnalysisSession == nil || got . DefaultAnalysisSession . Session . SessionKey != 10 {
t . Fatalf ( "default = %+v, want earlier completed session" , got . DefaultAnalysisSession )
}
}
func TestResolveWeekendContextOldIncompleteSessionDoesNotSuppressNextWeekend ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-16T12:00:00Z" )
svc := contextService ( t , now )
addContextMeeting ( t , svc , 1 , "British Grand Prix" , "2026-07-03T09:00:00Z" , "2026-07-05T16:00:00Z" , false )
addContextSession ( t , svc , 11 , 1 , "Race" , "2026-07-05T14:00:00Z" , "2026-07-05T16:00:00Z" , false )
addContextMeeting ( t , svc , 2 , "Belgian Grand Prix" , "2026-07-17T09:00:00Z" , "2026-07-19T16:00:00Z" , false )
addContextSession ( t , svc , 21 , 2 , "Practice 1" , "2026-07-17T09:00:00Z" , "2026-07-17T10:00:00Z" , false )
addContextSession ( t , svc , 22 , 2 , "Race" , "2026-07-19T14:00:00Z" , "2026-07-19T16:00:00Z" , false )
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . TemporalState != TemporalPreSession {
t . Fatalf ( "state = %s, want %s; context=%+v" , got . TemporalState , TemporalPreSession , got )
}
if got . FocusMeeting == nil || got . FocusMeeting . MeetingKey != 2 {
t . Fatalf ( "focus = %+v, want Belgian weekend" , got . FocusMeeting )
}
}
func TestResolveWeekendContextMissingScheduleDoesNotClaimSeasonComplete ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-01T12:00:00Z" )
svc := contextService ( t , now )
addContextMeeting ( t , svc , 1 , "British Grand Prix" , "" , "" , false )
addContextSession ( t , svc , 11 , 1 , "Race" , "" , "" , false )
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . TemporalState != TemporalBetweenWeekends {
t . Fatalf ( "state = %s, want limited %s context" , got . TemporalState , TemporalBetweenWeekends )
}
if got . TotalChampionshipRounds != 1 {
t . Fatalf ( "total rounds = %d, want scheduled round retained" , got . TotalChampionshipRounds )
}
}
2026-07-29 03:28:42 -04:00
func TestResolveWeekendContextRaceHubDefault ( t * testing . T ) {
seed := func ( t * testing . T , svc * Service ) {
addContextMeeting ( t , svc , 1 , "British Grand Prix" , "2026-07-03T09:00:00Z" , "2026-07-05T16:00:00Z" , false )
addContextSession ( t , svc , 11 , 1 , "Race" , "2026-07-05T14:00:00Z" , "2026-07-05T16:00:00Z" , false )
completeContextSession ( t , svc , 11 , 1 )
addContextMeeting ( t , svc , 2 , "Belgian Grand Prix" , "2026-07-17T09:00:00Z" , "2026-07-19T16:00:00Z" , false )
addContextSession ( t , svc , 21 , 2 , "Practice 1" , "2026-07-17T09:00:00Z" , "2026-07-17T10:00:00Z" , false )
}
t . Run ( "keeps completed analysis before handoff" , func ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-16T07:59:59Z" )
svc := contextService ( t , now )
seed ( t , svc )
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . RaceHubDefaultSession == nil || got . RaceHubDefaultSession . Session . SessionKey != 11 || got . RaceHubPreSession {
t . Fatalf ( "race hub default = %+v, pre-session = %t" , got . RaceHubDefaultSession , got . RaceHubPreSession )
}
if got . RaceHubRefreshAt != "2026-07-17T08:00:00Z" {
t . Fatalf ( "refresh = %q" , got . RaceHubRefreshAt )
}
} )
t . Run ( "hands off exactly one hour before first session" , func ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-17T08:00:00Z" )
svc := contextService ( t , now )
seed ( t , svc )
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . RaceHubDefaultSession == nil || got . RaceHubDefaultSession . Session . SessionKey != 21 || ! got . RaceHubPreSession {
t . Fatalf ( "race hub handoff = %+v, pre-session = %t" , got . RaceHubDefaultSession , got . RaceHubPreSession )
}
if got . RaceHubRefreshAt != "2026-07-17T09:00:00Z" {
t . Fatalf ( "refresh = %q" , got . RaceHubRefreshAt )
}
} )
2026-07-29 03:46:57 -04:00
t . Run ( "keeps the scheduled session pending after its start without live evidence" , func ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-17T09:00:00Z" )
svc := contextService ( t , now )
seed ( t , svc )
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . RaceHubDefaultSession == nil || got . RaceHubDefaultSession . Session . SessionKey != 21 || ! got . RaceHubPreSession {
t . Fatalf ( "scheduled race hub default = %+v, pre-session = %t" , got . RaceHubDefaultSession , got . RaceHubPreSession )
}
if got . RaceHubRefreshAt != "2026-07-17T09:00:15Z" {
t . Fatalf ( "refresh = %q" , got . RaceHubRefreshAt )
}
} )
2026-07-29 03:28:42 -04:00
t . Run ( "active live session wins" , func ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-17T08:30:00Z" )
svc := contextService ( t , now )
seed ( t , svc )
got , err := svc . ResolveWeekendContext ( LiveEvidence { Active : true , MeetingName : "Belgian Grand Prix" , SessionName : "Practice 1" , SessionType : "Practice 1" } )
if err != nil {
t . Fatal ( err )
}
if got . RaceHubDefaultSession == nil || got . RaceHubDefaultSession . Session . SessionKey != 21 || got . RaceHubPreSession {
t . Fatalf ( "live default = %+v, pre-session = %t" , got . RaceHubDefaultSession , got . RaceHubPreSession )
}
} )
t . Run ( "does not select an empty future session before handoff" , func ( t * testing . T ) {
now , _ := time . Parse ( time . RFC3339 , "2026-07-16T12:00:00Z" )
svc := contextService ( t , now )
addContextMeeting ( t , svc , 2 , "Belgian Grand Prix" , "2026-07-17T09:00:00Z" , "2026-07-19T16:00:00Z" , false )
addContextSession ( t , svc , 21 , 2 , "Practice 1" , "2026-07-17T09:00:00Z" , "2026-07-17T10:00:00Z" , false )
got , err := svc . ResolveWeekendContext ( LiveEvidence { } )
if err != nil {
t . Fatal ( err )
}
if got . RaceHubDefaultSession != nil || got . RaceHubPreSession {
t . Fatalf ( "unexpected empty future default: %+v" , got )
}
} )
}