Initial public release
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
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
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
"""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"
|
||||
Reference in New Issue
Block a user