From b11255a407b6fa7ed2d6c5f9ee6801e9d87c6ae4 Mon Sep 17 00:00:00 2001 From: a2a-cloud Date: Sun, 19 Jul 2026 19:59:13 +0000 Subject: [PATCH] a2a-source-edit: write tests/test_full_stack_contract.py --- tests/test_full_stack_contract.py | 74 +++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/tests/test_full_stack_contract.py b/tests/test_full_stack_contract.py index f6a0dd4..8df9ac5 100644 --- a/tests/test_full_stack_contract.py +++ b/tests/test_full_stack_contract.py @@ -1,10 +1,25 @@ +import asyncio from pathlib import Path +from a2a_pack import LocalRunContext, PlatformUserAuth from a2a_pack.cli.local import load_local_project 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(): 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") 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 "migrations:" in manifest and "db/migrations" in manifest 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 "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 "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" 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() + 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 assert databases, "live Agent Card must declare its managed database" assert databases[0].migrations is not None 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 == []