diff --git a/datatypes/epc/domain/tests/test_from_rdsap_schema.py b/datatypes/epc/domain/tests/test_from_rdsap_schema.py index a817414c..07fc7ddb 100644 --- a/datatypes/epc/domain/tests/test_from_rdsap_schema.py +++ b/datatypes/epc/domain/tests/test_from_rdsap_schema.py @@ -2710,22 +2710,48 @@ def test_rdsap_mappers_carry_main_heating_controls_display( (RdSapSchema17_1, EpcPropertyDataMapper.from_rdsap_schema_17_1, "17_1.json"), (RdSapSchema18_0, EpcPropertyDataMapper.from_rdsap_schema_18_0, "18_0.json"), (RdSapSchema20_0_0, EpcPropertyDataMapper.from_rdsap_schema_20_0_0, "20_0_0.json"), + (RdSapSchema19_0, EpcPropertyDataMapper.from_rdsap_schema_19_0, "19_0.json"), + (RdSapSchema21_0_0, EpcPropertyDataMapper.from_rdsap_schema_21_0_0, "21_0_0.json"), ], ) def test_rdsap_mappers_map_mechanical_ventilation_kind( schema_cls: Any, mapper: Any, fixture: str ) -> None: # Calc-facing: an MVHR cert (mechanical_ventilation=4) must reach the §2 - # ventilation cascade as MVHR, not be silently treated as natural. These - # three build a bare SapVentilation(sheltered_sides=…) and dropped the - # top-level mechanical_ventilation; 17.0 + 21.0.1 + full-SAP already map it - # (via _sap_17_1_ventilation / their own wiring). 19.0 + 21.0.0 set no - # sap_ventilation at all — a bigger, separate gap (see followups). Natural + # ventilation cascade as MVHR, not be silently treated as natural. 17.1 / + # 18.0 / 20.0.0 built a bare SapVentilation(sheltered_sides=…) and dropped + # the top-level mechanical_ventilation (fixed in #1333); 19.0 + 21.0.0 set + # no sap_ventilation at all, dropping the whole block (fixed here — the + # remaining ADR-0037 ventilation follow-up). 17.0 + 21.0.1 + full-SAP + # already map it (via _sap_17_1_ventilation / their own wiring). Natural # certs (code 0/5 → None) are unchanged, so the fix only moves genuine - # MEV/MVHR certs (ADR-0037 follow-up). + # MEV/MVHR certs. data = load(fixture) data["mechanical_ventilation"] = 4 result = mapper(from_dict(schema_cls, data)) assert result.sap_ventilation.mechanical_ventilation_kind == "MVHR" + + +@pytest.mark.parametrize( + "schema_cls, mapper, fixture", + [ + (RdSapSchema19_0, EpcPropertyDataMapper.from_rdsap_schema_19_0, "19_0.json"), + (RdSapSchema21_0_0, EpcPropertyDataMapper.from_rdsap_schema_21_0_0, "21_0_0.json"), + ], +) +def test_rdsap_19_0_21_0_0_construct_sap_ventilation_block( + schema_cls: Any, mapper: Any, fixture: str +) -> None: + # 19.0 + 21.0.0 previously passed no `sap_ventilation=` at all → the + # EpcPropertyData default empty SapVentilation, dropping the entire §2 + # block (sheltered_sides + kind). Mirroring 21.0.1, they now construct it. + # `sheltered_sides` derives from built_form per §S5 (both fixtures lodge + # built_form=2 Semi-Detached → 1 sheltered side); a missing/empty block + # would leave it None and over-count shelter via the cascade default of 2. + schema = from_dict(schema_cls, load(fixture)) + + result = mapper(schema) + + assert result.sap_ventilation.sheltered_sides == 1