test: expand npm install and update check coverage

This commit is contained in:
Peter Steinberger 2026-03-13 19:45:37 +00:00
parent cda4e904cd
commit b8a2b1b5cc
2 changed files with 152 additions and 1 deletions

View File

@ -91,6 +91,24 @@ describe("installFromNpmSpecArchive", () => {
expect(withTempDir).toHaveBeenCalledWith("openclaw-test-", expect.any(Function));
});
it("rejects unsupported npm specs before packing", async () => {
const installFromArchive = vi.fn(async () => ({ ok: true as const }));
const result = await installFromNpmSpecArchive({
tempDirPrefix: "openclaw-test-",
spec: "file:/tmp/openclaw.tgz",
timeoutMs: 1000,
installFromArchive,
});
expect(result).toEqual({
ok: false,
error: "unsupported npm spec",
});
expect(packNpmSpecToArchive).not.toHaveBeenCalled();
expect(installFromArchive).not.toHaveBeenCalled();
});
it("returns resolution metadata and installer result on success", async () => {
mockPackedSuccess({ name: "@openclaw/test", version: "1.0.0" });
const installFromArchive = vi.fn(async () => ({ ok: true as const, target: "done" }));
@ -176,6 +194,56 @@ describe("installFromNpmSpecArchive", () => {
const okResult = expectWrappedOkResult(result, { ok: false, error: "install failed" });
expect(okResult.integrityDrift).toBeUndefined();
});
it("rejects prerelease resolutions unless explicitly requested", async () => {
vi.mocked(packNpmSpecToArchive).mockResolvedValue({
ok: true,
archivePath: baseArchivePath,
metadata: {
resolvedSpec: "@openclaw/test@latest",
integrity: "sha512-same",
version: "1.1.0-beta.1",
},
});
const installFromArchive = vi.fn(async () => ({ ok: true as const }));
const result = await installFromNpmSpecArchive({
tempDirPrefix: "openclaw-test-",
spec: "@openclaw/test@latest",
timeoutMs: 1000,
installFromArchive,
});
expect(result.ok).toBe(false);
if (result.ok) {
throw new Error("expected prerelease rejection");
}
expect(result.error).toContain("prerelease version 1.1.0-beta.1");
expect(installFromArchive).not.toHaveBeenCalled();
});
it("allows prerelease resolutions when explicitly requested by tag", async () => {
vi.mocked(packNpmSpecToArchive).mockResolvedValue({
ok: true,
archivePath: baseArchivePath,
metadata: {
resolvedSpec: "@openclaw/test@beta",
integrity: "sha512-same",
version: "1.1.0-beta.1",
},
});
const installFromArchive = vi.fn(async () => ({ ok: true as const, pluginId: "beta-plugin" }));
const result = await installFromNpmSpecArchive({
tempDirPrefix: "openclaw-test-",
spec: "@openclaw/test@beta",
timeoutMs: 1000,
installFromArchive,
});
const okResult = expectWrappedOkResult(result, { ok: true, pluginId: "beta-plugin" });
expect(okResult.npmResolution.version).toBe("1.1.0-beta.1");
});
});
describe("installFromNpmSpecArchiveWithInstaller", () => {

View File

@ -1,5 +1,11 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { compareSemverStrings, resolveNpmChannelTag } from "./update-check.js";
import {
compareSemverStrings,
fetchNpmLatestVersion,
fetchNpmTagVersion,
formatGitInstallLabel,
resolveNpmChannelTag,
} from "./update-check.js";
describe("compareSemverStrings", () => {
it("handles stable and prerelease precedence for both legacy and beta formats", () => {
@ -72,4 +78,81 @@ describe("resolveNpmChannelTag", () => {
expect(resolved).toEqual({ tag: "latest", version: "1.0.1" });
});
it("keeps non-beta channels unchanged", async () => {
versionByTag.latest = "1.0.3";
await expect(resolveNpmChannelTag({ channel: "stable", timeoutMs: 1000 })).resolves.toEqual({
tag: "latest",
version: "1.0.3",
});
});
it("exposes tag fetch helpers for success and http failures", async () => {
versionByTag.latest = "1.0.4";
await expect(fetchNpmTagVersion({ tag: "latest", timeoutMs: 1000 })).resolves.toEqual({
tag: "latest",
version: "1.0.4",
});
await expect(fetchNpmLatestVersion({ timeoutMs: 1000 })).resolves.toEqual({
latestVersion: "1.0.4",
error: undefined,
});
await expect(fetchNpmTagVersion({ tag: "beta", timeoutMs: 1000 })).resolves.toEqual({
tag: "beta",
version: null,
error: "HTTP 404",
});
});
});
describe("formatGitInstallLabel", () => {
it("formats branch, detached tag, and non-git installs", () => {
expect(
formatGitInstallLabel({
root: "/repo",
installKind: "git",
packageManager: "pnpm",
git: {
root: "/repo",
sha: "1234567890abcdef",
tag: null,
branch: "main",
upstream: "origin/main",
dirty: false,
ahead: 0,
behind: 0,
fetchOk: true,
},
}),
).toBe("main · @ 12345678");
expect(
formatGitInstallLabel({
root: "/repo",
installKind: "git",
packageManager: "pnpm",
git: {
root: "/repo",
sha: "abcdef1234567890",
tag: "v1.2.3",
branch: "HEAD",
upstream: null,
dirty: false,
ahead: 0,
behind: 0,
fetchOk: null,
},
}),
).toBe("detached · tag v1.2.3 · @ abcdef12");
expect(
formatGitInstallLabel({
root: null,
installKind: "package",
packageManager: "pnpm",
}),
).toBeNull();
});
});