11using BikeTracking . Api . Application . Dashboard ;
22using BikeTracking . Api . Infrastructure . Persistence ;
33using BikeTracking . Api . Infrastructure . Persistence . Entities ;
4+ using BikeTracking . Api . Tests . TestSupport ;
45using Microsoft . EntityFrameworkCore ;
56
67namespace BikeTracking . Api . Tests . Application . Dashboard ;
@@ -37,7 +38,7 @@ public async Task GetAdvancedDashboardService_WithRidesInMultipleYears_ReturnsCo
3738 ) ;
3839 await dbContext . SaveChangesAsync ( ) ;
3940
40- var service = new GetAdvancedDashboardService ( dbContext ) ;
41+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
4142 var result = await service . GetAsync ( rider . UserId ) ;
4243
4344 // 20 miles / 20 mpg = 1 gallon + 10 miles / 10 mpg = 1 gallon = 2 total
@@ -79,7 +80,7 @@ public async Task GetAdvancedDashboardService_WithRideMissingGasPrice_FlagsFuelC
7980 ) ;
8081 await dbContext . SaveChangesAsync ( ) ;
8182
82- var service = new GetAdvancedDashboardService ( dbContext ) ;
83+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
8384 var result = await service . GetAsync ( rider . UserId ) ;
8485
8586 Assert . True ( result . SavingsWindows . AllTime . FuelCostEstimated ) ;
@@ -104,7 +105,7 @@ public async Task GetAdvancedDashboardService_UserWithNoMpgSetting_ReturnsMpgRem
104105 ) ;
105106 await dbContext . SaveChangesAsync ( ) ;
106107
107- var service = new GetAdvancedDashboardService ( dbContext ) ;
108+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
108109 var result = await service . GetAsync ( rider . UserId ) ;
109110
110111 Assert . True ( result . Reminders . MpgReminderRequired ) ;
@@ -129,7 +130,7 @@ public async Task GetAdvancedDashboardService_UserWithNoMileageRateSetting_Retur
129130 ) ;
130131 await dbContext . SaveChangesAsync ( ) ;
131132
132- var service = new GetAdvancedDashboardService ( dbContext ) ;
133+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
133134 var result = await service . GetAsync ( rider . UserId ) ;
134135
135136 Assert . False ( result . Reminders . MpgReminderRequired ) ;
@@ -171,7 +172,7 @@ public async Task GetAdvancedDashboardService_WithRidesInMultipleWindows_Returns
171172 ) ;
172173 await dbContext . SaveChangesAsync ( ) ;
173174
174- var service = new GetAdvancedDashboardService ( dbContext ) ;
175+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
175176 var result = await service . GetAsync ( rider . UserId ) ;
176177
177178 // Weekly: only the current-week ride (1 gallon)
@@ -200,7 +201,7 @@ public async Task GetAdvancedDashboardService_PartialMonthRides_HandlesZeroDivis
200201 ) ;
201202 await dbContext . SaveChangesAsync ( ) ;
202203
203- var service = new GetAdvancedDashboardService ( dbContext ) ;
204+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
204205 var result = await service . GetAsync ( rider . UserId ) ;
205206
206207 // Zero MPG rides should contribute null (not throw)
@@ -216,7 +217,11 @@ public async Task GetAdvancedDashboardService_RideThisWeek_ConsistencySuggestion
216217 using var dbContext = CreateDbContext ( ) ;
217218 var rider = await CreateRiderAsync ( dbContext , "Consistency Rider" ) ;
218219
219- var weekStart = DateTime . Now . Date . AddDays ( - ( ( ( int ) DateTime . Now . DayOfWeek - 1 + 7 ) % 7 ) ) ;
220+ // Fixed reference "now" (a Wednesday) removes dependency on wall-clock time so this
221+ // test can't flip near a real week boundary.
222+ var fixedNow = new DateTime ( 2026 , 1 , 14 , 12 , 0 , 0 , DateTimeKind . Utc ) ;
223+ var timeProvider = new FakeTimeProvider ( fixedNow ) ;
224+ var weekStart = fixedNow . Date . AddDays ( - ( ( ( int ) fixedNow . DayOfWeek - 1 + 7 ) % 7 ) ) ;
220225
221226 dbContext . Rides . Add (
222227 new RideEntity
@@ -229,7 +234,7 @@ public async Task GetAdvancedDashboardService_RideThisWeek_ConsistencySuggestion
229234 ) ;
230235 await dbContext . SaveChangesAsync ( ) ;
231236
232- var service = new GetAdvancedDashboardService ( dbContext ) ;
237+ var service = new GetAdvancedDashboardService ( dbContext , timeProvider ) ;
233238 var result = await service . GetAsync ( rider . UserId ) ;
234239
235240 var consistency = result . Suggestions . Single ( s => s . SuggestionKey == "consistency" ) ;
@@ -255,7 +260,7 @@ public async Task GetAdvancedDashboardService_CombinedSavingsExceed50_MilestoneS
255260 ) ;
256261 await dbContext . SaveChangesAsync ( ) ;
257262
258- var service = new GetAdvancedDashboardService ( dbContext ) ;
263+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
259264 var result = await service . GetAsync ( rider . UserId ) ;
260265
261266 var milestone = result . Suggestions . Single ( s => s . SuggestionKey == "milestone" ) ;
@@ -279,7 +284,7 @@ public async Task GetAdvancedDashboardService_LastRideMoreThan7DaysAgo_ComebackS
279284 ) ;
280285 await dbContext . SaveChangesAsync ( ) ;
281286
282- var service = new GetAdvancedDashboardService ( dbContext ) ;
287+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
283288 var result = await service . GetAsync ( rider . UserId ) ;
284289
285290 var comeback = result . Suggestions . Single ( s => s . SuggestionKey == "comeback" ) ;
@@ -294,7 +299,7 @@ public async Task GetAdvancedDashboardService_UserWithNoRides_ReturnsZeroValuesG
294299 using var dbContext = CreateDbContext ( ) ;
295300 var rider = await CreateRiderAsync ( dbContext , "No Rides Rider" ) ;
296301
297- var service = new GetAdvancedDashboardService ( dbContext ) ;
302+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
298303 var result = await service . GetAsync ( rider . UserId ) ;
299304
300305 Assert . Equal ( 0 , result . SavingsWindows . AllTime . RideCount ) ;
@@ -316,7 +321,7 @@ public async Task GetAdvancedDashboardService_NoSettings_BothReminderFlagsSet()
316321 using var dbContext = CreateDbContext ( ) ;
317322 var rider = await CreateRiderAsync ( dbContext , "NoSettings Rider" ) ;
318323
319- var service = new GetAdvancedDashboardService ( dbContext ) ;
324+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
320325 var result = await service . GetAsync ( rider . UserId ) ;
321326
322327 // No UserSettings row means both nulls
@@ -330,7 +335,7 @@ public async Task GetAdvancedDashboardService_ResponseIncludesAllThreeSuggestion
330335 using var dbContext = CreateDbContext ( ) ;
331336 var rider = await CreateRiderAsync ( dbContext , "AllSuggestions Rider" ) ;
332337
333- var service = new GetAdvancedDashboardService ( dbContext ) ;
338+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
334339 var result = await service . GetAsync ( rider . UserId ) ;
335340
336341 Assert . Equal ( 3 , result . Suggestions . Count ) ;
@@ -357,7 +362,7 @@ public async Task GetAdvancedDashboardService_MileageRateSavings_ComputedCorrect
357362 ) ;
358363 await dbContext . SaveChangesAsync ( ) ;
359364
360- var service = new GetAdvancedDashboardService ( dbContext ) ;
365+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
361366 var result = await service . GetAsync ( rider . UserId ) ;
362367
363368 // 10 miles × $0.67 = $6.70
@@ -412,7 +417,7 @@ public async Task GetAdvancedDashboardService_WithExpensesInWindow_IncludesExpen
412417 ) ;
413418 await dbContext . SaveChangesAsync ( ) ;
414419
415- var service = new GetAdvancedDashboardService ( dbContext ) ;
420+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
416421 var result = await service . GetAsync ( rider . UserId ) ;
417422
418423 Assert . Equal ( 50m , result . SavingsWindows . Monthly . TotalExpenses ) ;
@@ -450,7 +455,7 @@ public async Task GetAdvancedDashboardService_WithExpenses_NetSavingsIsCombinedM
450455 ) ;
451456 await dbContext . SaveChangesAsync ( ) ;
452457
453- var service = new GetAdvancedDashboardService ( dbContext ) ;
458+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
454459 var result = await service . GetAsync ( rider . UserId ) ;
455460
456461 // 100 miles × $0.67 = $67 combined savings - $30 expenses = $37 net
@@ -489,7 +494,7 @@ public async Task GetAdvancedDashboardService_ExpensesExceedSavings_NetSavingsIs
489494 ) ;
490495 await dbContext . SaveChangesAsync ( ) ;
491496
492- var service = new GetAdvancedDashboardService ( dbContext ) ;
497+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
493498 var result = await service . GetAsync ( rider . UserId ) ;
494499
495500 // Net savings should be negative: $6.70 - $20 = -$13.30
@@ -535,7 +540,7 @@ public async Task GetAdvancedDashboardService_WithOilChangePrice_IncludesWindowe
535540 ) ;
536541 await dbContext . SaveChangesAsync ( ) ;
537542
538- var service = new GetAdvancedDashboardService ( dbContext ) ;
543+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
539544 var result = await service . GetAsync ( rider . UserId ) ;
540545
541546 // 3200 miles total — crosses one 3000-mile interval → 1 oil change × $40 = $40
@@ -570,7 +575,7 @@ public async Task GetAdvancedDashboardService_WithNoOilChangePrice_OilChangeSavi
570575 ) ;
571576 await dbContext . SaveChangesAsync ( ) ;
572577
573- var service = new GetAdvancedDashboardService ( dbContext ) ;
578+ var service = new GetAdvancedDashboardService ( dbContext , TimeProvider . System ) ;
574579 var result = await service . GetAsync ( rider . UserId ) ;
575580
576581 Assert . Null ( result . SavingsWindows . AllTime . OilChangeSavings ) ;
0 commit comments