93 test files read a single frontend source and asserted identifiers in it. The
MapWorkspace split showed what that costs: 24 tests went red for a move that
changed no behaviour at all. A contract belongs to the feature — a container,
its hooks, its domain layer — not to whichever file currently holds it.
232 read sites now resolve through read_feature(). The distinction that makes
this safe is direction: a *positive* contract ("this is wired") may widen,
because the identifier must still exist somewhere in the feature; a *negative*
one ("this component performs no transport") is a statement about one file, and
widening it would quietly weaken the check. The 73 single-file reads that
remain are exactly those, and a guard now enforces the rule for new tests.
Verified rather than assumed: of the 732 migrated positive assertions, 644 still
match exactly one module — as specific as before — and the other 86 already
spanned a container and its hook by nature. Two apparent misses are an artefact
of the checking regex reading an escaped newline literally.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
279 lines
9.9 KiB
Python
279 lines
9.9 KiB
Python
from __future__ import annotations
|
|
|
|
import gzip
|
|
import importlib.util
|
|
import json
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
import pytest
|
|
from shapely.geometry import box, mapping, shape
|
|
|
|
from app.models import Dataset
|
|
from app.services.vector_feature_service import VectorFeatureService
|
|
from tests.frontend_contract import read_map_workspace, read_feature
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
SCRIPTS = ROOT / "scripts"
|
|
if str(SCRIPTS) not in sys.path:
|
|
sys.path.insert(0, str(SCRIPTS))
|
|
|
|
|
|
def load_script():
|
|
path = SCRIPTS / "provision_regional_bwk_natura2000.py"
|
|
spec = importlib.util.spec_from_file_location("test_provision_regional_bwk_natura2000", path)
|
|
assert spec is not None and spec.loader is not None
|
|
module = importlib.util.module_from_spec(spec)
|
|
sys.modules[spec.name] = module
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
class FakeResponse:
|
|
status_code = 200
|
|
ok = True
|
|
text = ""
|
|
|
|
def __init__(self, payload):
|
|
self.payload = payload
|
|
self.content = json.dumps(payload, separators=(",", ":")).encode("utf-8")
|
|
|
|
def json(self):
|
|
return self.payload
|
|
|
|
|
|
class FakeApiSession:
|
|
def __init__(self, payload):
|
|
self.payload = payload
|
|
self.calls = []
|
|
|
|
def post(self, url, **kwargs):
|
|
self.calls.append((url, kwargs))
|
|
return FakeResponse({"data": self.payload})
|
|
|
|
|
|
def source_feature(feature_id: str, geometry):
|
|
return {
|
|
"type": "Feature",
|
|
"id": feature_id,
|
|
"geometry": mapping(geometry),
|
|
"properties": {
|
|
"UIDN": feature_id,
|
|
"EVAL": "z",
|
|
"HAB1": "9190",
|
|
"PHAB1": 50,
|
|
"HABLEGENDE": "hab",
|
|
},
|
|
}
|
|
|
|
|
|
def test_partition_retains_gzipped_source_and_applies_member_context(tmp_path: Path, monkeypatch) -> None:
|
|
module = load_script()
|
|
scope = module.GeographicScope(
|
|
key="test-region",
|
|
display_name="Test region",
|
|
project_name="Test",
|
|
project_region="Test",
|
|
area_name="Test area",
|
|
authority_name="Test",
|
|
authority_url="https://example.test",
|
|
scope_type="test",
|
|
limitation_message="Test",
|
|
members=(module.ScopeMember("Mol", "13025"),),
|
|
)
|
|
boundary = box(5.0, 51.0, 5.1, 51.1)
|
|
payload = {
|
|
"type": "FeatureCollection",
|
|
"features": [source_feature("Bwkhab.1", box(4.98, 51.02, 5.05, 51.08))],
|
|
}
|
|
raw_bytes = json.dumps(payload, separators=(",", ":")).encode("utf-8")
|
|
monkeypatch.setattr(
|
|
module.bwk,
|
|
"iter_wfs_pages",
|
|
lambda *_args, **_kwargs: iter([(payload, "https://example.test/page", raw_bytes)]),
|
|
)
|
|
|
|
manifest = module.prepare_partition(
|
|
object(),
|
|
output_root=tmp_path,
|
|
scope=scope,
|
|
member=scope.members[0],
|
|
boundary_wgs84=boundary,
|
|
page_limit=100,
|
|
max_features=1000,
|
|
timeout=30,
|
|
force=False,
|
|
)
|
|
output = json.loads(Path(manifest["output_path"]).read_text(encoding="utf-8"))
|
|
feature = output["features"][0]
|
|
raw_path = Path(manifest["manifest_path"]).parent / manifest["raw_pages"][0]["artifact_path"]
|
|
|
|
assert manifest["feature_count"] == 1
|
|
assert feature["id"] == "BWK:Bwkhab:Bwkhab.1:13025"
|
|
assert feature["properties"]["municipality"] == "Mol"
|
|
assert feature["properties"]["coverage_scope"] == "test-region"
|
|
assert shape(feature["geometry"]).bounds == pytest.approx((5.0, 51.02, 5.05, 51.08), abs=1e-5)
|
|
assert gzip.decompress(raw_path.read_bytes()) == raw_bytes
|
|
|
|
cached = module.prepare_partition(
|
|
object(),
|
|
output_root=tmp_path,
|
|
scope=scope,
|
|
member=scope.members[0],
|
|
boundary_wgs84=boundary,
|
|
page_limit=100,
|
|
max_features=1000,
|
|
timeout=30,
|
|
force=False,
|
|
)
|
|
assert cached["output_sha256"] == manifest["output_sha256"]
|
|
|
|
|
|
def test_snapshot_assembles_unique_partitions_and_metrics(tmp_path: Path) -> None:
|
|
module = load_script()
|
|
scope = module.GeographicScope(
|
|
key="test-region",
|
|
display_name="Test region",
|
|
project_name="Test",
|
|
project_region="Test",
|
|
area_name="Test area",
|
|
authority_name="Test",
|
|
authority_url="https://example.test",
|
|
scope_type="test",
|
|
limitation_message="Test",
|
|
members=(module.ScopeMember("Left", "10001"), module.ScopeMember("Right", "10002")),
|
|
)
|
|
partitions = []
|
|
for index, member in enumerate(scope.members):
|
|
output_path, manifest_path, _raw_dir = module.partition_paths(tmp_path / scope.key, member.nis_code)
|
|
feature = source_feature(f"Bwkhab.{index}", box(index, 0, index + 0.5, 0.5))
|
|
feature["id"] = f"BWK:Bwkhab:Bwkhab.{index}:{member.nis_code}"
|
|
feature["properties"].update(
|
|
{
|
|
"clipped_area_ha": 1.0 + index,
|
|
"bwk_evaluation_code": "z",
|
|
"habitat_status_code": "hab",
|
|
"natura2000_area_ha": 0.5,
|
|
"regional_biotope_area_ha": 0.25,
|
|
"uncertain_habitat_area_ha": 0.0,
|
|
}
|
|
)
|
|
module.bwk.write_json_atomic(output_path, {"type": "FeatureCollection", "features": [feature]})
|
|
partitions.append(
|
|
{
|
|
"municipality": member.name,
|
|
"nis_code": member.nis_code,
|
|
"feature_count": 1,
|
|
"raw_source_feature_count": 1,
|
|
"page_count": 1,
|
|
"output_path": str(output_path),
|
|
"output_sha256": module.bwk.sha256_file(output_path),
|
|
"manifest_path": str(manifest_path),
|
|
}
|
|
)
|
|
|
|
output_path, _manifest_path, manifest = module.assemble_snapshot(
|
|
output_root=tmp_path,
|
|
scope=scope,
|
|
partitions=partitions,
|
|
member_boundaries_sha256="boundaries-hash",
|
|
max_total_features=10,
|
|
)
|
|
output = json.loads(output_path.read_text(encoding="utf-8"))
|
|
|
|
assert manifest["coverage_complete"] is True
|
|
assert manifest["feature_count"] == 2
|
|
assert manifest["evaluation_area_ha"]["z"] == 3.0
|
|
assert manifest["natura2000_area_ha"] == 1.0
|
|
assert len({feature["id"] for feature in output["features"]}) == 2
|
|
|
|
|
|
def test_upload_contract_is_regional_partitioned_and_canonical(tmp_path: Path) -> None:
|
|
module = load_script()
|
|
scope = module.GEOGRAPHIC_SCOPES["kempen-transport-region"]
|
|
path = tmp_path / "bwk.geojson"
|
|
path.write_text('{"type":"FeatureCollection","features":[]}', encoding="utf-8")
|
|
manifest_path = tmp_path / "manifest.json"
|
|
manifest = {
|
|
"coverage_complete": True,
|
|
"feature_count": 42,
|
|
"output_sha256": "output-hash",
|
|
"partition_identity_sha256": "partition-hash",
|
|
"partitions": [{} for _ in scope.members],
|
|
"generated_at": "2026-07-16T00:00:00+00:00",
|
|
"limitations": ["test"],
|
|
}
|
|
session = FakeApiSession({"id": "dataset-id", "feature_count": 42})
|
|
|
|
result = module.upload_snapshot(
|
|
session,
|
|
base_url="http://backend:8000",
|
|
project_id="project-id",
|
|
area_id="area-id",
|
|
scope=scope,
|
|
path=path,
|
|
manifest_path=manifest_path,
|
|
manifest=manifest,
|
|
timeout=30,
|
|
)
|
|
data = session.calls[0][1]["data"]
|
|
source_metadata = json.loads(data["source_metadata_json"])
|
|
provenance = json.loads(data["provenance_metadata_json"])
|
|
|
|
assert result["id"] == "dataset-id"
|
|
assert data["area_id"] == "area-id"
|
|
assert data["temporal_series_key"] == "inbo-bwk-natura2000:kempen-transport-region"
|
|
assert source_metadata["coverage_scope"] == "kempen-transport-region"
|
|
assert source_metadata["member_count"] == 28
|
|
assert source_metadata["partitioned_source_audit"] is True
|
|
assert source_metadata["selection_metrics"] == module.bwk.selection_metrics()
|
|
assert provenance["operator_tool"] == "provision_regional_bwk_natura2000.py"
|
|
assert provenance["raw_source_responses_retained"] is True
|
|
|
|
|
|
def test_regional_operator_is_packaged_release_checked_and_exact_area_is_preferred() -> None:
|
|
dockerfile = (ROOT / "deploy/unraid/Dockerfile.all-in-one").read_text(encoding="utf-8")
|
|
readiness = (ROOT / "scripts/run_readiness_check.sh").read_text(encoding="utf-8")
|
|
service = (ROOT / "backend/app/services/vector_feature_service.py").read_text(encoding="utf-8")
|
|
workspace = read_map_workspace()
|
|
catalog = read_feature("datasets")
|
|
model = (ROOT / "backend/app/models/entities.py").read_text(encoding="utf-8")
|
|
migration = (
|
|
ROOT / "backend/alembic/versions/202607160001_vector_feature_municipality_index.py"
|
|
).read_text(encoding="utf-8")
|
|
|
|
assert "COPY scripts/provision_regional_bwk_natura2000.py" in dockerfile
|
|
assert "py_compile scripts/provision_regional_bwk_natura2000.py" in readiness
|
|
assert '"provision_regional_bwk_natura2000.py"' in service
|
|
assert "dataset.area_id === selectedAreaId ? 10_000_000" in workspace
|
|
assert "largestBwkSnapshot" in catalog
|
|
assert "ix_vector_features_dataset_municipality" in model
|
|
assert "ix_vector_features_dataset_municipality" in migration
|
|
assert 'down_revision = "202607150001"' in migration
|
|
|
|
|
|
def test_regional_bwk_uses_only_canonical_preclipped_municipality_partitions() -> None:
|
|
dataset = Dataset(
|
|
name="regional-bwk.geojson",
|
|
dataset_type="vector",
|
|
status="ready",
|
|
source_metadata={
|
|
"partitioned_source_audit": True,
|
|
"geometry_clipped_to_area": True,
|
|
},
|
|
provenance_metadata={"operator_tool": "provision_regional_bwk_natura2000.py"},
|
|
)
|
|
|
|
assert VectorFeatureService.preclipped_partition_filter(
|
|
dataset, "Gemeente Mol - officiele grens"
|
|
) == ("municipality", "Mol")
|
|
assert VectorFeatureService.preclipped_partition_filter(
|
|
dataset, "Vervoerregio Kempen - officiële operationele grens"
|
|
) is None
|
|
|
|
dataset.provenance_metadata = {"operator_tool": "unrelated_operator.py"}
|
|
assert VectorFeatureService.preclipped_partition_filter(
|
|
dataset, "Gemeente Mol - officiele grens"
|
|
) is None
|