""" AFI conformance — same @client fixture, same schema, both adapters. Gates that mizan-django and mizan-fastapi emit equivalent schemas for the same registered functions. If this passes, the codegen produces equivalent TypeScript output regardless of which backend the frontend is generated against (codegen is deterministic over schema input). This is a substrate-level gate, not e2e. It catches adapter symmetry problems — Pydantic→OpenAPI converter divergence, metadata leakage, ordering non-determinism — without running a real frontend or backend. """ from __future__ import annotations import json import os import subprocess import sys from pathlib import Path import pytest HERE = Path(__file__).parent DJANGO_MANAGE = HERE / "django_app" / "manage.py" # ─── Schema fetchers ──────────────────────────────────────────────────────── def _fetch_django_schema() -> dict: """Spawn Django's management command and parse its stdout JSON.""" result = subprocess.run( [sys.executable, str(DJANGO_MANAGE), "export_mizan_schema", "--indent", "0"], capture_output=True, text=True, check=False, env={**os.environ, "PYTHONDONTWRITEBYTECODE": "1"}, ) if result.returncode != 0: pytest.fail(f"export_mizan_schema failed:\nstdout:\n{result.stdout}\nstderr:\n{result.stderr}") return json.loads(result.stdout) def _fetch_fastapi_schema() -> dict: """Build the FastAPI app inline (fresh registry) and call build_schema().""" sys.path.insert(0, str(HERE)) try: from mizan_core.registry import clear_registry from mizan_fastapi import build_schema from fastapi_app import make_app clear_registry() make_app() return build_schema() finally: sys.path.remove(str(HERE)) # ─── Tests ────────────────────────────────────────────────────────────────── @pytest.fixture(scope="module") def schemas() -> tuple[dict, dict]: return _fetch_django_schema(), _fetch_fastapi_schema() class AFISubsetTests: """The AFI surface — x-mizan-functions and x-mizan-contexts — must match.""" def test_x_mizan_functions_match(self, schemas): from schema_normalizer import afi_subset django, fastapi = schemas assert afi_subset(django)["x-mizan-functions"] == afi_subset(fastapi)["x-mizan-functions"] def test_x_mizan_contexts_match(self, schemas): from schema_normalizer import afi_subset django, fastapi = schemas assert afi_subset(django)["x-mizan-contexts"] == afi_subset(fastapi)["x-mizan-contexts"] class TypeSchemasTests: """Per-function Input/Output Pydantic→OpenAPI schemas — codegen feeds these to openapi-typescript.""" def test_function_io_schemas_match(self, schemas): from schema_normalizer import function_io_schemas django, fastapi = schemas assert function_io_schemas(django) == function_io_schemas(fastapi)