""" Tests for the One-Click Translation Workflow component (Story 7.20). """ import pytest from pathlib import Path import tempfile from datetime import datetime from PyQt6.QtWidgets import QApplication from src.ui.one_click_translation import ( WorkflowStep, WorkflowConfig, WorkflowResult, WorkflowProgress, OneClickWorkflowWidget, OneClickTranslationDialog, ) @pytest.fixture def app(qtbot): """Create QApplication for tests.""" return QApplication.instance() or QApplication([]) @pytest.fixture def sample_config(): """Create sample workflow config.""" return WorkflowConfig( source_lang="zh", target_lang="en", extract_terms=True, use_gpu=True ) @pytest.fixture def sample_result(): """Create sample workflow result.""" return WorkflowResult( success=True, steps_completed=[ WorkflowStep.IMPORTING, WorkflowStep.CLEANING, WorkflowStep.EXTRACTING_TERMS, WorkflowStep.TRANSLATING, WorkflowStep.FORMATTING, WorkflowStep.EXPORTING, ], total_chapters=10, completed_chapters=10, failed_chapters=0, total_words=30000, translated_words=29400, elapsed_time_seconds=600.0, output_path=Path("/output/translation") ) class TestWorkflowStep: """Tests for WorkflowStep enum.""" def test_step_values(self): """Test WorkflowStep enum values.""" assert WorkflowStep.IDLE.value == "idle" assert WorkflowStep.IMPORTING.value == "importing" assert WorkflowStep.TRANSLATING.value == "translating" assert WorkflowStep.COMPLETED.value == "completed" assert WorkflowStep.FAILED.value == "failed" class TestWorkflowConfig: """Tests for WorkflowConfig.""" def test_default_values(self): """Test default configuration values.""" config = WorkflowConfig() assert config.clean_empty_lines is True assert config.max_segment_length == 900 assert config.extract_terms is True assert config.use_gpu is True assert config.source_lang == "zh" assert config.target_lang == "en" def test_custom_values(self): """Test custom configuration.""" config = WorkflowConfig( source_lang="ja", target_lang="ko", extract_terms=False, batch_size=16 ) assert config.source_lang == "ja" assert config.target_lang == "ko" assert config.extract_terms is False assert config.batch_size == 16 class TestWorkflowResult: """Tests for WorkflowResult.""" def test_success_result(self, sample_result): """Test successful result.""" assert sample_result.success is True assert sample_result.completed_chapters == 10 assert sample_result.translated_words == 29400 def test_failure_result(self): """Test failed result.""" result = WorkflowResult( success=False, steps_completed=[WorkflowStep.IMPORTING], error="Network error" ) assert result.success is False assert result.error == "Network error" assert result.completed_chapters == 0 def test_completion_percentage(self, sample_result): """Test chapter completion rate.""" rate = sample_result.completed_chapters / sample_result.total_chapters assert rate == 1.0 class TestWorkflowProgress: """Tests for WorkflowProgress.""" def test_creation(self): """Test creating progress update.""" progress = WorkflowProgress( current_step=WorkflowStep.TRANSLATING, step_name="翻译中", progress=50, overall_progress=60, message="正在处理..." ) assert progress.current_step == WorkflowStep.TRANSLATING assert progress.progress == 50 assert progress.overall_progress == 60 def test_with_chapter(self): """Test progress with chapter info.""" progress = WorkflowProgress( current_step=WorkflowStep.TRANSLATING, step_name="翻译中", progress=25, overall_progress=50, message="翻译中", chapter="Chapter 1" ) assert progress.chapter == "Chapter 1" class TestOneClickWorkflowWidget: """Tests for OneClickWorkflowWidget.""" def test_initialization(self, qtbot): """Test widget initialization.""" widget = OneClickWorkflowWidget() qtbot.addWidget(widget) assert widget._input_files == [] assert widget._config is not None def test_config_property(self, qtbot): """Test config property.""" widget = OneClickWorkflowWidget() qtbot.addWidget(widget) config = widget.config assert config is not None assert isinstance(config, WorkflowConfig) def test_set_input_files(self, qtbot, tmp_path): """Test setting input files.""" widget = OneClickWorkflowWidget() qtbot.addWidget(widget) files = [tmp_path / "test1.txt", tmp_path / "test2.md"] for f in files: f.write_text("content") widget.set_input_files(files) assert widget.file_count == 2 def test_update_files_display(self, qtbot, tmp_path): """Test file display update.""" widget = OneClickWorkflowWidget() qtbot.addWidget(widget) # No files widget._update_files_display() assert widget._start_btn.isEnabled() is False # Add files files = [tmp_path / "test.txt"] files[0].write_text("content") widget._input_files = files widget._update_files_display() assert widget._start_btn.isEnabled() is True assert "1 个项目" in widget._files_label.text() def test_show_result(self, qtbot, sample_result): """Test showing result.""" widget = OneClickWorkflowWidget() qtbot.addWidget(widget) widget._show_result(sample_result) assert widget._result_group.isVisible() is True assert widget._last_result == sample_result def test_reset_ui(self, qtbot): """Test UI reset.""" widget = OneClickWorkflowWidget() qtbot.addWidget(widget) # Simulate some progress widget._progress_bar.setValue(50) widget._result_group.setVisible(True) widget._reset_ui() assert widget._progress_bar.value() == 0 assert widget._result_group.isVisible() is False assert widget._cancel_btn.isEnabled() is False class TestOneClickTranslationDialog: """Tests for OneClickTranslationDialog.""" def test_initialization_without_files(self, qtbot): """Test dialog initialization without files.""" dialog = OneClickTranslationDialog() qtbot.addWidget(dialog) assert dialog is not None assert dialog._widget is not None def test_initialization_with_files(self, qtbot, tmp_path): """Test dialog initialization with files.""" files = [tmp_path / "test.txt"] files[0].write_text("content") dialog = OneClickTranslationDialog(files) qtbot.addWidget(dialog) assert dialog is not None def test_set_input_files(self, qtbot, tmp_path): """Test setting input files on dialog.""" dialog = OneClickTranslationDialog() qtbot.addWidget(dialog) files = [tmp_path / "test.txt"] files[0].write_text("content") dialog.set_input_files(files) assert dialog._widget.file_count == 1