import type { ReactNode } from "react"; import { describe, expect, it, beforeEach, vi } from "vitest"; import { render, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { I18nProvider } from "@multica/core/i18n/react"; import enCommon from "../locales/en/common.json"; import enWorkspace from "../locales/en/workspace.json"; const TEST_RESOURCES = { en: { common: enCommon, workspace: enWorkspace }, }; const mockPush = vi.hoisted(() => vi.fn()); const mockCreateWorkspaceMutate = vi.hoisted(() => vi.fn()); const mockToastError = vi.hoisted(() => vi.fn()); vi.mock("../navigation", () => ({ useNavigation: () => ({ push: mockPush }), })); vi.mock("@multica/core/workspace/mutations", () => ({ useCreateWorkspace: () => ({ mutate: mockCreateWorkspaceMutate, isPending: false, }), })); vi.mock("@multica/ui/components/ui/dialog", () => ({ Dialog: ({ children }: { children: ReactNode }) =>
{children}
, DialogContent: ({ children }: { children: ReactNode }) =>
{children}
, DialogTitle: ({ children }: { children: ReactNode }) =>

{children}

, DialogDescription: ({ children }: { children: ReactNode }) => (

{children}

), })); vi.mock("sonner", () => ({ toast: { error: mockToastError, }, })); import { CreateWorkspaceModal } from "./create-workspace"; function I18nWrapper({ children }: { children: ReactNode }) { return ( {children} ); } function renderModal(props: { onClose: () => void }) { return render(, { wrapper: I18nWrapper }); } describe("CreateWorkspaceModal", () => { beforeEach(() => { vi.clearAllMocks(); }); it("auto-generates the slug until the user edits it", async () => { const user = userEvent.setup(); renderModal({ onClose: vi.fn() }); const nameInput = screen.getByPlaceholderText("My Workspace"); const slugInput = screen.getByPlaceholderText("my-workspace"); await user.type(nameInput, "My Team"); expect(slugInput).toHaveValue("my-team"); await user.clear(slugInput); await user.type(slugInput, "custom-team"); await user.clear(nameInput); await user.type(nameInput, "Renamed Team"); expect(slugInput).toHaveValue("custom-team"); }); it("shows a specific slug conflict error on 409 responses", async () => { const user = userEvent.setup(); mockCreateWorkspaceMutate.mockImplementation( ( _data: unknown, options: { onError: (error: unknown) => void }, ) => { options.onError({ status: 409 }); }, ); renderModal({ onClose: vi.fn() }); await user.type(screen.getByPlaceholderText("My Workspace"), "My Team"); await user.click(screen.getByRole("button", { name: "Create workspace" })); await waitFor(() => { expect( screen.getByText("That workspace URL is already taken."), ).toBeInTheDocument(); }); expect(mockToastError).toHaveBeenCalledWith( "Choose a different workspace URL", ); expect(mockCreateWorkspaceMutate).toHaveBeenCalledWith( { name: "My Team", slug: "my-team" }, expect.any(Object), ); }); it("navigates into the newly created workspace after success", async () => { const user = userEvent.setup(); const onClose = vi.fn(); mockCreateWorkspaceMutate.mockImplementation( ( _data: unknown, options: { onSuccess: (ws: { slug: string }) => void }, ) => { options.onSuccess({ slug: "my-team" }); }, ); renderModal({ onClose }); await user.type(screen.getByPlaceholderText("My Workspace"), "My Team"); await user.click(screen.getByRole("button", { name: "Create workspace" })); expect(onClose).toHaveBeenCalled(); expect(mockPush).toHaveBeenCalledWith("/my-team/issues"); }); });