Implement script generation endpoint (Task 18)
- Added ScriptRequest, ScriptResponse, and ScriptSegment Pydantic models - Created /api/tts/script POST endpoint in main.py - Integrated with TTSService to generate script segments using AI - Added generate_script_segments method to TTSService - Returns segments with unique IDs for frontend tracking - Handles errors gracefully when AI segmentation fails - Falls back to pattern-based segmentation when Ollama unavailable - Added comprehensive tests for the endpoint - Validates: Requirements 15.1, 15.2
This commit is contained in:
173
backend/test_script_endpoint.py
Normal file
173
backend/test_script_endpoint.py
Normal file
@@ -0,0 +1,173 @@
|
||||
"""
|
||||
Tests for the script generation endpoint.
|
||||
"""
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from main import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
def test_script_endpoint_exists():
|
||||
"""Test that the /api/tts/script endpoint exists."""
|
||||
response = client.post(
|
||||
"/api/tts/script",
|
||||
json={
|
||||
"text": "Alice: Hello there!\nBob: Hi Alice!",
|
||||
"roles": ["Alice", "Bob"]
|
||||
}
|
||||
)
|
||||
# Should not return 404
|
||||
assert response.status_code != 404
|
||||
|
||||
|
||||
def test_script_generation_with_valid_input():
|
||||
"""Test script generation with valid text and roles."""
|
||||
response = client.post(
|
||||
"/api/tts/script",
|
||||
json={
|
||||
"text": "Alice: Hello there!\nBob: Hi Alice, how are you?",
|
||||
"roles": ["Alice", "Bob", "Narrator"]
|
||||
}
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
|
||||
# Check response structure
|
||||
assert "segments" in data
|
||||
assert isinstance(data["segments"], list)
|
||||
assert len(data["segments"]) > 0
|
||||
|
||||
# Check each segment has required fields
|
||||
for segment in data["segments"]:
|
||||
assert "id" in segment
|
||||
assert "speaker" in segment
|
||||
assert "text" in segment
|
||||
assert isinstance(segment["id"], str)
|
||||
assert isinstance(segment["speaker"], str)
|
||||
assert isinstance(segment["text"], str)
|
||||
assert len(segment["text"]) > 0
|
||||
|
||||
|
||||
def test_script_generation_with_empty_text():
|
||||
"""Test that empty text returns validation error."""
|
||||
response = client.post(
|
||||
"/api/tts/script",
|
||||
json={
|
||||
"text": "",
|
||||
"roles": ["Alice", "Bob"]
|
||||
}
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
data = response.json()
|
||||
assert "error" in data
|
||||
assert data["error"] == "ValidationError"
|
||||
|
||||
|
||||
def test_script_generation_with_empty_roles():
|
||||
"""Test that empty roles list returns validation error."""
|
||||
response = client.post(
|
||||
"/api/tts/script",
|
||||
json={
|
||||
"text": "Some text here",
|
||||
"roles": []
|
||||
}
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
data = response.json()
|
||||
assert "error" in data
|
||||
assert data["error"] == "ValidationError"
|
||||
|
||||
|
||||
def test_script_generation_missing_text_field():
|
||||
"""Test that missing text field returns validation error."""
|
||||
response = client.post(
|
||||
"/api/tts/script",
|
||||
json={
|
||||
"roles": ["Alice", "Bob"]
|
||||
}
|
||||
)
|
||||
|
||||
# Our error handler converts 422 to 400
|
||||
assert response.status_code == 400
|
||||
data = response.json()
|
||||
assert "error" in data
|
||||
assert data["error"] == "ValidationError"
|
||||
|
||||
|
||||
def test_script_generation_missing_roles_field():
|
||||
"""Test that missing roles field returns validation error."""
|
||||
response = client.post(
|
||||
"/api/tts/script",
|
||||
json={
|
||||
"text": "Some text here"
|
||||
}
|
||||
)
|
||||
|
||||
# Our error handler converts 422 to 400
|
||||
assert response.status_code == 400
|
||||
data = response.json()
|
||||
assert "error" in data
|
||||
assert data["error"] == "ValidationError"
|
||||
|
||||
|
||||
def test_script_segments_have_unique_ids():
|
||||
"""Test that each segment has a unique ID."""
|
||||
response = client.post(
|
||||
"/api/tts/script",
|
||||
json={
|
||||
"text": "Alice: Hello!\nBob: Hi!\nAlice: How are you?\nBob: Good!",
|
||||
"roles": ["Alice", "Bob"]
|
||||
}
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
|
||||
segment_ids = [seg["id"] for seg in data["segments"]]
|
||||
# Check all IDs are unique
|
||||
assert len(segment_ids) == len(set(segment_ids))
|
||||
|
||||
|
||||
def test_script_generation_with_narrator_text():
|
||||
"""Test script generation with narrative text (no role markers)."""
|
||||
response = client.post(
|
||||
"/api/tts/script",
|
||||
json={
|
||||
"text": "The sun was setting over the horizon. It was a beautiful evening.",
|
||||
"roles": ["Narrator"]
|
||||
}
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
|
||||
assert len(data["segments"]) > 0
|
||||
# Should assign to Narrator since no role markers
|
||||
assert any(seg["speaker"] == "Narrator" for seg in data["segments"])
|
||||
|
||||
|
||||
def test_script_generation_with_mixed_content():
|
||||
"""Test script generation with both dialogue and narrative."""
|
||||
response = client.post(
|
||||
"/api/tts/script",
|
||||
json={
|
||||
"text": "The wizard looked into his crystal ball.\nWizard: I see danger approaching.\nThe knight heard the warning.",
|
||||
"roles": ["Wizard", "Narrator"]
|
||||
}
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
|
||||
assert len(data["segments"]) >= 2
|
||||
speakers = [seg["speaker"] for seg in data["segments"]]
|
||||
# Should have both Wizard and Narrator
|
||||
assert "Wizard" in speakers or "Narrator" in speakers
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
Reference in New Issue
Block a user