import { act, cleanup, render } from "@testing-library/react"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { CommandItem } from "@/lib/commands/types"; import { activateLocale, DEFAULT_LOCALE } from "@/lib/i18n"; import { GlobalCommands } from "./global-commands"; const mocks = vi.hoisted(() => { return { commands: [] as CommandItem[], destinations: [ { id: "stats", label: "Stats", icon: () => null, section: "insights" as const, href: "/stats", palette: { id: "nav-stats", labelKey: "common:commandGoToStats", keywordsKey: "common:commandGoToStatsKeywords", }, }, ], push: vi.fn(), quickChat: vi.fn(), quickChatLauncherCalls: [] as unknown[][], keyboardShortcutCalls: [] as unknown[][], setTheme: vi.fn(), }; }); vi.mock("@/components/state-provider", () => ({ useAppStore: (selector: (state: unknown) => unknown) => selector({ userSettings: { keyboardShortcuts: {} }, workspaces: { activeId: "workspace-1" }, }), })); vi.mock("@/components/theme/app-theme", () => ({ useTheme: () => ({ resolvedTheme: "dark", setTheme: mocks.setTheme }), })); vi.mock("@/hooks/use-app-destinations", () => ({ useStaticDestinations: () => mocks.destinations.map((destination) => ({ ...destination })), })); vi.mock("@/hooks/use-app-shortcuts", () => ({ useAppShortcuts: vi.fn() })); vi.mock("@/hooks/use-keyboard-shortcut", () => ({ useKeyboardShortcut: (...args: unknown[]) => mocks.keyboardShortcutCalls.push(args), })); vi.mock("@/hooks/use-plugin-shortcuts", () => ({ usePluginShortcuts: vi.fn() })); vi.mock("@/hooks/use-quick-chat-launcher", () => ({ useQuickChatLauncher: (...args: unknown[]) => { mocks.quickChatLauncherCalls.push(args); return mocks.quickChat; }, })); vi.mock("@/hooks/use-register-commands", () => ({ useRegisterCommands: (commands: CommandItem[]) => { mocks.commands = commands; }, })); vi.mock("@/lib/keyboard/shortcut-overrides", () => ({ getShortcut: () => undefined })); vi.mock("@/lib/routing/client-router", () => ({ useRouter: () => ({ push: mocks.push }), })); vi.mock("@/components/settings-discovery-commands", () => ({ SettingsDiscoveryCommands: () => null, })); function navigationCommand(): CommandItem { const command = mocks.commands.find((item) => item.id === "nav-stats"); if (!command) throw new Error("Missing Stats navigation command"); return command; } beforeEach(async () => { mocks.commands = []; mocks.quickChatLauncherCalls = []; mocks.keyboardShortcutCalls = []; mocks.push.mockReset(); await activateLocale(DEFAULT_LOCALE); }); afterEach(async () => { cleanup(); await activateLocale(DEFAULT_LOCALE); }); describe("GlobalCommands navigation commands", () => { it("maps destinations to commands and navigation actions", () => { render(); const command = navigationCommand(); expect(command).toMatchObject({ id: "nav-stats", label: "Stats", group: "Navigation", keywords: ["stats", "statistics", "analytics", "metrics"], }); command.action?.(); expect(mocks.push).toHaveBeenCalledWith("/stats"); }); it("does not request silent focus for global quick chat commands", () => { render(); expect(mocks.quickChatLauncherCalls).toEqual([ ["workspace-1", "chat", { silentFocusReturn: false, toggleWhenOpen: true }], ["workspace-1", "config", { silentFocusReturn: false }], ]); }); it("@covers AC-UI-QUICK-TERMINAL-001.10 captures the toggle before xterm can consume it", () => { render(); expect(mocks.keyboardShortcutCalls).toHaveLength(1); expect(mocks.keyboardShortcutCalls[0]?.[2]).toEqual({ capture: true, stopPropagation: true, }); }); // Drives a real locale switch rather than a stubbed `t`. The point of the // test is that the memo key tracks translated values, and only the real // catalog can show that end to end — a hand-written translation table proves // the memo reacts to the table, not to a locale change. it("keeps command identity until a translated command value changes", async () => { const { rerender } = render(); const first = navigationCommand(); rerender(); expect(navigationCommand()).toBe(first); await act(async () => { await activateLocale("pt-pt"); }); rerender(); const translated = navigationCommand(); expect(translated).not.toBe(first); expect(translated.group).toBe("Navegação"); expect(translated.keywords).toEqual(["estatísticas", "análises", "métricas"]); }); });