Files
generates-svg-video-game-9j…/tests/test_full_stack_contract.py

105 lines
3.9 KiB
Python

import os
from pathlib import Path
import pytest
from a2a_pack import PlatformUserAuth
from a2a_pack.cli.local import load_local_project
import agent as agent_module
from agent import GeneratesSvgVideoGame9jg9vdF0f510
ROOT = Path(__file__).resolve().parents[1]
def test_full_stack_product_contract():
manifest = (ROOT / "a2a.yaml").read_text(encoding="utf-8")
source = (ROOT / "agent.py").read_text(encoding="utf-8")
frontend = (ROOT / "frontend" / "src" / "App.jsx").read_text(encoding="utf-8")
assert "frontend:" in manifest and "mount: /app" in manifest
assert "public: false" in manifest
assert "resources:" in manifest and "databases:" in manifest
assert "migrations:" in manifest and "db/migrations" in manifest
assert "PlatformUserAuth" in source
assert "AgentPlatformResources" in source and "AgentDatabase(" in source
assert "Skill runner" not in frontend
assert "generate_svg_asset" in frontend
assert "DATABASE_URL" not in frontend
migrations = list((ROOT / "db" / "migrations").glob("*.sql"))
assert migrations and all(path.read_text(encoding="utf-8").strip() for path in migrations)
card = load_local_project(ROOT).agent_cls().card()
skill_names = {skill.name for skill in card.skills}
assert {"generate_svg_asset", "list_recent_receipts"} <= skill_names
databases = card.runtime.platform_resources.databases
assert databases, "live Agent Card must declare its managed database"
assert databases[0].migrations is not None
assert databases[0].migrations.path == "db/migrations"
@pytest.mark.asyncio
async def test_generate_svg_asset_smoke_without_database(monkeypatch):
monkeypatch.delenv("DATABASE_URL", raising=False)
auth = PlatformUserAuth(sub="stable-user", user_id=42, email="player@example.test")
result = await GeneratesSvgVideoGame9jg9vdF0f510().local_invoke(
"generate_svg_asset",
auth=auth,
asset_type="character",
theme="forest knight",
palette=["#22c55e", "#14532d", "#facc15"],
size=96,
style="pixel",
variant_count=2,
)
assert result.status == "ok"
assert result.receipt_id.startswith("rcpt_")
assert result.asset_id.startswith("asset_")
assert result.receipt_persisted is False
assert len(result.svg_assets) == 2
assert result.svg_assets[0]["svg"].startswith("<svg")
assert "DATABASE_URL" not in result.model_dump_json()
@pytest.mark.asyncio
async def test_generate_svg_asset_persists_receipt_when_database_configured(monkeypatch):
calls = []
def fake_persist(**kwargs):
calls.append(kwargs)
monkeypatch.setenv("DATABASE_URL", "postgresql://example.invalid/db")
monkeypatch.setattr(agent_module, "_persist_asset_and_receipt", fake_persist)
auth = PlatformUserAuth(sub="stable-user", user_id=7)
result = await GeneratesSvgVideoGame9jg9vdF0f510().local_invoke(
"generate_svg_asset",
auth=auth,
asset_type="item",
theme="crystal key",
palette=["#38bdf8", "#1e3a8a"],
size=128,
style="neon",
variant_count=1,
)
assert result.status == "ok"
assert result.receipt_persisted is True
assert calls
assert calls[0]["tenant_key"] == "user:7"
assert calls[0]["receipt_id"] == result.receipt_id
assert calls[0]["request"]["theme"] == "crystal key"
def test_primary_schema_is_bounded_and_mcp_compatible():
card = GeneratesSvgVideoGame9jg9vdF0f510().card()
skill = next(item for item in card.skills if item.name == "generate_svg_asset")
schema = skill.input_schema
props = schema["properties"]
assert set(schema["required"]) >= {"asset_type", "theme"}
assert props["theme"]["maxLength"] == 80
assert props["size"]["maximum"] == 512
assert props["variant_count"]["maximum"] == 4
assert props["asset_type"]["enum"] == ["character", "enemy", "item", "tile", "icon", "projectile"]
assert schema["additionalProperties"] is False