- "backend/routers/videos.py" - "backend/schemas.py" - "backend/tests/test_video_detail.py" GSD-Task: S01/T01
133 lines
4.5 KiB
Python
133 lines
4.5 KiB
Python
"""Tests for video detail and transcript endpoints.
|
|
|
|
Covers:
|
|
- GET /api/v1/videos/{video_id} — single video with creator info
|
|
- GET /api/v1/videos/{video_id}/transcript — ordered segments
|
|
"""
|
|
|
|
import uuid
|
|
|
|
import pytest
|
|
import pytest_asyncio
|
|
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
|
|
|
|
from models import ContentType, Creator, ProcessingStatus, SourceVideo, TranscriptSegment
|
|
|
|
|
|
@pytest_asyncio.fixture()
|
|
async def video_with_creator(db_engine):
|
|
"""Create a Creator + SourceVideo pair. Returns dict with IDs."""
|
|
factory = async_sessionmaker(db_engine, class_=AsyncSession, expire_on_commit=False)
|
|
async with factory() as session:
|
|
creator = Creator(
|
|
name="TestProducer",
|
|
slug="testproducer",
|
|
folder_name="TestProducer",
|
|
genres=["electronic"],
|
|
)
|
|
session.add(creator)
|
|
await session.flush()
|
|
|
|
video = SourceVideo(
|
|
creator_id=creator.id,
|
|
filename="synth-tutorial.mp4",
|
|
file_path="TestProducer/synth-tutorial.mp4",
|
|
duration_seconds=720,
|
|
content_type=ContentType.tutorial,
|
|
processing_status=ProcessingStatus.complete,
|
|
)
|
|
session.add(video)
|
|
await session.flush()
|
|
|
|
result = {
|
|
"creator_id": creator.id,
|
|
"creator_name": creator.name,
|
|
"creator_slug": creator.slug,
|
|
"video_id": video.id,
|
|
}
|
|
await session.commit()
|
|
return result
|
|
|
|
|
|
@pytest_asyncio.fixture()
|
|
async def video_with_segments(db_engine, video_with_creator):
|
|
"""Add transcript segments to the video. Returns video_with_creator + segment count."""
|
|
factory = async_sessionmaker(db_engine, class_=AsyncSession, expire_on_commit=False)
|
|
async with factory() as session:
|
|
segments = [
|
|
TranscriptSegment(
|
|
source_video_id=video_with_creator["video_id"],
|
|
start_time=float(i * 10),
|
|
end_time=float(i * 10 + 9),
|
|
text=f"Segment {i} text content.",
|
|
segment_index=i,
|
|
)
|
|
for i in range(5)
|
|
]
|
|
session.add_all(segments)
|
|
await session.commit()
|
|
return {**video_with_creator, "segment_count": 5}
|
|
|
|
|
|
# ── Video Detail ─────────────────────────────────────────────────────────────
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_video_detail_success(client, video_with_creator):
|
|
vid = video_with_creator["video_id"]
|
|
resp = await client.get(f"/api/v1/videos/{vid}")
|
|
assert resp.status_code == 200
|
|
|
|
data = resp.json()
|
|
assert data["id"] == str(vid)
|
|
assert data["filename"] == "synth-tutorial.mp4"
|
|
assert data["creator_name"] == "TestProducer"
|
|
assert data["creator_slug"] == "testproducer"
|
|
# video_url is always None for now
|
|
assert data["video_url"] is None
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_video_detail_404(client):
|
|
fake_id = uuid.uuid4()
|
|
resp = await client.get(f"/api/v1/videos/{fake_id}")
|
|
assert resp.status_code == 404
|
|
assert "not found" in resp.json()["detail"].lower()
|
|
|
|
|
|
# ── Transcript ───────────────────────────────────────────────────────────────
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_transcript_success(client, video_with_segments):
|
|
vid = video_with_segments["video_id"]
|
|
resp = await client.get(f"/api/v1/videos/{vid}/transcript")
|
|
assert resp.status_code == 200
|
|
|
|
data = resp.json()
|
|
assert data["video_id"] == str(vid)
|
|
assert data["total"] == 5
|
|
assert len(data["segments"]) == 5
|
|
# Verify ordering by segment_index
|
|
indices = [s["segment_index"] for s in data["segments"]]
|
|
assert indices == [0, 1, 2, 3, 4]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_transcript_404(client):
|
|
fake_id = uuid.uuid4()
|
|
resp = await client.get(f"/api/v1/videos/{fake_id}/transcript")
|
|
assert resp.status_code == 404
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_transcript_empty(client, video_with_creator):
|
|
"""Video exists but has no segments — returns empty list."""
|
|
vid = video_with_creator["video_id"]
|
|
resp = await client.get(f"/api/v1/videos/{vid}/transcript")
|
|
assert resp.status_code == 200
|
|
|
|
data = resp.json()
|
|
assert data["video_id"] == str(vid)
|
|
assert data["total"] == 0
|
|
assert data["segments"] == []
|