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

This commit is contained in:
a2a-cloud
2026-07-19 19:59:13 +00:00
parent 8199d065cc
commit b11255a407

View File

@@ -1,10 +1,25 @@
import asyncio
from pathlib import Path from pathlib import Path
from a2a_pack import LocalRunContext, PlatformUserAuth
from a2a_pack.cli.local import load_local_project from a2a_pack.cli.local import load_local_project
ROOT = Path(__file__).resolve().parents[1] ROOT = Path(__file__).resolve().parents[1]
FIXTURE = """From: alex@company.example
Subject: Concern about team behavior
Body: I want to report behavior that feels like harassment and retaliation after I raised a concern. What should I do next?
---
From: priya@company.example
Subject: Benefits enrollment for dependent
Body: I need to add a dependent to my insurance and want to understand eligibility and enrollment timing.
---
From: marco@company.example
Subject: PTO request next month
Body: I would like to take leave from May 6 to May 10. Can People approve this?
"""
def test_full_stack_product_contract(): def test_full_stack_product_contract():
manifest = (ROOT / "a2a.yaml").read_text(encoding="utf-8") manifest = (ROOT / "a2a.yaml").read_text(encoding="utf-8")
@@ -13,18 +28,77 @@ def test_full_stack_product_contract():
frontend_client = (ROOT / "frontend" / "src" / "a2a.js").read_text(encoding="utf-8") frontend_client = (ROOT / "frontend" / "src" / "a2a.js").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 "mailbox: true" 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 "AccountAccess(required=True, platform_skill_calls=3, after_trial=\"byok\")" in source
assert "AgentPlatformResources" in source and "AgentDatabase(" in source assert "AgentPlatformResources" in source and "AgentDatabase(" in source
assert "ctx.write_artifact" in source and "ctx.emit_artifact" in source
assert "Skill runner" not in frontend, "replace the generic scaffold with the product workflow" assert "Skill runner" not in frontend, "replace the generic scaffold with the product workflow"
assert "data-testid=\"agent-app\"" in frontend
assert "data-testid=\"agent-submit\"" in frontend
assert "data-testid=\"agent-result\"" in frontend
assert "data-testid=\"agent-download\"" in frontend
assert "unwrapInvokeResponse" in frontend_client, "unwrap the /invoke result envelope before rendering" assert "unwrapInvokeResponse" in frontend_client, "unwrap the /invoke result envelope before rendering"
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()
assert {skill.name for skill in card.skills} >= {
"triage_people_inbox",
"mailbox_status",
"receive_people_email",
}
triage = next(skill for skill in card.skills if skill.name == "triage_people_inbox")
assert set(triage.input_schema["properties"]) == {"inbox_text", "policy_text", "max_messages"}
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"
assert card.runtime.platform_resources.mailbox is True
assert card.runtime.account_access.required is True
assert card.runtime.account_access.platform_skill_calls == 3
assert card.runtime.account_access.after_trial == "byok"
def test_smoke_triage_returns_structured_result_without_secrets(monkeypatch):
monkeypatch.delenv("DATABASE_URL", raising=False)
project = load_local_project(ROOT)
agent = project.agent_cls()()
ctx = LocalRunContext(
auth=PlatformUserAuth(sub="user-123", user_id=123, email="person@example.com"),
task_id="test-triage",
)
result = asyncio.run(
agent.invoke(
"triage_people_inbox",
ctx,
inbox_text=FIXTURE,
max_messages=3,
)
)
assert result.status == "ok"
assert len(result.queue) == 3
assert result.queue[0].priority == "urgent"
assert result.queue[0].draft.approval_required is True
assert result.artifact.name == "people-team-inbox-triage.json"
assert result.artifact.media_type == "application/json"
assert "DATABASE_URL" not in result.model_dump_json()
assert "api_key" not in result.model_dump_json().lower()
assert ctx.artifacts["people-team-inbox-triage.json"]
assert result.receipt.receipt_id
def test_bad_input_returns_validation_error(monkeypatch):
monkeypatch.delenv("DATABASE_URL", raising=False)
project = load_local_project(ROOT)
agent = project.agent_cls()()
ctx = LocalRunContext(auth=PlatformUserAuth(sub="user-123", user_id=123), task_id="test-bad")
result = asyncio.run(agent.invoke("triage_people_inbox", ctx, inbox_text="short but long enough words"))
assert result.status == "validation_error"
assert result.queue == []