mmap-worker / tests /test_vision.py
jugalgajjar's picture
initial worker deploy
3b9a272
Raw
History Blame Contribute Delete
2.87 kB
"""Unit tests for the vision-language wrapper. OpenRouter is mocked."""
import base64
from unittest.mock import AsyncMock, patch
import pytest
from app.core.config import settings
from app.rag.openrouter import OpenRouterError
from app.vision import describe as vision
def test_data_url_is_correctly_base64_encoded():
raw = b"\x89PNG\r\n\x1a\n" + b"PAYLOAD"
url = vision._data_url(raw, "image/png")
assert url.startswith("data:image/png;base64,")
encoded = url.split(",", 1)[1]
assert base64.b64decode(encoded) == raw
def test_data_url_normalises_mime():
url = vision._data_url(b"x", "Image/JPEG; charset=binary")
assert url.startswith("data:image/jpeg;base64,")
async def test_describe_raises_when_api_key_missing(monkeypatch):
monkeypatch.setattr(settings, "openrouter_api_key", "")
with pytest.raises(vision.VisionError):
await vision.describe_image_bytes(b"fake", "image/png")
async def test_describe_returns_chat_completion_text(monkeypatch):
monkeypatch.setattr(settings, "openrouter_api_key", "fake-key")
monkeypatch.setattr(settings, "openrouter_vision_model", "vendor/vision-mock:free")
with patch(
"app.vision.describe.chat_completion",
new=AsyncMock(return_value="a green chart with three bars"),
) as fake:
out = await vision.describe_image_bytes(b"img-bytes", "image/png")
assert out == "a green chart with three bars"
args = fake.call_args.kwargs
assert args["model"] == "vendor/vision-mock:free"
# Single user message with text + image_url content parts
msgs = args["messages"]
assert len(msgs) == 1 and msgs[0]["role"] == "user"
parts = msgs[0]["content"]
assert any(p["type"] == "text" for p in parts)
assert any(p["type"] == "image_url" for p in parts)
img_part = next(p for p in parts if p["type"] == "image_url")
assert img_part["image_url"]["url"].startswith("data:image/png;base64,")
async def test_describe_wraps_openrouter_errors_in_vision_error(monkeypatch):
monkeypatch.setattr(settings, "openrouter_api_key", "fake-key")
with (
patch(
"app.vision.describe.chat_completion",
new=AsyncMock(side_effect=OpenRouterError(429, {"detail": "rate limited"})),
),
pytest.raises(vision.VisionError) as exc,
):
await vision.describe_image_bytes(b"x", "image/png")
assert "429" in str(exc.value)
async def test_describe_uses_low_temperature(monkeypatch):
"""Vision descriptions should be deterministic, not creative."""
monkeypatch.setattr(settings, "openrouter_api_key", "fake-key")
with patch(
"app.vision.describe.chat_completion",
new=AsyncMock(return_value="ok"),
) as fake:
await vision.describe_image_bytes(b"x", "image/jpeg")
assert fake.call_args.kwargs["temperature"] <= 0.2