carepath-api / scribe /tests /test_combined_app.py
tranth3truong's picture
Deploy public Scribe-only CarePath Space
cc678b9
Raw
History Blame Contribute Delete
3.54 kB
"""The combined service serves both products: scriber /api/v1/* and
interpreter /api/* + /ws/* from one FastAPI app with one lifespan."""
from __future__ import annotations
import os
import sys
import tempfile
import unittest
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(REPO_ROOT / "scribe"))
sys.path.insert(0, str(REPO_ROOT / "interpreter"))
# Hermetic keyless config for both products (same pattern as test_api.py).
os.environ.setdefault("ASR_PROVIDER", "mock")
os.environ.setdefault("ALLOW_MOCK_ASR", "true")
os.environ.setdefault("LLM_PROVIDER", "offline")
os.environ.setdefault("MEDICAL_LEXICON_PATH", str(REPO_ROOT / "data" / "medical_lexicon.json"))
os.environ.setdefault("CAREPATH_ENV_FILE", "__tests_no_env__")
os.environ.setdefault("PROVIDER_MODE", "mock")
_TMP_DB = Path(tempfile.mkdtemp(prefix="carepath_combined_")) / "combined.db"
os.environ["DATABASE_URL"] = f"sqlite:///{_TMP_DB.as_posix()}"
from fastapi.testclient import TestClient
import app.config as interpreter_config
import app.db as interpreter_db
from carepath.main import SITE_DIST_DIR, app, get_pipeline, get_settings
class CombinedAppTests(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
get_settings.cache_clear()
get_pipeline.cache_clear()
interpreter_config.get_settings.cache_clear()
interpreter_db.set_engine(None)
def test_lifespan_boots_both_products_and_serves_both_apis(self) -> None:
# The context manager runs the combined lifespan: scriber warmup plus
# interpreter init_db/seed_glossary/purge.
with TestClient(app) as client:
scriber_health = client.get("/api/v1/health")
self.assertEqual(scriber_health.status_code, 200, scriber_health.text)
self.assertEqual(scriber_health.json()["asr_provider"], "mock")
interpreter_health = client.get("/api/health")
self.assertEqual(interpreter_health.status_code, 200, interpreter_health.text)
self.assertEqual(interpreter_health.json()["provider_mode"], "mock")
created = client.post(
"/api/sessions",
json={"consent": {"language": "vi", "accepted": True}},
)
self.assertEqual(created.status_code, 201, created.text)
session_id = created.json()["session_id"]
with client.websocket_connect(f"/ws/sessions/{session_id}") as websocket:
snapshot = websocket.receive_json()
self.assertEqual(snapshot["type"], "session_state")
self.assertEqual(snapshot["turns"], [])
@unittest.skipUnless(SITE_DIST_DIR.is_dir(), "site build is not available")
def test_clinical_notes_route_serves_the_site_entrypoint(self) -> None:
with TestClient(app) as client:
response = client.get("/ghi-chep-lam-sang/")
self.assertEqual(response.status_code, 200, response.text)
self.assertIn('id="root"', response.text)
def test_public_interpreter_browser_paths_are_blocked(self) -> None:
with TestClient(app) as client:
responses = [
client.get("/phien-dich-y-khoa/"),
client.get("/phien-dich-y-khoa/assets/index.js"),
client.get("/console"),
client.get("/console/?lang=en"),
]
for response in responses:
self.assertEqual(response.status_code, 404, response.text)
if __name__ == "__main__":
unittest.main()