"""世界模型 API 测试(河图枢运行时,api-spec §12)。""" from collections.abc import AsyncGenerator import pytest from httpx import ASGITransport, AsyncClient from app.main import app @pytest.fixture async def client(auth_headers: dict[str, str]) -> AsyncGenerator[AsyncClient, None]: transport = ASGITransport(app=app) async with AsyncClient( transport=transport, base_url="http://test", headers=auth_headers ) as http_client: yield http_client @pytest.mark.asyncio async def test_list_entities_empty(client: AsyncClient) -> None: resp = await client.get("/api/v1/world/entities") assert resp.status_code == 200 body = resp.json() assert body["total"] == 0 assert body["items"] == [] @pytest.mark.asyncio async def test_create_and_get_entity(client: AsyncClient) -> None: created = await client.post( "/api/v1/world/entities", json={"name": "用户项目", "type": "project", "state_type": "fact", "confidence": 0.9}, ) assert created.status_code == 200 entity = created.json() assert entity["id"].startswith("world_entity_") assert entity["name"] == "用户项目" assert entity["type"] == "project" assert entity["state_type"] == "fact" assert entity["character_id"].startswith("character_") fetched = await client.get(f"/api/v1/world/entities/{entity['id']}") assert fetched.status_code == 200 assert fetched.json()["id"] == entity["id"] @pytest.mark.asyncio async def test_get_entity_not_found(client: AsyncClient) -> None: resp = await client.get("/api/v1/world/entities/world_entity_missing") assert resp.status_code == 404 @pytest.mark.asyncio async def test_list_entities_filter_by_type(client: AsyncClient) -> None: await client.post("/api/v1/world/entities", json={"name": "概念A", "type": "concept"}) await client.post("/api/v1/world/entities", json={"name": "项目B", "type": "project"}) filtered = await client.get("/api/v1/world/entities?type=project") assert filtered.status_code == 200 body = filtered.json() assert body["total"] == 1 assert body["items"][0]["type"] == "project" all_entities = await client.get("/api/v1/world/entities") assert all_entities.json()["total"] == 2 @pytest.mark.asyncio async def test_create_relation(client: AsyncClient) -> None: user = ( await client.post("/api/v1/world/entities", json={"name": "用户", "type": "person"}) ).json()["id"] project = ( await client.post("/api/v1/world/entities", json={"name": "魂镜项目", "type": "project"}) ).json()["id"] created = await client.post( "/api/v1/world/relations", json={"subject_id": user, "predicate": "正在进行", "object_id": project}, ) assert created.status_code == 200 relation = created.json() assert relation["id"].startswith("world_relation_") assert relation["predicate"] == "正在进行" assert relation["subject_id"] == user assert relation["object_id"] == project listed = await client.get("/api/v1/world/relations") assert listed.json()["total"] == 1 @pytest.mark.asyncio async def test_create_relation_rejects_missing_entity(client: AsyncClient) -> None: project = ( await client.post("/api/v1/world/entities", json={"name": "项目", "type": "project"}) ).json()["id"] # 主体不存在 resp = await client.post( "/api/v1/world/relations", json={"subject_id": "world_entity_missing", "predicate": "依赖", "object_id": project}, ) assert resp.status_code == 404