import { beforeEach, describe, expect, it, vi } from "vitest"; import { render, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { OnboardingWizard } from "./OnboardingWizard"; const mockPush = vi.fn(); const mockGetStatus = vi.fn(); const mockCreateBreakglass = vi.fn(); const mockConfigureOidc = vi.fn(); const mockTestProvider = vi.fn(); const mockAddProvider = vi.fn(); const mockCompleteOnboarding = vi.fn(); vi.mock("next/navigation", () => ({ useRouter: (): { push: typeof mockPush } => ({ push: mockPush, }), })); vi.mock("@/lib/api/onboarding", () => ({ fetchOnboardingStatus: (): ReturnType => mockGetStatus(), createBreakglassAdmin: (...args: unknown[]): ReturnType => mockCreateBreakglass(...args), configureOidcProvider: (...args: unknown[]): ReturnType => mockConfigureOidc(...args), testOnboardingProvider: (...args: unknown[]): ReturnType => mockTestProvider(...args), addOnboardingProvider: (...args: unknown[]): ReturnType => mockAddProvider(...args), completeOnboarding: (): ReturnType => mockCompleteOnboarding(), })); describe("OnboardingWizard", () => { beforeEach(() => { mockPush.mockReset(); mockGetStatus.mockReset(); mockCreateBreakglass.mockReset(); mockConfigureOidc.mockReset(); mockTestProvider.mockReset(); mockAddProvider.mockReset(); mockCompleteOnboarding.mockReset(); mockGetStatus.mockResolvedValue({ completed: false }); mockCreateBreakglass.mockResolvedValue({ id: "bg-1", username: "admin" }); mockConfigureOidc.mockResolvedValue(undefined); mockTestProvider.mockResolvedValue({ success: true }); mockAddProvider.mockResolvedValue({ id: "provider-1" }); mockCompleteOnboarding.mockResolvedValue(undefined); }); it("renders the first step with admin setup fields", async () => { render(); expect( await screen.findByText("Welcome to Mosaic Stack. Let's get you set up.") ).toBeInTheDocument(); expect(screen.getByLabelText("Username")).toBeInTheDocument(); expect(screen.getByLabelText("Password")).toBeInTheDocument(); expect(screen.getByLabelText("Confirm Password")).toBeInTheDocument(); expect(screen.getByText("1. Admin")).toBeInTheDocument(); }); it("validates admin form fields before submit", async () => { const user = userEvent.setup(); render(); await screen.findByText("Welcome to Mosaic Stack. Let's get you set up."); await user.click(screen.getByRole("button", { name: "Create Admin" })); expect(screen.getByText("Username must be at least 3 characters.")).toBeInTheDocument(); expect(mockCreateBreakglass).not.toHaveBeenCalled(); }); it("supports happy path with OIDC skipped", async () => { const user = userEvent.setup(); render(); await screen.findByText("Welcome to Mosaic Stack. Let's get you set up."); await user.type(screen.getByLabelText("Username"), "admin"); await user.type(screen.getByLabelText("Password"), "verysecurepassword"); await user.type(screen.getByLabelText("Confirm Password"), "verysecurepassword"); await user.click(screen.getByRole("button", { name: "Create Admin" })); await screen.findByText("Configure OIDC Provider (Optional)"); await user.click(screen.getByRole("button", { name: "Skip" })); await screen.findByText("Add Your First LLM Provider"); await user.type(screen.getByLabelText("Display Name"), "My OpenAI"); await user.type(screen.getByLabelText("API Key"), "sk-test-key"); await user.click(screen.getByRole("button", { name: "Test Connection" })); await screen.findByText("Connection successful."); const addProviderButton = screen.getByRole("button", { name: "Add Provider" }); expect(addProviderButton).toBeEnabled(); await user.click(addProviderButton); await screen.findByText("You're all set"); await user.click(screen.getByRole("button", { name: "Launch Mosaic Stack" })); await waitFor(() => { expect(mockPush).toHaveBeenCalledWith("/"); }); }); });