From b33735ef3076ac986fa8493c086c356ef27c9540 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Thu, 2 Jul 2026 11:03:38 +0000 Subject: [PATCH] =?UTF-8?q?NI=20(insulation=20present)=20and=20measured=20?= =?UTF-8?q?depths=20keep=20a=20vaulted=20roof=20ineligible=20=F0=9F=9F=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../modelling/test_roof_recommendation.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/domain/modelling/test_roof_recommendation.py b/tests/domain/modelling/test_roof_recommendation.py index defc239cd..3acdbb86f 100644 --- a/tests/domain/modelling/test_roof_recommendation.py +++ b/tests/domain/modelling/test_roof_recommendation.py @@ -130,6 +130,43 @@ def test_vaulted_ceiling_with_nd_thickness_on_limited_insulation_age_band_yields assert recommendation is None +def test_vaulted_ceiling_with_ni_thickness_yields_no_recommendation() -> None: + # Arrange — "NI" means insulation PRESENT at unknown thickness (RdSAP 10 + # §5.11.4: score as 50 mm), never "no insulation" — even on an age band + # whose as-built state is uninsulated (ADR-0047, the ND ≠ NI distinction). + baseline: EpcPropertyData = build_epc() + main: SapBuildingPart = _part(baseline, BuildingPartIdentifier.MAIN) + main.roof_construction_type = "Pitched (vaulted ceiling)" + main.roof_insulation_thickness = "NI" + main.construction_age_band = "B" + + # Act + recommendation: Recommendation | None = recommend_roof_insulation( + baseline, _StubProducts() + ) + + # Assert + assert recommendation is None + + +def test_vaulted_ceiling_with_measured_thickness_yields_no_recommendation() -> None: + # Arrange — an explicitly-lodged depth means the rafters are already + # insulated; the sentinel-aware trigger must not loosen the numeric rule. + baseline: EpcPropertyData = build_epc() + main: SapBuildingPart = _part(baseline, BuildingPartIdentifier.MAIN) + main.roof_construction_type = "Pitched (vaulted ceiling)" + main.roof_insulation_thickness = 100 + main.construction_age_band = "B" + + # Act + recommendation: Recommendation | None = recommend_roof_insulation( + baseline, _StubProducts() + ) + + # Assert + assert recommendation is None + + def test_loft_option_carries_cost_from_roof_area_and_product() -> None: # Arrange baseline: EpcPropertyData = build_epc() # MAIN roof area 14.85 m^2