| """Tests for UI initialization with BrowserState restoration.""" |
|
|
| from unittest.mock import Mock |
|
|
| from yomitalk.app import PaperPodcastApp |
|
|
|
|
| class TestUIInitialization: |
| """Test UI initialization and component updates.""" |
|
|
| def setup_method(self): |
| """Set up test fixtures.""" |
| self.app = PaperPodcastApp() |
| self.mock_request = Mock() |
| self.mock_request.session_hash = "test-gradio-hash" |
|
|
| def test_initialize_session_and_ui_empty_state(self): |
| """Test UI initialization with empty BrowserState.""" |
| empty_browser_state = { |
| "app_session_id": "", |
| "audio_generation_state": { |
| "is_generating": False, |
| "progress": 0.0, |
| "status": "idle", |
| "current_script": "", |
| "final_audio_path": None, |
| "streaming_parts": [], |
| "generation_id": None, |
| "start_time": None, |
| "estimated_total_parts": 1, |
| }, |
| "user_settings": { |
| "current_api_type": "gemini", |
| "document_type": "research_paper", |
| "podcast_mode": "academic", |
| "character1": "Zundamon", |
| "character2": "Shikoku Metan", |
| "openai_max_tokens": 4000, |
| "gemini_max_tokens": 8000, |
| "openai_model": "gpt-4o-mini", |
| "gemini_model": "gemini-1.5-flash", |
| }, |
| "ui_state": {"podcast_text": "", "terms_agreed": False}, |
| } |
|
|
| result = self.app.initialize_session_and_ui(self.mock_request, empty_browser_state) |
|
|
| |
| assert len(result) == 31 |
|
|
| |
| user_session = result[0] |
| updated_browser_state = result[1] |
| extracted_text_update = result[13] |
| podcast_text_update = result[25] |
| terms_checkbox_update = result[26] |
|
|
| |
| assert user_session is not None |
| assert user_session.session_id != "" |
| assert len(user_session.session_id) == 36 |
|
|
| |
| assert updated_browser_state["app_session_id"] == user_session.session_id |
|
|
| |
| assert extracted_text_update is not None |
| assert podcast_text_update is not None |
| assert terms_checkbox_update is not None |
|
|
| def test_initialize_session_and_ui_with_content(self): |
| """Test UI initialization with existing content in BrowserState.""" |
| browser_state_with_content = { |
| "app_session_id": "550e8400-e29b-41d4-a716-446655440000", |
| "audio_generation_state": { |
| "is_generating": False, |
| "progress": 1.0, |
| "status": "completed", |
| "current_script": "Previous script content", |
| "final_audio_path": "/path/to/audio.wav", |
| "streaming_parts": ["part1.wav", "part2.wav"], |
| "generation_id": "gen123", |
| "start_time": None, |
| "estimated_total_parts": 2, |
| }, |
| "user_settings": { |
| "current_api_type": "openai", |
| "document_type": "paper", |
| "podcast_mode": "standard", |
| "character1": "Kyushu Sora", |
| "character2": "Chugoku Usagi", |
| "openai_max_tokens": 3000, |
| "gemini_max_tokens": 6000, |
| "openai_model": "gpt-4", |
| "gemini_model": "gemini-1.5-pro", |
| }, |
| "ui_state": {"podcast_text": "これは既存のポッドキャストスクリプトです。", "terms_agreed": True}, |
| } |
|
|
| result = self.app.initialize_session_and_ui(self.mock_request, browser_state_with_content) |
|
|
| |
| user_session = result[0] |
| _ = result[1] |
| extracted_text_update = result[13] |
| podcast_text_update = result[25] |
| terms_checkbox_update = result[26] |
|
|
| |
| assert user_session.session_id == "550e8400-e29b-41d4-a716-446655440000" |
|
|
| |
| assert extracted_text_update is not None |
| assert podcast_text_update is not None |
| assert terms_checkbox_update is not None |
|
|
| def test_initialize_session_and_ui_settings_restoration(self): |
| """Test that user settings are properly restored during initialization.""" |
| browser_state = { |
| "app_session_id": "test-uuid", |
| "audio_generation_state": { |
| "is_generating": False, |
| "progress": 0.0, |
| "status": "idle", |
| "current_script": "", |
| "final_audio_path": None, |
| "streaming_parts": [], |
| "generation_id": None, |
| "start_time": None, |
| "estimated_total_parts": 1, |
| }, |
| "user_settings": { |
| "current_api_type": "openai", |
| "document_type": "paper", |
| "podcast_mode": "standard", |
| "character1": "Chubu Tsurugi", |
| "character2": "Kyushu Sora", |
| "openai_max_tokens": 2500, |
| "gemini_max_tokens": 7500, |
| "openai_model": "gpt-4-turbo", |
| "gemini_model": "gemini-1.5-flash", |
| }, |
| "ui_state": {"podcast_text": "", "terms_agreed": False}, |
| } |
|
|
| result = self.app.initialize_session_and_ui(self.mock_request, browser_state) |
|
|
| |
| document_type = result[2] |
| podcast_mode = result[3] |
| character1 = result[4] |
| character2 = result[5] |
| openai_max_tokens = result[6] |
| gemini_max_tokens = result[7] |
|
|
| |
| assert document_type == "論文" |
| assert podcast_mode == "概要解説" |
| assert character1 == "Chubu Tsurugi" |
| assert character2 == "Kyushu Sora" |
| assert openai_max_tokens == 2500 |
| assert gemini_max_tokens == 7500 |
|
|
| def test_ui_component_interactive_states(self): |
| """Test that all UI components are properly set to interactive.""" |
| browser_state = {"app_session_id": "", "audio_generation_state": {}, "user_settings": {}, "ui_state": {}} |
|
|
| result = self.app.initialize_session_and_ui(self.mock_request, browser_state) |
|
|
| |
| file_input_update = result[8] |
| url_input_update = result[9] |
| url_extract_btn_update = result[10] |
| auto_separator_checkbox_update = result[11] |
| clear_text_btn_update = result[12] |
| extracted_text_update = result[13] |
| document_type_radio_update = result[14] |
| podcast_mode_radio_update = result[15] |
| character1_dropdown_update = result[16] |
| character2_dropdown_update = result[17] |
|
|
| |
| assert file_input_update is not None |
| assert url_input_update is not None |
| assert url_extract_btn_update is not None |
| assert auto_separator_checkbox_update is not None |
| assert clear_text_btn_update is not None |
| assert extracted_text_update is not None |
| assert document_type_radio_update is not None |
| assert podcast_mode_radio_update is not None |
| assert character1_dropdown_update is not None |
| assert character2_dropdown_update is not None |
|
|
| def test_placeholder_behavior_consistency(self): |
| """Test consistent placeholder behavior across different content states.""" |
| |
| browser_state = {"app_session_id": "test-uuid", "audio_generation_state": {}, "user_settings": {}, "ui_state": {"podcast_text": "", "terms_agreed": False, "extracted_text": ""}} |
| result = self.app.initialize_session_and_ui(self.mock_request, browser_state) |
|
|
| extracted_text_update = result[13] |
| podcast_text_update = result[25] |
|
|
| |
| assert extracted_text_update is not None |
| assert podcast_text_update is not None |
|
|
|
|
| class TestAudioStateUpdate: |
| """Test audio state updates in BrowserState.""" |
|
|
| def setup_method(self): |
| """Set up test fixtures.""" |
| self.app = PaperPodcastApp() |
|
|
| def test_update_browser_state_ui_content(self): |
| """Test updating UI content in BrowserState.""" |
| browser_state = { |
| "app_session_id": "test-session", |
| "audio_generation_state": {}, |
| "user_settings": {}, |
| "ui_state": {"podcast_text": "old text", "terms_agreed": False}, |
| } |
|
|
| |
| updated_state = self.app.update_browser_state_ui_content(browser_state, "new podcast text", True) |
|
|
| |
| ui_state = updated_state["ui_state"] |
| assert ui_state["podcast_text"] == "new podcast text" |
| assert ui_state["terms_agreed"] is True |
|
|
| |
| assert updated_state["app_session_id"] == "test-session" |
| assert "audio_generation_state" in updated_state |
| assert "user_settings" in updated_state |
|
|