import React, { useState } from "react"; import "@testing-library/jest-dom"; import { fireEvent, render, screen, within, waitFor } from "@testing-library/react"; import { I18nProvider } from "./i18n/I18nProvider"; import JobTrackerThemeProvider from "./ThemeProvider"; import AppShell, { type NavItem } from "./layout/AppShell"; let mockMobile = true; jest.mock("@mui/material/useMediaQuery", () => ({ __esModule: true, default: () => mockMobile })); const nav: NavItem[] = [ { to: "/dashboard", label: "Dashboard", icon: }, { to: "/jobs", label: "Jobs", icon: , activeFor: ["/applications"], children: [{ to: "/companies", label: "Companies", icon: }] }, { to: "/discover", label: "Discovery", icon: }, { to: "/career", label: "Career profile", icon: , children: [{ to: "/career/builder", label: "CV Builder", icon: }] }, ]; const bottom: NavItem[] = [ { to: "/settings", label: "Settings", icon: }, { to: "/admin/users", label: "Hidden admin", icon: , hidden: true }, ]; function Shell({ initial = "/dashboard" }: { initial?: string }) { const [pathname, setPath] = useState(initial); const [open, setOpen] = useState(false); return { setOpen(false); setPath(to); }}> ; } beforeEach(() => { localStorage.clear(); mockMobile = true; }); test.each([ ["en", "Primary navigation", "Applications", "Discover", "Career", "More"], ["nb", "Hovednavigasjon", "Søknader", "Finn jobber", "Karriere", "Mer"], ])("%s hybrid navigation has five labelled destinations and retains secondary tools", (language, label, applications, discover, career, more) => { localStorage.setItem("uiLanguage", language); render(); const primary = screen.getByRole("navigation", { name: label }); expect(within(primary).getAllByRole("button")).toHaveLength(5); for (const name of [applications, discover, career, more]) expect(within(primary).getByRole("button", { name })).toBeVisible(); expect(within(primary).getByRole("button", { name: more })).toHaveAttribute("aria-current", "page"); fireEvent.click(within(primary).getByRole("button", { name: more })); const drawer = screen.getByRole("dialog"); expect(within(drawer).getByRole("button", { name: "Companies" })).toHaveAttribute("aria-current", "page"); expect(within(drawer).queryByText("Hidden admin")).not.toBeInTheDocument(); fireEvent.click(within(drawer).getByRole("button", { name: "Settings" })); expect(screen.getByRole("heading", { level: 1, name: "/settings" })).toHaveFocus(); }); test.each(["/career/builder/42", "/applications/42", "/jobs/42"])("%s selects its primary destination and keyboard route focus survives", initial => { localStorage.setItem("uiLanguage", "en"); render(); const primary = screen.getByRole("navigation", { name: "Primary navigation" }); expect(within(primary).getAllByRole("button").filter(button => button.getAttribute("aria-current") === "page")).toHaveLength(1); expect(within(primary).getByRole("button", { name: initial.startsWith("/career") ? "Career" : "Applications" })).toHaveAttribute("aria-current", "page"); fireEvent.click(within(primary).getByRole("button", { name: "Discover" })); expect(screen.getByRole("heading", { name: "/discover", level: 1 })).toHaveFocus(); }); test("desktop retains labelled collapse, persistence, and all secondary destinations", () => { mockMobile = false; localStorage.setItem("uiLanguage", "en"); render(); expect(screen.queryByRole("navigation", { name: "Primary navigation" })).not.toBeInTheDocument(); fireEvent.click(screen.getByRole("button", { name: "Collapse sidebar" })); expect(localStorage.getItem("appShellDesktopSidebarCollapsed")).toBe("1"); fireEvent.click(screen.getByRole("button", { name: "Jobs" })); expect(within(screen.getByRole("menu")).getByRole("menuitem", { name: "Companies" })).toBeVisible(); }); test("choosing the current destination from More closes the drawer and focuses its heading", async () => { localStorage.setItem("uiLanguage", "en"); render(); fireEvent.click(within(screen.getByRole("navigation", { name: "Primary navigation" })).getByRole("button", { name: "More" })); fireEvent.click(within(screen.getByRole("dialog")).getByRole("button", { name: "Companies" })); await waitFor(() => expect(screen.queryByRole("dialog")).not.toBeInTheDocument()); expect(screen.getByRole("heading", { level: 1, name: "/companies" })).toHaveFocus(); });