Files
my-pi/pi-permission-system/test/node-modules-discovery.test.ts

98 lines
3.1 KiB
TypeScript

import { beforeEach, describe, expect, test, vi } from "vitest";
// Hoisted stubs for mocks that reference them in vi.mock factories.
const { mockSpawnSync, mockExistsSync } = vi.hoisted(() => ({
mockSpawnSync: vi.fn(),
mockExistsSync: vi.fn(),
}));
// Mock node:child_process so tests don't spawn real subprocesses.
vi.mock("node:child_process", () => ({
spawnSync: mockSpawnSync,
default: { spawnSync: mockSpawnSync },
}));
// Mock node:fs so existsSync is controllable.
vi.mock("node:fs", () => ({
existsSync: mockExistsSync,
default: { existsSync: mockExistsSync },
}));
import { discoverGlobalNodeModulesRoot } from "#src/node-modules-discovery";
describe("discoverGlobalNodeModulesRoot", () => {
beforeEach(() => {
mockSpawnSync.mockReset();
mockExistsSync.mockReset();
});
test("returns node_modules root when URL is inside a node_modules tree", () => {
const fakeUrl =
"file:///opt/homebrew/lib/node_modules/@gotgenes/pi-permission-system/dist/external-directory.js";
const result = discoverGlobalNodeModulesRoot(fakeUrl);
expect(result).toBe("/opt/homebrew/lib/node_modules");
expect(mockSpawnSync).not.toHaveBeenCalled();
});
test("calls npm root -g as fallback when walk-up finds no node_modules ancestor", () => {
const npmRootPath = "/opt/homebrew/lib/node_modules";
mockSpawnSync.mockReturnValue({
status: 0,
stdout: `${npmRootPath}\n`,
});
mockExistsSync.mockReturnValue(true);
const fakeUrl = "file:///Users/dev/my-project/src/external-directory.ts";
const result = discoverGlobalNodeModulesRoot(fakeUrl);
expect(mockSpawnSync).toHaveBeenCalledWith(
"npm",
["root", "-g"],
expect.objectContaining({ encoding: "utf-8" }),
);
expect(result).toBe(npmRootPath);
});
test("returns null when walk-up fails and npm root -g returns non-zero exit", () => {
mockSpawnSync.mockReturnValue({ status: 1, stdout: "" });
const fakeUrl = "file:///Users/dev/my-project/src/external-directory.ts";
const result = discoverGlobalNodeModulesRoot(fakeUrl);
expect(result).toBeNull();
});
test("returns null when walk-up fails and spawnSync throws", () => {
mockSpawnSync.mockImplementation(() => {
throw new Error("ENOENT");
});
const fakeUrl = "file:///Users/dev/my-project/src/external-directory.ts";
const result = discoverGlobalNodeModulesRoot(fakeUrl);
expect(result).toBeNull();
});
test("returns null when walk-up fails and npm root -g returns non-existent path", () => {
mockSpawnSync.mockReturnValue({
status: 0,
stdout: "/some/nonexistent/node_modules\n",
});
mockExistsSync.mockReturnValue(false);
const fakeUrl = "file:///Users/dev/my-project/src/external-directory.ts";
const result = discoverGlobalNodeModulesRoot(fakeUrl);
expect(result).toBeNull();
});
test("returns null when walk-up fails and npm root -g returns empty stdout", () => {
mockSpawnSync.mockReturnValue({ status: 0, stdout: " " });
const fakeUrl = "file:///Users/dev/my-project/src/external-directory.ts";
const result = discoverGlobalNodeModulesRoot(fakeUrl);
expect(result).toBeNull();
});
});