mirror of https://github.com/openclaw/openclaw.git
218 lines
6.4 KiB
TypeScript
218 lines
6.4 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
collectChangedExtensionIdsFromPaths,
|
|
collectPublishablePluginPackageErrors,
|
|
parsePluginReleaseArgs,
|
|
parsePluginReleaseSelection,
|
|
parsePluginReleaseSelectionMode,
|
|
resolveChangedPublishablePluginPackages,
|
|
resolveSelectedPublishablePluginPackages,
|
|
type PublishablePluginPackage,
|
|
} from "../scripts/lib/plugin-npm-release.ts";
|
|
|
|
describe("parsePluginReleaseSelection", () => {
|
|
it("returns an empty list for blank input", () => {
|
|
expect(parsePluginReleaseSelection("")).toEqual([]);
|
|
expect(parsePluginReleaseSelection(" ")).toEqual([]);
|
|
expect(parsePluginReleaseSelection(undefined)).toEqual([]);
|
|
});
|
|
|
|
it("dedupes and sorts comma or whitespace separated package names", () => {
|
|
expect(
|
|
parsePluginReleaseSelection(" @openclaw/zalo, @openclaw/feishu @openclaw/zalo "),
|
|
).toEqual(["@openclaw/feishu", "@openclaw/zalo"]);
|
|
});
|
|
});
|
|
|
|
describe("parsePluginReleaseSelectionMode", () => {
|
|
it("accepts the supported explicit selection modes", () => {
|
|
expect(parsePluginReleaseSelectionMode("selected")).toBe("selected");
|
|
expect(parsePluginReleaseSelectionMode("all-publishable")).toBe("all-publishable");
|
|
});
|
|
|
|
it("rejects unsupported selection modes", () => {
|
|
expect(() => parsePluginReleaseSelectionMode("all")).toThrowError(
|
|
'Unknown selection mode: all. Expected "selected" or "all-publishable".',
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("parsePluginReleaseArgs", () => {
|
|
it("rejects blank explicit plugin selections", () => {
|
|
expect(() => parsePluginReleaseArgs(["--plugins", " "])).toThrowError(
|
|
"`--plugins` must include at least one package name.",
|
|
);
|
|
});
|
|
|
|
it("requires plugin names for selected explicit publish mode", () => {
|
|
expect(() => parsePluginReleaseArgs(["--selection-mode", "selected"])).toThrowError(
|
|
"`--selection-mode selected` requires `--plugins`.",
|
|
);
|
|
});
|
|
|
|
it("rejects plugin names when all-publishable mode is selected", () => {
|
|
expect(() =>
|
|
parsePluginReleaseArgs([
|
|
"--selection-mode",
|
|
"all-publishable",
|
|
"--plugins",
|
|
"@openclaw/zalo",
|
|
]),
|
|
).toThrowError("`--selection-mode all-publishable` must not be combined with `--plugins`.");
|
|
});
|
|
|
|
it("parses explicit all-publishable mode", () => {
|
|
expect(parsePluginReleaseArgs(["--selection-mode", "all-publishable"])).toMatchObject({
|
|
selectionMode: "all-publishable",
|
|
selection: [],
|
|
pluginsFlagProvided: false,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("collectPublishablePluginPackageErrors", () => {
|
|
it("accepts a valid publishable plugin package candidate", () => {
|
|
expect(
|
|
collectPublishablePluginPackageErrors({
|
|
extensionId: "zalo",
|
|
packageDir: "extensions/zalo",
|
|
packageJson: {
|
|
name: "@openclaw/zalo",
|
|
version: "2026.3.15",
|
|
openclaw: {
|
|
extensions: ["./index.ts"],
|
|
release: {
|
|
publishToNpm: true,
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
).toEqual([]);
|
|
});
|
|
|
|
it("flags invalid publishable plugin metadata", () => {
|
|
expect(
|
|
collectPublishablePluginPackageErrors({
|
|
extensionId: "broken",
|
|
packageDir: "extensions/broken",
|
|
packageJson: {
|
|
name: "broken",
|
|
version: "latest",
|
|
private: true,
|
|
openclaw: {
|
|
extensions: [""],
|
|
release: {
|
|
publishToNpm: true,
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
).toEqual([
|
|
'package name must start with "@openclaw/"; found "broken".',
|
|
"package.json private must not be true.",
|
|
'package.json version must match YYYY.M.D or YYYY.M.D-beta.N; found "latest".',
|
|
"openclaw.extensions must contain only non-empty strings.",
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("resolveSelectedPublishablePluginPackages", () => {
|
|
const publishablePlugins: PublishablePluginPackage[] = [
|
|
{
|
|
extensionId: "feishu",
|
|
packageDir: "extensions/feishu",
|
|
packageName: "@openclaw/feishu",
|
|
version: "2026.3.15",
|
|
channel: "stable",
|
|
publishTag: "latest",
|
|
},
|
|
{
|
|
extensionId: "zalo",
|
|
packageDir: "extensions/zalo",
|
|
packageName: "@openclaw/zalo",
|
|
version: "2026.3.15-beta.1",
|
|
channel: "beta",
|
|
publishTag: "beta",
|
|
},
|
|
];
|
|
|
|
it("returns all publishable plugins when no selection is provided", () => {
|
|
expect(
|
|
resolveSelectedPublishablePluginPackages({
|
|
plugins: publishablePlugins,
|
|
selection: [],
|
|
}),
|
|
).toEqual(publishablePlugins);
|
|
});
|
|
|
|
it("filters by selected publishable package names", () => {
|
|
expect(
|
|
resolveSelectedPublishablePluginPackages({
|
|
plugins: publishablePlugins,
|
|
selection: ["@openclaw/zalo"],
|
|
}),
|
|
).toEqual([publishablePlugins[1]]);
|
|
});
|
|
|
|
it("throws when the selection contains an unknown package name", () => {
|
|
expect(() =>
|
|
resolveSelectedPublishablePluginPackages({
|
|
plugins: publishablePlugins,
|
|
selection: ["@openclaw/missing"],
|
|
}),
|
|
).toThrowError("Unknown or non-publishable plugin package selection: @openclaw/missing.");
|
|
});
|
|
});
|
|
|
|
describe("collectChangedExtensionIdsFromPaths", () => {
|
|
it("extracts unique extension ids from changed extension paths", () => {
|
|
expect(
|
|
collectChangedExtensionIdsFromPaths([
|
|
"extensions/zalo/index.ts",
|
|
"extensions/zalo/package.json",
|
|
"extensions/feishu/src/client.ts",
|
|
"docs/reference/RELEASING.md",
|
|
]),
|
|
).toEqual(["feishu", "zalo"]);
|
|
});
|
|
});
|
|
|
|
describe("resolveChangedPublishablePluginPackages", () => {
|
|
const publishablePlugins: PublishablePluginPackage[] = [
|
|
{
|
|
extensionId: "feishu",
|
|
packageDir: "extensions/feishu",
|
|
packageName: "@openclaw/feishu",
|
|
version: "2026.3.15",
|
|
channel: "stable",
|
|
publishTag: "latest",
|
|
},
|
|
{
|
|
extensionId: "zalo",
|
|
packageDir: "extensions/zalo",
|
|
packageName: "@openclaw/zalo",
|
|
version: "2026.3.15-beta.1",
|
|
channel: "beta",
|
|
publishTag: "beta",
|
|
},
|
|
];
|
|
|
|
it("returns only changed publishable plugins", () => {
|
|
expect(
|
|
resolveChangedPublishablePluginPackages({
|
|
plugins: publishablePlugins,
|
|
changedExtensionIds: ["zalo"],
|
|
}),
|
|
).toEqual([publishablePlugins[1]]);
|
|
});
|
|
|
|
it("returns an empty list when no publishable plugins changed", () => {
|
|
expect(
|
|
resolveChangedPublishablePluginPackages({
|
|
plugins: publishablePlugins,
|
|
changedExtensionIds: [],
|
|
}),
|
|
).toEqual([]);
|
|
});
|
|
});
|