Add automated unit and mock integration test suite
- Configure conftest.py with pytest tmp_path DB isolation fixtures - Add test_db.py for schema connection validations - Add test_fetcher.py with mocked yt-dlp subprocess parser checks - Add test_summarizer.py with mocked transcripts and Claude API requests - Add test_main.py for FastAPI router endpoints and state updates Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from main import app, get_db
|
||||
import aiosqlite
|
||||
from unittest.mock import patch
|
||||
|
||||
@pytest.fixture
|
||||
def client(test_db):
|
||||
# Override get_db dependency to use the isolated test database
|
||||
async def override_get_db():
|
||||
yield test_db
|
||||
app.dependency_overrides[get_db] = override_get_db
|
||||
yield TestClient(app)
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
def test_health(client):
|
||||
response = client.get("/api/health")
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"status": "ok"}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_videos(client, test_db):
|
||||
# Insert mock videos with different statuses
|
||||
await test_db.execute("""
|
||||
INSERT INTO videos (video_id, title, url, status)
|
||||
VALUES
|
||||
('v1', 'Pending Video', 'https://youtube.com/v1', 'pending'),
|
||||
('v2', 'Read Video', 'https://youtube.com/v2', 'read'),
|
||||
('v3', 'Skipped Video', 'https://youtube.com/v3', 'skipped')
|
||||
""")
|
||||
await test_db.commit()
|
||||
|
||||
# Test pending filter
|
||||
resp = client.get("/api/videos?status=pending")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert len(data) == 1
|
||||
assert data[0]["video_id"] == "v1"
|
||||
|
||||
# Test read filter
|
||||
resp = client.get("/api/videos?status=read")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert len(data) == 1
|
||||
assert data[0]["video_id"] == "v2"
|
||||
|
||||
def test_update_status_success(client, test_db):
|
||||
# Insert pending video
|
||||
test_db.execute_insert = lambda *args: None # Helper since we execute raw
|
||||
async def insert():
|
||||
await test_db.execute("""
|
||||
INSERT INTO videos (video_id, title, url, status)
|
||||
VALUES ('status_vid', 'Title', 'https://youtube.com/watch?v=status_vid', 'pending')
|
||||
""")
|
||||
await test_db.commit()
|
||||
|
||||
import asyncio
|
||||
asyncio.run(insert())
|
||||
|
||||
# Send status update
|
||||
resp = client.post("/api/videos/status_vid/status", json={"status": "read"})
|
||||
assert resp.status_code == 200
|
||||
assert resp.json() == {"message": "Video status_vid status updated to read."}
|
||||
|
||||
# Verify db was updated
|
||||
async def verify():
|
||||
cursor = await test_db.execute("SELECT status FROM videos WHERE video_id = 'status_vid'")
|
||||
row = await cursor.fetchone()
|
||||
return row["status"]
|
||||
|
||||
status = asyncio.run(verify())
|
||||
assert status == "read"
|
||||
|
||||
def test_update_status_invalid_value(client):
|
||||
resp = client.post("/api/videos/status_vid/status", json={"status": "archived"})
|
||||
assert resp.status_code == 400
|
||||
assert "Invalid status value" in resp.json()["detail"]
|
||||
|
||||
def test_update_status_not_found(client):
|
||||
resp = client.post("/api/videos/missing_vid/status", json={"status": "read"})
|
||||
assert resp.status_code == 404
|
||||
assert "Video not found" in resp.json()["detail"]
|
||||
|
||||
def test_trigger_fetch(client):
|
||||
with patch("main.bg_fetch_and_summarize") as mock_task:
|
||||
resp = client.post("/api/videos/fetch")
|
||||
assert resp.status_code == 200
|
||||
assert "sync and summarization running in background" in resp.json()["message"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_trigger_summarize(client, test_db):
|
||||
# Insert video
|
||||
await test_db.execute("""
|
||||
INSERT INTO videos (video_id, title, url, status)
|
||||
VALUES ('sum_vid', 'Title', 'https://youtube.com/watch?v=sum_vid', 'pending')
|
||||
""")
|
||||
await test_db.commit()
|
||||
|
||||
with patch("main.summarize_video") as mock_sum:
|
||||
resp = client.post("/api/videos/sum_vid/summarize")
|
||||
assert resp.status_code == 200
|
||||
assert "summarization for video sum_vid queued" in resp.json()["message"].lower()
|
||||
|
||||
def test_trigger_summarize_not_found(client):
|
||||
resp = client.post("/api/videos/missing_sum/summarize")
|
||||
assert resp.status_code == 404
|
||||
assert "Video not found" in resp.json()["detail"]
|
||||
Reference in New Issue
Block a user