From 865cca39e66e682da147435821ed47542c4af84a Mon Sep 17 00:00:00 2001 From: Jim Lancaster <40281233+zoltan57@users.noreply.github.com> Date: Wed, 24 Jun 2026 17:33:51 -0500 Subject: [PATCH] Step 3 complete --- tests/services/test_transcription.py | 127 +++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 tests/services/test_transcription.py diff --git a/tests/services/test_transcription.py b/tests/services/test_transcription.py new file mode 100644 index 0000000..48f6a9e --- /dev/null +++ b/tests/services/test_transcription.py @@ -0,0 +1,127 @@ +"""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): + load_prompt_text(settings=settings) + + +@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): + load_image_payload(missing) + + +@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): + transcribe_document_image(image_path, settings=settings, provider=provider)