- Add FastAPI application with complete router structure - Implement search, articles, ask, feedback, and health endpoints - Add comprehensive Pydantic schemas for API requests/responses - Include stub service implementations for all business logic - Add full test suite with pytest-asyncio integration - Configure conventional commits enforcement via git hooks - Add project documentation and contribution guidelines - Support both OpenAI and Gemini LLM integration options
65 lines
2.2 KiB
Python
65 lines
2.2 KiB
Python
import pytest
|
|
import httpx
|
|
|
|
from news_api.main import create_app
|
|
|
|
|
|
@pytest.fixture()
|
|
async def client():
|
|
app = create_app()
|
|
async with httpx.AsyncClient(app=app, base_url="http://testserver") as async_client:
|
|
yield async_client
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_healthz(client: httpx.AsyncClient) -> None:
|
|
response = await client.get("/healthz")
|
|
assert response.status_code == 200
|
|
assert response.json() == {"status": "ok"}
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_search_defaults(client: httpx.AsyncClient) -> None:
|
|
response = await client.get("/v1/search", params={"q": "energy"})
|
|
assert response.status_code == 200
|
|
payload = response.json()
|
|
assert payload["mode"] == "hybrid"
|
|
assert payload["page"] == 1
|
|
assert payload["results"], "Expected at least one search result"
|
|
first = payload["results"][0]
|
|
assert first["title"].startswith("Stubbed headline")
|
|
assert first["badges"][0]["name"] == "Reuters"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_article_by_id(client: httpx.AsyncClient) -> None:
|
|
article_id = "stub-article"
|
|
response = await client.get(f"/v1/articles/{article_id}")
|
|
assert response.status_code == 200
|
|
payload = response.json()
|
|
assert payload["id"] == article_id
|
|
assert payload["canonical_url"].startswith("https://www.reuters.com")
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_ask_endpoint_returns_citations(client: httpx.AsyncClient) -> None:
|
|
response = await client.post("/v1/ask", json={"query": "What is the latest in energy?"})
|
|
assert response.status_code == 200
|
|
payload = response.json()
|
|
assert payload["answer"], "Expected sentences in answer"
|
|
assert payload["citations"], "Expected citations"
|
|
assert all(sentence["citations"] for sentence in payload["answer"])
|
|
assert payload["conversation_id"], "Expected conversation id"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_feedback_endpoint_acknowledges(client: httpx.AsyncClient) -> None:
|
|
response = await client.post(
|
|
"/v1/feedback",
|
|
json={"query": "test", "answer_id": "stub", "verdict": "up", "comment": "nice"},
|
|
)
|
|
assert response.status_code == 200
|
|
payload = response.json()
|
|
assert payload["status"] == "queued"
|
|
assert "received_at" in payload
|