File size: 2,678 Bytes
70e641d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
"""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