@@ -369,6 +369,99 @@ def _mock_fetch_config_options():
369369 else :
370370 print ("PASS T12: run_all() restores config: overrides inside the per-tariff loop, not just once at the end" )
371371
372+ # ------------------------------------------------------------------
373+ # T13: run_single() re-plans iBoost against the tariff's own rates
374+ # instead of leaving it stuck with the plan computed for the live
375+ # tariff (the compare-plan iBoost timing bug)
376+ # ------------------------------------------------------------------
377+ cmp , pb = _make_compare ()
378+ pb .iboost_enable = True
379+ pb .iboost_solar = False
380+ pb .iboost_charging = False
381+ pb .iboost_smart = True
382+ pb .iboost_today = 3.0
383+ pb .import_today_now = 0
384+ pb .export_today_now = 0
385+ pb .cost_today_sofar = 0
386+ pb .carbon_today_sofar = 0
387+ pb .forecast_plan_hours = 48
388+ pb .manual_charge_times = None
389+ pb .manual_export_times = None
390+ pb .manual_freeze_charge_times = None
391+ pb .manual_freeze_export_times = None
392+ pb .manual_demand_times = None
393+ pb .manual_all_times = None
394+ pb .octopus_intelligent_charging = False
395+ pb .iboost_plan = ["stale_plan_from_live_tariff" ]
396+
397+ tariff_plan_calls = []
398+
399+ def _mock_plan_iboost_smart ():
400+ tariff_plan_calls .append (1 )
401+ return ["fresh_plan_for_this_tariff" ]
402+
403+ pb .plan_iboost_smart = _mock_plan_iboost_smart
404+
405+ cmp .fetch_config = lambda tariff : None
406+ cmp .apply_hardware_overrides = lambda tariff , pb : None
407+ cmp .fetch_rates = lambda tariff , base_import , base_export : "existing"
408+ cmp .recompute_car_charging = lambda slots : None
409+ cmp .run_scenario = lambda end_record : {"cost" : 0 , "metric" : 0 }
410+
411+ result = cmp .run_single ({"name" : "test_tariff" , "id" : "test" }, {}, {}, 48 * 60 , fetch_sensor = False )
412+
413+ if not tariff_plan_calls :
414+ print ("ERROR T13: plan_iboost_smart() was not called during run_single()" )
415+ failed += 1
416+ elif pb .iboost_plan != ["fresh_plan_for_this_tariff" ]:
417+ print ("ERROR T13: iboost_plan should be replaced with the tariff-specific plan, got {}" .format (pb .iboost_plan ))
418+ failed += 1
419+ else :
420+ print ("PASS T13: run_single() re-plans iBoost using the compared tariff's own rates" )
421+
422+ # ------------------------------------------------------------------
423+ # T14: run_single() clears iboost_plan (rather than reusing a stale one)
424+ # when iBoost smart-rate planning isn't applicable for this tariff run
425+ # ------------------------------------------------------------------
426+ cmp , pb = _make_compare ()
427+ pb .iboost_enable = True
428+ pb .iboost_solar = True
429+ pb .iboost_charging = True
430+ pb .iboost_smart = False
431+ pb .iboost_today = 0
432+ pb .import_today_now = 0
433+ pb .export_today_now = 0
434+ pb .cost_today_sofar = 0
435+ pb .carbon_today_sofar = 0
436+ pb .forecast_plan_hours = 48
437+ pb .manual_charge_times = None
438+ pb .manual_export_times = None
439+ pb .manual_freeze_charge_times = None
440+ pb .manual_freeze_export_times = None
441+ pb .manual_demand_times = None
442+ pb .manual_all_times = None
443+ pb .octopus_intelligent_charging = False
444+ pb .iboost_plan = ["stale_plan_from_live_tariff" ]
445+ pb .plan_iboost_smart = lambda : tariff_plan_calls .append (1 ) or []
446+
447+ cmp .fetch_config = lambda tariff : None
448+ cmp .apply_hardware_overrides = lambda tariff , pb : None
449+ cmp .fetch_rates = lambda tariff , base_import , base_export : "existing"
450+ cmp .recompute_car_charging = lambda slots : None
451+ cmp .run_scenario = lambda end_record : {"cost" : 0 , "metric" : 0 }
452+
453+ tariff_plan_calls .clear ()
454+ cmp .run_single ({"name" : "test_tariff2" , "id" : "test2" }, {}, {}, 48 * 60 , fetch_sensor = False )
455+
456+ if tariff_plan_calls :
457+ print ("ERROR T14: plan_iboost_smart() should not be called when iboost_charging/iboost_solar handle boosting and iboost_smart is off" )
458+ failed += 1
459+ elif pb .iboost_plan != []:
460+ print ("ERROR T14: stale iboost_plan from the live tariff should be cleared, got {}" .format (pb .iboost_plan ))
461+ failed += 1
462+ else :
463+ print ("PASS T14: run_single() clears stale iboost_plan when smart-rate planning isn't applicable" )
464+
372465 if failed :
373466 print ("**** compare tests FAILED: {} errors ****\n " .format (failed ))
374467 else :
0 commit comments