# `client` fixture from conftest (per-test Registry on tmp data_dir; default # tenant runtime pre-warmed by the app lifespan inside the TestClient loop). import json def test_session_creates_new(client): r = client.post("/api/chat/session", json={}) assert r.status_code == 200 d = r.json() assert "session_id" in d and d["is_new"] is True and d["ended"] is False def test_session_resume_active(client): sid = client.post("/api/chat/session", json={}).json()["session_id"] r = client.post("/api/chat/session", json={"session_id": sid}) assert r.json()["is_new"] is False def test_history_new_session_empty(client): sid = client.post("/api/chat/session", json={}).json()["session_id"] r = client.get(f"/api/chat/{sid}/messages") assert r.status_code == 200 and r.json() == [] def test_history_404_unknown_sid(client): assert client.get("/api/chat/nope/messages").status_code == 404 def test_history_rejects_non_app_session(client): # widget-source conversations are not readable via this public endpoint # (narrow the read surface to app only). 经真实 WS 路由造 widget 会话: # 租户 engine 的常驻连接绑定 TestClient 的事件循环,测试线程不得另起 # asyncio.run 直开其 session_factory(跨循环复用会死锁)。 with client.websocket_connect("/ws/chat") as ws: ws.send_text(json.dumps({"source": "widget"})) sid = ws.receive_json()["session_id"] assert client.get(f"/api/chat/{sid}/messages").status_code == 404