test: expand runtime guard and path prepend coverage
This commit is contained in:
33
src/infra/path-prepend.test.ts
Normal file
33
src/infra/path-prepend.test.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { mergePathPrepend, normalizePathPrepend } from "./path-prepend.js";
|
||||
|
||||
describe("path prepend helpers", () => {
|
||||
it("normalizes prepend lists by trimming, skipping blanks, and deduping", () => {
|
||||
expect(
|
||||
normalizePathPrepend([
|
||||
" /custom/bin ",
|
||||
"",
|
||||
" /custom/bin ",
|
||||
"/opt/bin",
|
||||
// oxlint-disable-next-line typescript/no-explicit-any
|
||||
42 as any,
|
||||
]),
|
||||
).toEqual(["/custom/bin", "/opt/bin"]);
|
||||
expect(normalizePathPrepend()).toEqual([]);
|
||||
});
|
||||
|
||||
it("merges prepended paths ahead of existing values without duplicates", () => {
|
||||
expect(mergePathPrepend(`/usr/bin${path.delimiter}/opt/bin`, ["/custom/bin", "/usr/bin"])).toBe(
|
||||
["/custom/bin", "/usr/bin", "/opt/bin"].join(path.delimiter),
|
||||
);
|
||||
expect(mergePathPrepend(undefined, ["/custom/bin"])).toBe("/custom/bin");
|
||||
expect(mergePathPrepend("/usr/bin", [])).toBe("/usr/bin");
|
||||
});
|
||||
|
||||
it("trims existing path entries while preserving order", () => {
|
||||
expect(
|
||||
mergePathPrepend(` /usr/bin ${path.delimiter} ${path.delimiter} /opt/bin `, ["/custom/bin"]),
|
||||
).toBe(["/custom/bin", "/usr/bin", "/opt/bin"].join(path.delimiter));
|
||||
});
|
||||
});
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
detectRuntime,
|
||||
isAtLeast,
|
||||
parseSemver,
|
||||
isSupportedNodeVersion,
|
||||
type RuntimeDetails,
|
||||
runtimeSatisfies,
|
||||
} from "./runtime-guard.js";
|
||||
@@ -12,6 +13,7 @@ describe("runtime-guard", () => {
|
||||
it("parses semver with or without leading v", () => {
|
||||
expect(parseSemver("v22.1.3")).toEqual({ major: 22, minor: 1, patch: 3 });
|
||||
expect(parseSemver("1.3.0")).toEqual({ major: 1, minor: 3, patch: 0 });
|
||||
expect(parseSemver("22.16.0-beta.1")).toEqual({ major: 22, minor: 16, patch: 0 });
|
||||
expect(parseSemver("invalid")).toBeNull();
|
||||
});
|
||||
|
||||
@@ -49,6 +51,9 @@ describe("runtime-guard", () => {
|
||||
expect(runtimeSatisfies(nodeOld)).toBe(false);
|
||||
expect(runtimeSatisfies(nodeTooOld)).toBe(false);
|
||||
expect(runtimeSatisfies(unknown)).toBe(false);
|
||||
expect(isSupportedNodeVersion("22.16.0")).toBe(true);
|
||||
expect(isSupportedNodeVersion("22.15.9")).toBe(false);
|
||||
expect(isSupportedNodeVersion(null)).toBe(false);
|
||||
});
|
||||
|
||||
it("throws via exit when runtime is too old", () => {
|
||||
@@ -67,6 +72,7 @@ describe("runtime-guard", () => {
|
||||
};
|
||||
expect(() => assertSupportedRuntime(runtime, details)).toThrow("exit");
|
||||
expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining("requires Node"));
|
||||
expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining("Detected: node 20.0.0"));
|
||||
});
|
||||
|
||||
it("returns silently when runtime meets requirements", () => {
|
||||
@@ -84,4 +90,25 @@ describe("runtime-guard", () => {
|
||||
expect(() => assertSupportedRuntime(runtime, details)).not.toThrow();
|
||||
expect(runtime.exit).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("reports unknown runtimes with fallback labels", () => {
|
||||
const runtime = {
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
exit: vi.fn(() => {
|
||||
throw new Error("exit");
|
||||
}),
|
||||
};
|
||||
const details: RuntimeDetails = {
|
||||
kind: "unknown",
|
||||
version: null,
|
||||
execPath: null,
|
||||
pathEnv: "(not set)",
|
||||
};
|
||||
|
||||
expect(() => assertSupportedRuntime(runtime, details)).toThrow("exit");
|
||||
expect(runtime.error).toHaveBeenCalledWith(
|
||||
expect.stringContaining("Detected: unknown runtime (exec: unknown)."),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user