import aiohttp import pytest from app.backend_adapters import ( HistoryDisabledBackendAdapter, HttpBackendAdapter, NullBackendAdapter, build_backend_adapter, ) @pytest.mark.asyncio async def test_build_backend_adapter_without_url_returns_null_adapter(): adapter = build_backend_adapter( backend_url=None, backend_mode="auto", history_enabled=True, timeout_sec=3, ) assert isinstance(adapter, NullBackendAdapter) assert await adapter.fetch_assistant_config("assistant_1") is None assert ( await adapter.create_call_record( user_id=1, assistant_id="assistant_1", source="debug", ) is None ) assert ( await adapter.add_transcript( call_id="call_1", turn_index=0, speaker="human", content="hi", start_ms=0, end_ms=100, confidence=0.9, duration_ms=100, ) is False ) assert ( await adapter.finalize_call_record( call_id="call_1", status="connected", duration_seconds=2, ) is False ) assert await adapter.search_knowledge_context(kb_id="kb_1", query="hello", n_results=3) == [] assert await adapter.fetch_tool_resource("tool_1") is None @pytest.mark.asyncio async def test_http_backend_adapter_create_call_record_posts_expected_payload(monkeypatch): captured = {} class _FakeResponse: def __init__(self, status=200, payload=None): self.status = status self._payload = payload if payload is not None else {} async def __aenter__(self): return self async def __aexit__(self, exc_type, exc, tb): return None async def json(self): return self._payload def raise_for_status(self): if self.status >= 400: raise RuntimeError("http_error") class _FakeClientSession: def __init__(self, timeout=None): captured["timeout"] = timeout async def __aenter__(self): return self async def __aexit__(self, exc_type, exc, tb): return None def post(self, url, json=None): captured["url"] = url captured["json"] = json return _FakeResponse(status=200, payload={"id": "call_123"}) monkeypatch.setattr("app.backend_adapters.aiohttp.ClientSession", _FakeClientSession) adapter = build_backend_adapter( backend_url="http://localhost:8100", backend_mode="auto", history_enabled=True, timeout_sec=7, ) assert isinstance(adapter, HttpBackendAdapter) call_id = await adapter.create_call_record( user_id=99, assistant_id="assistant_9", source="debug", ) assert call_id == "call_123" assert captured["url"] == "http://localhost:8100/api/history" assert captured["json"] == { "user_id": 99, "assistant_id": "assistant_9", "source": "debug", "status": "connected", } assert isinstance(captured["timeout"], aiohttp.ClientTimeout) assert captured["timeout"].total == 7 @pytest.mark.asyncio async def test_backend_mode_disabled_forces_null_even_with_url(): adapter = build_backend_adapter( backend_url="http://localhost:8100", backend_mode="disabled", history_enabled=True, timeout_sec=7, ) assert isinstance(adapter, NullBackendAdapter) @pytest.mark.asyncio async def test_history_disabled_wraps_backend_adapter(): adapter = build_backend_adapter( backend_url="http://localhost:8100", backend_mode="auto", history_enabled=False, timeout_sec=7, ) assert isinstance(adapter, HistoryDisabledBackendAdapter) assert await adapter.create_call_record(user_id=1, assistant_id="a1", source="debug") is None assert await adapter.add_transcript( call_id="c1", turn_index=0, speaker="human", content="hi", start_ms=0, end_ms=10, duration_ms=10, ) is False