describe("compareReleaseVersions", () => {
it("treats stable as newer than same-day beta", () => {
expect(compareReleaseVersions("2026.3.29", "2026.3.29-beta.2")).toBe(1);
});
it("treats a newer beta day as newer than an older stable day", () => {
expect(compareReleaseVersions("2026.4.1-beta.1", "2026.3.29")).toBe(1);
});
it("orders stable correction releases after the base stable release", () => {
expect(compareReleaseVersions("2026.3.29-2", "2026.3.29")).toBe(1);
});
it("returns null when either version is not release-shaped", () => {
expect(compareReleaseVersions("latest", "2026.3.29")).toBeNull();
});
});
describe("utcCalendarDayDistance", () => {
it("compares UTC calendar days rather than wall-clock hours", () => { const left = new Date("2026-03-09T23:59:59Z"); const right = new Date("2026-03-11T00:00:01Z");
expect(utcCalendarDayDistance(left, right)).toBe(2);
});
});
describe("resolveNpmCommandInvocation", () => {
it("uses npm_execpath when it points to npm", () => {
expect(
resolveNpmCommandInvocation({
npmExecPath: "/usr/local/lib/node_modules/npm/bin/npm-cli.js",
nodeExecPath: "/usr/local/bin/node",
platform: "linux",
}),
).toEqual({
command: "/usr/local/bin/node",
args: ["/usr/local/lib/node_modules/npm/bin/npm-cli.js"],
});
});
it("falls back to the npm command when npm_execpath points to pnpm", () => {
expect(
resolveNpmCommandInvocation({
npmExecPath: "/home/test/.cache/node/corepack/v1/pnpm/10.23.0/bin/pnpm.cjs",
nodeExecPath: "/usr/local/bin/node",
platform: "linux",
}),
).toEqual({
command: "npm",
args: [],
});
});
it("uses the platform npm command when npm_execpath is missing", () => {
expect(resolveNpmCommandInvocation({ platform: "win32" })).toEqual({
command: "npm.cmd",
args: [],
});
});
});
it("returns null when no JSON payload is present", () => {
expect(parseNpmPackJsonOutput("> openclaw@2026.3.23 prepack")).toBeNull();
});
});
describe("collectControlUiPackErrors", () => {
it("rejects packs that ship the dashboard HTML without the asset payload", () => {
expect(collectControlUiPackErrors(["dist/control-ui/index.html"])).toEqual([
...REQUIRED_PACKED_PATHS.map(
(requiredPath) =>
`npm package is missing required path "${requiredPath}". Ensure UI assets are built and included before publish.`,
), 'npm package is missing Control UI asset payload under "dist/control-ui/assets/". Refuse release when the dashboard tarball would be empty.',
]);
});
it("accepts packs that ship dashboard HTML and bundled assets", () => {
expect(
collectControlUiPackErrors([ "dist/control-ui/index.html",
...REQUIRED_PACKED_PATHS, "dist/control-ui/assets/index-Bu8rSoJV.js", "dist/control-ui/assets/index-BK0yXA_h.css",
]),
).toEqual([]);
});
});
describe("collectForbiddenPackedPathErrors", () => {
it("rejects generated docs artifacts in npm pack output", () => {
expect(
collectForbiddenPackedPathErrors([ "dist/index.js", "docs/.generated/config-baseline.json", "docs/.generated/config-baseline.plugin.json",
]),
).toEqual([ 'npm package must not include generated docs artifact "docs/.generated/config-baseline.json".', 'npm package must not include generated docs artifact "docs/.generated/config-baseline.plugin.json".',
]);
});
it("rejects private qa artifacts in npm pack output", () => {
expect(
collectForbiddenPackedPathErrors([ "dist/extensions/qa-channel/runtime-api.js", "dist/extensions/qa-channel/package.json", "dist/extensions/qa-lab/runtime-api.js", "dist/extensions/qa-lab/src/cli.js", "dist/plugin-sdk/extensions/qa-lab/cli.d.ts", "dist/qa-runtime-B9LDtssJ.js", "qa/scenarios/index.md",
]),
).toEqual([ 'npm package must not include private QA channel artifact "dist/extensions/qa-channel/package.json".', 'npm package must not include private QA channel artifact "dist/extensions/qa-channel/runtime-api.js".', 'npm package must not include private QA lab artifact "dist/extensions/qa-lab/runtime-api.js".', 'npm package must not include private QA lab artifact "dist/extensions/qa-lab/src/cli.js".', 'npm package must not include private QA lab type artifact "dist/plugin-sdk/extensions/qa-lab/cli.d.ts".', 'npm package must not include private QA runtime chunk "dist/qa-runtime-B9LDtssJ.js".', 'npm package must not include private QA suite artifact "qa/scenarios/index.md".',
]);
});
it("rejects legacy update verifier QA runtime sidecars", () => {
expect(
collectForbiddenPackedPathErrors([ "dist/extensions/qa-channel/runtime-api.js", "dist/extensions/qa-lab/runtime-api.js",
]),
).toEqual([ 'npm package must not include private QA channel artifact "dist/extensions/qa-channel/runtime-api.js".', 'npm package must not include private QA lab artifact "dist/extensions/qa-lab/runtime-api.js".',
]);
});
it("rejects root dist chunks that still reference the private qa lab", () => { const rootDir = mkdtempSync(join(tmpdir(), "openclaw-pack-private-qa-"));
describe("collectPackedTestCargoErrors", () => {
it("rejects packed test files and test directories", () => {
expect(
collectPackedTestCargoErrors([ "dist/extensions/webhooks/node_modules/zod/src/v3/tests/all-errors.test.ts", "dist/extensions/whatsapp/node_modules/pino/test/basic.test.js", "dist/extensions/whatsapp/node_modules/@jimp/plugin-crop/src/__snapshots__/crop.test.ts.snap", "dist/index.js",
]),
).toEqual([ 'npm package must not include test cargo "dist/extensions/webhooks/node_modules/zod/src/v3/tests/all-errors.test.ts".', 'npm package must not include test cargo "dist/extensions/whatsapp/node_modules/@jimp/plugin-crop/src/__snapshots__/crop.test.ts.snap".', 'npm package must not include test cargo "dist/extensions/whatsapp/node_modules/pino/test/basic.test.js".',
]);
});
it("allows legitimate package roots named test under node_modules", () => {
expect(
collectPackedTestCargoErrors([ "dist/extensions/fixture-plugin/node_modules/direct/node_modules/test/index.js", "dist/extensions/fixture-plugin/node_modules/direct/node_modules/@scope/tests/index.js",
]),
).toEqual([]);
});
it("allows leaf runtime filenames named test or tests", () => {
expect(
collectPackedTestCargoErrors([ "dist/extensions/fixture-plugin/node_modules/direct/bin/test", "dist/extensions/fixture-plugin/node_modules/direct/bin/tests",
]),
).toEqual([]);
});
it("normalizes Windows or mixed separators before classifying test cargo", () => {
expect(
collectPackedTestCargoErrors([
String.raw`dist\extensions\fixture-plugin\node_modules\direct\__tests__\index.js`,
String.raw`dist/extensions/fixture-plugin\node_modules/direct/src/runtime.spec.ts`,
String.raw`dist\extensions\fixture-plugin\node_modules\direct\node_modules\test\index.js`,
]),
).toEqual([
`npm package must not include test cargo "${String.raw`dist/extensions/fixture-plugin\node_modules/direct/src/runtime.spec.ts`}".`,
`npm package must not include test cargo "${String.raw`dist\extensions\fixture-plugin\node_modules\direct\__tests__\index.js`}".`,
]);
});
});
describe("collectReleaseTagErrors", () => {
it("accepts versions within the two-day CalVer window", () => {
expect(
collectReleaseTagErrors({
packageVersion: "2026.3.10",
releaseTag: "v2026.3.10",
now: new Date("2026-03-11T12:00:00Z"),
}),
).toEqual([]);
});
it("rejects versions outside the two-day CalVer window", () => {
expect(
collectReleaseTagErrors({
packageVersion: "2026.3.10",
releaseTag: "v2026.3.10",
now: new Date("2026-03-13T00:00:00Z"),
}),
).toContainEqual(expect.stringContaining("must be within 2 days"));
});
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.