feat: enforce backend endpoint classification
This commit is contained in:
@@ -2,7 +2,9 @@ from __future__ import annotations
|
||||
|
||||
import ast
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
|
||||
@@ -30,6 +32,92 @@ class PlatformInterfaceInventoryTests(unittest.TestCase):
|
||||
inventory.canonical_api_path("/api/v2/campaigns/{campaign_id}"),
|
||||
"/campaigns/{}",
|
||||
)
|
||||
self.assertEqual(
|
||||
inventory.canonical_api_path("/api/v1/calendar/events/delta${querySuffix}"),
|
||||
"/calendar/events/delta",
|
||||
)
|
||||
self.assertEqual(
|
||||
inventory.canonical_api_path("/api/v1/calendar/events/${eventId}"),
|
||||
"/calendar/events/{}",
|
||||
)
|
||||
|
||||
def test_endpoint_declarations_are_exact_and_require_missing_ui_issue(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = Path(directory) / "endpoints.json"
|
||||
path.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"schema_version": 1,
|
||||
"endpoints": [
|
||||
{
|
||||
"repository": "govoplan-example",
|
||||
"method": "GET",
|
||||
"path": "/example/items/{}",
|
||||
"category": "public_integration",
|
||||
"rationale": "Published integration API.",
|
||||
}
|
||||
],
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
declarations = inventory._load_endpoint_declarations(path)
|
||||
|
||||
self.assertIn(
|
||||
("govoplan-example", "GET", "/example/items/{}"),
|
||||
declarations,
|
||||
)
|
||||
payload = json.loads(path.read_text(encoding="utf-8"))
|
||||
payload["endpoints"][0]["category"] = "missing_ui"
|
||||
path.write_text(json.dumps(payload), encoding="utf-8")
|
||||
with self.assertRaisesRegex(ValueError, "tracking_issue"):
|
||||
inventory._load_endpoint_declarations(path)
|
||||
|
||||
def test_inventory_reports_unclassified_and_stale_endpoint_declarations(
|
||||
self,
|
||||
) -> None:
|
||||
webui = {
|
||||
"frontendApiReferences": [],
|
||||
"translationUsages": [],
|
||||
"translationCatalog": {"en": {}, "de": {}},
|
||||
"fields": [],
|
||||
"labels": [],
|
||||
"visibleText": [],
|
||||
"routes": [],
|
||||
"navigation": [],
|
||||
"uiCapabilities": [],
|
||||
"dynamicTranslationUsages": [],
|
||||
}
|
||||
endpoint = {
|
||||
"repository": "govoplan-example",
|
||||
"method": "GET",
|
||||
"path": "/api/v1/example/items",
|
||||
"file": "src/example.py",
|
||||
"line": 1,
|
||||
"handler": "items",
|
||||
"router": "router",
|
||||
}
|
||||
stale = {
|
||||
"repository": "govoplan-example",
|
||||
"method": "GET",
|
||||
"path": "/example/removed",
|
||||
"category": "removable",
|
||||
"rationale": "Removal is pending.",
|
||||
}
|
||||
|
||||
result = inventory._assemble_inventory(
|
||||
webui=webui,
|
||||
backend_endpoints=[endpoint],
|
||||
manifests=[],
|
||||
endpoint_declarations={
|
||||
("govoplan-example", "GET", "/example/removed"): stale,
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(1, result["summary"]["unclassified_backend_endpoints"])
|
||||
self.assertEqual(1, result["summary"]["stale_endpoint_declarations"])
|
||||
self.assertIsNone(result["api"]["backend_endpoints"][0]["surface"])
|
||||
|
||||
def test_fastapi_route_scanner_includes_router_prefix(self) -> None:
|
||||
tree = ast.parse(
|
||||
|
||||
Reference in New Issue
Block a user