diff --git a/tests/test_full_stack_contract.py b/tests/test_full_stack_contract.py index f6a0dd4..e4db8b5 100644 --- a/tests/test_full_stack_contract.py +++ b/tests/test_full_stack_contract.py @@ -1,7 +1,11 @@ +import asyncio from pathlib import Path +from a2a_pack import LocalRunContext, PlatformUserAuth from a2a_pack.cli.local import load_local_project +import agent + ROOT = Path(__file__).resolve().parents[1] @@ -13,18 +17,62 @@ 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 "resources:" in manifest and "databases:" in manifest - assert "migrations:" in manifest and "db/migrations" in manifest + assert "runtime:" in manifest and "platform_skill_calls: 3" 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 "Skill runner" not in frontend, "replace the generic scaffold with the product workflow" - assert "unwrapInvokeResponse" in frontend_client, "unwrap the /invoke result envelope before rendering" + assert "Skill runner" not in frontend, "replace generic scaffold with 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 + 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() + skills = {skill.name: skill for skill in card.skills} + assert {"build_dashboard", "list_history", "scheduled_rollup"}.issubset(skills) + assert "updates_text" in skills["build_dashboard"].input_schema["properties"] + assert "run_key" in skills["scheduled_rollup"].input_schema["properties"] 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.account_access.platform_skill_calls == 3 + + +def test_deterministic_analysis_fixture(): + rows = agent._analyze_updates(agent.DEFAULT_UPDATES) + assert len(rows) == 4 + exceptions = agent._build_exceptions(rows) + trends = agent._build_trends(rows) + assert trends["status_counts"] == {"green": 2, "yellow": 1, "red": 1} + assert trends["average_utilization"] == 78.8 + assert len(exceptions) == 3 + csv_text = agent._rows_to_csv(rows) + assert "agency-ops-dashboard" not in csv_text + assert "Acme Portal" in csv_text + + +def test_missing_database_returns_setup_required(): + async def run(): + app = agent.ProductionProofV116HighUtili72551() + ctx = LocalRunContext( + auth=PlatformUserAuth(sub="stable-user", user_id=123, email="dev@example.local"), + task_id="test-dashboard", + ) + result = await app.invoke("build_dashboard", ctx) + return result, ctx + + result, ctx = asyncio.run(run()) + assert result.status == "setup_required" + assert result.dashboard_data + assert result.artifact.name == "agency-ops-dashboard.csv" + assert result.artifact.media_type == "text/csv" + assert "DATABASE_URL" not in result.summary + assert "agency-ops-dashboard.csv" in ctx.artifacts