Files
opus-agent/tests/test_api_topics.py

206 lines
5.8 KiB
Python

import pytest
from httpx import AsyncClient, ASGITransport
@pytest.fixture
def app():
from src.backend.main import app
return app
@pytest.fixture
async def client(app):
transport = ASGITransport(app=app)
async with AsyncClient(
transport=transport,
base_url="http://test",
headers={"X-Api-Key": "test-key-12345"},
) as ac:
yield ac
@pytest.fixture
async def client_no_auth(app):
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as ac:
yield ac
@pytest.mark.asyncio
async def test_request_without_api_key_returns_403(client_no_auth):
resp = await client_no_auth.get("/api/health")
assert resp.status_code == 403
@pytest.mark.asyncio
async def test_request_with_wrong_api_key_returns_403(app):
transport = ASGITransport(app=app)
async with AsyncClient(
transport=transport,
base_url="http://test",
headers={"X-Api-Key": "wrong-key"},
) as ac:
resp = await ac.get("/api/health")
assert resp.status_code == 403
@pytest.mark.asyncio
async def test_create_topic(client):
resp = await client.post(
"/api/topics",
json={
"name": "coding",
"system_prompt": "You are an expert coder.",
"summary": "Coding topic",
"model": "claude-sonnet-4-6",
},
)
assert resp.status_code == 201
data = resp.json()
assert data["success"] is True
assert data["data"]["name"] == "coding"
assert data["data"]["model"] == "claude-sonnet-4-6"
assert "id" in data["data"]
@pytest.mark.asyncio
async def test_create_topic_minimal(client):
resp = await client.post(
"/api/topics",
json={"name": "analysis", "system_prompt": "You analyze data."},
)
assert resp.status_code == 201
data = resp.json()
assert data["data"]["summary"] == ""
assert data["data"]["model"] is None
@pytest.mark.asyncio
async def test_create_topic_duplicate_name_fails(client):
await client.post(
"/api/topics",
json={"name": "coding", "system_prompt": "Prompt 1"},
)
resp = await client.post(
"/api/topics",
json={"name": "coding", "system_prompt": "Prompt 2"},
)
assert resp.status_code == 409
@pytest.mark.asyncio
async def test_list_topics(client):
await client.post(
"/api/topics", json={"name": "a", "system_prompt": "A"}
)
await client.post(
"/api/topics", json={"name": "b", "system_prompt": "B"}
)
resp = await client.get("/api/topics")
assert resp.status_code == 200
data = resp.json()
assert len(data["data"]) == 2
@pytest.mark.asyncio
async def test_get_topic(client):
create_resp = await client.post(
"/api/topics", json={"name": "coding", "system_prompt": "Code"}
)
topic_id = create_resp.json()["data"]["id"]
resp = await client.get(f"/api/topics/{topic_id}")
assert resp.status_code == 200
assert resp.json()["data"]["name"] == "coding"
@pytest.mark.asyncio
async def test_get_topic_not_found(client):
resp = await client.get("/api/topics/nonexistent-id")
assert resp.status_code == 404
@pytest.mark.asyncio
async def test_update_topic(client):
create_resp = await client.post(
"/api/topics", json={"name": "coding", "system_prompt": "Old"}
)
topic_id = create_resp.json()["data"]["id"]
resp = await client.put(
f"/api/topics/{topic_id}",
json={"system_prompt": "New prompt"},
)
assert resp.status_code == 200
assert resp.json()["data"]["system_prompt"] == "New prompt"
assert resp.json()["data"]["name"] == "coding"
@pytest.mark.asyncio
async def test_delete_topic(client):
create_resp = await client.post(
"/api/topics", json={"name": "coding", "system_prompt": "Code"}
)
topic_id = create_resp.json()["data"]["id"]
resp = await client.delete(f"/api/topics/{topic_id}")
assert resp.status_code == 200
resp = await client.get(f"/api/topics/{topic_id}")
assert resp.status_code == 404
@pytest.mark.asyncio
async def test_summarize_topic(client):
create_resp = await client.post(
"/api/topics",
json={"name": "summarize-test", "system_prompt": "You help."},
)
topic_id = create_resp.json()["data"]["id"]
from src.backend.db.database import get_db, create_request, complete_request
db = await get_db()
try:
req1 = await create_request(db, "Question 1", topic_id)
await complete_request(db, req1["id"], "Answer 1")
req2 = await create_request(db, "Question 2", topic_id)
await complete_request(db, req2["id"], "Answer 2")
finally:
await db.close()
from unittest.mock import patch, AsyncMock, MagicMock
mock_worker = MagicMock()
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = {
"success": True,
"summary": "Comprehensive summary of all exchanges.",
}
mock_client = AsyncMock()
mock_client.post.return_value = mock_response
mock_client.__aenter__ = AsyncMock(return_value=mock_client)
mock_client.__aexit__ = AsyncMock(return_value=False)
with patch("src.backend.services.worker_client.httpx.AsyncClient", return_value=mock_client):
resp = await client.post(f"/api/topics/{topic_id}/summarize")
assert resp.status_code == 200
data = resp.json()
assert data["success"] is True
assert "summary" in data["data"]
@pytest.mark.asyncio
async def test_summarize_topic_no_requests(client):
create_resp = await client.post(
"/api/topics",
json={"name": "empty-topic", "system_prompt": "Empty."},
)
topic_id = create_resp.json()["data"]["id"]
resp = await client.post(f"/api/topics/{topic_id}/summarize")
assert resp.status_code == 400