import { readFileSync } from "node:fs"; import { join } from "node:path"; import { describe, expect, it } from "vitest"; const root = process.cwd(); const source = readFileSync( join(root, "src/components/models/navigation/items/NavigationMenuItemsAdmin.vue"), "utf8" ).replace(/\r\n/g, "\n"); const superuserSource = readFileSync( join(root, "src/components/models/navigation/items/NavigationMenuItemsSuperUser.vue"), "utf8" ).replace(/\r\n/g, "\n"); const legacyAdminMenuSource = readFileSync(join(root, "src/components/menus/admin/AdminLeftMenu.vue"), "utf8").replace( /\r\n/g, "\n" ); const superuserLeftMenuSource = readFileSync( join(root, "src/components/menus/superuser/SuperUserLeftMenu.vue"), "utf8" ).replace(/\r\n/g, "\n"); const orderBookingsSource = readFileSync( join(root, "src/components/session/token/SessionUser/Objects/OrderBookings.vue"), "utf8" ).replace(/\r\n/g, "\n"); describe("NavigationMenuItemsAdmin contract", () => { it("derives department id from synced route context without router import", () => { expect(source).not.toContain('import { router } from "@/router.js";'); expect(source).toContain("const routeContext = ref("); expect(source).toContain("const syncAdminNavigationRoute = (route: any) => {"); expect(source).toContain("const currentRoute = routeContext.value;"); expect(source).toContain("currentRoute?.params?.departmentId"); expect(source).toContain("currentRoute?.path?.match(/^\\/admin\\/(\\d+)(?:\\/|$)/)"); }); it("uses explicit booking-count permissions before polling count badges", () => { expect(source).toContain("hasExplicitBookingCountPermission(SessionUser)"); expect(source).toContain("const canUseAdminBookingNavigationCounts = () =>"); expect(source).toContain("canUseAdminNavigationCounts() && hasExplicitBookingCountPermission(SessionUser)"); expect(source).toContain("if (!canUseAdminBookingNavigationCounts())"); expect(superuserSource).toContain("hasExplicitBookingCountPermission(SessionUser)"); expect(superuserSource).toContain("const canUseSuperUserBookingNavigationCounts = () =>"); expect(superuserSource).toContain( "canUseSuperUserNavigationCounts() && hasExplicitBookingCountPermission(SessionUser)" ); expect(superuserSource).toContain("if (!canUseSuperUserBookingNavigationCounts())"); }); it("does not hardcode the bookings label in the legacy admin menu", () => { expect(legacyAdminMenuSource).toContain("const getBookingsLabel = () =>"); expect(legacyAdminMenuSource).not.toContain('name: "Bookinger"'); }); it("derives order-bookings labels from shared i18n translations", () => { expect(orderBookingsSource).toContain('import i18n from "@/i18n";'); expect(orderBookingsSource).toContain('return tf("nav.bookings", "Bookings")'); expect(orderBookingsSource).toContain('return tf("objects.order_bookings.single", "Booking")'); expect(orderBookingsSource).not.toContain('title: "Bookinger"'); }); it("surfaces system security in both superuser navigation menus", () => { expect(superuserSource).toContain('to: "/superuser"'); expect(superuserSource).not.toContain('to: "/superuser/system/status"'); expect(superuserSource).toContain('to: "/superuser/system/security/overview"'); expect(superuserSource).toContain('t("security.nav")'); expect(superuserSource).toContain('t("system_status.cards.minio")'); expect(superuserSource).toContain('t("system_status.cards.redis")'); expect(superuserSource).not.toContain('to: "/superuser/system/replication"'); expect(superuserLeftMenuSource).toContain("value: null"); expect(superuserLeftMenuSource).not.toContain('value: "/system/status"'); expect(superuserLeftMenuSource).toContain('t("security.nav", "Security")'); expect(superuserLeftMenuSource).toContain('value: "/system/security/overview"'); expect(superuserLeftMenuSource).toContain('t("cron.system_nav", "System")'); }); });