Files
codetutor/backend/tests/test_api.py

180 lines
5.7 KiB
Python

from typing import Any
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession
from src.models import Category, Difficulty, Explanation, Pattern, Question, Solution
SampleData = dict[str, Any]
async def create_sample_data(db_session: AsyncSession) -> SampleData:
category = Category(name="Arrays", slug="arrays", description="Array problems")
db_session.add(category)
pattern = Pattern(
name="Two Pointers",
slug="two-pointers",
description="Two pointer technique",
)
db_session.add(pattern)
await db_session.flush()
question = Question(
title="Two Sum",
slug="two-sum",
difficulty=Difficulty.EASY,
description="Find two numbers that add up to target.",
leetcode_id=1,
leetcode_url="https://leetcode.com/problems/two-sum/",
)
question.categories = [category]
question.patterns = [pattern]
db_session.add(question)
await db_session.flush()
explanation = Explanation(
question_id=question.id,
approach="Use a hash map.",
intuition="Store seen values for O(1) lookup.",
time_complexity="O(n)",
space_complexity="O(n)",
)
db_session.add(explanation)
solution = Solution(
question_id=question.id,
approach_name="Hash Map",
code="def two_sum(nums, target): pass",
is_optimal=True,
)
db_session.add(solution)
await db_session.commit()
return {"question": question, "category": category, "pattern": pattern}
async def test_health_check(client: AsyncClient) -> None:
response = await client.get("/api/health")
assert response.status_code == 200
assert response.json() == {"status": "healthy"}
async def test_list_questions_empty(client: AsyncClient) -> None:
response = await client.get("/api/questions")
assert response.status_code == 200
data = response.json()
assert data["items"] == []
assert data["total"] == 0
async def test_list_questions(client: AsyncClient, db_session: AsyncSession) -> None:
await create_sample_data(db_session)
response = await client.get("/api/questions")
assert response.status_code == 200
data = response.json()
assert data["total"] == 1
assert len(data["items"]) == 1
assert data["items"][0]["title"] == "Two Sum"
assert data["items"][0]["difficulty"] == "easy"
async def test_list_questions_filter_difficulty(
client: AsyncClient, db_session: AsyncSession
) -> None:
await create_sample_data(db_session)
response = await client.get("/api/questions?difficulty=easy")
assert response.status_code == 200
assert response.json()["total"] == 1
response = await client.get("/api/questions?difficulty=hard")
assert response.status_code == 200
assert response.json()["total"] == 0
async def test_list_questions_invalid_difficulty(client: AsyncClient) -> None:
response = await client.get("/api/questions?difficulty=invalid")
assert response.status_code == 400
async def test_get_question(client: AsyncClient, db_session: AsyncSession) -> None:
await create_sample_data(db_session)
response = await client.get("/api/questions/two-sum")
assert response.status_code == 200
data = response.json()
assert data["title"] == "Two Sum"
assert data["explanation"]["time_complexity"] == "O(n)"
assert len(data["solutions"]) == 1
async def test_get_question_not_found(client: AsyncClient) -> None:
response = await client.get("/api/questions/nonexistent")
assert response.status_code == 404
async def test_list_categories_empty(client: AsyncClient) -> None:
response = await client.get("/api/categories")
assert response.status_code == 200
assert response.json()["items"] == []
async def test_list_categories(client: AsyncClient, db_session: AsyncSession) -> None:
await create_sample_data(db_session)
response = await client.get("/api/categories")
assert response.status_code == 200
data = response.json()
assert len(data["items"]) == 1
assert data["items"][0]["name"] == "Arrays"
assert data["items"][0]["question_count"] == 1
async def test_list_patterns_empty(client: AsyncClient) -> None:
response = await client.get("/api/patterns")
assert response.status_code == 200
assert response.json()["items"] == []
async def test_list_patterns(client: AsyncClient, db_session: AsyncSession) -> None:
await create_sample_data(db_session)
response = await client.get("/api/patterns")
assert response.status_code == 200
data = response.json()
assert len(data["items"]) == 1
assert data["items"][0]["name"] == "Two Pointers"
async def test_get_pattern(client: AsyncClient, db_session: AsyncSession) -> None:
await create_sample_data(db_session)
response = await client.get("/api/patterns/two-pointers")
assert response.status_code == 200
data = response.json()
assert data["name"] == "Two Pointers"
assert data["question_count"] == 1
async def test_get_pattern_not_found(client: AsyncClient) -> None:
response = await client.get("/api/patterns/nonexistent")
assert response.status_code == 404
async def test_get_stats_empty(client: AsyncClient) -> None:
response = await client.get("/api/stats")
assert response.status_code == 200
data = response.json()
assert data["total_questions"] == 0
assert data["by_difficulty"]["easy"] == 0
async def test_get_stats(client: AsyncClient, db_session: AsyncSession) -> None:
await create_sample_data(db_session)
response = await client.get("/api/stats")
assert response.status_code == 200
data = response.json()
assert data["total_questions"] == 1
assert data["by_difficulty"]["easy"] == 1
assert len(data["by_category"]) == 1
assert len(data["by_pattern"]) == 1