TorbatYar/backend/services/healthcare/app/tests/test_api.py
Mortezakoohjani 625275e55b feat(healthcare): add backend service and finalize frontend build
Add the Healthcare platform backend (phases 13.0–13.7) with Alembic migration revision fix, production deploy script, validation reports, shared UI exports, and loyalty list page client directives so Next.js build succeeds.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 11:38:31 +03:30

166 lines
5.2 KiB
Python

"""API, health, tenant isolation, and foundation flow tests."""
from __future__ import annotations
from app.events.publisher import get_event_publisher
from app.tests.conftest import TENANT_A, TENANT_B, tenant_headers
async def test_health_capabilities_metrics(client):
health = await client.get("/health")
assert health.status_code == 200
body = health.json()
assert body["status"] == "ok"
assert body["service"] == "healthcare-service"
caps = await client.get("/capabilities")
assert caps.status_code == 200
c = caps.json()
assert c["phase"] == "13.7"
assert c["commercial_product"] == "Torbat Healthcare"
assert c["features"]["foundation"] is True
assert c["features"]["doctors"] is True
assert c["features"]["appointments"] is True
assert c["features"]["visits"] is True
assert c["features"]["patient_portal"] is True
assert c["features"]["medical_records"] is True
assert c["features"]["pharmacy"] is True
assert c["features"]["delivery_integration"] is True
assert c["independence"]["integration_mode"] == "api_and_events_only"
metrics = await client.get("/metrics")
assert metrics.status_code == 200
assert metrics.json()["phase"] == "13.7"
async def test_foundation_flow_and_events(client):
headers = tenant_headers(TENANT_A)
clinic = await client.post(
"/api/v1/clinics",
headers=headers,
json={"code": "CLN1", "name": "City Clinic", "status": "active"},
)
assert clinic.status_code == 201, clinic.text
clinic_id = clinic.json()["id"]
branch = await client.post(
"/api/v1/branches",
headers=headers,
json={
"clinic_id": clinic_id,
"code": "BR1",
"name": "Main Branch",
},
)
assert branch.status_code == 201, branch.text
department = await client.post(
"/api/v1/departments",
headers=headers,
json={
"clinic_id": clinic_id,
"code": "CARDIO",
"name": "Cardiology",
},
)
assert department.status_code == 201, department.text
doctor = await client.post(
"/api/v1/doctors",
headers=headers,
json={
"user_id": "user-doctor-1",
"clinic_id": clinic_id,
"code": "DOC1",
"display_name": "Dr. Smith",
},
)
assert doctor.status_code == 201, doctor.text
patient = await client.post(
"/api/v1/patients",
headers=headers,
json={
"user_id": "user-patient-1",
"code": "PAT1",
"display_name": "Jane Doe",
},
)
assert patient.status_code == 201, patient.text
provider = await client.post(
"/api/v1/external-providers",
headers=headers,
json={
"clinic_id": clinic_id,
"code": "COMM_X",
"name": "External Comm X",
"provider_kind": "communication",
"adapter_key": "mock_comm",
},
)
assert provider.status_code == 201, provider.text
cfg = await client.post(
"/api/v1/configurations",
headers=headers,
json={"clinic_id": clinic_id, "code": "DEFAULT"},
)
assert cfg.status_code == 201, cfg.text
setting = await client.put(
"/api/v1/settings",
headers=headers,
json={
"clinic_id": clinic_id,
"key": "default_locale",
"value": {"code": "fa"},
},
)
assert setting.status_code == 200, setting.text
audit = await client.get(
"/api/v1/audit",
headers=headers,
params={"entity_type": "clinic", "entity_id": clinic_id},
)
assert audit.status_code == 200
assert len(audit.json()) >= 1
published = [e.event_type for e in get_event_publisher().published]
assert "healthcare.clinic.created" in published
assert "healthcare.branch.created" in published
assert "healthcare.department.created" in published
assert "healthcare.doctor.created" in published
assert "healthcare.patient.created" in published
assert "healthcare.external_provider.registered" in published
assert "healthcare.setting.updated" in published
async def test_tenant_isolation(client):
headers_a = tenant_headers(TENANT_A)
headers_b = tenant_headers(TENANT_B)
created = await client.post(
"/api/v1/clinics",
headers=headers_a,
json={"code": "ISO1", "name": "Tenant A Clinic"},
)
assert created.status_code == 201
clinic_id = created.json()["id"]
denied = await client.get(f"/api/v1/clinics/{clinic_id}", headers=headers_b)
assert denied.status_code == 404
listed_b = await client.get("/api/v1/clinics", headers=headers_b)
assert listed_b.status_code == 200
assert listed_b.json() == []
listed_a = await client.get("/api/v1/clinics", headers=headers_a)
assert listed_a.status_code == 200
assert len(listed_a.json()) == 1
async def test_missing_tenant_header_rejected(client):
res = await client.get("/api/v1/clinics")
assert res.status_code in (400, 422)