2026-01-08 02:44:09 +00:00
|
|
|
import path from "node:path";
|
2026-01-05 02:48:25 +01:00
|
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
|
|
|
2026-01-05 02:51:56 +01:00
|
|
|
const fsMocks = vi.hoisted(() => ({
|
|
|
|
|
access: vi.fn(),
|
|
|
|
|
realpath: vi.fn(),
|
|
|
|
|
}));
|
2026-01-05 02:48:25 +01:00
|
|
|
|
|
|
|
|
vi.mock("node:fs/promises", () => ({
|
2026-01-05 02:51:56 +01:00
|
|
|
default: { access: fsMocks.access, realpath: fsMocks.realpath },
|
|
|
|
|
access: fsMocks.access,
|
|
|
|
|
realpath: fsMocks.realpath,
|
2026-01-05 02:48:25 +01:00
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
import { resolveGatewayProgramArguments } from "./program-args.js";
|
|
|
|
|
|
|
|
|
|
const originalArgv = [...process.argv];
|
|
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
|
process.argv = [...originalArgv];
|
|
|
|
|
vi.resetAllMocks();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe("resolveGatewayProgramArguments", () => {
|
|
|
|
|
it("uses realpath-resolved dist entry when running via npx shim", async () => {
|
2026-01-30 03:15:10 +01:00
|
|
|
const argv1 = path.resolve("/tmp/.npm/_npx/63c3/node_modules/.bin/openclaw");
|
2026-01-31 17:26:39 +09:00
|
|
|
const entryPath = path.resolve("/tmp/.npm/_npx/63c3/node_modules/openclaw/dist/entry.mjs");
|
2026-01-08 02:44:09 +00:00
|
|
|
process.argv = ["node", argv1];
|
|
|
|
|
fsMocks.realpath.mockResolvedValue(entryPath);
|
2026-01-05 02:51:56 +01:00
|
|
|
fsMocks.access.mockImplementation(async (target: string) => {
|
2026-01-08 02:44:09 +00:00
|
|
|
if (target === entryPath) {
|
2026-01-05 02:48:25 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
throw new Error("missing");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const result = await resolveGatewayProgramArguments({ port: 18789 });
|
|
|
|
|
|
|
|
|
|
expect(result.programArguments).toEqual([
|
|
|
|
|
process.execPath,
|
2026-01-08 02:44:09 +00:00
|
|
|
entryPath,
|
2026-01-08 07:16:05 +01:00
|
|
|
"gateway",
|
2026-01-05 02:48:25 +01:00
|
|
|
"--port",
|
|
|
|
|
"18789",
|
|
|
|
|
]);
|
|
|
|
|
});
|
|
|
|
|
|
2026-01-23 19:52:26 +08:00
|
|
|
it("prefers symlinked path over realpath for stable service config", async () => {
|
2026-01-30 03:15:10 +01:00
|
|
|
// Simulates pnpm global install where node_modules/openclaw is a symlink
|
|
|
|
|
// to .pnpm/openclaw@X.Y.Z/node_modules/openclaw
|
2026-01-23 19:52:26 +08:00
|
|
|
const symlinkPath = path.resolve(
|
2026-01-31 17:26:39 +09:00
|
|
|
"/Users/test/Library/pnpm/global/5/node_modules/openclaw/dist/entry.mjs",
|
2026-01-23 19:52:26 +08:00
|
|
|
);
|
|
|
|
|
const realpathResolved = path.resolve(
|
2026-01-31 17:26:39 +09:00
|
|
|
"/Users/test/Library/pnpm/global/5/node_modules/.pnpm/openclaw@2026.1.21-2/node_modules/openclaw/dist/entry.mjs",
|
2026-01-23 19:52:26 +08:00
|
|
|
);
|
|
|
|
|
process.argv = ["node", symlinkPath];
|
|
|
|
|
fsMocks.realpath.mockResolvedValue(realpathResolved);
|
|
|
|
|
fsMocks.access.mockResolvedValue(undefined); // Both paths exist
|
|
|
|
|
|
|
|
|
|
const result = await resolveGatewayProgramArguments({ port: 18789 });
|
|
|
|
|
|
|
|
|
|
// Should use the symlinked path, not the realpath-resolved versioned path
|
|
|
|
|
expect(result.programArguments[1]).toBe(symlinkPath);
|
|
|
|
|
expect(result.programArguments[1]).not.toContain("@2026.1.21-2");
|
|
|
|
|
});
|
|
|
|
|
|
2026-01-05 02:48:25 +01:00
|
|
|
it("falls back to node_modules package dist when .bin path is not resolved", async () => {
|
2026-01-30 03:15:10 +01:00
|
|
|
const argv1 = path.resolve("/tmp/.npm/_npx/63c3/node_modules/.bin/openclaw");
|
2026-01-31 15:25:06 +09:00
|
|
|
const indexPath = path.resolve("/tmp/.npm/_npx/63c3/node_modules/openclaw/dist/index.mjs");
|
2026-01-08 02:44:09 +00:00
|
|
|
process.argv = ["node", argv1];
|
2026-01-05 02:51:56 +01:00
|
|
|
fsMocks.realpath.mockRejectedValue(new Error("no realpath"));
|
|
|
|
|
fsMocks.access.mockImplementation(async (target: string) => {
|
2026-01-08 02:44:09 +00:00
|
|
|
if (target === indexPath) {
|
2026-01-05 02:48:25 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
throw new Error("missing");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const result = await resolveGatewayProgramArguments({ port: 18789 });
|
|
|
|
|
|
|
|
|
|
expect(result.programArguments).toEqual([
|
|
|
|
|
process.execPath,
|
2026-01-08 02:44:09 +00:00
|
|
|
indexPath,
|
2026-01-08 07:16:05 +01:00
|
|
|
"gateway",
|
2026-01-05 02:48:25 +01:00
|
|
|
"--port",
|
|
|
|
|
"18789",
|
|
|
|
|
]);
|
|
|
|
|
});
|
|
|
|
|
});
|