GeoIntel release gates / Compile, test, contracts and builds (push) Successful in 1m49s
GeoIntel release gates / Python and npm vulnerability policy (push) Successful in 21s
GeoIntel release gates / Production AI image, SBOM and container scan (push) Successful in 5m39s
GeoIntel release gates / Deploy exact gated revision to Unraid (push) Failing after 58m43s
130 lines
4.2 KiB
Python
130 lines
4.2 KiB
Python
"""An exported GeoJSON must say what it is and what it leaves out.
|
|
|
|
The vector selection export caps its features and records ``truncated`` in the
|
|
export *record*. The file itself said nothing: an operator downloads
|
|
``mol-selection.geojson``, opens it in QGIS and sees 250 buildings where the
|
|
workbench said 1.400, with nothing in the file to indicate the difference.
|
|
|
|
For a product whose promise is that an export is a reproducible result, a file
|
|
that looks complete and is not is the sharpest possible violation. RFC 7946
|
|
allows foreign members on a FeatureCollection, and the detection export already
|
|
uses one; this makes that convention uniform.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime, timezone
|
|
from uuid import uuid4
|
|
|
|
from app.services.export_service import ExportService
|
|
|
|
|
|
def test_provenance_names_the_source_and_the_moment() -> None:
|
|
dataset_id = uuid4()
|
|
project_id = uuid4()
|
|
|
|
member = ExportService.provenance_member(
|
|
source="vector_selection",
|
|
project_id=project_id,
|
|
dataset_id=dataset_id,
|
|
source_name="grb",
|
|
source_version="2024-06",
|
|
observed_at=datetime(2024, 6, 1, tzinfo=timezone.utc),
|
|
)
|
|
|
|
assert member["source"] == "vector_selection"
|
|
assert member["dataset_id"] == str(dataset_id)
|
|
assert member["project_id"] == str(project_id)
|
|
assert member["source_name"] == "grb"
|
|
assert member["source_version"] == "2024-06"
|
|
assert member["observed_at"].startswith("2024-06-01")
|
|
assert member["exported_at"]
|
|
|
|
|
|
def test_a_truncated_export_says_so_in_words() -> None:
|
|
member = ExportService.provenance_member(
|
|
source="vector_selection",
|
|
project_id=uuid4(),
|
|
dataset_id=uuid4(),
|
|
feature_count=250,
|
|
total_feature_count=1_400,
|
|
truncated=True,
|
|
)
|
|
|
|
assert member["complete"] is False
|
|
assert member["feature_count"] == 250
|
|
assert member["total_feature_count"] == 1_400
|
|
assert "1400" in member["completeness_note"].replace(".", "").replace(",", "")
|
|
assert "250" in member["completeness_note"]
|
|
|
|
|
|
def test_a_complete_export_is_stated_as_complete() -> None:
|
|
member = ExportService.provenance_member(
|
|
source="detection_run",
|
|
project_id=uuid4(),
|
|
dataset_id=uuid4(),
|
|
feature_count=12,
|
|
total_feature_count=12,
|
|
truncated=False,
|
|
)
|
|
|
|
assert member["complete"] is True
|
|
assert member["completeness_note"] is None
|
|
|
|
|
|
def test_counts_that_disagree_are_treated_as_incomplete() -> None:
|
|
"""A caller that forgets the flag must not produce a file claiming completeness."""
|
|
|
|
member = ExportService.provenance_member(
|
|
source="vector_selection",
|
|
project_id=uuid4(),
|
|
dataset_id=uuid4(),
|
|
feature_count=100,
|
|
total_feature_count=140,
|
|
truncated=False,
|
|
)
|
|
|
|
assert member["complete"] is False
|
|
|
|
|
|
def test_selection_context_travels_with_the_file() -> None:
|
|
area_id = uuid4()
|
|
bbox = {"min_x": 5.0, "min_y": 51.1, "max_x": 5.2, "max_y": 51.3, "crs": "EPSG:4326"}
|
|
|
|
member = ExportService.provenance_member(
|
|
source="vector_selection",
|
|
project_id=uuid4(),
|
|
dataset_id=uuid4(),
|
|
selection_bbox=bbox,
|
|
selection_area_id=area_id,
|
|
warnings=["22 van de 100 objecten liggen deels buiten de selectie."],
|
|
)
|
|
|
|
assert member["selection_bbox"] == bbox
|
|
assert member["selection_area_id"] == str(area_id)
|
|
assert member["warnings"] == ["22 van de 100 objecten liggen deels buiten de selectie."]
|
|
|
|
|
|
def test_empty_context_is_omitted_rather_than_written_as_null_noise() -> None:
|
|
member = ExportService.provenance_member(
|
|
source="dataset",
|
|
project_id=uuid4(),
|
|
dataset_id=uuid4(),
|
|
)
|
|
|
|
assert "selection_bbox" not in member
|
|
assert "warnings" not in member
|
|
assert "source_version" not in member
|
|
|
|
|
|
def test_the_member_attaches_under_a_reserved_key() -> None:
|
|
collection = {"type": "FeatureCollection", "features": []}
|
|
|
|
ExportService.attach_provenance(
|
|
collection,
|
|
ExportService.provenance_member(source="dataset", project_id=uuid4(), dataset_id=uuid4()),
|
|
)
|
|
|
|
assert collection["type"] == "FeatureCollection"
|
|
assert collection["geointel_provenance"]["source"] == "dataset"
|