102 lines
3.1 KiB
Python
102 lines
3.1 KiB
Python
from datetime import UTC, datetime
|
|
from unittest.mock import AsyncMock
|
|
|
|
import pytest
|
|
from fastapi import HTTPException
|
|
|
|
from app.api.v1 import realtime_sources
|
|
from app.models.datasource import DataSource
|
|
from app.models.datasource_config import DataSourceConfig
|
|
from app.models.vessel import AISSourceHealth
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_serialize_builtin_aisstream_includes_health_config_and_stats(monkeypatch):
|
|
datasource = DataSource(
|
|
id=28,
|
|
name="AISStream Vessels",
|
|
source="aisstream_vessels",
|
|
module="L4",
|
|
priority="P1",
|
|
collector_class="aisstream_vessels",
|
|
is_active=True,
|
|
)
|
|
config = DataSourceConfig(
|
|
id=3,
|
|
name="aisstream_vessels",
|
|
source_type="websocket",
|
|
endpoint="wss://stream.aisstream.io/v0/stream",
|
|
auth_type="api_key",
|
|
auth_config={"api_key": "test-key"},
|
|
config={
|
|
"message_types": ["PositionReport"],
|
|
"bounding_boxes": [[[-10, 50], [35, 75]]],
|
|
},
|
|
is_active=True,
|
|
)
|
|
health = AISSourceHealth(
|
|
source="aisstream_vessels",
|
|
connection_state="connected",
|
|
last_seen_at=datetime(2026, 5, 13, 1, 0, tzinfo=UTC),
|
|
)
|
|
|
|
class _Session:
|
|
async def get(self, _model, key):
|
|
assert key == "aisstream_vessels"
|
|
return health
|
|
|
|
monkeypatch.setattr(
|
|
realtime_sources,
|
|
"_load_realtime_stats",
|
|
AsyncMock(
|
|
return_value={
|
|
"total_observations": 10,
|
|
"observations_24h": 4,
|
|
"observations_1h": 1,
|
|
"unique_mmsi_total": 8,
|
|
"unique_mmsi_24h": 3,
|
|
"latest_observed_at": "2026-05-13T01:00:00Z",
|
|
"latest_collected_at": "2026-05-13T01:00:01Z",
|
|
}
|
|
),
|
|
)
|
|
monkeypatch.setattr(realtime_sources, "is_collector_running", lambda source: False)
|
|
|
|
payload = await realtime_sources._serialize_builtin_aisstream(_Session(), datasource, config)
|
|
|
|
assert payload["source"] == "aisstream_vessels"
|
|
assert payload["kind"] == "builtin"
|
|
assert payload["credential_configured"] is True
|
|
assert payload["message_types"] == ["PositionReport"]
|
|
assert payload["runtime"]["running"] is False
|
|
assert payload["health"]["connection_state"] == "connected"
|
|
assert payload["stats"]["total_observations"] == 10
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_start_builtin_realtime_source_rejects_disabled(monkeypatch):
|
|
datasource = DataSource(
|
|
id=28,
|
|
name="AISStream Vessels",
|
|
source="aisstream_vessels",
|
|
module="L4",
|
|
priority="P1",
|
|
collector_class="aisstream_vessels",
|
|
is_active=False,
|
|
)
|
|
monkeypatch.setattr(
|
|
realtime_sources,
|
|
"_load_builtin_aisstream",
|
|
AsyncMock(return_value=(datasource, None)),
|
|
)
|
|
|
|
with pytest.raises(HTTPException) as excinfo:
|
|
await realtime_sources.start_realtime_source(
|
|
"aisstream_vessels",
|
|
current_user=object(),
|
|
db=object(),
|
|
)
|
|
|
|
assert excinfo.value.status_code == 400
|
|
assert "disabled" in excinfo.value.detail
|