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_notifications.backend.manifest import get_manifest REPO_ROOT = Path(__file__).resolve().parents[1] class NotificationsInterfaceDocumentationContractTests(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 = { "notifications.page.inbox", "notifications.page.detail", "notifications.page.delivery", "notifications.action.mark-read", "notifications.action.acknowledge", "notifications.action.cancel", "notifications.action.dispatch", "notifications.settings.preferences", "notifications.widget.summary", } self.assertEqual(expected, set(surfaces)) self.assertEqual( "notifications.route.notifications", frontend.routes[0].surface_id, # type: ignore[union-attr] ) self.assertEqual( "notifications.route.notifications", surfaces["notifications.page.inbox"].parent_id, ) self.assertEqual( "notifications.route.notifications", surfaces["notifications.page.detail"].parent_id, ) self.assertEqual( "notifications.page.detail", surfaces["notifications.page.delivery"].parent_id, ) self.assertEqual( "notifications.page.delivery", surfaces["notifications.action.dispatch"].parent_id, ) def test_help_and_consequence_metadata_remain_published(self) -> None: topics = {topic.id: topic for topic in get_manifest().documentation} center = topics["notifications.center-and-preferences"] delivery = topics["notifications.delivery-operations"] self.assertIn("notifications.page.detail", center.metadata["help_contexts"]) self.assertIn("notifications.settings.preferences", center.metadata["help_contexts"]) self.assertIn("acknowledge", center.metadata["consequence_classes"]) self.assertIn("cancel", center.metadata["consequence_classes"]) self.assertIn("notifications.action.dispatch", delivery.metadata["help_contexts"]) self.assertIn("dispatch_pending", delivery.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)) center = next(topic for topic in topics if topic.id == "notifications.center-and-preferences") delivery = next(topic for topic in topics if topic.id == "notifications.delivery-operations") self.assertEqual("workflow", center.metadata["kind"]) self.assertTrue(center.conditions) self.assertEqual("reference", delivery.metadata["kind"]) def test_webui_uses_shared_consequence_and_draft_patterns(self) -> None: center = (REPO_ROOT / "webui/src/features/notifications/NotificationCenterPage.tsx").read_text(encoding="utf-8") settings = (REPO_ROOT / "webui/src/features/notifications/NotificationSettingsPanel.tsx").read_text(encoding="utf-8") widget = (REPO_ROOT / "webui/src/features/notifications/NotificationSummaryWidget.tsx").read_text(encoding="utf-8") for component in ( "ActionBlockerHint", "ConfirmDialog", "DocumentationHelpLink", "SelectionList", ): self.assertIn(component, center) for component in ( "ActionBlockerHint", "DocumentationHelpLink", "ReferenceMultiSelect", "useUnsavedDraftGuard", ): self.assertIn(component, settings) contribution = (REPO_ROOT / "webui/src/module.ts").read_text(encoding="utf-8") self.assertIn("documentation: NOTIFICATIONS_DOCUMENTATION", contribution) self.assertNotIn("DocumentationHelpLink", widget) if __name__ == "__main__": unittest.main()