Files
dreamweaver/backend/tests/test_reading_events.py
zhangtuo e9d7f8832a Initial commit: clean project structure
- Backend: FastAPI + SQLAlchemy + Celery (Python 3.11+)
- Frontend: Vue 3 + TypeScript + Pinia + Tailwind
- Admin Frontend: separate Vue 3 app for management
- Docker Compose: 9 services orchestration
- Specs: design prototypes, memory system PRD, product roadmap

Cleanup performed:
- Removed temporary debug scripts from backend root
- Removed deprecated admin_app.py (embedded UI)
- Removed duplicate docs from admin-frontend
- Updated .gitignore for Vite cache and egg-info
2026-01-20 18:20:03 +08:00

144 lines
4.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
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()