// @vitest-environment jsdom import { act, cleanup, renderHook } from "@testing-library/react"; import { Bot } from "lucide-react-native"; import { SvgXml } from "react-native-svg"; import { afterEach, describe, expect, it } from "vitest"; import { replaceProviderSnapshotIcons } from "@/data/provider-icons"; import { useProviderIcon, useProviderIcons, type ProviderIconComponent } from "./provider-icons"; afterEach(cleanup); function renderIcon(Component: ProviderIconComponent) { if (typeof Component !== "function") throw new Error("Expected a function component"); return (Component as (props: { size: number; color: string }) => unknown)({ size: 18, color: "#123456", }); } describe("useProviderIcon", () => { it("renders registered snapshot SVG metadata with the requested size and color", () => { const svg = ''; replaceProviderSnapshotIcons("server-1", [{ provider: "rendered-provider", iconSvg: svg }]); const rendered = renderIcon( renderHook(() => useProviderIcon("rendered-provider", "server-1")).result.current, ); expect(rendered).toMatchObject({ type: SvgXml, props: { xml: svg, width: 18, height: 18, color: "#123456" }, }); }); it("uses the normal Bot fallback without snapshot SVG metadata", () => { replaceProviderSnapshotIcons("server-1", [{ provider: "plain-provider" }]); expect(renderHook(() => useProviderIcon("plain-provider", "server-1")).result.current).toBe( Bot, ); }); }); it("updates a mounted consumer when the plugin snapshot arrives after mount", () => { const serverId = "cold-reload-host"; const provider = "plugin-provider"; const svg = ''; replaceProviderSnapshotIcons(serverId, []); const { result, unmount } = renderHook(() => useProviderIcon(provider, serverId)); expect(result.current).toBe(Bot); act(() => replaceProviderSnapshotIcons(serverId, [{ provider, iconSvg: svg }])); expect(renderIcon(result.current)).toMatchObject({ type: SvgXml, props: { xml: svg, width: 18, height: 18, color: "#123456" }, }); unmount(); }); it("keeps host SVGs isolated, updates replacements, and clears removed icons", () => { const provider = "shared-plugin-provider"; const firstSvg = ''; const secondSvg = ''; replaceProviderSnapshotIcons("first-host", [{ provider, iconSvg: firstSvg }]); replaceProviderSnapshotIcons("second-host", [{ provider, iconSvg: secondSvg }]); const first = renderHook(() => useProviderIcon(provider, "first-host")); const second = renderHook(() => useProviderIcon(provider, "second-host")); const firstIcon = first.result.current; expect(renderIcon(firstIcon)).toMatchObject({ props: { xml: firstSvg } }); expect(renderIcon(second.result.current)).toMatchObject({ props: { xml: secondSvg } }); act(() => replaceProviderSnapshotIcons("second-host", [{ provider, iconSvg: firstSvg }])); expect(renderIcon(second.result.current)).toMatchObject({ props: { xml: firstSvg } }); expect(first.result.current).toBe(firstIcon); act(() => replaceProviderSnapshotIcons("second-host", [])); expect(second.result.current).toBe(Bot); expect(first.result.current).toBe(firstIcon); }); it("updates collection consumers when their host snapshot arrives", () => { const serverId = "collection-host"; const provider = "collection-plugin-provider"; const svg = ''; replaceProviderSnapshotIcons(serverId, []); const { result } = renderHook(() => useProviderIcons(serverId)); expect(result.current(provider)).toBe(Bot); act(() => replaceProviderSnapshotIcons(serverId, [{ provider, iconSvg: svg }])); expect(renderIcon(result.current(provider))).toMatchObject({ props: { xml: svg } }); });