from __future__ import annotations
from pathlib import Path
import unittest
from govoplan_calendar.backend.manifest import get_manifest
REPO_ROOT = Path(__file__).resolve().parents[1]
class CalendarInterfaceDocumentationContractTests(unittest.TestCase):
def test_all_static_topics_have_complete_german_content(self) -> None:
for topic in get_manifest().documentation:
german = (topic.translations or {}).get("de", {})
self.assertEqual({"title", "summary", "body"}, set(german), topic.id)
self.assertTrue(
all(str(value).strip() for value in german.values()), topic.id
)
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 = {
"calendar.navigation",
"calendar.page",
"calendar.page.sidebar",
"calendar.page.agenda",
"calendar.page.workspace",
"calendar.event-editor",
"calendar.collection-editor",
"calendar.sync-status",
"calendar.outbox",
"calendar.migration",
"calendar.settings.preferences",
"calendar.quick_access.agenda",
"calendar.widget.upcoming",
}
self.assertEqual(expected, set(surfaces))
self.assertEqual("calendar.page", surfaces["calendar.page.sidebar"].parent_id)
self.assertEqual(
"calendar.page.sidebar", surfaces["calendar.page.agenda"].parent_id
)
self.assertEqual("calendar.page", surfaces["calendar.page.workspace"].parent_id)
self.assertEqual("calendar.page", surfaces["calendar.event-editor"].parent_id)
self.assertEqual(
"calendar.page.sidebar", surfaces["calendar.collection-editor"].parent_id
)
self.assertEqual(
"calendar.collection-editor", surfaces["calendar.sync-status"].parent_id
)
self.assertEqual("calendar.sync-status", surfaces["calendar.outbox"].parent_id)
self.assertEqual(
"calendar.sync-status", surfaces["calendar.migration"].parent_id
)
def test_help_and_consequence_metadata_remain_published(self) -> None:
topics = {topic.id: topic for topic in get_manifest().documentation}
events = topics["calendar.manage-calendars-and-events"]
sources = topics["calendar.external-sources-and-sync"]
recovery = topics["calendar.outbound-change-recovery"]
self.assertIn("calendar.event-editor", events.metadata["help_contexts"])
self.assertIn("save_event", events.metadata["consequence_classes"])
self.assertIn("delete_event", events.metadata["consequence_classes"])
self.assertIn("calendar.collection-editor", sources.metadata["help_contexts"])
self.assertIn("force_full_sync", sources.metadata["consequence_classes"])
self.assertIn("execute_remote_move", sources.metadata["consequence_classes"])
self.assertIn("calendar.outbox", recovery.metadata["help_contexts"])
self.assertIn("reconcile_outbox", recovery.metadata["consequence_classes"])
quick_tool = get_manifest().frontend.quick_access_tools[0]
self.assertEqual(("calendar.event",), quick_tool.returned_reference_kinds)
self.assertEqual("calendar.quick_access.agenda", quick_tool.help_context_id)
self.assertEqual("/calendar", quick_tool.full_page_path)
def test_quick_access_is_bounded_temporal_and_owner_launched(self) -> None:
quick_access = (
REPO_ROOT / "webui/src/features/calendar/CalendarQuickAccess.tsx"
).read_text(encoding="utf-8")
page = (REPO_ROOT / "webui/src/features/calendar/CalendarPage.tsx").read_text(
encoding="utf-8"
)
self.assertIn("const AGENDA_LIMIT = 7", quick_access)
self.assertIn("launchContext.temporalContext", quick_access)
self.assertIn("limit: AGENDA_LIMIT", quick_access)
self.assertIn('kind: "event"', quick_access)
self.assertIn("quickAccessLaunchState(launchContext)", quick_access)
self.assertIn('parameters.get("quickAction") !== "create-event"', page)
def test_webui_uses_shared_help_guard_and_confirmation_components(self) -> None:
event_dialog = (
REPO_ROOT / "webui/src/features/calendar/CalendarEventDialog.tsx"
).read_text(encoding="utf-8")
collection_dialog = (
REPO_ROOT / "webui/src/features/calendar/CalendarCollectionDialogs.tsx"
).read_text(encoding="utf-8")
settings_panel = (
REPO_ROOT / "webui/src/features/calendar/CalendarSettingsPanel.tsx"
).read_text(encoding="utf-8")
for component in (
"ActionBlockerHint",
"ConfirmDialog",
"titleHelp={}",
"useUnsavedDraftGuard",
):
self.assertIn(component, event_dialog)
for component in (
"ActionBlockerHint",
"titleHelp={}",
"useUnsavedDraftGuard",
):
self.assertIn(component, collection_dialog)
for component in (
"titleHelp={}",
"useUnsavedDraftGuard",
):
self.assertIn(component, settings_panel)
if __name__ == "__main__":
unittest.main()