Files
production-proof-v116-high-…/tests/test_full_stack_contract.py

107 lines
4.4 KiB
Python

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 _agent():
loaded = load_local_project(ROOT).agent_cls()
return loaded if hasattr(loaded, "invoke") else loaded()
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")
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 = _agent().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)
agent = _agent()
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 "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)
agent = _agent()
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 == []