from __future__ import annotations import importlib.util import json from pathlib import Path ROOT = Path(__file__).resolve().parents[1] SCAN_PATH = ROOT / "skills" / "keys-receipt-scanner" / "scripts" / "scan.py" def _load_scan(): spec = importlib.util.spec_from_file_location("lamp_scan", SCAN_PATH) assert spec and spec.loader mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) return mod def test_post_gemma_sends_image_url(tmp_path: Path, monkeypatch) -> None: scan = _load_scan() jpeg = tmp_path / "r.jpg" jpeg.write_bytes(b"fake-jpeg") captured: dict = {} def fake_json_req(url, *, data=None, headers=None, timeout=30.0): captured["url"] = url captured["body"] = json.loads(data.decode()) captured["headers"] = headers return { "choices": [ { "message": { "content": json.dumps( {"doc_kind": "receipt", "vendor": "Cafe", "total": 3.5} ) } } ] } monkeypatch.setattr(scan, "_json_req", fake_json_req) out = scan.post_gemma("http://gpu:8080/v1", "google/gemma-4-12B-it", jpeg) assert out["vendor"] == "Cafe" assert captured["url"].endswith("/v1/chat/completions") content = captured["body"]["messages"][1]["content"] kinds = {p["type"] for p in content} assert "image_url" in kinds url = next(p["image_url"]["url"] for p in content if p["type"] == "image_url") assert url.startswith("data:image/jpeg;base64,") def test_post_studio_polls_job(tmp_path: Path, monkeypatch) -> None: scan = _load_scan() jpeg = tmp_path / "r.jpg" jpeg.write_bytes(b"fake-jpeg") calls: list[str] = [] def fake_json_req(url, *, data=None, headers=None, timeout=30.0): calls.append(url) if url.endswith("/api/inbox"): return {"ok": True, "job_id": "abc"} if url.endswith("/api/jobs/abc"): return {"state": "done", "vendor": "Whole Foods", "total": "12.00"} raise AssertionError(url) monkeypatch.setattr(scan, "_json_req", fake_json_req) out = scan.post_studio("http://gpu:7860", jpeg) assert out["vendor"] == "Whole Foods" assert any(u.endswith("/api/inbox") for u in calls) assert any("/api/jobs/abc" in u for u in calls)