import os import uuid from datetime import date import pytest from fastapi.testclient import TestClient # Ensure required env vars before importing app os.environ.setdefault("SECRET_KEY", "x" * 32) os.environ.setdefault("DATABASE_URL", "sqlite:////tmp/delphi_test.sqlite") from app.main import app # noqa: E402 from app.auth.security import get_current_user # noqa: E402 import app.api.qdros as qdros_module # noqa: E402 from sqlalchemy.orm import Session # noqa: E402 from app.database.base import get_db # noqa: E402 from app.models.lookups import SystemSetup # noqa: E402 from tests.test_qdros_api import _create_customer_and_file # noqa: E402 class _User: def __init__(self): self.id = 1 self.username = "tester" self.is_admin = True self.is_active = True self.is_approver = True @pytest.fixture() def client(): app.dependency_overrides[get_current_user] = lambda: _User() try: yield TestClient(app) finally: app.dependency_overrides.pop(get_current_user, None) class DummyNotification: def __init__(self): self.events = [] def emit(self, event_type: str, payload: dict): self.events.append((event_type, payload)) def test_qdro_transition_emits_notification_when_notify_true(client: TestClient, monkeypatch): dummy = DummyNotification() # Patch the module-level service reference used by endpoints monkeypatch.setattr(qdros_module, "notification_service", dummy, raising=False) # Arrange: create file and qdro _, file_no = _create_customer_and_file(client) resp = client.post("/api/qdros", json={"file_no": file_no}) assert resp.status_code == 200, resp.text qid = resp.json()["id"] # Act: submit for approval with notify=True resp = client.post( f"/api/qdros/{qid}/submit-for-approval", json={"reason": "send to approver", "notify": True, "effective_date": date.today().isoformat()}, ) assert resp.status_code == 200, resp.text # Assert: one event captured with expected shape assert dummy.events, "Expected a notification event to be emitted" event_type, payload = dummy.events[-1] assert event_type == "QDRO_STATUS_CHANGED" assert payload.get("qdro_id") == qid assert payload.get("file_no") == file_no assert payload.get("from") == "DRAFT" assert payload.get("to") == "APPROVAL_PENDING" def test_qdro_transition_no_notification_when_notify_false(client: TestClient, monkeypatch): dummy = DummyNotification() monkeypatch.setattr(qdros_module, "notification_service", dummy, raising=False) _, file_no = _create_customer_and_file(client) resp = client.post("/api/qdros", json={"file_no": file_no}) assert resp.status_code == 200, resp.text qid = resp.json()["id"] # notify omitted/false resp = client.post(f"/api/qdros/{qid}/submit-for-approval", json={"reason": "send"}) assert resp.status_code == 200, resp.text assert dummy.events == [] def _upsert_system_setting(db: Session, key: str, value: str): row = db.query(SystemSetup).filter(SystemSetup.setting_key == key).first() if row: row.setting_value = value else: row = SystemSetup(setting_key=key, setting_value=value) db.add(row) db.commit() def test_per_file_routing_overrides_email_and_webhook(client: TestClient, monkeypatch): dummy = DummyNotification() monkeypatch.setattr(qdros_module, "notification_service", dummy, raising=False) # Create file and qdro _, file_no = _create_customer_and_file(client) # Get DB session from dependency directly db_gen = get_db() db = next(db_gen) # Configure per-file routes _upsert_system_setting(db, f"notifications.qdro.email.to.file.{file_no}", "lawyer@example.com, clerk@example.com") _upsert_system_setting(db, f"notifications.qdro.webhook.url.file.{file_no}", "https://hooks.example.com/qdro-test") _upsert_system_setting(db, f"notifications.qdro.webhook.secret.file.{file_no}", "s3cr3t") resp = client.post("/api/qdros", json={"file_no": file_no, "plan_id": "PL-ABC"}) assert resp.status_code == 200, resp.text qid = resp.json()["id"] resp = client.post( f"/api/qdros/{qid}/submit-for-approval", json={"reason": "send", "notify": True, "effective_date": date.today().isoformat()}, ) assert resp.status_code == 200, resp.text # Last event should include override markers assert dummy.events, "Expected a notification" _, payload = dummy.events[-1] assert payload.get("__notify_override") is True assert "lawyer@example.com" in str(payload.get("__notify_to")) assert payload.get("__webhook_override") is True assert payload.get("__webhook_url") == "https://hooks.example.com/qdro-test" assert payload.get("__webhook_secret") == "s3cr3t" # Close session try: db_gen.close() except Exception: pass def test_plan_routing_applies_when_no_file_override(client: TestClient, monkeypatch): dummy = DummyNotification() monkeypatch.setattr(qdros_module, "notification_service", dummy, raising=False) # Create file + qdro with plan _, file_no = _create_customer_and_file(client) db_gen = get_db() db = next(db_gen) plan_id = "PL-RTE" _upsert_system_setting(db, f"notifications.qdro.email.to.plan.{plan_id}", "plan@example.com") resp = client.post("/api/qdros", json={"file_no": file_no, "plan_id": plan_id}) assert resp.status_code == 200, resp.text qid = resp.json()["id"] resp = client.post( f"/api/qdros/{qid}/submit-for-approval", json={"reason": "send", "notify": True, "effective_date": date.today().isoformat()}, ) assert resp.status_code == 200, resp.text _, payload = dummy.events[-1] assert payload.get("__notify_override") is True assert payload.get("__notify_to") == "plan@example.com" try: db_gen.close() except Exception: pass