- 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
174 lines
4.8 KiB
Python
174 lines
4.8 KiB
Python
"""
|
|
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"])
|