Download backend/tests/test_api.py from Shwy1001/BioPatch: direct link, hf CLI and curl.
- Browser
- Download file 5.72 kB
-
https://huggingface.co/spaces/Shwy1001/BioPatch/resolve/main/backend/tests/test_api.py
- Command line
-
hf download hf://spaces/Shwy1001/BioPatch/backend/tests/test_api.py
-
curl -L -o test_api.py https://huggingface.co/spaces/Shwy1001/BioPatch/resolve/main/backend/tests/test_api.py
5.72 kB
| """End-to-end smoke tests for the BioPatch API. | |
| Uses an in-memory SQLite shared across connections so the TestClient and the | |
| WebSocket use the same data. The simulator and auto-seeder are disabled here | |
| so we can drive the system deterministically. | |
| """ | |
| from __future__ import annotations | |
| import os | |
| import sys | |
| from pathlib import Path | |
| os.environ["DATABASE_URL"] = "sqlite+pysqlite:///file:biopatch_test?mode=memory&cache=shared&uri=true" | |
| os.environ["ENABLE_SIMULATOR"] = "false" | |
| os.environ["AUTO_SEED"] = "false" | |
| os.environ["JWT_SECRET"] = "test-secret-for-pytest-only-not-for-prod-use" | |
| sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) | |
| import pytest | |
| from fastapi.testclient import TestClient | |
| from core.database import init_db # noqa: E402 | |
| from main import app # noqa: E402 | |
| def client(): | |
| init_db() | |
| with TestClient(app) as c: | |
| yield c | |
| def _register_and_login(client: TestClient, role: str = "admin") -> str: | |
| email = f"{role}@biopatch.io" | |
| client.post( | |
| "/api/auth/register", | |
| json={ | |
| "email": email, | |
| "full_name": f"Test {role.title()}", | |
| "password": "TestPassword!1", | |
| "role": role, | |
| }, | |
| ) | |
| resp = client.post( | |
| "/api/auth/login/json", | |
| json={"email": email, "password": "TestPassword!1"}, | |
| ) | |
| assert resp.status_code == 200, resp.text | |
| return resp.json()["access_token"] | |
| def test_health(client: TestClient) -> None: | |
| r = client.get("/api/health") | |
| assert r.status_code == 200 | |
| assert r.json()["status"] == "ok" | |
| def test_auth_required_on_patients(client: TestClient) -> None: | |
| r = client.get("/api/patients") | |
| assert r.status_code == 401 | |
| def test_full_patient_flow(client: TestClient) -> None: | |
| token = _register_and_login(client, role="admin") | |
| h = {"Authorization": f"Bearer {token}"} | |
| # Create a patient | |
| r = client.post( | |
| "/api/patients", | |
| json={ | |
| "mrn": "MRN-TEST-1", | |
| "full_name": "Test Patient", | |
| "age": 60, | |
| "sex": "M", | |
| "ward": "TestWard", | |
| "bed": "1", | |
| "surgery_type": "Appendectomy", | |
| "surgery_date": "2025-05-10T08:00:00Z", | |
| }, | |
| headers=h, | |
| ) | |
| assert r.status_code == 201, r.text | |
| patient_id = r.json()["id"] | |
| # Attach a sensor | |
| r = client.post( | |
| f"/api/patients/{patient_id}/sensors", | |
| json={"device_id": "BP-TEST-001", "location": "incision"}, | |
| headers=h, | |
| ) | |
| assert r.status_code == 201, r.text | |
| sensor_id = r.json()["id"] | |
| # Ingest a vital that triggers critical | |
| r = client.post( | |
| f"/api/patients/{patient_id}/vitals", | |
| json={"temperature_c": 38.6, "ph": 8.1, "humidity": 88.0, "sensor_id": sensor_id}, | |
| headers=h, | |
| ) | |
| assert r.status_code == 201, r.text | |
| vital = r.json() | |
| assert vital["severity"] == "critical" | |
| assert vital["sepsis_risk"] >= 75 | |
| assert vital["bacterial_signature"] is not None | |
| # List shows the latest score | |
| r = client.get("/api/patients", headers=h) | |
| assert r.status_code == 200 | |
| items = r.json() | |
| target = next(p for p in items if p["id"] == patient_id) | |
| assert target["latest_severity"] == "critical" | |
| assert target["online_sensor_count"] == 1 | |
| # Vitals history | |
| r = client.get(f"/api/patients/{patient_id}/vitals?hours=1", headers=h) | |
| assert r.status_code == 200 | |
| assert len(r.json()) == 1 | |
| # Clinical note | |
| r = client.post( | |
| f"/api/patients/{patient_id}/notes", | |
| json={"body": "Started broad-spectrum antibiotics.", "category": "intervention", "severity": "warning"}, | |
| headers=h, | |
| ) | |
| assert r.status_code == 201, r.text | |
| assert r.json()["author_name"] == "Test Admin" | |
| r = client.get(f"/api/patients/{patient_id}/notes", headers=h) | |
| assert r.status_code == 200 | |
| assert len(r.json()) == 1 | |
| def test_role_enforcement_for_patient_create(client: TestClient) -> None: | |
| token = _register_and_login(client, role="nurse") | |
| h = {"Authorization": f"Bearer {token}"} | |
| r = client.post( | |
| "/api/patients", | |
| json={ | |
| "mrn": "MRN-TEST-NURSE", | |
| "full_name": "Should Fail", | |
| "age": 50, | |
| "sex": "F", | |
| "ward": "X", | |
| "bed": "1", | |
| "surgery_type": "X", | |
| "surgery_date": "2025-05-10T08:00:00Z", | |
| }, | |
| headers=h, | |
| ) | |
| assert r.status_code == 403 | |
| def test_websocket_snapshot_and_broadcast(client: TestClient) -> None: | |
| token = _register_and_login(client, role="admin") | |
| # Unauthenticated handshake closes immediately | |
| with client.websocket_connect("/ws/stream") as ws: | |
| msg = ws.receive_json() | |
| assert msg["type"] == "error" | |
| with client.websocket_connect(f"/ws/stream?token={token}") as ws: | |
| snap = ws.receive_json() | |
| assert snap["type"] == "snapshot" | |
| assert "patients" in snap["data"] | |
| # Drive a new reading -> the WS must broadcast it | |
| h = {"Authorization": f"Bearer {token}"} | |
| patients = client.get("/api/patients", headers=h).json() | |
| assert patients, "expected at least one patient from previous test" | |
| pid = patients[0]["id"] | |
| r = client.post( | |
| f"/api/patients/{pid}/vitals", | |
| json={"temperature_c": 34.0, "ph": 6.0, "humidity": 75.0}, | |
| headers=h, | |
| ) | |
| assert r.status_code == 201 | |
| seen_types: set[str] = set() | |
| for _ in range(5): | |
| event = ws.receive_json() | |
| seen_types.add(event["type"]) | |
| if "vitals" in seen_types: | |
| break | |
| assert "vitals" in seen_types | |