From bf6da81028ca2bfbef6a1c9054161351c87c9eb2 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 13 Mar 2026 20:04:35 +0000 Subject: [PATCH] test: dedupe is-main and shell coverage --- src/infra/infra-parsing.test.ts | 109 -------------------------------- src/infra/is-main.test.ts | 80 +++++++++++++++++++++++ src/infra/node-shell.test.ts | 35 ++++++++++ 3 files changed, 115 insertions(+), 109 deletions(-) create mode 100644 src/infra/is-main.test.ts create mode 100644 src/infra/node-shell.test.ts diff --git a/src/infra/infra-parsing.test.ts b/src/infra/infra-parsing.test.ts index 8bded6fef27..b87dca7bfa2 100644 --- a/src/infra/infra-parsing.test.ts +++ b/src/infra/infra-parsing.test.ts @@ -1,116 +1,7 @@ import { describe, expect, it } from "vitest"; -import { isMainModule } from "./is-main.js"; -import { buildNodeShellCommand } from "./node-shell.js"; import { parseSshTarget } from "./ssh-tunnel.js"; describe("infra parsing", () => { - describe("isMainModule", () => { - it("returns true when argv[1] matches current file", () => { - expect( - isMainModule({ - currentFile: "/repo/dist/index.js", - argv: ["node", "/repo/dist/index.js"], - cwd: "/repo", - env: {}, - }), - ).toBe(true); - }); - - it("returns true under PM2 when pm_exec_path matches current file", () => { - expect( - isMainModule({ - currentFile: "/repo/dist/index.js", - argv: ["node", "/pm2/lib/ProcessContainerFork.js"], - cwd: "/repo", - env: { pm_exec_path: "/repo/dist/index.js", pm_id: "0" }, - }), - ).toBe(true); - }); - - it("returns true for dist/entry.js when launched via openclaw.mjs wrapper", () => { - expect( - isMainModule({ - currentFile: "/repo/dist/entry.js", - argv: ["node", "/repo/openclaw.mjs"], - cwd: "/repo", - env: {}, - wrapperEntryPairs: [{ wrapperBasename: "openclaw.mjs", entryBasename: "entry.js" }], - }), - ).toBe(true); - }); - - it("returns false for wrapper launches when wrapper pair is not configured", () => { - expect( - isMainModule({ - currentFile: "/repo/dist/entry.js", - argv: ["node", "/repo/openclaw.mjs"], - cwd: "/repo", - env: {}, - }), - ).toBe(false); - }); - - it("returns false when wrapper pair targets a different entry basename", () => { - expect( - isMainModule({ - currentFile: "/repo/dist/index.js", - argv: ["node", "/repo/openclaw.mjs"], - cwd: "/repo", - env: {}, - wrapperEntryPairs: [{ wrapperBasename: "openclaw.mjs", entryBasename: "entry.js" }], - }), - ).toBe(false); - }); - - it("returns false when running under PM2 but this module is imported", () => { - expect( - isMainModule({ - currentFile: "/repo/node_modules/openclaw/dist/index.js", - argv: ["node", "/repo/app.js"], - cwd: "/repo", - env: { pm_exec_path: "/repo/app.js", pm_id: "0" }, - }), - ).toBe(false); - }); - }); - - describe("buildNodeShellCommand", () => { - it("uses cmd.exe for win32", () => { - expect(buildNodeShellCommand("echo hi", "win32")).toEqual([ - "cmd.exe", - "/d", - "/s", - "/c", - "echo hi", - ]); - }); - - it("uses cmd.exe for windows labels", () => { - expect(buildNodeShellCommand("echo hi", "windows")).toEqual([ - "cmd.exe", - "/d", - "/s", - "/c", - "echo hi", - ]); - expect(buildNodeShellCommand("echo hi", "Windows 11")).toEqual([ - "cmd.exe", - "/d", - "/s", - "/c", - "echo hi", - ]); - }); - - it("uses /bin/sh for darwin", () => { - expect(buildNodeShellCommand("echo hi", "darwin")).toEqual(["/bin/sh", "-lc", "echo hi"]); - }); - - it("uses /bin/sh when platform missing", () => { - expect(buildNodeShellCommand("echo hi")).toEqual(["/bin/sh", "-lc", "echo hi"]); - }); - }); - describe("parseSshTarget", () => { it("parses user@host:port targets", () => { expect(parseSshTarget("me@example.com:2222")).toEqual({ diff --git a/src/infra/is-main.test.ts b/src/infra/is-main.test.ts new file mode 100644 index 00000000000..b2f6197ad24 --- /dev/null +++ b/src/infra/is-main.test.ts @@ -0,0 +1,80 @@ +import { describe, expect, it } from "vitest"; +import { isMainModule } from "./is-main.js"; + +describe("isMainModule", () => { + it("returns true when argv[1] matches current file", () => { + expect( + isMainModule({ + currentFile: "/repo/dist/index.js", + argv: ["node", "/repo/dist/index.js"], + cwd: "/repo", + env: {}, + }), + ).toBe(true); + }); + + it("returns true under PM2 when pm_exec_path matches current file", () => { + expect( + isMainModule({ + currentFile: "/repo/dist/index.js", + argv: ["node", "/pm2/lib/ProcessContainerFork.js"], + cwd: "/repo", + env: { pm_exec_path: "/repo/dist/index.js", pm_id: "0" }, + }), + ).toBe(true); + }); + + it("returns true for configured wrapper-to-entry pairs", () => { + expect( + isMainModule({ + currentFile: "/repo/dist/entry.js", + argv: ["node", "/repo/openclaw.mjs"], + cwd: "/repo", + env: {}, + wrapperEntryPairs: [{ wrapperBasename: "openclaw.mjs", entryBasename: "entry.js" }], + }), + ).toBe(true); + }); + + it("returns false for unmatched wrapper launches", () => { + expect( + isMainModule({ + currentFile: "/repo/dist/entry.js", + argv: ["node", "/repo/openclaw.mjs"], + cwd: "/repo", + env: {}, + }), + ).toBe(false); + expect( + isMainModule({ + currentFile: "/repo/dist/index.js", + argv: ["node", "/repo/openclaw.mjs"], + cwd: "/repo", + env: {}, + wrapperEntryPairs: [{ wrapperBasename: "openclaw.mjs", entryBasename: "entry.js" }], + }), + ).toBe(false); + }); + + it("returns false when this module is only imported under PM2", () => { + expect( + isMainModule({ + currentFile: "/repo/node_modules/openclaw/dist/index.js", + argv: ["node", "/repo/app.js"], + cwd: "/repo", + env: { pm_exec_path: "/repo/app.js", pm_id: "0" }, + }), + ).toBe(false); + }); + + it("falls back to basename matching for relative or symlinked entrypoints", () => { + expect( + isMainModule({ + currentFile: "/repo/dist/index.js", + argv: ["node", "../other/index.js"], + cwd: "/repo/dist", + env: {}, + }), + ).toBe(true); + }); +}); diff --git a/src/infra/node-shell.test.ts b/src/infra/node-shell.test.ts new file mode 100644 index 00000000000..8a0dc72bde1 --- /dev/null +++ b/src/infra/node-shell.test.ts @@ -0,0 +1,35 @@ +import { describe, expect, it } from "vitest"; +import { buildNodeShellCommand } from "./node-shell.js"; + +describe("buildNodeShellCommand", () => { + it("uses cmd.exe for win-prefixed platform labels", () => { + expect(buildNodeShellCommand("echo hi", "win32")).toEqual([ + "cmd.exe", + "/d", + "/s", + "/c", + "echo hi", + ]); + expect(buildNodeShellCommand("echo hi", "windows")).toEqual([ + "cmd.exe", + "/d", + "/s", + "/c", + "echo hi", + ]); + expect(buildNodeShellCommand("echo hi", " Windows 11 ")).toEqual([ + "cmd.exe", + "/d", + "/s", + "/c", + "echo hi", + ]); + }); + + it("uses /bin/sh for non-windows and missing platform values", () => { + expect(buildNodeShellCommand("echo hi", "darwin")).toEqual(["/bin/sh", "-lc", "echo hi"]); + expect(buildNodeShellCommand("echo hi", "linux")).toEqual(["/bin/sh", "-lc", "echo hi"]); + expect(buildNodeShellCommand("echo hi")).toEqual(["/bin/sh", "-lc", "echo hi"]); + expect(buildNodeShellCommand("echo hi", null)).toEqual(["/bin/sh", "-lc", "echo hi"]); + }); +});