"""Tests for meeting_room.server — FastAPI app, REST API, WebSocket/SSE.""" from __future__ import annotations import asyncio import pytest from fastapi.testclient import TestClient from meeting_room.events import AsyncEventBridge, EventEmitter from meeting_room.server import Session, SessionStore, app, store @pytest.fixture(autouse=True) def _reset_store(): """Clear the global session store before each test.""" store._sessions.clear() yield @pytest.fixture def client(): """FastAPI test client.""" return TestClient(app) # --------------------------------------------------------------------------- # SessionStore # --------------------------------------------------------------------------- class TestSessionStore: def test_create_session(self) -> None: store = SessionStore() session = store.create({"providers": {}, "roles": {}, "defaults": {}}, _minimal_discussion_config()) assert session.id assert session.status == "created" def test_get_session(self) -> None: store = SessionStore() session = store.create({"providers": {}, "roles": {}, "defaults": {}}, _minimal_discussion_config()) found = store.get(session.id) assert found is session def test_get_nonexistent_session(self) -> None: store = SessionStore() assert store.get("nonexistent") is None def test_list_sessions(self) -> None: store = SessionStore() store.create({"providers": {}, "roles": {}, "defaults": {}}, _minimal_discussion_config()) store.create({"providers": {}, "roles": {}, "defaults": {}}, _minimal_discussion_config()) assert len(store.list_sessions()) == 2 # --------------------------------------------------------------------------- # REST API endpoints # --------------------------------------------------------------------------- class TestCreateSession: def test_create_session_returns_id_and_status(self, client) -> None: response = client.post("/api/sessions") assert response.status_code == 200 data = response.json() assert "id" in data assert data["status"] == "created" class TestListSessions: def test_list_empty(self, client) -> None: response = client.get("/api/sessions") assert response.status_code == 200 assert response.json() == [] def test_list_after_create(self, client) -> None: client.post("/api/sessions") client.post("/api/sessions") response = client.get("/api/sessions") assert response.status_code == 200 assert len(response.json()) == 2 class TestGetSession: def test_get_existing_session(self, client) -> None: create_resp = client.post("/api/sessions") session_id = create_resp.json()["id"] response = client.get(f"/api/sessions/{session_id}") assert response.status_code == 200 assert response.json()["id"] == session_id def test_get_nonexistent_session(self, client) -> None: response = client.get("/api/sessions/nonexistent") assert response.status_code == 404 class TestRolesAndProviders: def test_list_roles(self, client) -> None: response = client.get("/api/roles") assert response.status_code == 200 data = response.json() assert "moderator" in data or isinstance(data, dict) def test_list_providers(self, client) -> None: response = client.get("/api/providers") assert response.status_code == 200 data = response.json() assert isinstance(data, dict) # --------------------------------------------------------------------------- # Session model # --------------------------------------------------------------------------- class TestSession: def test_build_engine(self) -> None: config = _minimal_config() session = Session("test-id", config, _minimal_discussion_config()) engine = session.build_engine() assert engine is not None # --------------------------------------------------------------------------- # Helper # --------------------------------------------------------------------------- def _minimal_config() -> dict: return { "providers": { "test_provider": { "base_url": "https://api.example.com/v1", "api_key": "test-key", } }, "roles": { "moderator": { "name": "Moderator", "provider": "test_provider", "model": "gpt-4o-mini", "temperature": 0.7, "tools": "none", "system_prompt": "You are a moderator.", } }, "defaults": { "max_rounds": 3, "language": "en", "framework": "custom", "workdir": ".", }, } def _minimal_discussion_config(): from meeting_room.models import DefaultsConfig, DiscussionConfig return DiscussionConfig( providers={"test_provider": {"base_url": "https://api.example.com/v1", "api_key": "test-key"}}, roles={"moderator": {"name": "Moderator", "provider": "test_provider", "model": "gpt-4o-mini"}}, defaults=DefaultsConfig(max_rounds=3), )