test(resilience): cover broken plugin startup and onboarding

This commit is contained in:
Vincent Koc
2026-04-14 19:19:55 +01:00
parent 58a9905976
commit 95cdaf957b
3 changed files with 224 additions and 0 deletions

View File

@@ -3437,6 +3437,105 @@ module.exports = {
expect(diagnostic!.message).toContain("failed to load setup entry");
});
it("keeps healthy sibling channel plugins loadable when a setup entry throws", () => {
useNoBundledPlugins();
const brokenDir = makeTempDir();
fs.writeFileSync(
path.join(brokenDir, "package.json"),
JSON.stringify(
{
name: "@openclaw/setup-entry-throws-sibling-test",
openclaw: {
extensions: ["./index.cjs"],
setupEntry: "./setup-entry.cjs",
},
},
null,
2,
),
"utf-8",
);
fs.writeFileSync(
path.join(brokenDir, "openclaw.plugin.json"),
JSON.stringify(
{
id: "setup-entry-throws-sibling-test",
configSchema: EMPTY_PLUGIN_SCHEMA,
channels: ["broken-chat"],
},
null,
2,
),
"utf-8",
);
fs.writeFileSync(
path.join(brokenDir, "index.cjs"),
`module.exports = { id: "setup-entry-throws-sibling-test", register() {} };`,
"utf-8",
);
fs.writeFileSync(
path.join(brokenDir, "setup-entry.cjs"),
`module.exports = {
kind: "bundled-channel-setup-entry",
loadSetupPlugin: () => { throw new Error("boom: setup plugin missing"); },
};`,
"utf-8",
);
const healthy = writePlugin({
id: "healthy-channel",
filename: "healthy-channel.cjs",
body: `module.exports = { id: "healthy-channel", register(api) {
api.registerChannel({
plugin: {
id: "healthy-chat",
meta: {
id: "healthy-chat",
label: "Healthy Chat",
selectionLabel: "Healthy Chat",
docsPath: "/channels/healthy-chat",
blurb: "healthy sibling channel",
},
capabilities: { chatTypes: ["direct"] },
config: {
listAccountIds: () => [],
resolveAccount: () => ({ accountId: "default" }),
},
outbound: { deliveryMode: "direct" },
}
});
} };`,
});
const registry = loadOpenClawPlugins({
cache: false,
config: {
plugins: {
enabled: true,
load: { paths: [brokenDir, healthy.file] },
allow: ["setup-entry-throws-sibling-test", "healthy-channel"],
},
},
});
expect(
registry.channels.find((entry) => entry.plugin.id === "healthy-chat")?.plugin.meta,
).toMatchObject({
label: "Healthy Chat",
docsPath: "/channels/healthy-chat",
});
expect(registry.plugins.find((entry) => entry.id === "healthy-channel")?.status).toBe("loaded");
expect(
registry.diagnostics.some(
(diag) =>
diag.pluginId === "setup-entry-throws-sibling-test" &&
diag.level === "error" &&
diag.message.includes("failed to load setup entry"),
),
).toBe(true);
});
it("prefers setupEntry for configured channel loads during startup when opted in", () => {
expect(
__testing.shouldLoadChannelPluginInSetupRuntime({