test: tighten warning and npm integrity coverage

This commit is contained in:
Peter Steinberger 2026-03-13 19:01:16 +00:00
parent 2622b05c0b
commit e928f55537
2 changed files with 110 additions and 32 deletions

View File

@ -6,23 +6,34 @@ import {
describe("resolveNpmIntegrityDrift", () => { describe("resolveNpmIntegrityDrift", () => {
it("returns proceed=true when integrity is missing or unchanged", async () => { it("returns proceed=true when integrity is missing or unchanged", async () => {
await expect( const createPayload = vi.fn(() => "unused");
resolveNpmIntegrityDrift({ const cases = [
spec: "@openclaw/test@1.0.0", {
expectedIntegrity: "sha512-same", expectedIntegrity: undefined,
resolution: { integrity: "sha512-same", resolvedAt: "2026-01-01T00:00:00.000Z" }, resolution: { integrity: "sha512-same", resolvedAt: "2026-01-01T00:00:00.000Z" },
createPayload: () => "unused", },
}), {
).resolves.toEqual({ proceed: true });
await expect(
resolveNpmIntegrityDrift({
spec: "@openclaw/test@1.0.0",
expectedIntegrity: "sha512-same", expectedIntegrity: "sha512-same",
resolution: { resolvedAt: "2026-01-01T00:00:00.000Z" }, resolution: { resolvedAt: "2026-01-01T00:00:00.000Z" },
createPayload: () => "unused", },
}), {
).resolves.toEqual({ proceed: true }); expectedIntegrity: "sha512-same",
resolution: { integrity: "sha512-same", resolvedAt: "2026-01-01T00:00:00.000Z" },
},
];
for (const testCase of cases) {
await expect(
resolveNpmIntegrityDrift({
spec: "@openclaw/test@1.0.0",
expectedIntegrity: testCase.expectedIntegrity,
resolution: testCase.resolution,
createPayload,
}),
).resolves.toEqual({ proceed: true });
}
expect(createPayload).not.toHaveBeenCalled();
}); });
it("uses callback on integrity drift", async () => { it("uses callback on integrity drift", async () => {
@ -52,6 +63,31 @@ describe("resolveNpmIntegrityDrift", () => {
}); });
}); });
it("returns payload when the drift callback allows continuing", async () => {
const result = await resolveNpmIntegrityDrift({
spec: "@openclaw/test@1.0.0",
expectedIntegrity: "sha512-old",
resolution: {
integrity: "sha512-new",
resolvedAt: "2026-01-01T00:00:00.000Z",
},
createPayload: ({ spec, actualIntegrity }) => ({ spec, actualIntegrity }),
onIntegrityDrift: async () => true,
});
expect(result).toEqual({
integrityDrift: {
expectedIntegrity: "sha512-old",
actualIntegrity: "sha512-new",
},
payload: {
spec: "@openclaw/test@1.0.0",
actualIntegrity: "sha512-new",
},
proceed: true,
});
});
it("warns by default when no callback is provided", async () => { it("warns by default when no callback is provided", async () => {
const warn = vi.fn(); const warn = vi.fn();
const result = await resolveNpmIntegrityDrift({ const result = await resolveNpmIntegrityDrift({
@ -100,4 +136,22 @@ describe("resolveNpmIntegrityDrift", () => {
"aborted: npm package integrity drift detected for @openclaw/test@1.0.0", "aborted: npm package integrity drift detected for @openclaw/test@1.0.0",
); );
}); });
it("falls back to the original spec when resolvedSpec is missing", async () => {
const warn = vi.fn();
await resolveNpmIntegrityDriftWithDefaultMessage({
spec: "@openclaw/test@1.0.0",
expectedIntegrity: "sha512-old",
resolution: {
integrity: "sha512-new",
resolvedAt: "2026-01-01T00:00:00.000Z",
},
warn,
});
expect(warn).toHaveBeenCalledWith(
"Integrity drift detected for @openclaw/test@1.0.0: expected sha512-old, got sha512-new",
);
});
}); });

View File

@ -12,6 +12,10 @@ function resetWarningFilterInstallState(): void {
process.emitWarning = baseEmitWarning; process.emitWarning = baseEmitWarning;
} }
async function flushWarnings(): Promise<void> {
await new Promise((resolve) => setImmediate(resolve));
}
describe("warning filter", () => { describe("warning filter", () => {
beforeEach(() => { beforeEach(() => {
resetWarningFilterInstallState(); resetWarningFilterInstallState();
@ -23,36 +27,49 @@ describe("warning filter", () => {
}); });
it("suppresses known deprecation and experimental warning signatures", () => { it("suppresses known deprecation and experimental warning signatures", () => {
expect( const ignoredWarnings = [
shouldIgnoreWarning({ {
name: "DeprecationWarning", name: "DeprecationWarning",
code: "DEP0040", code: "DEP0040",
message: "The punycode module is deprecated.", message: "The punycode module is deprecated.",
}), },
).toBe(true); {
expect(
shouldIgnoreWarning({
name: "DeprecationWarning", name: "DeprecationWarning",
code: "DEP0060", code: "DEP0060",
message: "The `util._extend` API is deprecated.", message: "The `util._extend` API is deprecated.",
}), },
).toBe(true); {
expect(
shouldIgnoreWarning({
name: "ExperimentalWarning", name: "ExperimentalWarning",
message: "SQLite is an experimental feature and might change at any time", message: "SQLite is an experimental feature and might change at any time",
}), },
).toBe(true); ];
for (const warning of ignoredWarnings) {
expect(shouldIgnoreWarning(warning)).toBe(true);
}
}); });
it("keeps unknown warnings visible", () => { it("keeps unknown warnings visible", () => {
expect( const visibleWarnings = [
shouldIgnoreWarning({ {
name: "DeprecationWarning", name: "DeprecationWarning",
code: "DEP9999", code: "DEP9999",
message: "Totally new warning", message: "Totally new warning",
}), },
).toBe(false); {
name: "ExperimentalWarning",
message: "Different experimental warning",
},
{
name: "DeprecationWarning",
code: "DEP0040",
message: "Different deprecated module",
},
];
for (const warning of visibleWarnings) {
expect(shouldIgnoreWarning(warning)).toBe(false);
}
}); });
it("installs once and suppresses known warnings at emit time", async () => { it("installs once and suppresses known warnings at emit time", async () => {
@ -82,11 +99,18 @@ describe("warning filter", () => {
type: "DeprecationWarning", type: "DeprecationWarning",
code: "DEP0060", code: "DEP0060",
}); });
await new Promise((resolve) => setImmediate(resolve)); emitWarning(
Object.assign(new Error("The punycode module is deprecated."), {
name: "DeprecationWarning",
code: "DEP0040",
}),
);
await flushWarnings();
expect(seenWarnings.find((warning) => warning.code === "DEP0060")).toBeUndefined(); expect(seenWarnings.find((warning) => warning.code === "DEP0060")).toBeUndefined();
expect(seenWarnings.find((warning) => warning.code === "DEP0040")).toBeUndefined();
emitWarning("Visible warning", { type: "Warning", code: "OPENCLAW_TEST_WARNING" }); emitWarning("Visible warning", { type: "Warning", code: "OPENCLAW_TEST_WARNING" });
await new Promise((resolve) => setImmediate(resolve)); await flushWarnings();
expect( expect(
seenWarnings.find((warning) => warning.code === "OPENCLAW_TEST_WARNING"), seenWarnings.find((warning) => warning.code === "OPENCLAW_TEST_WARNING"),
).toBeDefined(); ).toBeDefined();