import type { ReactNode } from "react"; import { describe, expect, it, beforeEach, vi } from "vitest"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; // The shared Dialog is a Base UI portal that's awkward to test — strip it to // simple pass-through wrappers. The typed-confirmation logic lives in the // dialog body, not in Base UI, so this doesn't reduce coverage. vi.mock("@multica/ui/components/ui/dialog", () => ({ Dialog: ({ children, open }: { children: ReactNode; open: boolean }) => open ?
{children}
: null, DialogContent: ({ children }: { children: ReactNode }) =>
{children}
, DialogHeader: ({ children }: { children: ReactNode }) =>
{children}
, DialogTitle: ({ children }: { children: ReactNode }) =>

{children}

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

{children}

, DialogFooter: ({ children }: { children: ReactNode }) =>
{children}
, })); import { DeleteWorkspaceDialog } from "./delete-workspace-dialog"; describe("DeleteWorkspaceDialog", () => { beforeEach(() => { vi.clearAllMocks(); }); it("disables Delete when input is empty", () => { render( , ); expect(screen.getByRole("button", { name: "Delete workspace" })).toBeDisabled(); }); it("keeps Delete disabled when input doesn't match (case-sensitive)", async () => { const user = userEvent.setup(); render( , ); await user.type(screen.getByRole("textbox"), "ACME"); // wrong case expect(screen.getByRole("button", { name: "Delete workspace" })).toBeDisabled(); await user.clear(screen.getByRole("textbox")); await user.type(screen.getByRole("textbox"), "acme "); // trailing space expect(screen.getByRole("button", { name: "Delete workspace" })).toBeDisabled(); }); it("enables Delete on exact match and calls onConfirm when clicked", async () => { const user = userEvent.setup(); const onConfirm = vi.fn(); render( , ); await user.type(screen.getByRole("textbox"), "acme"); const deleteBtn = screen.getByRole("button", { name: "Delete workspace" }); expect(deleteBtn).toBeEnabled(); await user.click(deleteBtn); expect(onConfirm).toHaveBeenCalledTimes(1); }); it("submits on Enter when matched; ignores Enter when not matched", async () => { const user = userEvent.setup(); const onConfirm = vi.fn(); render( , ); const input = screen.getByRole("textbox"); await user.type(input, "acm{Enter}"); // not yet matched expect(onConfirm).not.toHaveBeenCalled(); await user.type(input, "e{Enter}"); // now matches "acme" expect(onConfirm).toHaveBeenCalledTimes(1); }); it("Cancel closes the dialog and does not call onConfirm", async () => { const user = userEvent.setup(); const onOpenChange = vi.fn(); const onConfirm = vi.fn(); render( , ); await user.click(screen.getByRole("button", { name: "Cancel" })); expect(onOpenChange).toHaveBeenCalledWith(false); expect(onConfirm).not.toHaveBeenCalled(); }); it("shows loading state and disables both buttons while pending", () => { render( , ); expect(screen.getByRole("button", { name: "Deleting..." })).toBeDisabled(); expect(screen.getByRole("button", { name: "Cancel" })).toBeDisabled(); }); it("matches names with spaces, unicode, and other non-ASCII characters literally", async () => { const user = userEvent.setup(); const onConfirm = vi.fn(); render( , ); const input = screen.getByRole("textbox"); await user.type(input, "My 团队 🚀"); expect(screen.getByRole("button", { name: "Delete workspace" })).toBeEnabled(); await user.click(screen.getByRole("button", { name: "Delete workspace" })); expect(onConfirm).toHaveBeenCalledTimes(1); }); it("resets the input when the workspace being deleted changes (e.g. rename mid-dialog)", () => { const { rerender } = render( , ); const input = screen.getByRole("textbox") as HTMLInputElement; // Simulate user typing (set value directly since userEvent.type would // lose focus across re-renders). input.value = "old-name"; rerender( , ); expect(screen.getByRole("textbox")).toHaveValue(""); }); it("clears the input when reopened so prior attempts don't leak", async () => { const user = userEvent.setup(); const { rerender } = render( , ); await user.type(screen.getByRole("textbox"), "partial"); expect(screen.getByRole("textbox")).toHaveValue("partial"); // Simulate close → reopen (e.g. user canceled, then clicked Delete again) rerender( , ); rerender( , ); expect(screen.getByRole("textbox")).toHaveValue(""); }); });