161 lines
5.5 KiB
Python
161 lines
5.5 KiB
Python
"""Reading event API tests."""
|
|
|
|
import pytest
|
|
from httpx import ASGITransport, AsyncClient
|
|
from sqlalchemy import select
|
|
|
|
from app.db.database import get_db
|
|
from app.db.models import MemoryItem
|
|
from app.main import app
|
|
|
|
pytestmark = pytest.mark.asyncio
|
|
|
|
|
|
async def _create_profile(client: AsyncClient) -> str:
|
|
response = await client.post(
|
|
"/api/profiles",
|
|
json={"name": "小明", "gender": "male"},
|
|
)
|
|
assert response.status_code == 201
|
|
return response.json()["id"]
|
|
|
|
|
|
async def test_create_reading_event_updates_stats_and_memory(
|
|
db_session,
|
|
test_user,
|
|
auth_token,
|
|
test_story,
|
|
):
|
|
async def override_get_db():
|
|
yield db_session
|
|
|
|
app.dependency_overrides[get_db] = override_get_db
|
|
transport = ASGITransport(app=app)
|
|
|
|
try:
|
|
async with AsyncClient(transport=transport, base_url="http://test") as client:
|
|
client.cookies.set("access_token", auth_token)
|
|
profile_id = await _create_profile(client)
|
|
|
|
response = await client.post(
|
|
"/api/reading-events",
|
|
json={
|
|
"child_profile_id": profile_id,
|
|
"story_id": test_story.id,
|
|
"event_type": "completed",
|
|
"reading_time": 120,
|
|
},
|
|
)
|
|
assert response.status_code == 201
|
|
data = response.json()
|
|
assert data["child_profile_id"] == profile_id
|
|
assert data["story_id"] == test_story.id
|
|
assert data["event_type"] == "completed"
|
|
|
|
response = await client.get(f"/api/profiles/{profile_id}")
|
|
assert response.status_code == 200
|
|
profile = response.json()
|
|
assert profile["stories_count"] == 1
|
|
assert profile["total_reading_time"] == 120
|
|
|
|
result = await db_session.execute(
|
|
select(MemoryItem).where(MemoryItem.child_profile_id == profile_id)
|
|
)
|
|
items = result.scalars().all()
|
|
assert len(items) == 1
|
|
assert items[0].type == "recent_story"
|
|
assert items[0].value["story_id"] == test_story.id
|
|
assert items[0].value["mode"] == test_story.mode
|
|
assert items[0].value["reading_time"] == 120
|
|
assert items[0].value["source"] == "reading_event"
|
|
|
|
timeline_response = await client.get(f"/api/profiles/{profile_id}/timeline")
|
|
assert timeline_response.status_code == 200
|
|
timeline_events = timeline_response.json()["events"]
|
|
reading_events = [
|
|
event for event in timeline_events if event["type"] == "reading_event"
|
|
]
|
|
memory_events = [event for event in timeline_events if event["type"] == "memory"]
|
|
assert reading_events
|
|
assert memory_events
|
|
assert reading_events[0]["metadata"]["story_id"] == test_story.id
|
|
assert reading_events[0]["metadata"]["reading_time"] == 120
|
|
assert memory_events[0]["metadata"]["memory_type"] == "recent_story"
|
|
assert memory_events[0]["metadata"]["story_id"] == test_story.id
|
|
|
|
response = await client.post(
|
|
"/api/reading-events",
|
|
json={
|
|
"child_profile_id": profile_id,
|
|
"story_id": test_story.id,
|
|
"event_type": "skipped",
|
|
"reading_time": 0,
|
|
},
|
|
)
|
|
assert response.status_code == 201
|
|
|
|
result = await db_session.execute(
|
|
select(MemoryItem).where(MemoryItem.child_profile_id == profile_id)
|
|
)
|
|
assert len(result.scalars().all()) == 1
|
|
|
|
response = await client.post(
|
|
"/api/reading-events",
|
|
json={
|
|
"child_profile_id": profile_id,
|
|
"story_id": test_story.id,
|
|
"event_type": "completed",
|
|
"reading_time": 0,
|
|
},
|
|
)
|
|
assert response.status_code == 201
|
|
|
|
response = await client.get(f"/api/profiles/{profile_id}")
|
|
assert response.status_code == 200
|
|
profile = response.json()
|
|
assert profile["stories_count"] == 1
|
|
assert profile["total_reading_time"] == 120
|
|
finally:
|
|
app.dependency_overrides.clear()
|
|
|
|
|
|
async def test_reading_event_validation_errors(
|
|
db_session,
|
|
test_user,
|
|
auth_token,
|
|
):
|
|
async def override_get_db():
|
|
yield db_session
|
|
|
|
app.dependency_overrides[get_db] = override_get_db
|
|
transport = ASGITransport(app=app)
|
|
|
|
try:
|
|
async with AsyncClient(transport=transport, base_url="http://test") as client:
|
|
client.cookies.set("access_token", auth_token)
|
|
|
|
response = await client.post(
|
|
"/api/reading-events",
|
|
json={
|
|
"child_profile_id": "not-exist",
|
|
"event_type": "started",
|
|
"reading_time": 0,
|
|
},
|
|
)
|
|
assert response.status_code == 404
|
|
|
|
profile_id = await _create_profile(client)
|
|
|
|
response = await client.post(
|
|
"/api/reading-events",
|
|
json={
|
|
"child_profile_id": profile_id,
|
|
"story_id": 999999,
|
|
"event_type": "completed",
|
|
"reading_time": 0,
|
|
},
|
|
)
|
|
assert response.status_code == 404
|
|
finally:
|
|
app.dependency_overrides.clear()
|