""" Tests for the TranslationProvider base class and schemas. """ import pytest from abc import ABC from services.providers.base import TranslationProvider from services.providers.schemas import ( TranslationRequest, TranslationResponse, BatchTranslationRequest, BatchTranslationResponse, ProviderHealthStatus, ) class ConcreteTranslationProvider(TranslationProvider): """Concrete implementation for testing abstract base class.""" def __init__(self, name: str = "test", available: bool = True): self._name = name self._available = available def translate_text(self, request: TranslationRequest) -> TranslationResponse: return TranslationResponse( translated_text=f"[{request.target_language}] {request.text}", provider_name=self._name, from_cache=False, ) def get_name(self) -> str: return self._name def is_available(self) -> bool: return self._available class TestSchemas: """Tests for Pydantic schema models.""" def test_translation_request_defaults(self): """Test TranslationRequest with default values.""" request = TranslationRequest(text="Hello", target_language="fr") assert request.text == "Hello" assert request.target_language == "fr" assert request.source_language == "auto" def test_translation_request_custom_source(self): """Test TranslationRequest with custom source language.""" request = TranslationRequest( text="Hello", target_language="fr", source_language="en" ) assert request.source_language == "en" def test_translation_response_defaults(self): """Test TranslationResponse with default values.""" response = TranslationResponse(translated_text="Bonjour", provider_name="test") assert response.translated_text == "Bonjour" assert response.provider_name == "test" assert response.from_cache is False assert response.source_language is None assert response.error is None assert response.success is True def test_translation_response_with_error(self): """Test TranslationResponse with error.""" response = TranslationResponse( translated_text="Hello", provider_name="test", error="API Error", ) assert response.error == "API Error" assert response.success is False def test_translation_request_invalid_language(self): """Test TranslationRequest rejects invalid language codes.""" with pytest.raises(ValueError): TranslationRequest(text="Hello", target_language="invalid123") def test_batch_translation_request(self): """Test BatchTranslationRequest.""" request = BatchTranslationRequest( texts=["Hello", "World"], target_language="fr" ) assert len(request.texts) == 2 assert request.source_language == "auto" def test_batch_translation_response(self): """Test BatchTranslationResponse.""" response = BatchTranslationResponse( translated_texts=["Bonjour", "Monde"], provider_name="test", from_cache_count=1, ) assert len(response.translated_texts) == 2 assert response.from_cache_count == 1 def test_provider_health_status(self): """Test ProviderHealthStatus.""" status = ProviderHealthStatus(name="test", available=True, latency_ms=50.5) assert status.name == "test" assert status.available is True assert status.latency_ms == 50.5 assert status.error is None def test_provider_health_status_with_error(self): """Test ProviderHealthStatus with error.""" status = ProviderHealthStatus( name="test", available=False, error="Connection refused" ) assert status.available is False assert status.error == "Connection refused" class TestTranslationProviderBaseClass: """Tests for the TranslationProvider abstract base class.""" def test_is_abstract(self): """Test that TranslationProvider cannot be instantiated directly.""" assert issubclass(TranslationProvider, ABC) with pytest.raises(TypeError): TranslationProvider() def test_concrete_implementation_works(self): """Test that a concrete implementation can be instantiated.""" provider = ConcreteTranslationProvider() assert provider.get_name() == "test" assert provider.is_available() is True def test_translate_text(self): """Test translate_text method.""" provider = ConcreteTranslationProvider() request = TranslationRequest(text="Hello", target_language="fr") response = provider.translate_text(request) assert response.translated_text == "[fr] Hello" assert response.provider_name == "test" def test_translate_batch_default_implementation(self): """Test default translate_batch implementation.""" provider = ConcreteTranslationProvider() requests = [ TranslationRequest(text="Hello", target_language="fr"), TranslationRequest(text="World", target_language="fr"), ] responses = provider.translate_batch(requests) assert len(responses) == 2 assert responses[0].translated_text == "[fr] Hello" assert responses[1].translated_text == "[fr] World" def test_health_check_available(self): """Test health_check for available provider.""" provider = ConcreteTranslationProvider(available=True) status = provider.health_check() assert status.name == "test" assert status.available is True assert status.error is None assert status.latency_ms is not None def test_health_check_unavailable(self): """Test health_check for unavailable provider.""" provider = ConcreteTranslationProvider(available=False) status = provider.health_check() assert status.available is False assert status.error == "Provider not available" def test_get_name_abstract(self): """Test that get_name is abstract.""" assert "get_name" in TranslationProvider.__abstractmethods__ def test_is_available_abstract(self): """Test that is_available is abstract.""" assert "is_available" in TranslationProvider.__abstractmethods__ def test_translate_text_abstract(self): """Test that translate_text is abstract.""" assert "translate_text" in TranslationProvider.__abstractmethods__