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