from __future__ import annotations from pathlib import Path import unittest from govoplan_core.core.modules import ( documentation_structured_translation_issues, localizable_documentation_metadata_keys, ) from govoplan_dashboard.backend.manifest import READ_SCOPE, get_manifest REPO_ROOT = Path(__file__).resolve().parents[1] class DashboardInterfaceDocumentationContractTests(unittest.TestCase): def test_dashboard_surface_requires_explicit_read_permission(self) -> None: manifest = get_manifest() self.assertEqual({READ_SCOPE}, {item.scope for item in manifest.permissions}) self.assertIn( READ_SCOPE, next( item.permissions for item in manifest.role_templates if item.slug == "dashboard_user" ), ) self.assertEqual((READ_SCOPE,), manifest.nav_items[0].required_all) self.assertEqual((READ_SCOPE,), manifest.frontend.routes[0].required_all) # type: ignore[union-attr] self.assertEqual((READ_SCOPE,), manifest.frontend.nav_items[0].required_all) # type: ignore[union-attr] def test_surface_hierarchy_remains_declared(self) -> None: frontend = get_manifest().frontend self.assertIsNotNone(frontend) surfaces = {item.id: item for item in frontend.view_surfaces} # type: ignore[union-attr] self.assertEqual( { "dashboard.page", "dashboard.summary", "dashboard.library", "dashboard.grid", "dashboard.widget-settings", "dashboard.widget.installed-modules", }, set(surfaces), ) self.assertEqual("dashboard.page", surfaces["dashboard.library"].parent_id) self.assertEqual("dashboard.page", surfaces["dashboard.grid"].parent_id) self.assertEqual("dashboard.grid", surfaces["dashboard.widget-settings"].parent_id) def test_help_and_consequence_metadata_remain_published(self) -> None: topics = {topic.id: topic for topic in get_manifest().documentation} home = topics["dashboard.configurable-home"] reference = topics["dashboard.reference.layout-and-widgets"] self.assertIn("dashboard.state.browser-fallback", home.metadata["help_contexts"]) self.assertEqual("workflow", home.metadata["kind"]) self.assertEqual((READ_SCOPE,), home.conditions[0].required_scopes) self.assertIn("dashboard.field.widget-size", reference.metadata["help_contexts"]) self.assertIn("save_layout", reference.metadata["consequence_classes"]) self.assertIn("remove_widget", reference.metadata["consequence_classes"]) def test_german_reference_documentation_is_complete(self) -> None: topics = get_manifest().documentation self.assertEqual(3, len(topics)) for topic in topics: translation = topic.translations.get("de", {}) self.assertTrue(translation.get("title"), topic.id) self.assertTrue(translation.get("summary"), topic.id) self.assertTrue(translation.get("body"), topic.id) if localizable_documentation_metadata_keys(topic): self.assertEqual("1", topic.structured_translation_version, topic.id) self.assertIn("de", topic.structured_translations, topic.id) self.assertEqual((), documentation_structured_translation_issues(topic)) reference = next( topic for topic in topics if topic.id == "dashboard.reference.layout-and-widgets" ) self.assertEqual("reference", reference.metadata["kind"]) def test_webui_guards_layout_and_nested_widget_drafts(self) -> None: page = (REPO_ROOT / "webui/src/features/dashboard/DashboardPage.tsx").read_text( encoding="utf-8" ) dialog = ( REPO_ROOT / "webui/src/features/dashboard/WidgetConfigurationDialog.tsx" ).read_text(encoding="utf-8") library = ( REPO_ROOT / "webui/src/features/dashboard/WidgetLibrary.tsx" ).read_text(encoding="utf-8") self.assertEqual( 1, page.count("titleHelp={}"), ) self.assertNotIn("helpAction=", page) self.assertIn("useUnsavedDraftGuard", page) self.assertIn("useUnsavedDraftGuard", dialog) self.assertIn( "titleHelp={}", dialog, ) self.assertIn("disabled={atCapacity}", library) def test_widget_help_uses_provider_reference_at_the_existing_title(self) -> None: grid = (REPO_ROOT / "webui/src/features/dashboard/DashboardGrid.tsx").read_text(encoding="utf-8") self.assertEqual( 2, grid.count("titleHelp={widget.documentation && }"), "Regular cards and height-preserving drag cards retain provider documentation beside their existing title.", ) self.assertNotIn("helpAction=", grid) if __name__ == "__main__": unittest.main()