import { act, cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react"; import { type ReactElement, type ReactNode, cloneElement } from "react"; import { afterEach, describe, expect, it, vi } from "vitest"; import { FolderPicker } from "./folder-picker"; import { listDirectory, type DirectoryListing } from "@/lib/api/domains/fs-api"; let setPopoverOpen: ((open: boolean) => void) | undefined; vi.mock("@kandev/ui/popover", () => ({ Popover: ({ children, onOpenChange, }: { children: ReactNode; onOpenChange: (open: boolean) => void; }) => { setPopoverOpen = onOpenChange; return
{children}
; }, PopoverTrigger: ({ children }: { children: ReactElement<{ onClick?: () => void }> }) => cloneElement(children, { onClick: () => setPopoverOpen?.(true) }), PopoverContent: ({ children }: { children: ReactNode }) =>
{children}
, })); vi.mock("@kandev/ui/tooltip", () => ({ Tooltip: ({ children }: { children: ReactNode }) => <>{children}, TooltipTrigger: ({ children }: { children: ReactNode }) => <>{children}, TooltipContent: ({ children }: { children: ReactNode }) => <>{children}, })); vi.mock("@/lib/api/domains/fs-api", async (importOriginal) => { const original = await importOriginal(); return { ...original, listDirectory: vi.fn() }; }); const mockedListDirectory = vi.mocked(listDirectory); const BUTTON_ROLE = "button"; const TRIGGER_TEST_ID = "folder-picker-trigger"; const VIRTUAL_ROOT = "/"; const DRIVE_E_ROOT = "E:\\"; const SUCCESS_PATH = "E:\\Success"; const SUCCESS_NAME = "Success"; afterEach(() => { cleanup(); mockedListDirectory.mockReset(); setPopoverOpen = undefined; delete (window as Window & { __TAURI_INTERNALS__?: unknown }).__TAURI_INTERNALS__; delete (window as Window & { __KANDEV_BOOT_PAYLOAD__?: unknown }).__KANDEV_BOOT_PAYLOAD__; }); describe("FolderPicker", () => { it("preserves the separator when displaying the POSIX root", () => { render(); expect(screen.getByTestId(TRIGGER_TEST_ID).textContent).toBe("/"); }); it("preserves the separator when displaying a Windows drive root", () => { render(); expect(screen.getByTestId(TRIGGER_TEST_ID).textContent).toBe("C:\\"); }); it("uses the native picker in a Tauri WebView without listing directories over HTTP", async () => { const invoke = vi.fn(async () => ({ status: "selected", path: "/Users/example/Code" })); Object.defineProperty(window, "__TAURI_INTERNALS__", { configurable: true, value: { invoke }, }); Object.defineProperty(window, "__KANDEV_BOOT_PAYLOAD__", { configurable: true, value: { runtime: { nativeFolderPickerAvailable: true } }, }); const onChange = vi.fn(); render(); fireEvent.click(screen.getByTestId(TRIGGER_TEST_ID)); await waitFor(() => expect(onChange).toHaveBeenCalledWith("/Users/example/Code")); expect(invoke).toHaveBeenCalledWith("pick_directory", undefined); expect(mockedListDirectory).not.toHaveBeenCalled(); expect(screen.queryByTestId("folder-picker-popover")).toBeNull(); }); it("builds Windows breadcrumbs with a virtual root and native drive paths", async () => { mockedListDirectory .mockResolvedValueOnce( listing(VIRTUAL_ROOT, false, [{ name: DRIVE_E_ROOT, path: DRIVE_E_ROOT }]), ) .mockResolvedValueOnce(listing("E:\\Projects\\Kandev", true)) .mockResolvedValueOnce(listing(VIRTUAL_ROOT, false)); render(); fireEvent.click(screen.getByTestId(TRIGGER_TEST_ID)); fireEvent.click(await screen.findByRole(BUTTON_ROLE, { name: DRIVE_E_ROOT })); await screen.findByRole(BUTTON_ROLE, { name: "Kandev" }); expect(screen.getByRole(BUTTON_ROLE, { name: VIRTUAL_ROOT })).toBeTruthy(); expect(screen.getByRole(BUTTON_ROLE, { name: DRIVE_E_ROOT })).toBeTruthy(); expect(screen.getByRole(BUTTON_ROLE, { name: "Projects" })).toBeTruthy(); fireEvent.click(screen.getByRole(BUTTON_ROLE, { name: VIRTUAL_ROOT })); expect(mockedListDirectory).toHaveBeenLastCalledWith(VIRTUAL_ROOT); }); it("clears a stale selectable listing when navigation fails", async () => { mockedListDirectory .mockResolvedValueOnce(listing("C:\\", true, [{ name: "Denied", path: "C:\\Denied" }])) .mockRejectedValueOnce(new Error("failed to list directory")); render(); fireEvent.click(screen.getByTestId(TRIGGER_TEST_ID)); fireEvent.click(await screen.findByRole(BUTTON_ROLE, { name: "Denied" })); await screen.findByTestId("folder-picker-error"); await waitFor(() => expect(screen.getByTestId("folder-picker-choose").hasAttribute("disabled")).toBe(true), ); expect(screen.queryByRole(BUTTON_ROLE, { name: "C:\\" })).toBeNull(); }); it("ignores an old success after a value change starts a successor load", async () => { const oldLoad = deferred(); const successorLoad = deferred(); mockedListDirectory .mockReturnValueOnce(oldLoad.promise) .mockReturnValueOnce(successorLoad.promise); const { rerender } = render(); fireEvent.click(screen.getByTestId(TRIGGER_TEST_ID)); await waitFor(() => expect(mockedListDirectory).toHaveBeenCalledWith("")); rerender(); await waitFor(() => expect(mockedListDirectory).toHaveBeenCalledWith(SUCCESS_PATH)); await act(async () => successorLoad.resolve(listing(SUCCESS_PATH, true))); await waitFor(() => expect(screen.getAllByRole(BUTTON_ROLE, { name: SUCCESS_NAME })).toHaveLength(2), ); await act(async () => oldLoad.resolve(listing("C:\\Stale", true))); expect(screen.queryByRole(BUTTON_ROLE, { name: "Stale" })).toBeNull(); expect(screen.getAllByRole(BUTTON_ROLE, { name: SUCCESS_NAME })).toHaveLength(2); }); it("ignores an old error after close and reopen completes a successor load", async () => { const oldLoad = deferred(); const successorLoad = deferred(); mockedListDirectory .mockReturnValueOnce(oldLoad.promise) .mockReturnValueOnce(successorLoad.promise); render(); fireEvent.click(screen.getByTestId(TRIGGER_TEST_ID)); await waitFor(() => expect(mockedListDirectory).toHaveBeenCalledTimes(1)); act(() => setPopoverOpen?.(false)); act(() => setPopoverOpen?.(true)); await waitFor(() => expect(mockedListDirectory).toHaveBeenCalledTimes(2)); await act(async () => successorLoad.resolve(listing(SUCCESS_PATH, true))); await screen.findByRole(BUTTON_ROLE, { name: SUCCESS_NAME }); await act(async () => oldLoad.reject(new Error("stale failure"))); expect(screen.queryByTestId("folder-picker-error")).toBeNull(); expect(screen.getByRole(BUTTON_ROLE, { name: SUCCESS_NAME })).toBeTruthy(); expect(screen.getByTestId("folder-picker-choose").hasAttribute("disabled")).toBe(false); }); }); function listing( path: string, choosable: boolean, entries: DirectoryListing["entries"] = [], ): DirectoryListing { return { path, parent: "", entries, choosable }; } function deferred() { let resolve!: (value: T) => void; let reject!: (reason?: unknown) => void; const promise = new Promise((resolvePromise, rejectPromise) => { resolve = resolvePromise; reject = rejectPromise; }); return { promise, resolve, reject }; }