from unittest.mock import ANY, MagicMock, patch import pytest from app import process @pytest.fixture(autouse=True) def reset_app_mocks(): """Replace app module's crew2 imports with mocks before each test.""" import app as _app_mod _app_mod.run_pipeline = MagicMock( return_value={ "prompt": "A dragon", "result_corroborate": "Evidence 1", "result_opposite": "Counter 1", } ) _app_mod.generate_image = MagicMock(return_value=b"fake_png_bytes") _app_mod.generate_caption = MagicMock( return_value={"caption": "A beautiful narration.", "voice_style": "girl"} ) _app_mod.generate_voice = MagicMock(return_value=b"fake_wav_bytes") _app_mod.transcribe_audio = MagicMock(return_value="transcribed text") # Also mock PIL.Image.open patcher = patch("PIL.Image.open", return_value="fake_image_object") patcher.start() yield patcher.stop() class TestProcess: def test_text_input_returns_all_outputs(self): image, audio_path, caption, style = process("test statement", None) import app as _app_mod assert image == "fake_image_object" assert isinstance(audio_path, str) assert audio_path.endswith(".wav") assert caption == "A beautiful narration." assert style == "girl" _app_mod.run_pipeline.assert_called_once_with("test statement", session_id=ANY) _app_mod.transcribe_audio.assert_not_called() def test_audio_input_transcribes_first(self): process(None, "/path/to/audio.wav") import app as _app_mod _app_mod.transcribe_audio.assert_called_once_with("/path/to/audio.wav", session_id=ANY) _app_mod.run_pipeline.assert_called_once_with("transcribed text", session_id=ANY) def test_empty_text_raises_error(self): with pytest.raises(Exception, match="provide text"): process("", None) def test_none_input_raises_error(self): with pytest.raises(Exception, match="provide text"): process(None, None) def test_caption_not_found_fallback(self): import app as _app_mod _app_mod.generate_caption.return_value = { "caption": None, "voice_style": None, } image, audio_path, caption, style = process("test", None) assert caption == "(not found)" assert style == "(not found)" def test_audio_has_priority_over_text(self): import app as _app_mod process("ignored text", "/path/to/audio.wav") _app_mod.transcribe_audio.assert_called_once_with("/path/to/audio.wav", session_id=ANY) _app_mod.run_pipeline.assert_called_once_with("transcribed text", session_id=ANY)