"""Gateway RPC tests for pet generation (pet.generate / pet.hatch). Image generation is mocked, so these assert the RPC contract + staging behavior (draft tokens, data-URI previews, expiry, activation) without any API calls. """ from __future__ import annotations import pytest pytest.importorskip("PIL") from PIL import Image # noqa: E402 from tui_gateway import server # noqa: E402 def _png(path): Image.new("RGBA", (64, 64), (200, 80, 80, 255)).save(path) def test_pet_generate_requires_prompt(): resp = server._methods["pet.generate"]("r1", {"prompt": " "}) assert "error" in resp def _fake_drafts_factory(tmp_path): def fake_drafts(prompt, *, n=4, style="auto", reference_images=None, provider=None, on_draft=None, is_cancelled=None): paths = [] for i in range(n): p = tmp_path / f"d{i}.png" _png(p) paths.append(p) if on_draft is not None: on_draft(i, p) return paths return fake_drafts def _fake_hatch_factory(captured): """A hatch that registers a real local pet (so the preview payload populates).""" import agent.pet.generate as gen from agent.pet import store def fake_hatch(*, base_image, slug, display_name="", description="", concept="", style="auto", on_progress=None, provider=None, is_cancelled=None): captured["base_image"] = str(base_image) captured["slug"] = slug pet = store.register_local_pet( Image.new("RGBA", (192, 208), (10, 20, 30, 255)), slug=slug, display_name=display_name, description=description, ) return gen.HatchResult( slug=pet.slug, display_name=display_name or pet.display_name, spritesheet=pet.spritesheet, states=["idle", "wave"], validation={"ok": True, "warnings": ["state 'jump' has no frames"]}, ) return fake_hatch