// @vitest-environment jsdom import { flushSync } from "react-dom"; import { createRoot, type Root } from "react-dom/client"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { TaskChatRedesignGate } from "./TaskChatRedesignGate"; import { useTaskChatRedesignEnabled } from "@/hooks/useTaskChatRedesignEnabled"; const mockInstanceSettingsApi = vi.hoisted(() => ({ getExperimental: vi.fn(), })); vi.mock("@/api/instanceSettings", () => ({ instanceSettingsApi: mockInstanceSettingsApi, })); vi.mock("@/lib/router", () => ({ Navigate: ({ to, replace }: { to: string; replace?: boolean }) => (
), Outlet: () =>
gated content
, })); async function flushReact() { for (let index = 0; index < 5; index += 1) { await Promise.resolve(); await new Promise((resolve) => window.setTimeout(resolve, 0)); } flushSync(() => {}); } describe("TaskChatRedesignGate", () => { let container: HTMLDivElement; let root: Root | null = null; async function renderGate() { root = createRoot(container); const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }); flushSync(() => { root!.render( , ); }); await flushReact(); } beforeEach(() => { container = document.createElement("div"); document.body.appendChild(container); }); afterEach(() => { flushSync(() => { root?.unmount(); }); root = null; container.remove(); vi.clearAllMocks(); }); it("redirects to the company home when the flag is off (flag-off isolation)", async () => { mockInstanceSettingsApi.getExperimental.mockResolvedValue({ enableTaskChatRedesign: false }); await renderGate(); const navigate = container.querySelector('[data-testid="navigate"]'); expect(navigate?.getAttribute("data-to")).toBe("/dashboard"); expect(container.querySelector('[data-testid="outlet"]')).toBeNull(); }); it("renders the gated harness when the flag is on", async () => { mockInstanceSettingsApi.getExperimental.mockResolvedValue({ enableTaskChatRedesign: true }); await renderGate(); expect(container.querySelector('[data-testid="outlet"]')).not.toBeNull(); expect(container.querySelector('[data-testid="navigate"]')).toBeNull(); }); }); describe("useTaskChatRedesignEnabled", () => { it("resolves to flag-off when rendered without a QueryClientProvider", () => { // Rendered detached (no provider) it must default OFF and loaded — this is // what makes flag-off the provable current behavior at every call site. let captured: { enabled: boolean; loaded: boolean } | null = null; function Probe() { captured = useTaskChatRedesignEnabled(); return null; } const container = document.createElement("div"); const root = createRoot(container); flushSync(() => root.render()); flushSync(() => root.unmount()); expect(captured).toEqual({ enabled: false, loaded: true }); }); });