a2a-source-edit: write tests/test_full_stack_contract.py

This commit is contained in:
a2a-cloud
2026-07-18 16:55:55 +00:00
parent 32caa34c2d
commit 96cda5c2d2

View File

@@ -1,7 +1,14 @@
import os
from pathlib import Path from pathlib import Path
import pytest
from a2a_pack import PlatformUserAuth
from a2a_pack.cli.local import load_local_project from a2a_pack.cli.local import load_local_project
import agent as agent_module
from agent import GeneratesSvgVideoGame9jg9vdF0f510
ROOT = Path(__file__).resolve().parents[1] ROOT = Path(__file__).resolve().parents[1]
@@ -12,17 +19,86 @@ def test_full_stack_product_contract():
frontend = (ROOT / "frontend" / "src" / "App.jsx").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 "frontend:" in manifest and "mount: /app" in manifest
assert "public: false" in manifest
assert "resources:" in manifest and "databases:" in manifest assert "resources:" in manifest and "databases:" in manifest
assert "migrations:" in manifest and "db/migrations" in manifest assert "migrations:" in manifest and "db/migrations" in manifest
assert "PlatformUserAuth" in source assert "PlatformUserAuth" in source
assert "AgentPlatformResources" in source and "AgentDatabase(" in source assert "AgentPlatformResources" in source and "AgentDatabase(" in source
assert "Skill runner" not in frontend, "replace the generic scaffold with the product workflow" 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")) migrations = list((ROOT / "db" / "migrations").glob("*.sql"))
assert migrations and all(path.read_text(encoding="utf-8").strip() for path in migrations) assert migrations and all(path.read_text(encoding="utf-8").strip() for path in migrations)
card = load_local_project(ROOT).agent_cls().card() 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 databases = card.runtime.platform_resources.databases
assert databases, "live Agent Card must declare its managed database" assert databases, "live Agent Card must declare its managed database"
assert databases[0].migrations is not None assert databases[0].migrations is not None
assert databases[0].migrations.path == "db/migrations" 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