from __future__ import annotations from pathlib import Path import unittest from govoplan_ops.backend.manifest import get_manifest REPO_ROOT = Path(__file__).resolve().parents[1] class OpsInterfaceDocumentationContractTests(unittest.TestCase): def test_backend_surfaces_and_hierarchy_remain_declared(self) -> None: frontend = get_manifest().frontend self.assertIsNotNone(frontend) surfaces = {item.id: item for item in frontend.view_surfaces} # type: ignore[union-attr] expected = { "ops.navigation", "ops.page", "ops.page.summary", "ops.page.health", "ops.page.runtime", "ops.page.recovery", "ops.page.governance", "ops.page.deployment", "ops.page.sizing", "ops.action.run-probes", "ops.action.drain-node", "ops.widget.health", } self.assertEqual(expected, set(surfaces)) for surface_id in ( "ops.page.summary", "ops.page.health", "ops.page.runtime", "ops.page.recovery", "ops.page.governance", "ops.page.deployment", "ops.page.sizing", ): self.assertEqual("ops.page", surfaces[surface_id].parent_id) self.assertEqual("ops.page.health", surfaces["ops.action.run-probes"].parent_id) self.assertEqual("ops.page.runtime", surfaces["ops.action.drain-node"].parent_id) def test_help_and_consequence_metadata_remain_published(self) -> None: topics = {topic.id: topic for topic in get_manifest().documentation} status = topics["ops.health-governance-and-sizing"] recovery = topics["ops.runtime-coordination-and-recovery"] self.assertIn("ops.page.health", status.metadata["help_contexts"]) self.assertIn("run_probes", status.metadata["consequence_classes"]) self.assertIn("ops.action.drain-node", recovery.metadata["help_contexts"]) self.assertIn("drain_node", recovery.metadata["consequence_classes"]) self.assertIn("cancel_node_drain", recovery.metadata["consequence_classes"]) self.assertIn("inspect_recovery", recovery.metadata["consequence_classes"]) def test_webui_uses_shared_operational_patterns(self) -> None: page = (REPO_ROOT / "webui/src/features/ops/OpsPage.tsx").read_text(encoding="utf-8") widget = (REPO_ROOT / "webui/src/features/ops/OpsHealthWidget.tsx").read_text(encoding="utf-8") for component in ( "ActionBlockerHint", "ConfirmDialog", "DataGrid", "DocumentationHelpLink", "LoadingFrame", "MetricCard", "TableActionGroup", ): self.assertIn(component, page) self.assertIn("DocumentationHelpLink", widget) self.assertIn("LoadingFrame", widget) if __name__ == "__main__": unittest.main()