vidzly / tests /test_script_generator.py
tiena2cva's picture
squash commit
b7681c8
"""
Unit tests for script_generator tool.
"""
import os
import json
import pytest
from unittest.mock import Mock, patch, MagicMock
import sys
# Add src to path to import modules
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
from app.tools.script_generator import script_generator
class TestScriptGenerator:
"""Test cases for script_generator function."""
def test_script_generator_with_multiple_videos(self, temp_video_file):
"""Test script_generator with multiple video inputs."""
with (
patch("app.tools.script_generator.cv2.VideoCapture") as mock_capture,
patch("app.tools.script_generator.genai.Client") as mock_client,
):
mock_cap = Mock()
mock_cap.isOpened.return_value = True
mock_cap.get.side_effect = lambda prop: {
5: 30.0,
7: 900,
3: 1920,
4: 1080,
}.get(prop, 0)
mock_capture.return_value = mock_cap
mock_genai_client = Mock()
mock_response = Mock()
mock_response.text = """Here's a comprehensive video script:
```json
{
"concept": "Energetic travel montage",
"target_duration": 30.0,
"total_duration": 30.0,
"scenes": [
{
"scene_id": 1,
"source_video": 0,
"start_time": 0.0,
"end_time": 10.0,
"duration": 10.0,
"description": "Opening scene",
"transition_in": "fade",
"transition_out": "crossfade"
}
],
"audio": {
"mood": "energetic",
"style": "upbeat",
"bpm": 120,
"volume": 0.7
},
"text_overlays": [],
"visual_effects": ["color_grading"],
"call_to_action": "Subscribe for more"
}
```
This is a narrative description of the script."""
mock_genai_client.models.generate_content.return_value = mock_response
mock_client.return_value = mock_genai_client
video_inputs = [temp_video_file, temp_video_file]
with patch.dict(os.environ, {"GOOGLE_API_KEY": "test_key"}):
result = script_generator(
video_inputs, user_prompt="Create an energetic video"
)
result_json = json.loads(result)
assert "videos_analyzed" in result_json
assert "script_narrative" in result_json
assert len(result_json["videos_analyzed"]) == 2
def test_script_generator_without_prompt(self, temp_video_file):
"""Test script_generator without user prompt."""
with (
patch("app.tools.script_generator.cv2.VideoCapture") as mock_capture,
patch("app.tools.script_generator.genai.Client") as mock_client,
):
mock_cap = Mock()
mock_cap.isOpened.return_value = True
mock_cap.get.side_effect = lambda prop: {
5: 30.0,
7: 900,
3: 1920,
4: 1080,
}.get(prop, 0)
mock_capture.return_value = mock_cap
mock_genai_client = Mock()
mock_response = Mock()
mock_response.text = "Auto-generated script based on video analysis."
mock_genai_client.models.generate_content.return_value = mock_response
mock_client.return_value = mock_genai_client
video_inputs = [temp_video_file]
with patch.dict(os.environ, {"GOOGLE_API_KEY": "test_key"}):
result = script_generator(video_inputs)
result_json = json.loads(result)
assert "videos_analyzed" in result_json
assert "script_narrative" in result_json
assert result_json["user_prompt"] == "Auto-generated based on materials"
def test_script_generator_with_string_input(self, temp_video_file):
"""Test script_generator with single string video input."""
with (
patch("app.tools.script_generator.cv2.VideoCapture") as mock_capture,
patch("app.tools.script_generator.genai.Client") as mock_client,
):
mock_cap = Mock()
mock_cap.isOpened.return_value = True
mock_cap.get.side_effect = lambda prop: {
5: 30.0,
7: 900,
3: 1920,
4: 1080,
}.get(prop, 0)
mock_capture.return_value = mock_cap
mock_genai_client = Mock()
mock_response = Mock()
mock_response.text = "Generated script."
mock_genai_client.models.generate_content.return_value = mock_response
mock_client.return_value = mock_genai_client
with patch.dict(os.environ, {"GOOGLE_API_KEY": "test_key"}):
result = script_generator(temp_video_file)
result_json = json.loads(result)
assert "videos_analyzed" in result_json
assert len(result_json["videos_analyzed"]) == 1
def test_script_generator_with_tuple_input(self, temp_video_file):
"""Test script_generator with tuple input (Gradio format)."""
with (
patch("app.tools.script_generator.cv2.VideoCapture") as mock_capture,
patch("app.tools.script_generator.genai.Client") as mock_client,
):
mock_cap = Mock()
mock_cap.isOpened.return_value = True
mock_cap.get.side_effect = lambda prop: {
5: 30.0,
7: 900,
3: 1920,
4: 1080,
}.get(prop, 0)
mock_capture.return_value = mock_cap
mock_genai_client = Mock()
mock_response = Mock()
mock_response.text = "Generated script."
mock_genai_client.models.generate_content.return_value = mock_response
mock_client.return_value = mock_genai_client
video_input = (temp_video_file, "subtitle.srt")
with patch.dict(os.environ, {"GOOGLE_API_KEY": "test_key"}):
result = script_generator(video_input)
result_json = json.loads(result)
assert "videos_analyzed" in result_json
def test_script_generator_with_empty_input(self):
"""Test script_generator with no video input."""
result = script_generator([])
result_json = json.loads(result)
assert "error" in result_json
assert result_json["error"] == "No video files provided"
def test_script_generator_with_nonexistent_file(self):
"""Test script_generator with nonexistent video file."""
result = script_generator(["/nonexistent/video.mp4"])
result_json = json.loads(result)
assert "error" in result_json
assert "not found" in result_json["error"]
def test_script_generator_without_api_key(self, temp_video_file):
"""Test script_generator without GOOGLE_API_KEY."""
with patch("app.tools.script_generator.cv2.VideoCapture") as mock_capture:
mock_cap = Mock()
mock_cap.isOpened.return_value = True
mock_cap.get.side_effect = lambda prop: {
5: 30.0,
7: 900,
3: 1920,
4: 1080,
}.get(prop, 0)
mock_capture.return_value = mock_cap
with patch.dict(os.environ, {}, clear=True):
result = script_generator([temp_video_file])
result_json = json.loads(result)
assert "error" in result_json
assert "GOOGLE_API_KEY" in result_json["error"]
assert "videos_analyzed" in result_json
def test_script_generator_with_invalid_video(self, temp_video_file):
"""Test script_generator with video that cannot be opened."""
with patch("app.tools.script_generator.cv2.VideoCapture") as mock_capture:
mock_cap = Mock()
mock_cap.isOpened.return_value = False
mock_capture.return_value = mock_cap
result = script_generator([temp_video_file])
result_json = json.loads(result)
assert "error" in result_json
assert "Could not open video file" in result_json["error"]
def test_script_generator_structured_script_parsing(self, temp_video_file):
"""Test that structured JSON is properly extracted and parsed."""
with (
patch("app.tools.script_generator.cv2.VideoCapture") as mock_capture,
patch("app.tools.script_generator.genai.Client") as mock_client,
):
mock_cap = Mock()
mock_cap.isOpened.return_value = True
mock_cap.get.side_effect = lambda prop: {
5: 30.0,
7: 900,
3: 1920,
4: 1080,
}.get(prop, 0)
mock_capture.return_value = mock_cap
mock_genai_client = Mock()
mock_response = Mock()
mock_response.text = """Here's the script:
```json
{
"concept": "Test concept",
"target_duration": 30.0,
"scenes": []
}
```
Narrative description."""
mock_genai_client.models.generate_content.return_value = mock_response
mock_client.return_value = mock_genai_client
with patch.dict(os.environ, {"GOOGLE_API_KEY": "test_key"}):
result = script_generator([temp_video_file])
result_json = json.loads(result)
assert "structured_script" in result_json
assert result_json["structured_script"]["concept"] == "Test concept"
assert result_json["structured_script"]["target_duration"] == 30.0
def test_script_generator_with_custom_prompt(self, temp_video_file):
"""Test script_generator with custom user prompt."""
with (
patch("app.tools.script_generator.cv2.VideoCapture") as mock_capture,
patch("app.tools.script_generator.genai.Client") as mock_client,
):
mock_cap = Mock()
mock_cap.isOpened.return_value = True
mock_cap.get.side_effect = lambda prop: {
5: 30.0,
7: 900,
3: 1920,
4: 1080,
}.get(prop, 0)
mock_capture.return_value = mock_cap
mock_genai_client = Mock()
mock_response = Mock()
mock_response.text = "Custom prompt response."
mock_genai_client.models.generate_content.return_value = mock_response
mock_client.return_value = mock_genai_client
custom_prompt = "Create a dramatic product reveal"
with patch.dict(os.environ, {"GOOGLE_API_KEY": "test_key"}):
result = script_generator([temp_video_file], user_prompt=custom_prompt)
result_json = json.loads(result)
assert result_json["user_prompt"] == custom_prompt
assert "script_narrative" in result_json