"""Tests for transcription.services.transcription.""" from pathlib import Path import pytest from transcription.config import Settings from transcription.providers.base import ProviderError, TranscriptionResult from transcription.services.transcription import ( PromptLoadError, TranscriptionError, load_image_payload, load_prompt_text, transcribe_document_image, ) class _FakeProvider: def __init__(self, *, result: TranscriptionResult | None = None, error: Exception | None = None): self._result = result or TranscriptionResult( text="Transcript output", provider="openrouter", model="test-model", ) self._error = error self.calls: list[dict[str, object]] = [] def transcribe(self, *, prompt_text: str, image_bytes: bytes, mime_type: str) -> TranscriptionResult: self.calls.append( { "prompt_text": prompt_text, "image_bytes": image_bytes, "mime_type": mime_type, } ) if self._error: raise self._error return self._result @pytest.mark.unit class TestPromptLoading: """Verify prompt artifact loading and validation.""" def test_loads_prompt_text_from_prompt_dir(self, tmp_path: Path): """Prompt loader returns canonical prompt text from configured prompt directory.""" prompt_dir = tmp_path / "prompts" prompt_dir.mkdir() prompt_file = prompt_dir / "transcribe_document.md" prompt_file.write_text("Prompt body", encoding="utf-8") settings = Settings(openrouter_api_key="test-key", prompt_dir=prompt_dir) text = load_prompt_text(settings=settings) assert text == "Prompt body" def test_missing_prompt_raises_error(self, tmp_path: Path): """Prompt loader raises PromptLoadError when the file is missing.""" prompt_dir = tmp_path / "prompts" prompt_dir.mkdir() settings = Settings(openrouter_api_key="test-key", prompt_dir=prompt_dir) with pytest.raises(PromptLoadError) as exc_info: load_prompt_text(settings=settings) assert exc_info.value.category.value == "infrastructure_persistent_error" assert "verify prompt_dir" in exc_info.value.suggestion.lower() @pytest.mark.unit class TestImageLoading: """Verify local image payload loading and mime detection.""" def test_load_image_payload_reads_bytes_and_mime_type(self, tmp_path: Path): """Image loader returns file bytes and a detected MIME type for supported files.""" image_path = tmp_path / "sample.png" image_bytes = b"\x89PNG\r\n\x1a\n" image_path.write_bytes(image_bytes) loaded_bytes, mime_type = load_image_payload(image_path) assert loaded_bytes == image_bytes assert mime_type == "image/png" def test_missing_image_raises_error(self, tmp_path: Path): """Image loader raises TranscriptionError when image file does not exist.""" missing = tmp_path / "missing.png" with pytest.raises(TranscriptionError) as exc_info: load_image_payload(missing) assert exc_info.value.category.value == "not_found_error" assert "verify" in exc_info.value.suggestion.lower() @pytest.mark.unit class TestTranscriptionService: """Verify service orchestration across prompt, image, and provider calls.""" def test_transcribe_document_image_calls_provider_once(self, tmp_path: Path): """Service loads prompt and image, then invokes provider exactly once.""" prompt_dir = tmp_path / "prompts" prompt_dir.mkdir() (prompt_dir / "transcribe_document.md").write_text("Prompt body", encoding="utf-8") image_path = tmp_path / "document.jpg" image_path.write_bytes(b"jpeg-bytes") settings = Settings(openrouter_api_key="test-key", prompt_dir=prompt_dir) provider = _FakeProvider() result = transcribe_document_image(image_path, settings=settings, provider=provider) assert result.text == "Transcript output" assert len(provider.calls) == 1 assert provider.calls[0]["prompt_text"] == "Prompt body" assert provider.calls[0]["image_bytes"] == b"jpeg-bytes" assert provider.calls[0]["mime_type"] == "image/jpeg" def test_provider_error_is_wrapped(self, tmp_path: Path): """Service wraps provider failures in TranscriptionError.""" prompt_dir = tmp_path / "prompts" prompt_dir.mkdir() (prompt_dir / "transcribe_document.md").write_text("Prompt body", encoding="utf-8") image_path = tmp_path / "document.png" image_path.write_bytes(b"png-bytes") settings = Settings(openrouter_api_key="test-key", prompt_dir=prompt_dir) provider = _FakeProvider(error=ProviderError("upstream failure")) with pytest.raises(TranscriptionError) as exc_info: transcribe_document_image(image_path, settings=settings, provider=provider) assert exc_info.value.category.value == "external_provider_error" assert exc_info.value.retriable is True assert "retry" in exc_info.value.suggestion.lower()