import { EnvironmentId } from "@t3tools/contracts"; import type { ReactElement } from "react"; import { beforeEach, describe, expect, it, vi } from "vite-plus/test"; import { visitElements } from "../../test/reactElementTree"; import { reactHookHarness as hooks } from "../../test/reactHookHarness"; vi.mock("react", async (importOriginal) => { const actual = await importOriginal(); const { reactHookHarness } = await import("../../test/reactHookHarness"); return { ...actual, useMemo: reactHookHarness.useMemo, useState: reactHookHarness.useState, }; }); vi.mock("react/compiler-runtime", async () => { const { reactHookHarness } = await import("../../test/reactHookHarness"); return { c: reactHookHarness.useMemoCache }; }); vi.mock("@effect/atom-react", () => ({ useAtomValue: () => ({}), })); vi.mock("~/state/server", () => ({ primaryServerKeybindingsAtom: Symbol("keybindings"), })); vi.mock("~/hooks/useTheme", () => ({ useTheme: () => ({ resolvedTheme: "dark" }), })); vi.mock("../files/projectFilesQueryState", () => ({ useProjectFilePickerQuery: () => ({ entries: [], error: null, isPending: false, matchedQuery: "", }), })); vi.mock("../ui/toast", () => ({ toastManager: { add: vi.fn() }, })); import { toastManager } from "../ui/toast"; import { canPickExternalProjectFavicon, ProjectFaviconPickerDialog, } from "./ProjectFaviconPickerDialog"; describe("ProjectFaviconPickerDialog", () => { beforeEach(() => { hooks.reset(); vi.stubGlobal("navigator", { platform: "MacIntel" }); }); it("selects an image from the native file picker", async () => { const onOpenChange = vi.fn(); const onPickExternal = vi.fn().mockResolvedValue("/Users/me/Pictures/icon.png"); const onSelect = vi.fn(); hooks.beginRender(); const picker = ProjectFaviconPickerDialog({ cwd: "/Users/me/project", environmentId: EnvironmentId.make("local"), onOpenChange, onPickExternal, onSelect, open: true, projectName: "Project", } as Parameters[0] & { readonly onPickExternal: () => Promise; }) as ReactElement>; const button = visitElements(picker, (element) => element.props.children === "Open in Finder"); expect(button).not.toBeNull(); (button?.props.onClick as (() => void) | undefined)?.(); await Promise.resolve(); await Promise.resolve(); expect(onPickExternal).toHaveBeenCalledTimes(1); expect(onOpenChange).toHaveBeenCalledWith(false); expect(onSelect).toHaveBeenCalledWith("/Users/me/Pictures/icon.png"); }); it("hides the native picker for WSL project paths", () => { expect(canPickExternalProjectFavicon("/home/me/project", "Win32")).toBe(false); expect(canPickExternalProjectFavicon("C:\\Users\\me\\project", "Win32")).toBe(true); }); it("keeps the dialog open when the native picker fails", async () => { const onOpenChange = vi.fn(); const onSelect = vi.fn(); const props = { cwd: "/Users/me/project", environmentId: EnvironmentId.make("local"), onOpenChange, onPickExternal: vi.fn().mockRejectedValue(new Error("picker failed")), onSelect, open: true, projectName: "Project", } as Parameters[0] & { readonly onPickExternal: () => Promise; }; hooks.beginRender(); const picker = ProjectFaviconPickerDialog(props) as ReactElement>; const button = visitElements(picker, (element) => element.props.children === "Open in Finder"); (button?.props.onClick as (() => void) | undefined)?.(); await Promise.resolve(); await Promise.resolve(); expect(onOpenChange).not.toHaveBeenCalled(); expect(onSelect).not.toHaveBeenCalled(); expect(toastManager.add).toHaveBeenCalledWith({ type: "error", title: "Could not open image picker", description: "picker failed", }); }); });