60 lines
2.1 KiB
Python
60 lines
2.1 KiB
Python
"""Tests del CoreClient: cómo mapea respuestas HTTP del core a dicts.
|
|
|
|
Importante para el dashboard: una ejecución correcta (``AgentExecution`` serializado)
|
|
incluye SIEMPRE el campo ``error`` (``str | None``). El wrapper que el cliente añade
|
|
ante un 4xx debe usar una clave distinta (``api_error``) para no colisionar con ese
|
|
campo; si usara ``error``, las páginas no podrían distinguir "el agente terminó sin
|
|
error" de "la API devolvió 404/409/422".
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable
|
|
|
|
import httpx
|
|
import pytest
|
|
|
|
from forja_dashboard.client import CoreClient
|
|
|
|
|
|
def _client_with(handler: Callable[[httpx.Request], httpx.Response]) -> CoreClient:
|
|
client = CoreClient(base_url="http://test")
|
|
client._client.close()
|
|
client._client = httpx.Client(base_url="http://test", transport=httpx.MockTransport(handler))
|
|
return client
|
|
|
|
|
|
def test_post_2xx_devuelve_el_cuerpo_verbatim_incluido_error_none() -> None:
|
|
"""Un AgentExecution con ``error=None`` se devuelve tal cual, sin envolver."""
|
|
execution = {
|
|
"trace_id": "11111111-1111-1111-1111-111111111111",
|
|
"status": "completed",
|
|
"error": None,
|
|
"violations": [],
|
|
"decision_path": [],
|
|
}
|
|
|
|
def handler(_: httpx.Request) -> httpx.Response:
|
|
return httpx.Response(200, json=execution)
|
|
|
|
result = _client_with(handler).invoke_agent("incident_analyzer", {"input": "x"})
|
|
assert result == execution
|
|
assert "api_error" not in result
|
|
|
|
|
|
@pytest.mark.parametrize("status", [404, 409, 422])
|
|
def test_post_4xx_envuelve_el_detalle_en_api_error(status: int) -> None:
|
|
def handler(_: httpx.Request) -> httpx.Response:
|
|
return httpx.Response(status, json={"detail": "boom"})
|
|
|
|
result = _client_with(handler).invoke_agent("incident_analyzer", {"input": "y"})
|
|
assert result == {"api_error": {"detail": "boom"}}
|
|
|
|
|
|
def test_post_5xx_propaga_la_excepcion() -> None:
|
|
def handler(_: httpx.Request) -> httpx.Response:
|
|
return httpx.Response(500, json={"detail": "kaput"})
|
|
|
|
with pytest.raises(httpx.HTTPStatusError):
|
|
_client_with(handler).invoke_agent("incident_analyzer", {"input": "z"})
|