"""Tests de la API FastAPI del Runtime (Sprint 4).""" from __future__ import annotations import asyncio import httpx import pytest from vmssailor.runtime.server.api import create_app from vmssailor.runtime.server.runtime_app import build_runtime from vmssailor.tools.generate_test_project import build_demo_project @pytest.fixture async def runtime_client(): project = build_demo_project() runtime = build_runtime(project, simulator_tick_s=0.2) app = create_app(runtime) transport = httpx.ASGITransport(app=app) async with ( httpx.AsyncClient(transport=transport, base_url="http://test") as client, app.router.lifespan_context(app), ): # Dar un tick para que el simulator produzca al menos un valor await asyncio.sleep(0.4) yield client, runtime @pytest.mark.asyncio async def test_health_endpoint(runtime_client): client, _runtime = runtime_client r = await client.get("/health") assert r.status_code == 200 body = r.json() assert body["status"] == "ok" assert "tag_store" in body assert body["tag_store"]["total_tags"] > 0 @pytest.mark.asyncio async def test_project_endpoint(runtime_client): client, _runtime = runtime_client r = await client.get("/project") assert r.status_code == 200 body = r.json() assert body["name"] assert body["vessel"]["loa_m"] > 0 @pytest.mark.asyncio async def test_tags_listing_and_simulator_values(runtime_client): client, _runtime = runtime_client r = await client.get("/tags") assert r.status_code == 200 tags = r.json() assert len(tags) > 0 # Al menos alguno debería tener value no nulo después del tick with_value = [t for t in tags if t["value"] is not None] assert len(with_value) > 0 @pytest.mark.asyncio async def test_tag_detail_404(runtime_client): client, _runtime = runtime_client r = await client.get("/tags/ghost.tag") assert r.status_code == 404 @pytest.mark.asyncio async def test_history_endpoint(runtime_client): client, _runtime = runtime_client # Le damos al simulator más tiempo para que el historian acumule await asyncio.sleep(1.2) # Tomamos un tag con valor numérico list_r = await client.get("/tags") tag_id = next( t["id"] for t in list_r.json() if isinstance(t["value"], (int, float)) ) r = await client.get(f"/tags/{tag_id}/history") assert r.status_code == 200 rows = r.json() # En 1.2s con simulator de 0.2s -> ~6 muestras assert len(rows) >= 3 @pytest.mark.asyncio async def test_alarms_endpoint(runtime_client): client, _runtime = runtime_client r = await client.get("/alarms") assert r.status_code == 200 assert isinstance(r.json(), list)