img2threejs / tests /conftest.py
Mike0021's picture
Add persistent community gallery and v1.3 previews
37e3d5a verified
Raw
History Blame Contribute Delete
3.88 kB
"""Shared pytest fixtures for the img2threejs Space test suite."""
from __future__ import annotations
import json
import struct
import sys
import zlib
from pathlib import Path
import pytest
REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT))
FIXTURES = Path(__file__).resolve().parent / "fixtures"
def write_png(path: Path, w: int = 64, h: int = 64) -> Path:
"""Write a minimal valid RGB PNG with a gradient (no Pillow needed)."""
raw = bytearray()
for y in range(h):
raw.append(0)
for x in range(w):
raw += bytes(((x * 4) % 256, (y * 4) % 256, ((x + y) * 2) % 256))
def chunk(tag: bytes, data: bytes) -> bytes:
c = struct.pack(">I", len(data)) + tag + data
return c + struct.pack(">I", zlib.crc32(tag + data) & 0xFFFFFFFF)
ihdr = struct.pack(">IIBBBBB", w, h, 8, 2, 0, 0, 0)
png = (b"\x89PNG\r\n\x1a\n"
+ chunk(b"IHDR", ihdr)
+ chunk(b"IDAT", zlib.compress(bytes(raw), 9))
+ chunk(b"IEND", b""))
path.write_bytes(png)
return path
@pytest.fixture(scope="session")
def ref_png_bytes() -> bytes:
import tempfile
with tempfile.TemporaryDirectory() as tmp:
path = write_png(Path(tmp) / "ref.png")
return path.read_bytes()
@pytest.fixture(scope="session")
def canned_spec() -> dict:
return json.loads((FIXTURES / "canned_spec.json").read_text(encoding="utf-8"))
@pytest.fixture(scope="session")
def canned_spec_text() -> str:
return (FIXTURES / "canned_spec.json").read_text(encoding="utf-8")
class MockLLM:
"""Drop-in for app.llm.LLMClient returning queued canned replies.
replies: list of strings returned in order (last one repeats).
Records every call for assertions.
"""
def __init__(self, replies: list[str]) -> None:
from app.llm import LLMResponse
self._response_cls = LLMResponse
self.replies = list(replies)
self.calls: list[dict] = []
async def complete_vision(self, *, system: str, messages: list[dict]):
self.calls.append({"system": system, "messages": messages})
index = min(len(self.calls) - 1, len(self.replies) - 1)
return self._response_cls(
text=self.replies[index], stop_reason="end_turn", style="anthropic")
@pytest.fixture()
def make_settings():
"""Build Settings instances from a controlled environment."""
from app.config import Settings
def _make(**overrides):
import os
runs_dir = overrides.pop("runs_dir", "/tmp/i2t-test-runs")
env = {
"LLM_API_KEY": "test-key-not-real",
"LLM_MODEL": "test-model",
"LLM_BASE_URL": "https://llm.test/api",
"RUNS_DIR": runs_dir,
"GALLERY_DIR": overrides.pop(
"gallery_dir", str(Path(runs_dir).parent / "gallery")
),
}
env.update({k: str(v) for k, v in overrides.items()})
old = {k: os.environ.get(k) for k in env}
os.environ.update(env)
try:
return Settings()
finally:
for key, value in old.items():
if value is None:
os.environ.pop(key, None)
else:
os.environ[key] = value
return _make
@pytest.fixture(scope="session")
def factory_fixture_ts() -> Path:
"""tests/fixtures/factory_fixture.ts, regenerated through the real
pipeline when missing (pure stdlib — always runnable)."""
target = FIXTURES / "factory_fixture.ts"
if not target.exists():
import subprocess
proc = subprocess.run(
[sys.executable, str(REPO_ROOT / "scripts" / "build_fixture_factory.py")],
capture_output=True, text=True)
assert proc.returncode == 0, f"fixture build failed:\n{proc.stdout}\n{proc.stderr}"
return target