import { describe, it, expect, vi, beforeEach } from "vitest"; import { fireEvent, render, screen } from "@testing-library/react"; import { useAppState } from "../../store/appState"; import type { AppSettings, CatalogItem, MarketplaceSnapshot } from "../../lib/types"; import type { MarketplaceApi } from "../../hooks/useMarketplace"; vi.mock("./InstallControls", () => ({ default: ({ headCommit }: { headCommit: string | null }) =>
install controls at {headCommit}
, })); vi.mock("./AddMarketplaceModal", () => ({ default: () =>
add modal
})); import BrowsePane from "./BrowsePane"; const it_ = (kind: CatalogItem["kind"], key: string, patch: Partial = {}): CatalogItem => ({ kind, key, name: key, description: `${key} description`, path: key, invalid: null, hook_commands: [], preview: `${key} preview body`, ...patch, }); const snapshot: MarketplaceSnapshot = { marketplace_id: "m1", head_commit: "a".repeat(40), fetched_at: "2026-09-27T12:00:00Z", fetch_error: "network unreachable", items: [it_("agent", "code-reviewer"), it_("hook", "notify-on-stop"), it_("skill", "broken", { invalid: "SKILL.md missing" })], }; function api(patch: Partial = {}): MarketplaceApi { return { snapshots: [snapshot], updates: [], loading: false, refreshing: [], load: vi.fn(), refresh: vi.fn(), reloadState: vi.fn(), install: vi.fn(), uninstall: vi.fn(), setDisabled: vi.fn(), update: vi.fn(), forget: vi.fn(), remove: vi.fn(async () => true), ...patch, }; } describe("BrowsePane", () => { beforeEach(() => { useAppState.setState({ appSettings: { marketplaces: [{ id: "m1", name: "Starter", url: "https://github.com/s/m.git", branch: null, account_id: null }], marketplace_accounts: [], global_marketplace_installs: [], } as unknown as AppSettings, projects: [], marketplaceFilterProjectId: null, }); }); it("lists items, filters by kind and search, and shows detail", () => { render(); expect(screen.getByText("network unreachable")).toBeInTheDocument(); expect(screen.getByRole("button", { name: /code-reviewer/ })).toBeInTheDocument(); expect(screen.getByRole("button", { name: /notify-on-stop/ })).toBeInTheDocument(); fireEvent.click(screen.getByRole("radio", { name: "Hooks" })); expect(screen.queryByRole("button", { name: /code-reviewer/ })).not.toBeInTheDocument(); fireEvent.click(screen.getByRole("radio", { name: "All" })); fireEvent.change(screen.getByLabelText("Search items"), { target: { value: "review" } }); expect(screen.queryByRole("button", { name: /notify-on-stop/ })).not.toBeInTheDocument(); fireEvent.click(screen.getByRole("button", { name: /code-reviewer/ })); expect(screen.getByText("code-reviewer preview body")).toBeInTheDocument(); expect(screen.getByText(`install controls at ${"a".repeat(40)}`)).toBeInTheDocument(); }); it("I2: installs pin the head the shown item was read at, not a later one", () => { const mp = api(); const { rerender } = render(); fireEvent.click(screen.getByRole("button", { name: /code-reviewer/ })); rerender(); expect(screen.getByText(`install controls at ${"a".repeat(40)}`)).toBeInTheDocument(); }); it("shows why an item is invalid", () => { render(); fireEvent.click(screen.getByRole("button", { name: /broken/ })); expect(screen.getByText("SKILL.md missing")).toBeInTheDocument(); }); it("refreshes one marketplace", () => { const mp = api(); render(); fireEvent.click(screen.getByRole("button", { name: "Refresh Starter" })); expect(mp.refresh).toHaveBeenCalledWith("m1"); }); it("offers Add when there are no marketplaces", () => { useAppState.setState({ appSettings: { marketplaces: [], marketplace_accounts: [], global_marketplace_installs: [] } as unknown as AppSettings, }); render(); fireEvent.click(screen.getByRole("button", { name: "Add marketplace" })); expect(screen.getByText("add modal")).toBeInTheDocument(); }); it("confirms before removing a marketplace (F6)", () => { const mp = api(); render(); fireEvent.click(screen.getByRole("button", { name: "Remove Starter" })); expect(screen.getByText(/Source removed/)).toBeInTheDocument(); expect(screen.getByText(/Forget/)).toBeInTheDocument(); expect(mp.remove).not.toHaveBeenCalled(); fireEvent.click(screen.getByRole("button", { name: "Remove marketplace" })); expect(mp.remove).toHaveBeenCalledWith("m1"); }); });