diff --git a/tests/domain/epc_prediction/test_epc_prediction.py b/tests/domain/epc_prediction/test_epc_prediction.py index 4b0ff149..c7ffbf52 100644 --- a/tests/domain/epc_prediction/test_epc_prediction.py +++ b/tests/domain/epc_prediction/test_epc_prediction.py @@ -17,6 +17,7 @@ from datatypes.epc.domain.epc_property_data import ( SapEnergySource, SapFloorDimension, SapHeating, + SapVentilation, SapWindow, ) from domain.geospatial.coordinates import Coordinates @@ -54,6 +55,7 @@ def _epc( meter_type: str = "2", main_heating_label: str = "Boiler and radiators, mains gas", main_heating_controls_label: Optional[str] = None, + mechanical_ventilation_kind: Optional[str] = None, ) -> EpcPropertyData: epc: EpcPropertyData = object.__new__(EpcPropertyData) epc.property_type = "2" @@ -108,6 +110,10 @@ def _epc( ) epc.has_hot_water_cylinder = has_hot_water_cylinder epc.solar_water_heating = solar_water_heating + epc.sap_ventilation = SapVentilation( + mechanical_ventilation_kind=mechanical_ventilation_kind, + sheltered_sides=1, + ) energy: SapEnergySource = object.__new__(SapEnergySource) energy.meter_type = meter_type epc.sap_energy_source = energy @@ -557,6 +563,31 @@ def test_heating_is_a_coherent_donor_not_the_structural_template() -> None: assert predicted.has_hot_water_cylinder is True +def test_ventilation_kind_follows_the_cohort_mode() -> None: + # Mechanical ventilation (MEV/MVHR) is a new-build / retrofit feature that + # clusters by era and street — like glazing — so the predicted ventilation + # kind takes the recency/geo-weighted cohort mode, not the size-template's. + # The size-closest template here is natural (None); the cohort is + # predominantly MVHR, so the prediction must reflect the MVHR neighbourhood + # rather than leave the template's empty ventilation (predicted property + # 721167 follow-up). Natural-vent cohorts mode to None and stay natural. + cohort = _cohort( + _epc(mechanical_ventilation_kind=None), # template (size tie → first) + _epc(mechanical_ventilation_kind="MVHR"), + _epc(mechanical_ventilation_kind="MVHR"), + _epc(mechanical_ventilation_kind="MVHR"), + ) + + # Act + predicted: EpcPropertyData = EpcPrediction().predict( + PredictionTarget(postcode="LS6 1AA", property_type="2"), cohort + ) + + # Assert — the predicted kind is the cohort's MVHR mode, not the template's None. + assert predicted.sap_ventilation is not None + assert predicted.sap_ventilation.mechanical_ventilation_kind == "MVHR" + + def test_glazing_follows_the_recency_weighted_cohort_mode() -> None: # Arrange — an old majority single-glazed (type 1, 2015) and a recent # minority double-glazed (type 3, 2025). Glazing is retrofitted over time