//=========================================== // THIS FILE IS AUTO-GENERATED FROM TEMPLATE. DO NOT EDIT IT DIRECTLY UNLESS YOU ALSO EDIT THE CORRESPONDING FILE IN packages/template //=========================================== // @vitest-environment jsdom import React, { act } from "react"; import { createRoot, type Root } from "react-dom/client"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { CurrentUser } from "../lib/hexclave-app"; import type { StackClientApp } from "../lib/hexclave-app/apps/interfaces/client-app"; import { TranslationProviderClient } from "../providers/translation-provider-client"; import { Onboarding } from "./onboarding"; const appMockState = vi.hoisted(() => ({ app: null as unknown, user: null as unknown, })); vi.mock("..", () => ({ useStackApp: () => { if (appMockState.app == null) { throw new Error("Expected test app to be set before rendering."); } return appMockState.app; }, useUser: () => appMockState.user, })); vi.mock("@hexclave/ui", async () => { const React = await import("react"); return { Button: (props: { children: React.ReactNode, onClick?: () => void }) => ( ), Input: (props: Record) => , Typography: (props: { children: React.ReactNode }) =>
{props.children}
, cn: (...classes: (string | false | null | undefined)[]) => classes.filter(Boolean).join(" "), }; }); const previousActEnvironment = Reflect.get(globalThis, "IS_REACT_ACT_ENVIRONMENT"); function createAppTestDouble() { const app = { redirectToSignIn: vi.fn(async () => {}), redirectToAfterSignIn: vi.fn(async () => {}), }; // This test double intentionally implements only the StackClientApp surface that Onboarding touches. return app as unknown as StackClientApp & { redirectToSignIn: ReturnType, redirectToAfterSignIn: ReturnType, }; } function createUserTestDouble(user: Partial) { // Same as the app test double: only the surface Onboarding touches. return { isAnonymous: false, isRestricted: true, restrictedReason: null, restrictedByAdmin: false, restrictedByAdminReason: null, primaryEmail: "user@example.com", signOut: vi.fn(async () => {}), ...user, } as unknown as CurrentUser; } let root: Root | null = null; let container: HTMLDivElement | null = null; async function renderOnboarding(options: { app: StackClientApp, user: unknown, }) { appMockState.app = options.app; appMockState.user = options.user; container = document.createElement("div"); document.body.append(container); root = createRoot(container); await act(async () => { root?.render( ); }); return container; } describe("Onboarding", () => { beforeEach(() => { Reflect.set(globalThis, "IS_REACT_ACT_ENVIRONMENT", true); }); afterEach(() => { act(() => { root?.unmount(); }); container?.remove(); root = null; container = null; appMockState.app = null; appMockState.user = null; vi.restoreAllMocks(); Reflect.set(globalThis, "IS_REACT_ACT_ENVIRONMENT", previousActEnvironment); }); it("redirects signed-out users to sign-in", async () => { const app = createAppTestDouble(); const container = await renderOnboarding({ app, user: null }); expect(app.redirectToSignIn).toHaveBeenCalled(); expect(container.textContent).toBe(""); }); it("redirects anonymous users to sign-in", async () => { const app = createAppTestDouble(); const container = await renderOnboarding({ app, user: createUserTestDouble({ isAnonymous: true, restrictedReason: { type: "anonymous" } }) }); expect(app.redirectToSignIn).toHaveBeenCalled(); expect(container.textContent).toBe(""); }); it("redirects users that are no longer restricted to their destination", async () => { const app = createAppTestDouble(); await renderOnboarding({ app, user: createUserTestDouble({ isRestricted: false }) }); expect(app.redirectToAfterSignIn).toHaveBeenCalled(); expect(app.redirectToSignIn).not.toHaveBeenCalled(); }); it("shows the administrator's public reason to admin-restricted users", async () => { const app = createAppTestDouble(); const container = await renderOnboarding({ app, user: createUserTestDouble({ restrictedReason: { type: "restricted_by_administrator" }, restrictedByAdmin: true, restrictedByAdminReason: "Your sign-up was flagged by our fraud prevention rules.", }), }); expect(container.textContent).toContain("Your account has been restricted"); expect(container.textContent).toContain("Your sign-up was flagged by our fraud prevention rules."); expect(container.textContent).not.toContain("Complete your account setup"); }); it("falls back to a generic restricted message when no public reason is set", async () => { const app = createAppTestDouble(); const container = await renderOnboarding({ app, user: createUserTestDouble({ restrictedReason: { type: "restricted_by_administrator" }, restrictedByAdmin: true, restrictedByAdminReason: null, }), }); expect(container.textContent).toContain("Your account has been restricted"); expect(container.textContent).toContain("An administrator has restricted your account."); }); it("shows the setup-required message for unknown restricted reasons", async () => { const app = createAppTestDouble(); const container = await renderOnboarding({ app, // The reason types are a closed union, so an unknown reason can only come from a newer backend. user: createUserTestDouble({ restrictedReason: { type: "some_future_reason" } as unknown as CurrentUser["restrictedReason"] }), }); expect(container.textContent).toContain("Complete your account setup"); }); });