central/tests/test_apply_enrichment_coordless.py

78 lines
2.8 KiB
Python
Raw Normal View History

"""Regression tests for apply_enrichment's coordless path.
Design principle: every event from an adapter that declares enrichment_locations
must carry data["_enriched"] populated when coordinates resolve, an all-null
bundle when they don't (e.g. removal tombstones with no lat/lon). Adapters that
declare no enrichment_locations are still skipped entirely.
"""
from datetime import datetime, timezone
from typing import Any
import pytest
from central.config_models import EnrichmentConfig
from central.enrichment.cache import EnrichmentCache
from central.enrichment.geocoder import GeocoderEnricher, all_null_bundle
from central.models import Event, Geo
from central.supervisor import apply_enrichment, build_enrichers
def _make_event(data: dict[str, Any]) -> Event:
return Event(
id="evt-1",
adapter="usgs_quake",
category="quake.event.test",
time=datetime(2026, 1, 1, tzinfo=timezone.utc),
geo=Geo(),
data=data,
)
class _PopulatingBackend:
"""Deterministic backend that resolves any real coords to a fixed place."""
async def reverse(self, lat: float, lon: float) -> dict[str, Any]:
return {**all_null_bundle(), "city": "Boise", "state": "ID"}
@pytest.mark.asyncio
async def test_coordless_event_with_declared_locations_gets_null_bundle(tmp_path):
"""An event whose declared coord paths are all None still gets _enriched."""
cache = EnrichmentCache(tmp_path / "enrichment_cache.db")
enrichers = build_enrichers(EnrichmentConfig(), cache)
event = _make_event(
{"latitude": None, "longitude": None, "reason": "fallen_off_current_service"}
)
assert "_enriched" not in event.data
await apply_enrichment(event, [("latitude", "longitude")], enrichers)
assert event.data["_enriched"]["geocoder"] == all_null_bundle()
@pytest.mark.asyncio
async def test_event_with_coords_still_enriches_normally(tmp_path):
"""The coord-bearing path is unchanged: the backend is consulted and its
resolved fields land in the bundle."""
cache = EnrichmentCache(tmp_path / "enrichment_cache.db")
enricher = GeocoderEnricher(_PopulatingBackend(), cache=cache)
event = _make_event({"latitude": 43.0, "longitude": -116.0})
await apply_enrichment(event, [("latitude", "longitude")], [enricher])
bundle = event.data["_enriched"]["geocoder"]
assert bundle["state"] == "ID"
assert bundle["city"] == "Boise"
@pytest.mark.asyncio
async def test_adapter_with_no_enrichment_locations_still_skipped(tmp_path):
"""Adapters declaring no enrichment_locations are skipped — no _enriched."""
cache = EnrichmentCache(tmp_path / "enrichment_cache.db")
enrichers = build_enrichers(EnrichmentConfig(), cache)
event = _make_event({"latitude": 43.0, "longitude": -116.0})
await apply_enrichment(event, [], enrichers)
assert "_enriched" not in event.data