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
138 lines
4.8 KiB
Python
138 lines
4.8 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime
|
|
from pathlib import Path
|
|
from uuid import uuid4
|
|
|
|
import pytest
|
|
|
|
from app.core.errors import AppError
|
|
from app.models import Dataset
|
|
from app.services.temporal_compatibility_service import TemporalCompatibilityService
|
|
|
|
|
|
ROOT = Path(__file__).parents[2]
|
|
|
|
|
|
def dataset(
|
|
*,
|
|
dataset_type: str,
|
|
source_name: str,
|
|
observed_at: datetime | None = None,
|
|
valid_from: datetime | None = None,
|
|
valid_to: datetime | None = None,
|
|
temporal_granularity: str | None = None,
|
|
source_metadata: dict | None = None,
|
|
) -> Dataset:
|
|
return Dataset(
|
|
id=uuid4(),
|
|
project_id=uuid4(),
|
|
name="temporal-source",
|
|
dataset_type=dataset_type,
|
|
source=source_name,
|
|
source_name=source_name,
|
|
observed_at=observed_at,
|
|
valid_from=valid_from,
|
|
valid_to=valid_to,
|
|
temporal_granularity=temporal_granularity,
|
|
source_metadata=source_metadata,
|
|
)
|
|
|
|
|
|
def test_historical_orthophoto_is_rejected_for_detection() -> None:
|
|
historical = dataset(
|
|
dataset_type="raster",
|
|
source_name="digitaal_vlaanderen_orthophoto",
|
|
observed_at=datetime(2020, 1, 1, tzinfo=UTC),
|
|
valid_from=datetime(2020, 1, 1, tzinfo=UTC),
|
|
valid_to=datetime(2020, 12, 31, 23, 59, 59, tzinfo=UTC),
|
|
temporal_granularity="year",
|
|
source_metadata={"product_key": "2020", "supports_detection": False},
|
|
)
|
|
|
|
with pytest.raises(AppError) as exc_info:
|
|
TemporalCompatibilityService.ensure_detection_source_supported(historical)
|
|
|
|
assert exc_info.value.code == "DETECTION_SOURCE_TEMPORALLY_UNSUPPORTED"
|
|
assert exc_info.value.status_code == 422
|
|
|
|
|
|
def test_historical_detection_qa_rejects_current_reference() -> None:
|
|
historical = dataset(
|
|
dataset_type="raster",
|
|
source_name="digitaal_vlaanderen_orthophoto",
|
|
valid_from=datetime(2020, 1, 1, tzinfo=UTC),
|
|
valid_to=datetime(2020, 12, 31, 23, 59, 59, tzinfo=UTC),
|
|
temporal_granularity="year",
|
|
source_metadata={"product_key": "2020", "supports_detection": False},
|
|
)
|
|
current_reference = dataset(
|
|
dataset_type="vector",
|
|
source_name="grb",
|
|
valid_from=datetime(2026, 7, 1, tzinfo=UTC),
|
|
valid_to=datetime(2026, 7, 31, 23, 59, 59, tzinfo=UTC),
|
|
temporal_granularity="month",
|
|
)
|
|
|
|
with pytest.raises(AppError) as exc_info:
|
|
TemporalCompatibilityService.assess_detection_qa(historical, current_reference)
|
|
|
|
assert exc_info.value.code == "DETECTION_QA_TEMPORAL_MISMATCH"
|
|
assert exc_info.value.status_code == 422
|
|
|
|
|
|
def test_historical_detection_qa_accepts_overlapping_reference_edition() -> None:
|
|
historical = dataset(
|
|
dataset_type="raster",
|
|
source_name="digitaal_vlaanderen_orthophoto",
|
|
valid_from=datetime(2020, 1, 1, tzinfo=UTC),
|
|
valid_to=datetime(2020, 12, 31, 23, 59, 59, tzinfo=UTC),
|
|
temporal_granularity="year",
|
|
source_metadata={"product_key": "2020", "supports_detection": False},
|
|
)
|
|
historical_reference = dataset(
|
|
dataset_type="vector",
|
|
source_name="manual",
|
|
valid_from=datetime(2020, 6, 1, tzinfo=UTC),
|
|
valid_to=datetime(2020, 6, 30, 23, 59, 59, tzinfo=UTC),
|
|
temporal_granularity="month",
|
|
)
|
|
|
|
result = TemporalCompatibilityService.assess_detection_qa(historical, historical_reference)
|
|
|
|
assert result["status"] == "compatible"
|
|
assert result["candidate_historical"] is True
|
|
assert result["candidate_interval"]["start"].startswith("2020-01-01")
|
|
assert result["reference_interval"]["start"].startswith("2020-06-01")
|
|
|
|
|
|
def test_current_source_with_unbounded_current_reference_remains_supported() -> None:
|
|
current = dataset(
|
|
dataset_type="raster",
|
|
source_name="digitaal_vlaanderen_orthophoto",
|
|
observed_at=datetime(2026, 7, 17, tzinfo=UTC),
|
|
valid_from=datetime(2026, 7, 17, tzinfo=UTC),
|
|
temporal_granularity="snapshot",
|
|
source_metadata={"product_key": "most_recent", "supports_detection": True},
|
|
)
|
|
current_reference = dataset(
|
|
dataset_type="vector",
|
|
source_name="grb",
|
|
observed_at=datetime(2026, 7, 16, tzinfo=UTC),
|
|
temporal_granularity="snapshot",
|
|
)
|
|
|
|
TemporalCompatibilityService.ensure_detection_source_supported(current)
|
|
result = TemporalCompatibilityService.assess_detection_qa(current, current_reference)
|
|
|
|
assert result["status"] == "compatible"
|
|
assert result["candidate_historical"] is False
|
|
|
|
|
|
def test_detection_frontend_has_no_implicit_first_raster_fallback() -> None:
|
|
source = (ROOT / "frontend" / "src" / "hooks" / "useDetectionWorkflow.ts").read_text(encoding="utf-8")
|
|
|
|
assert "rasterDatasets[0]" not in source
|
|
assert "setSelectedDetectionDatasetId(rasterDatasets" not in source
|
|
assert "const datasetId = selectedDetectionDatasetId" in source
|