|
| 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