generated from john/python-template
128 lines
4.6 KiB
Python
128 lines
4.6 KiB
Python
"""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)
|