From a7ae408ab2afc949d3602e5544ca2bcb738bd853 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Mon, 27 Jul 2026 11:22:28 +0000 Subject: [PATCH] =?UTF-8?q?Report=20a=20void=20property=20when=20Abri=20fi?= =?UTF-8?q?nds=20no=20tenancy=20for=20the=20place=20=F0=9F=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 (1M context) --- domain/abri/models.py | 15 ++++++++++++++- ...tscstenantdata_notenancyfound_response.xml | 6 ++++++ tests/infrastructure/abri/test_abri_client.py | 19 +++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/abri/abri_relay_getscstenantdata_notenancyfound_response.xml diff --git a/domain/abri/models.py b/domain/abri/models.py index f60729382..adc3b876e 100644 --- a/domain/abri/models.py +++ b/domain/abri/models.py @@ -108,7 +108,20 @@ class TenancyData: tenants: Tuple[Tenant, ...] -GetTenantDataResult = Union[TenancyData, AbriRequestRejected] +@dataclass(frozen=True) +class NoTenancyFound: + """Abri reports no live tenancy for the place: the property is void. + + Distinct from a TenancyData carrying no tenants (a tenancy exists, but + nobody is recorded against it) and from a rejection (the request itself + was refused). Only Abri's exact No_tenancy_found signal means this; the + query-dump variant of the same words is a genuine failure. + """ + + place_ref: PlaceRef + + +GetTenantDataResult = Union[TenancyData, NoTenancyFound, AbriRequestRejected] @dataclass(frozen=True) diff --git a/tests/abri/abri_relay_getscstenantdata_notenancyfound_response.xml b/tests/abri/abri_relay_getscstenantdata_notenancyfound_response.xml new file mode 100644 index 000000000..f1157d057 --- /dev/null +++ b/tests/abri/abri_relay_getscstenantdata_notenancyfound_response.xml @@ -0,0 +1,6 @@ + + + false + RelayError + No_tenancy_found + diff --git a/tests/infrastructure/abri/test_abri_client.py b/tests/infrastructure/abri/test_abri_client.py index cf6308863..7fa5a95a4 100644 --- a/tests/infrastructure/abri/test_abri_client.py +++ b/tests/infrastructure/abri/test_abri_client.py @@ -15,6 +15,7 @@ from domain.abri.models import ( JobAbandoned, JobLogged, LogJobRequest, + NoTenancyFound, PlaceRef, ) from infrastructure.abri.abri_client import AbriClient @@ -556,3 +557,21 @@ def test_abandon_job_sends_the_recorded_canceljob_envelope_to_the_relay_endpoint assert ET.canonicalize(xml_data=sent_body, strip_text=True) == ET.canonicalize( xml_data=expected_body, strip_text=True ) + + +# --- get_tenant_data: a void property is not a rejection --- + + +def test_get_tenant_data_reports_a_void_property_when_abri_finds_no_tenancy( + client: AbriClient, mock_session: MagicMock +) -> None: + # Arrange: Abri's agreed signal that the place is known to be empty. + mock_session.post.return_value.content = _load_fixture( + "abri_relay_getscstenantdata_notenancyfound_response.xml" + ) + + # Act + result = client.get_tenant_data(PlaceRef("1004202A")) + + # Assert + assert result == NoTenancyFound(place_ref=PlaceRef("1004202A"))