Files
high-utility-one-page-start…/tests/test_full_stack_contract.py

101 lines
4.3 KiB
Python

import asyncio
import base64
from pathlib import Path
from a2a_pack.auth import PlatformUserAuth
from a2a_pack.cli.local import load_local_project
from a2a_pack.context import LocalRunContext
from agent import (
BrowserDocument,
DocumentRequest,
HighUtilityOnePageStartupsWE3c73,
OUTPUT_FILENAME,
_decode_browser_document,
)
ROOT = Path(__file__).resolve().parents[1]
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")
migration = (ROOT / "db" / "migrations" / "001_app_records.sql").read_text(encoding="utf-8")
assert "frontend:" in manifest and "mount: /app" in manifest
assert "auth: inherit" in manifest
assert "resources:" in manifest and "databases:" in manifest
assert "migrations:" in manifest and "db/migrations" in manifest
assert "runtime:" in manifest and "account_access:" 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"
assert "DATABASE_URL" not in frontend and "A2A_LITELLM" not in frontend
assert "CREATE TABLE IF NOT EXISTS execution_receipts" in migration
card = load_local_project(ROOT).agent_cls().card()
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.required is True
assert card.runtime.account_access.platform_skill_calls == 3
skill_names = {skill.name for skill in card.skills}
assert {"generate_document", "validate_browser_upload", "generate_document_from_upload"}.issubset(skill_names)
def test_upload_bridge_validation_success_and_failure():
good = BrowserDocument(
filename="notes.txt",
media_type="text/plain",
data_base64=base64.b64encode(b"leasing traffic steady; vendor delay on two turns").decode("ascii"),
)
parsed = _decode_browser_document(good)
assert parsed.status == "ok"
assert "leasing traffic" in parsed.extracted_text
bad = BrowserDocument(filename="notes.txt", media_type="text/plain", data_base64="not-base64!!!")
rejected = _decode_browser_document(bad)
assert rejected.status == "validation_error"
assert "base64" in rejected.message
def test_generate_document_smoke_returns_preview_and_artifact(monkeypatch):
monkeypatch.delenv("DATABASE_URL", raising=False)
agent = HighUtilityOnePageStartupsWE3c73()
ctx = LocalRunContext(
auth=PlatformUserAuth(sub="user-123", user_id=123, email="pm@example.com"),
task_id="test-task",
)
request = DocumentRequest(
client_name="Northstar Property Group",
property_name="Maple Ridge Apartments",
property_type="multifamily",
city="Austin",
goal="owner update",
intake=(
"Owner wants a concise update on leasing momentum, delayed make-readies, "
"and resident communication. Traffic is steady but follow-up is inconsistent."
),
tone="professional",
)
result = asyncio.run(agent.generate_document(ctx, request))
assert result.document is not None
assert result.document.filename == OUTPUT_FILENAME
assert result.document.media_type == "text/markdown"
assert result.document_preview.startswith("# Owner Update: Maple Ridge Apartments")
assert OUTPUT_FILENAME in ctx.artifacts
assert result.persisted_receipt is False
assert result.status == "persistence_warning"