@@ -28,6 +28,8 @@ def test_octopus_download_rates(my_predbat):
2828 10. download_octopus_rates_func - HTTP error status
2929 11. download_octopus_rates_func - JSON decode error
3030 12. download_octopus_rates_func - missing 'results' key
31+ 13. No current/future rates (#2726) - falls back to stale cache when available
32+ 14. No current/future rates (#2726) - raises ValueError when no cache available
3133 """
3234 print ("\n === Test Octopus download_octopus_rates ===" )
3335 failed = False
@@ -38,6 +40,11 @@ def test_octopus_download_rates(my_predbat):
3840 my_predbat .midnight_utc = datetime .strptime ("2024-06-12T00:00:00+00:00" , "%Y-%m-%dT%H:%M:%S%z" )
3941 my_predbat .debug_enable = False
4042 my_predbat .failures_total = 0
43+ # All the mock rate data below starts at minute 0 and covers forward from there - pin "now"
44+ # to 0 so the #2726 "has current rates" check (added below, tested explicitly in Test 13/14)
45+ # passes for scenarios that aren't about that check, regardless of real wall-clock time or
46+ # whatever a previous test left minutes_now as.
47+ my_predbat .minutes_now = 0
4148
4249 # Mock the download_octopus_rates_func to return rate data
4350 mock_rate_data = {
@@ -195,6 +202,50 @@ def test_octopus_download_rates(my_predbat):
195202 else :
196203 print ("✓ Test 6 passed - Retry mechanism works correctly" )
197204
205+ # Test 13: No current/future rates (#2726) - falls back to stale cache when available.
206+ # A retired Octopus product's URL can still return a valid 200/JSON response with genuine
207+ # historical results, so this can't be caught by any of the existing failure paths above -
208+ # it needs its own check that the data actually reaches "now" onward.
209+ print ("\n Test 13: No current/future rates (#2726) - falls back to stale cache" )
210+ test_url = "https://api.octopus.energy/test-stale-product"
211+ stale_cached_data = {0 : 8.0 , 60 : 9.0 }
212+ my_predbat .octopus_url_cache = {
213+ test_url : {
214+ "stamp" : datetime .now () - timedelta (minutes = 50 ), # expired, forces a fresh download
215+ "midnight_utc" : my_predbat .midnight_utc ,
216+ "data" : stale_cached_data ,
217+ }
218+ }
219+ my_predbat .minutes_now = 120
220+ # Every key is before "now" (120) - looks like a retired product still serving historical data.
221+ historical_only_data = {0 : 5.0 , 60 : 6.0 }
222+
223+ with patch .object (my_predbat , 'download_octopus_rates_func' , return_value = historical_only_data ):
224+ result = my_predbat .download_octopus_rates (test_url )
225+
226+ if result != stale_cached_data :
227+ print (f"✗ Test 13 failed - Expected stale cached data { stale_cached_data } , got { result } " )
228+ failed = True
229+ else :
230+ print ("✓ Test 13 passed - No current rates falls back to stale cache" )
231+
232+ # Test 14: No current/future rates (#2726) - raises ValueError when no cache available
233+ print ("\n Test 14: No current/future rates (#2726) - raises ValueError when no cache" )
234+ test_url = "https://api.octopus.energy/test-stale-product-no-cache"
235+ my_predbat .octopus_url_cache = {}
236+ my_predbat .minutes_now = 120
237+ historical_only_data = {0 : 5.0 , 60 : 6.0 }
238+
239+ with patch .object (my_predbat , 'download_octopus_rates_func' , return_value = historical_only_data ):
240+ try :
241+ result = my_predbat .download_octopus_rates (test_url )
242+ print ("✗ Test 14 failed - Expected ValueError to be raised" )
243+ failed = True
244+ except ValueError :
245+ print ("✓ Test 14 passed - ValueError raised when no current rates and no cache" )
246+
247+ my_predbat .minutes_now = 0 # restore for the remaining tests below
248+
198249 # Test 7: download_octopus_rates_func - successful single page
199250 print ("\n Test 7: download_octopus_rates_func - successful single page" )
200251 my_predbat .debug_enable = False
0 commit comments