Skip to content

Commit d3e1a0f

Browse files
bokelleyclaude
andauthored
test(examples): regression test for seller_agent PRODUCTS schema compliance (#324) (#327)
Validates all static products in seller_agent.py against the local AdCP 3.0.1 schema cache via the Python jsonschema validator, anchoring the Python-side verdict that the CI divergence is in @adcp/client's Ajv oneOf error reporter rather than in the response shape we emit. https://claude.ai/code/session_019rDGvdv7HHDKwJeNri9Lff Co-authored-by: Claude <noreply@anthropic.com>
1 parent ce4c5df commit d3e1a0f

1 file changed

Lines changed: 67 additions & 0 deletions

File tree

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""Regression test: every static product in seller_agent.py is 3.0.1 schema-valid.
2+
3+
Anchors the Python-side verdict on issue #324 (CI vs local divergence with
4+
@adcp/client@5.21.1's Ajv validator). The Python jsonschema validator confirms
5+
all products are compliant; the CI failures are in the npm-side oneOf error
6+
reporter, not in the response shape we emit.
7+
"""
8+
9+
from __future__ import annotations
10+
11+
import importlib.util
12+
from pathlib import Path
13+
from types import ModuleType
14+
from typing import Any
15+
16+
import pytest
17+
18+
from adcp.validation.schema_validator import validate_response
19+
20+
21+
def _load_seller_agent() -> ModuleType:
22+
path = Path(__file__).parent.parent / "examples" / "seller_agent.py"
23+
spec = importlib.util.spec_from_file_location("_seller_agent_test_module", path)
24+
assert spec is not None and spec.loader is not None
25+
module = importlib.util.module_from_spec(spec)
26+
spec.loader.exec_module(module)
27+
return module
28+
29+
30+
# Snapshot at collection time — seed_product() mutates PRODUCTS in-place, so
31+
# a bare reference would change parametrize IDs across test runs in the same
32+
# process if an integration test instantiates DemoStore and calls seed_product.
33+
_PRODUCTS: list[dict[str, Any]] = list(_load_seller_agent().PRODUCTS)
34+
35+
36+
class TestStaticProductsSchemaCompliance:
37+
"""All static PRODUCTS in seller_agent.py must pass get_products response
38+
validation against the local AdCP 3.0.1 schema cache."""
39+
40+
def test_full_products_list_passes_response_validation(self) -> None:
41+
outcome = validate_response("get_products", {"products": _PRODUCTS})
42+
assert outcome.variant != "skipped", (
43+
"get_products schema not loaded — regression anchor is a no-op; "
44+
"check that schemas/cache/ is present"
45+
)
46+
assert outcome.valid, (
47+
f"get_products response with all {len(_PRODUCTS)} products failed "
48+
f"Python-side schema validation: {outcome.issues}"
49+
)
50+
51+
@pytest.mark.parametrize(
52+
"product",
53+
_PRODUCTS,
54+
ids=[p["product_id"] for p in _PRODUCTS],
55+
)
56+
def test_individual_product_passes_response_validation(
57+
self, product: dict[str, Any]
58+
) -> None:
59+
outcome = validate_response("get_products", {"products": [product]})
60+
assert outcome.variant != "skipped", (
61+
"get_products schema not loaded — regression anchor is a no-op; "
62+
"check that schemas/cache/ is present"
63+
)
64+
assert outcome.valid, (
65+
f"Product {product.get('product_id')!r} failed Python-side schema "
66+
f"validation: {outcome.issues}"
67+
)

0 commit comments

Comments
 (0)