// @vitest-environment jsdom
import { act } from "react";
import { createRoot } from "react-dom/client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { PluginSettings } from "./PluginSettings";
const mockPluginsApi = vi.hoisted(() => ({
get: vi.fn(),
health: vi.fn(),
dashboard: vi.fn(),
logs: vi.fn(),
getConfig: vi.fn(),
}));
const mockSetBreadcrumbs = vi.hoisted(() => vi.fn());
vi.mock("@/api/plugins", () => ({
pluginsApi: mockPluginsApi,
}));
vi.mock("@/context/BreadcrumbContext", () => ({
useBreadcrumbs: () => ({
setBreadcrumbs: mockSetBreadcrumbs,
}),
}));
vi.mock("@/context/CompanyContext", () => ({
useCompany: () => ({
selectedCompany: { id: "company-1", name: "Paperclip", issuePrefix: "PAP" },
selectedCompanyId: "company-1",
}),
}));
vi.mock("@/lib/router", () => ({
Link: ({ to, children }: { to: string; children: React.ReactNode }) => {children},
Navigate: () => null,
useParams: () => ({ companyPrefix: "PAP", pluginId: "plugin-1" }),
}));
vi.mock("@/plugins/slots", () => ({
PluginSlotMount: () => null,
usePluginSlots: () => ({ slots: [] }),
}));
vi.mock("@/components/PageTabBar", () => ({
PageTabBar: () => null,
}));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(globalThis as any).IS_REACT_ACT_ENVIRONMENT = true;
async function flushReact() {
await act(async () => {
await Promise.resolve();
await new Promise((resolve) => window.setTimeout(resolve, 0));
});
}
describe("PluginSettings", () => {
let container: HTMLDivElement;
beforeEach(() => {
container = document.createElement("div");
document.body.appendChild(container);
mockPluginsApi.get.mockResolvedValue({
id: "plugin-1",
pluginKey: "paperclip.e2b-sandbox-provider",
packageName: "@paperclipai/plugin-e2b",
version: "0.1.0",
status: "error",
categories: ["automation"],
manifestJson: {
displayName: "E2B Sandbox Provider",
version: "0.1.0",
description: "E2B environments for Paperclip.",
author: "Paperclip",
capabilities: ["environment.drivers.register"],
environmentDrivers: [
{
driverKey: "e2b",
kind: "sandbox_provider",
displayName: "E2B Cloud Sandbox",
},
],
},
lastError: null,
});
mockPluginsApi.dashboard.mockResolvedValue(null);
});
afterEach(() => {
container.remove();
document.body.innerHTML = "";
vi.clearAllMocks();
});
it("routes environment-provider plugins to company environments when they have no instance config", async () => {
const root = createRoot(container);
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
});
await act(async () => {
root.render(
,
);
});
await flushReact();
await flushReact();
expect(container.textContent).toContain("Configure this plugin from Company Environments.");
expect(container.textContent).toContain("company-scoped instead of instance-global");
const link = container.querySelector('a[href="/company/settings/environments"]');
expect(link?.textContent).toContain("Open Company Environments");
await act(async () => {
root.unmount();
});
});
});