"""Unit tests for ProcessingResultDto""" import pytest from datetime import datetime from src.application.dtos.processing_result_dto import ProcessingResultDto class TestProcessingResultDto: """Test cases for ProcessingResultDto""" def test_valid_success_processing_result_dto(self): """Test creating a valid successful ProcessingResultDto""" dto = ProcessingResultDto( success=True, original_text="Hello world", translated_text="Hola mundo", audio_path="/tmp/output.wav", processing_time=5.2, metadata={"correlation_id": "test-123"} ) assert dto.success is True assert dto.original_text == "Hello world" assert dto.translated_text == "Hola mundo" assert dto.audio_path == "/tmp/output.wav" assert dto.processing_time == 5.2 assert dto.metadata == {"correlation_id": "test-123"} assert dto.error_message is None assert dto.error_code is None assert isinstance(dto.timestamp, datetime) def test_valid_error_processing_result_dto(self): """Test creating a valid error ProcessingResultDto""" dto = ProcessingResultDto( success=False, error_message="Processing failed", error_code="STT_ERROR", processing_time=2.1, metadata={"correlation_id": "test-456"} ) assert dto.success is False assert dto.error_message == "Processing failed" assert dto.error_code == "STT_ERROR" assert dto.processing_time == 2.1 assert dto.metadata == {"correlation_id": "test-456"} assert dto.original_text is None assert dto.translated_text is None assert dto.audio_path is None assert isinstance(dto.timestamp, datetime) def test_processing_result_dto_with_defaults(self): """Test creating ProcessingResultDto with default values""" dto = ProcessingResultDto(success=True, original_text="Test") assert dto.success is True assert dto.original_text == "Test" assert dto.translated_text is None assert dto.audio_path is None assert dto.processing_time == 0.0 assert dto.error_message is None assert dto.error_code is None assert dto.metadata == {} assert isinstance(dto.timestamp, datetime) def test_processing_result_dto_with_explicit_timestamp(self): """Test creating ProcessingResultDto with explicit timestamp""" test_timestamp = datetime(2023, 1, 1, 12, 0, 0) dto = ProcessingResultDto( success=True, original_text="Test", timestamp=test_timestamp ) assert dto.timestamp == test_timestamp def test_invalid_success_type_validation(self): """Test validation with invalid success type""" with pytest.raises(ValueError, match="Success must be a boolean value"): ProcessingResultDto( success="true", # String instead of boolean original_text="Test" ) def test_negative_processing_time_validation(self): """Test validation with negative processing time""" with pytest.raises(ValueError, match="Processing time cannot be negative"): ProcessingResultDto( success=True, original_text="Test", processing_time=-1.0 ) def test_successful_processing_without_output_validation(self): """Test validation for successful processing without any output""" with pytest.raises(ValueError, match="Successful processing must have at least one output"): ProcessingResultDto( success=True, # No original_text, translated_text, or audio_path ) def test_failed_processing_without_error_message_validation(self): """Test validation for failed processing without error message""" with pytest.raises(ValueError, match="Failed processing must include an error message"): ProcessingResultDto( success=False, # No error_message ) def test_invalid_error_code_validation(self): """Test validation with invalid error code""" with pytest.raises(ValueError, match="Invalid error code"): ProcessingResultDto( success=False, error_message="Test error", error_code="INVALID_CODE" ) def test_valid_error_codes(self): """Test all valid error codes""" valid_error_codes = [ 'STT_ERROR', 'TRANSLATION_ERROR', 'TTS_ERROR', 'AUDIO_FORMAT_ERROR', 'VALIDATION_ERROR', 'SYSTEM_ERROR' ] for error_code in valid_error_codes: # Should not raise exception dto = ProcessingResultDto( success=False, error_message="Test error", error_code=error_code ) assert dto.error_code == error_code def test_invalid_metadata_type_validation(self): """Test validation with invalid metadata type""" with pytest.raises(ValueError, match="Metadata must be a dictionary"): ProcessingResultDto( success=True, original_text="Test", metadata="invalid" # String instead of dict ) def test_has_text_output_property(self): """Test has_text_output property""" # With original text only dto1 = ProcessingResultDto(success=True, original_text="Test") assert dto1.has_text_output is True # With translated text only dto2 = ProcessingResultDto(success=True, translated_text="Prueba") assert dto2.has_text_output is True # With both texts dto3 = ProcessingResultDto(success=True, original_text="Test", translated_text="Prueba") assert dto3.has_text_output is True # With no text dto4 = ProcessingResultDto(success=True, audio_path="/tmp/test.wav") assert dto4.has_text_output is False def test_has_audio_output_property(self): """Test has_audio_output property""" # With audio path dto1 = ProcessingResultDto(success=True, audio_path="/tmp/test.wav") assert dto1.has_audio_output is True # Without audio path dto2 = ProcessingResultDto(success=True, original_text="Test") assert dto2.has_audio_output is False def test_is_complete_property(self): """Test is_complete property""" # Successful processing dto1 = ProcessingResultDto(success=True, original_text="Test") assert dto1.is_complete is True # Failed processing with error message dto2 = ProcessingResultDto(success=False, error_message="Error") assert dto2.is_complete is True # This shouldn't happen due to validation, but test the logic dto3 = ProcessingResultDto.__new__(ProcessingResultDto) dto3.success = False dto3.error_message = None assert dto3.is_complete is False def test_add_metadata_method(self): """Test add_metadata method""" dto = ProcessingResultDto(success=True, original_text="Test") dto.add_metadata("key1", "value1") dto.add_metadata("key2", 123) assert dto.metadata["key1"] == "value1" assert dto.metadata["key2"] == 123 def test_add_metadata_method_with_none_metadata(self): """Test add_metadata method when metadata is None""" dto = ProcessingResultDto.__new__(ProcessingResultDto) dto.success = True dto.original_text = "Test" dto.metadata = None dto.add_metadata("key", "value") assert dto.metadata == {"key": "value"} def test_get_metadata_method(self): """Test get_metadata method""" dto = ProcessingResultDto( success=True, original_text="Test", metadata={"existing_key": "existing_value"} ) # Get existing key assert dto.get_metadata("existing_key") == "existing_value" # Get non-existing key with default assert dto.get_metadata("non_existing", "default") == "default" # Get non-existing key without default assert dto.get_metadata("non_existing") is None def test_get_metadata_method_with_none_metadata(self): """Test get_metadata method when metadata is None""" dto = ProcessingResultDto.__new__(ProcessingResultDto) dto.success = True dto.original_text = "Test" dto.metadata = None assert dto.get_metadata("key", "default") == "default" assert dto.get_metadata("key") is None def test_to_dict_method(self): """Test to_dict method""" test_timestamp = datetime(2023, 1, 1, 12, 0, 0) dto = ProcessingResultDto( success=True, original_text="Hello world", translated_text="Hola mundo", audio_path="/tmp/output.wav", processing_time=5.2, error_message=None, error_code=None, metadata={"correlation_id": "test-123"}, timestamp=test_timestamp ) result = dto.to_dict() assert result['success'] is True assert result['original_text'] == "Hello world" assert result['translated_text'] == "Hola mundo" assert result['audio_path'] == "/tmp/output.wav" assert result['processing_time'] == 5.2 assert result['error_message'] is None assert result['error_code'] is None assert result['metadata'] == {"correlation_id": "test-123"} assert result['timestamp'] == test_timestamp.isoformat() assert result['has_text_output'] is True assert result['has_audio_output'] is True assert result['is_complete'] is True def test_to_dict_method_with_none_timestamp(self): """Test to_dict method with None timestamp""" dto = ProcessingResultDto.__new__(ProcessingResultDto) dto.success = True dto.original_text = "Test" dto.translated_text = None dto.audio_path = None dto.processing_time = 0.0 dto.error_message = None dto.error_code = None dto.metadata = {} dto.timestamp = None result = dto.to_dict() assert result['timestamp'] is None def test_success_result_class_method(self): """Test success_result class method""" result = ProcessingResultDto.success_result( original_text="Hello world", translated_text="Hola mundo", audio_path="/tmp/output.wav", processing_time=3.5, metadata={"test": "value"} ) assert isinstance(result, ProcessingResultDto) assert result.success is True assert result.original_text == "Hello world" assert result.translated_text == "Hola mundo" assert result.audio_path == "/tmp/output.wav" assert result.processing_time == 3.5 assert result.metadata == {"test": "value"} assert result.error_message is None assert result.error_code is None def test_success_result_class_method_with_defaults(self): """Test success_result class method with default values""" result = ProcessingResultDto.success_result(original_text="Test") assert result.success is True assert result.original_text == "Test" assert result.translated_text is None assert result.audio_path is None assert result.processing_time == 0.0 assert result.metadata is None def test_error_result_class_method(self): """Test error_result class method""" result = ProcessingResultDto.error_result( error_message="Processing failed", error_code="STT_ERROR", processing_time=2.1, metadata={"correlation_id": "test-456"} ) assert isinstance(result, ProcessingResultDto) assert result.success is False assert result.error_message == "Processing failed" assert result.error_code == "STT_ERROR" assert result.processing_time == 2.1 assert result.metadata == {"correlation_id": "test-456"} assert result.original_text is None assert result.translated_text is None assert result.audio_path is None def test_error_result_class_method_with_defaults(self): """Test error_result class method with default values""" result = ProcessingResultDto.error_result("Test error") assert result.success is False assert result.error_message == "Test error" assert result.error_code is None assert result.processing_time == 0.0 assert result.metadata is None def test_from_dict_class_method(self): """Test from_dict class method""" test_timestamp = datetime(2023, 1, 1, 12, 0, 0) data = { 'success': True, 'original_text': 'Hello world', 'translated_text': 'Hola mundo', 'audio_path': '/tmp/output.wav', 'processing_time': 5.2, 'error_message': None, 'error_code': None, 'metadata': {'correlation_id': 'test-123'}, 'timestamp': test_timestamp.isoformat() } dto = ProcessingResultDto.from_dict(data) assert dto.success is True assert dto.original_text == 'Hello world' assert dto.translated_text == 'Hola mundo' assert dto.audio_path == '/tmp/output.wav' assert dto.processing_time == 5.2 assert dto.error_message is None assert dto.error_code is None assert dto.metadata == {'correlation_id': 'test-123'} assert dto.timestamp == test_timestamp def test_from_dict_class_method_with_z_timestamp(self): """Test from_dict class method with Z-suffixed timestamp""" data = { 'success': True, 'original_text': 'Test', 'timestamp': '2023-01-01T12:00:00Z' } dto = ProcessingResultDto.from_dict(data) assert dto.timestamp == datetime(2023, 1, 1, 12, 0, 0) def test_from_dict_class_method_with_defaults(self): """Test from_dict class method with default values""" data = { 'success': True, 'original_text': 'Test' } dto = ProcessingResultDto.from_dict(data) assert dto.success is True assert dto.original_text == 'Test' assert dto.translated_text is None assert dto.audio_path is None assert dto.processing_time == 0.0 assert dto.error_message is None assert dto.error_code is None assert dto.metadata is None assert dto.timestamp is None def test_validation_called_on_init(self): """Test that validation is called during initialization""" # This should trigger validation and raise an error with pytest.raises(ValueError): ProcessingResultDto( success="invalid", # Invalid type original_text="Test" ) def test_metadata_default_initialization(self): """Test that metadata is initialized to empty dict if None""" dto = ProcessingResultDto( success=True, original_text="Test", metadata=None ) assert dto.metadata == {} def test_timestamp_default_initialization(self): """Test that timestamp is initialized to current time if None""" before = datetime.utcnow() dto = ProcessingResultDto( success=True, original_text="Test", timestamp=None ) after = datetime.utcnow() assert before <= dto.timestamp <= after