morphos / backend /tests /test_api.py
Jose Salazar
Añadir el stack nuevo: Vite/TypeScript + FastAPI
70e641d
Raw
History Blame Contribute Delete
2.68 kB
"""Pruebas de la API: guarda de autenticación, flujo de sesión y cabeceras de seguridad.
Verifican en concreto los arreglos del audit: /api/interpret ya NO es anónimo, la sesión
emite CSRF, y las cabeceras de seguridad se aplican.
"""
from __future__ import annotations
import pytest
from fastapi.testclient import TestClient
from app.main import app
from app.schemas import InterpretacionClinica, RespuestaInterpretacion
@pytest.fixture
def cliente():
# El context manager dispara el lifespan (inicializa la BD).
with TestClient(app) as c:
yield c
def test_health(cliente):
r = cliente.get("/api/health")
assert r.status_code == 200
assert r.json()["ok"] is True
def test_interpret_requiere_sesion(cliente):
r = cliente.post("/api/interpret", json={"paciente": {"especie": "canino"}})
assert r.status_code == 401
def test_cabeceras_seguridad_presentes(cliente):
r = cliente.get("/api/health")
assert r.headers.get("X-Content-Type-Options") == "nosniff"
assert "Content-Security-Policy" in r.headers
assert r.headers.get("X-Frame-Options") == "DENY"
def test_flujo_registro_login_e_interpret(cliente, monkeypatch):
# Registro emite sesión + CSRF.
reg = cliente.post(
"/api/auth/registro",
json={"nombre": "Ana", "apellido": "Vet", "email": "ana@example.com", "password": "clave-segura-1"},
)
assert reg.status_code == 200
csrf = reg.json()["csrf"]
assert cliente.cookies.get("morphos_sesion")
# Estado autenticado.
est = cliente.get("/api/auth")
assert est.json()["autenticado"] is True
# Monkeypatch del servicio de IA para no depender de un modelo real.
async def _fake_interpretar(pet):
return RespuestaInterpretacion(
resultado=InterpretacionClinica(interpretacion="Interpretación de prueba."),
modelo="fake:test",
fuentes_rag=0,
)
monkeypatch.setattr("app.routers.interpret.interpretar", _fake_interpretar)
# Sin CSRF → 403.
sin_csrf = cliente.post("/api/interpret", json={"paciente": {"especie": "canino"}})
assert sin_csrf.status_code == 403
# Con CSRF → 200 y salida estructurada.
ok = cliente.post(
"/api/interpret",
json={"paciente": {"especie": "canino"}},
headers={"X-CSRF-Token": csrf},
)
assert ok.status_code == 200, ok.text
assert ok.json()["resultado"]["idioma"] == "es"
def test_registro_rechaza_password_corta(cliente):
r = cliente.post(
"/api/auth/registro",
json={"nombre": "B", "apellido": "C", "email": "b@example.com", "password": "corta"},
)
assert r.status_code == 422