from fastapi.testclient import TestClient from services.shared.security import issue_app_token from services.voice_adapter_service.app import app as voice_app def _admin_headers() -> dict[str, str]: return {"X-User": "admin", "X-Role": "admin"} def test_voice_event_ingest_and_read_with_admin_headers(): client = TestClient(voice_app) created = client.post( "/integrations/voice/events", headers=_admin_headers(), json={ "event_type": "call.started", "call_id": "call_voice_test_admin", "interaction_id": "int_voice_test_admin", "payload": {"source": "unit-test"}, }, ) assert created.status_code == 200 listed = client.get("/integrations/voice/events", headers=_admin_headers()) assert listed.status_code == 200 assert any(item["event_id"] == created.json()["event_id"] for item in listed.json()) def test_voice_event_ingest_allows_trusted_service_subject(monkeypatch): monkeypatch.setenv("ALLOW_LEGACY_HEADER_AUTH", "0") monkeypatch.setenv("APP_TOKEN_SECRET", "track9-voice-service-subject") monkeypatch.setenv("VOICE_ADAPTER_TRUSTED_SERVICE_SUBJECTS", "svc:asterisk-bridge") client = TestClient(voice_app) token = issue_app_token( subject="svc:asterisk-bridge", username="asterisk-bridge", role="admin", auth_source="service", provider="track9-test", ttl_seconds=300, ) allowed = client.post( "/integrations/voice/events", headers={"Authorization": f"Bearer {token}"}, json={ "event_type": "call.ended", "call_id": "call_voice_test_service", "interaction_id": "int_voice_test_service", "payload": {"source": "service-test"}, }, ) assert allowed.status_code == 200 bad = issue_app_token( subject="svc:other", username="other-service", role="admin", auth_source="service", provider="track9-test", ttl_seconds=300, ) denied = client.post( "/integrations/voice/events", headers={"Authorization": f"Bearer {bad}"}, json={ "event_type": "call.ended", "call_id": "call_voice_test_denied", "interaction_id": "int_voice_test_denied", "payload": {"source": "service-test"}, }, ) assert denied.status_code == 403 def test_voice_event_ingest_is_idempotent_by_source_event_id(): client = TestClient(voice_app) source_event_id = "bridge_evt_voice_idempotent" payload = { "event_type": "call.started", "call_id": "call_voice_idempotent", "interaction_id": "int_voice_idempotent", "source_event_id": source_event_id, "payload": {"source": "bridge-test"}, } first = client.post( "/integrations/voice/events", headers=_admin_headers(), json=payload, ) second = client.post( "/integrations/voice/events", headers=_admin_headers(), json=payload, ) assert first.status_code == 200 assert second.status_code == 200 assert first.json()["event_id"] == second.json()["event_id"] assert first.json()["source_event_id"] == source_event_id listed = client.get("/integrations/voice/events", headers=_admin_headers()) assert listed.status_code == 200 matching = [item for item in listed.json() if item["call_id"] == payload["call_id"]] assert len(matching) == 1