File size: 4,973 Bytes
70e641d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61cd0db
70e641d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61cd0db
 
70e641d
 
 
61cd0db
 
 
 
 
 
 
 
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"""Pruebas de la API de laboratorio: auth de dispositivo, ingesta, y consulta por sesión."""

from __future__ import annotations

import pytest
from fastapi.testclient import TestClient

from app.config import obtener_config
from app.main import app

PAYLOAD = {
    "muestra_id": "ABC-123",
    "instrumento_id": "vetscan-1",
    "fabricante": "Abaxis",
    "observaciones": [
        {"codigo_prueba": "GLU", "valor": "5.0", "unidad": "mmol/L"},
        {"codigo_prueba": "CREA", "valor": "1.2", "unidad": "mg/dL"},
    ],
    "momento": "2026-07-25T10:00:00Z",
}


@pytest.fixture
def cliente():
    with TestClient(app) as c:
        yield c


def _con_sesion(cliente, email="lab@example.com"):
    reg = cliente.post(
        "/api/auth/registro",
        json={"nombre": "Lab", "apellido": "Vet", "email": email, "password": "clave-segura-1"},
    )
    assert reg.status_code == 200, reg.text
    return reg.json()["csrf"]


def test_ingesta_sin_keys_configuradas_es_503(cliente, monkeypatch):
    monkeypatch.setattr(obtener_config(), "lab_api_keys", [])
    r = cliente.post("/api/lab/ingesta", json=PAYLOAD, headers={"Authorization": "Bearer x"})
    assert r.status_code == 503


def test_ingesta_sin_bearer_es_401(cliente, monkeypatch):
    monkeypatch.setattr(obtener_config(), "lab_api_keys", ["k-secreta"])
    r = cliente.post("/api/lab/ingesta", json=PAYLOAD)
    assert r.status_code == 401


def test_ingesta_bearer_erroneo_es_401(cliente, monkeypatch):
    monkeypatch.setattr(obtener_config(), "lab_api_keys", ["k-secreta"])
    r = cliente.post("/api/lab/ingesta", json=PAYLOAD, headers={"Authorization": "Bearer mala"})
    assert r.status_code == 401


def test_ingesta_y_consulta_completa(cliente, monkeypatch, alta_abierta):
    monkeypatch.setattr(obtener_config(), "lab_api_keys", ["k-secreta"])

    # Ingesta con key válida.
    r = cliente.post("/api/lab/ingesta", json=PAYLOAD, headers={"Authorization": "Bearer k-secreta"})
    assert r.status_code == 200, r.text
    cuerpo = r.json()
    assert cuerpo["muestra_id"] == "ABC-123"
    assert cuerpo["analitos_mapeados"] == 2
    assert cuerpo["no_mapeados"] == []

    # Consulta sin sesión → 401.
    sin_sesion = cliente.get("/api/lab/resultados", params={"muestra": "ABC-123"})
    assert sin_sesion.status_code == 401

    # Con sesión → 200 y analitos mapeados (match case-insensitive del ID).
    _con_sesion(cliente)
    q = cliente.get("/api/lab/resultados", params={"muestra": "abc-123"})
    assert q.status_code == 200, q.text
    analitos = q.json()["analitos"]
    assert "gluc" in analitos and "creat" in analitos
    assert analitos["gluc"]["valor"] == round(5.0 * 18.016, 4)

    # Muestra desconocida → 404.
    nope = cliente.get("/api/lab/resultados", params={"muestra": "NO-EXISTE"})
    assert nope.status_code == 404


def test_ingesta_rechaza_observaciones_vacias(cliente, monkeypatch):
    monkeypatch.setattr(obtener_config(), "lab_api_keys", ["k-secreta"])
    payload = {**PAYLOAD, "observaciones": []}
    r = cliente.post("/api/lab/ingesta", json=payload, headers={"Authorization": "Bearer k-secreta"})
    assert r.status_code == 422


def test_pendientes_requiere_sesion(cliente):
    """401 antes que 404: la dependencia de sesión corre antes del cuerpo del endpoint, así que
    la cola apagada no convierte esto en un endpoint anónimo."""
    assert cliente.get("/api/lab/pendientes").status_code == 401


def test_pendientes_desactivada_por_defecto_es_404(cliente, alta_abierta):
    """Con sesión válida y la cola apagada (el defecto), 404: indistinguible de no existir."""
    _con_sesion(cliente, email="pend-off@example.com")
    assert cliente.get("/api/lab/pendientes").status_code == 404


def test_pendientes_lista_mas_reciente_primero(cliente, monkeypatch, alta_abierta):
    monkeypatch.setattr(obtener_config(), "lab_pendientes_habilitado", True)
    monkeypatch.setattr(obtener_config(), "lab_api_keys", ["k-secreta"])
    for muestra in ("PEND-1", "PEND-2"):
        cliente.post(
            "/api/lab/ingesta",
            json={**PAYLOAD, "muestra_id": muestra},
            headers={"Authorization": "Bearer k-secreta"},
        )
    _con_sesion(cliente, email="pend@example.com")
    r = cliente.get("/api/lab/pendientes")
    assert r.status_code == 200
    ids = [x["muestra_id"] for x in r.json()]
    assert "PEND-1" in ids and "PEND-2" in ids
    assert ids.index("PEND-2") < ids.index("PEND-1")  # el último ingerido, primero


def test_persistencia_escribe_en_db(cliente, monkeypatch):
    from app import db

    monkeypatch.setattr(obtener_config(), "lab_api_keys", ["k-secreta"])
    monkeypatch.setattr(obtener_config(), "lab_persistir", True)
    r = cliente.post(
        "/api/lab/ingesta",
        json={**PAYLOAD, "muestra_id": "PERSIST-1"},
        headers={"Authorization": "Bearer k-secreta"},
    )
    assert r.status_code == 200
    assert any("PERSIST-1" in p for p in db.cargar_resultados_lab())