test: expand npm registry spec coverage

This commit is contained in:
Peter Steinberger 2026-03-13 18:54:21 +00:00
parent cf39c03801
commit d4d7174773
1 changed files with 88 additions and 0 deletions

View File

@ -1,5 +1,8 @@
import { describe, expect, it } from "vitest";
import {
formatPrereleaseResolutionError,
isExactSemverVersion,
isPrereleaseSemverVersion,
isPrereleaseResolutionAllowed,
parseRegistryNpmSpec,
validateRegistryNpmSpec,
@ -22,6 +25,51 @@ describe("npm registry spec validation", () => {
"exact version or dist-tag",
);
});
it("rejects unsupported registry protocols and malformed selectors", () => {
expect(validateRegistryNpmSpec("https://npmjs.org/pkg.tgz")).toContain("URLs are not allowed");
expect(validateRegistryNpmSpec("git+ssh://github.com/openclaw/openclaw")).toContain(
"URLs are not allowed",
);
expect(validateRegistryNpmSpec("@openclaw/voice-call@")).toContain(
"missing version/tag after @",
);
expect(validateRegistryNpmSpec("@openclaw/voice-call@../beta")).toContain(
"invalid version/tag",
);
});
});
describe("npm registry spec parsing helpers", () => {
it("parses bare, tag, and exact prerelease specs", () => {
expect(parseRegistryNpmSpec("@openclaw/voice-call")).toEqual({
name: "@openclaw/voice-call",
raw: "@openclaw/voice-call",
selectorKind: "none",
selectorIsPrerelease: false,
});
expect(parseRegistryNpmSpec("@openclaw/voice-call@beta")).toEqual({
name: "@openclaw/voice-call",
raw: "@openclaw/voice-call@beta",
selector: "beta",
selectorKind: "tag",
selectorIsPrerelease: false,
});
expect(parseRegistryNpmSpec("@openclaw/voice-call@1.2.3-beta.1")).toEqual({
name: "@openclaw/voice-call",
raw: "@openclaw/voice-call@1.2.3-beta.1",
selector: "1.2.3-beta.1",
selectorKind: "exact-version",
selectorIsPrerelease: true,
});
});
it("detects exact and prerelease semver versions", () => {
expect(isExactSemverVersion("v1.2.3")).toBe(true);
expect(isExactSemverVersion("1.2")).toBe(false);
expect(isPrereleaseSemverVersion("1.2.3-beta.1")).toBe(true);
expect(isPrereleaseSemverVersion("1.2.3")).toBe(false);
});
});
describe("npm prerelease resolution policy", () => {
@ -66,4 +114,44 @@ describe("npm prerelease resolution policy", () => {
}),
).toBe(true);
});
it("allows stable resolutions even for bare and latest specs", () => {
const bareSpec = parseRegistryNpmSpec("@openclaw/voice-call");
const latestSpec = parseRegistryNpmSpec("@openclaw/voice-call@latest");
expect(bareSpec).not.toBeNull();
expect(latestSpec).not.toBeNull();
expect(
isPrereleaseResolutionAllowed({
spec: bareSpec!,
resolvedVersion: "1.2.3",
}),
).toBe(true);
expect(
isPrereleaseResolutionAllowed({
spec: latestSpec!,
resolvedVersion: undefined,
}),
).toBe(true);
});
it("formats prerelease resolution guidance based on selector intent", () => {
const bareSpec = parseRegistryNpmSpec("@openclaw/voice-call");
const tagSpec = parseRegistryNpmSpec("@openclaw/voice-call@beta");
expect(bareSpec).not.toBeNull();
expect(tagSpec).not.toBeNull();
expect(
formatPrereleaseResolutionError({
spec: bareSpec!,
resolvedVersion: "1.2.3-beta.1",
}),
).toContain(`Use "@openclaw/voice-call@beta"`);
expect(
formatPrereleaseResolutionError({
spec: tagSpec!,
resolvedVersion: "1.2.3-rc.1",
}),
).toContain("Use an explicit prerelease tag or exact prerelease version");
});
});