@@ -1281,6 +1281,52 @@ async def test_treat_runtimeparams_preserves_high_out_of_band_soc_init(self):
12811281 self .assertEqual (params_out ["passed_data" ]["soc_init" ], 0.95 )
12821282 self .assertEqual (params_out ["passed_data" ]["soc_final" ], 0.6 )
12831283
1284+ async def test_treat_runtimeparams_ignore_pv_feedback_during_curtailment (self ):
1285+ """Wiring for ignore_pv_feedback_during_curtailment runtime flag (#818).
1286+
1287+ The read site in forecast.py reads from params["passed_data"]; this
1288+ test pins the runtime → passed_data path for the four realistic input
1289+ shapes: missing key (default False), JSON bool true, string "true",
1290+ string "false". The string cases document the bool() coerce behaviour.
1291+ """
1292+ params = await TestUtils .get_test_params ()
1293+ params_json = orjson .dumps (params ).decode ("utf-8" )
1294+ retrieve_hass_conf , optim_conf , plant_conf = utils .get_yaml_parse (params_json , logger )
1295+
1296+ async def run (runtimeparams_dict ):
1297+ runtimeparams_json = orjson .dumps (runtimeparams_dict ).decode ("utf-8" )
1298+ params_out , _ , _ , _ = await treat_runtimeparams (
1299+ runtimeparams_json ,
1300+ params_json ,
1301+ retrieve_hass_conf ,
1302+ optim_conf ,
1303+ plant_conf ,
1304+ "naive-mpc-optim" ,
1305+ logger ,
1306+ emhass_conf ,
1307+ )
1308+ return orjson .loads (params_out )
1309+
1310+ # Case 1: key absent -> default False
1311+ out = await run ({"prediction_horizon" : 10 })
1312+ self .assertIs (out ["passed_data" ]["ignore_pv_feedback_during_curtailment" ], False )
1313+
1314+ # Case 2: JSON bool true -> True
1315+ out = await run ({"prediction_horizon" : 10 , "ignore_pv_feedback_during_curtailment" : True })
1316+ self .assertIs (out ["passed_data" ]["ignore_pv_feedback_during_curtailment" ], True )
1317+
1318+ # Case 3: string "true" -> bool() coerce -> True
1319+ out = await run ({"prediction_horizon" : 10 , "ignore_pv_feedback_during_curtailment" : "true" })
1320+ self .assertIs (out ["passed_data" ]["ignore_pv_feedback_during_curtailment" ], True )
1321+
1322+ # Case 4: string "false" -> bool() coerce -> True (Python bool("false") is True)
1323+ # Documents the known limitation of bool() on non-empty strings;
1324+ # JSON bool transport is the supported shape.
1325+ out = await run (
1326+ {"prediction_horizon" : 10 , "ignore_pv_feedback_during_curtailment" : "false" }
1327+ )
1328+ self .assertIs (out ["passed_data" ]["ignore_pv_feedback_during_curtailment" ], True )
1329+
12841330 def test_param_to_config (self ):
12851331 """Test converting built params back to a flat config dictionary and masking secrets."""
12861332 # Create a mock parameter dictionary with the required categories
0 commit comments