import * as React from "react";
import { afterEach, describe, expect, it, vi } from "vitest";
import {
resolveContentEditorPanels,
type ContentEditorPanelContext,
} from "../../src/lib/content-editor-panels";
import type { PluginAdmins } from "../../src/lib/plugin-context";
function Panel(_props: ContentEditorPanelContext) {
return
Panel
;
}
afterEach(() => {
vi.restoreAllMocks();
});
describe("resolveContentEditorPanels", () => {
it("selects enabled panels by collection and role", () => {
const pluginAdmins: PluginAdmins = {
insights: {
contentEditorPanels: [
{ id: "summary", title: "Summary", component: Panel, collections: ["posts"] },
{ id: "pages", title: "Pages", component: Panel, collections: ["pages"] },
{ id: "admin", title: "Admin", component: Panel, minRole: 50 },
],
},
};
expect(
resolveContentEditorPanels(pluginAdmins, "posts", 40, {
insights: { enabled: true },
}),
).toEqual([
expect.objectContaining({
pluginId: "insights",
extension: expect.objectContaining({ id: "summary" }),
}),
]);
});
it("ignores disabled and stale registry modules", () => {
const pluginAdmins: PluginAdmins = {
enabled: {
contentEditorPanels: [{ id: "kept", title: "Kept", component: Panel }],
},
disabled: {
contentEditorPanels: [{ id: "disabled", title: "Disabled", component: Panel }],
},
stale: {
contentEditorPanels: [{ id: "stale", title: "Stale", component: Panel }],
},
};
expect(
resolveContentEditorPanels(pluginAdmins, "posts", 50, {
enabled: { enabled: true },
disabled: { enabled: false },
}),
).toEqual([
expect.objectContaining({
pluginId: "enabled",
extension: expect.objectContaining({ id: "kept" }),
}),
]);
});
it("orders panels deterministically and ignores duplicate ids per plugin", () => {
const warningSpy = vi.spyOn(console, "warn").mockImplementation(() => undefined);
const pluginAdmins: PluginAdmins = {
zeta: {
contentEditorPanels: [{ id: "later", title: "Later", component: Panel, order: 5 }],
},
alpha: {
contentEditorPanels: [
{ id: "first", title: "First", component: Panel, order: -1 },
{ id: "first", title: "Duplicate", component: Panel, order: -2 },
],
},
};
expect(resolveContentEditorPanels(pluginAdmins, "posts", 50)).toMatchObject([
{ pluginId: "alpha", extension: { id: "first" } },
{ pluginId: "zeta", extension: { id: "later" } },
]);
expect(warningSpy).toHaveBeenCalledOnce();
});
it("contains collection predicate failures", () => {
const errorSpy = vi.spyOn(console, "error").mockImplementation(() => undefined);
const pluginAdmins: PluginAdmins = {
broken: {
contentEditorPanels: [
{
id: "broken",
title: "Broken",
component: Panel,
collections: () => {
throw new Error("predicate failed");
},
},
],
},
};
expect(resolveContentEditorPanels(pluginAdmins, "posts", 50)).toEqual([]);
expect(errorSpy).toHaveBeenCalledOnce();
});
it("ignores malformed panel exports without throwing", () => {
const warningSpy = vi.spyOn(console, "warn").mockImplementation(() => undefined);
const pluginAdmins = {
broken: {
contentEditorPanels: [
{ id: "", title: "Missing id", component: Panel },
{ id: "title", title: "", component: Panel },
{ id: "component", title: "Component" },
{ id: "order", title: "Order", component: Panel, order: Number.NaN },
],
},
} as unknown as PluginAdmins;
expect(resolveContentEditorPanels(pluginAdmins, "posts", 50)).toEqual([]);
expect(warningSpy).toHaveBeenCalledTimes(4);
});
});