/** * @file Tests for server/lib/shell-path.js — login-shell PATH hydration with a * stubbed spawner (noisy rc output, errors, opt-out, dedupe) plus one real * `/bin/sh` run to prove the argv works end to end. * @author Nguyễn Ngọc Trí Vĩ */ const { describe, it, beforeEach, afterEach } = require("node:test"); const assert = require("node:assert/strict"); const { hydrateShellPath, shellPath } = require("../lib/shell-path"); const M = "__AGENTHUB_PATH__"; const stub = (stdout, err = null) => (_cmd, _args, _opts, cb) => { setImmediate(() => cb(err, stdout)); return { stdin: { end() {} } }; }; describe("hydrateShellPath", () => { let saved; beforeEach(() => { saved = { PATH: process.env.PATH, OPT: process.env.AGENTHUB_SHELL_PATH }; process.env.PATH = "/usr/bin:/bin"; delete process.env.AGENTHUB_SHELL_PATH; }); afterEach(() => { process.env.PATH = saved.PATH; if (saved.OPT === undefined) delete process.env.AGENTHUB_SHELL_PATH; else process.env.AGENTHUB_SHELL_PATH = saved.OPT; }); it("appends new segments from between the delimiters, ignoring rc noise", async () => { const ok = await hydrateShellPath({ spawn: stub(`welcome!\n${M}/home/u/.local/bin:/usr/bin:/opt/x${M}bye`), }); assert.equal(ok, true); assert.equal(process.env.PATH, "/usr/bin:/bin:/home/u/.local/bin:/opt/x"); }); it("remembers the shell's own PATH in the shell's order", async () => { await hydrateShellPath({ spawn: stub(`${M}/home/u/.nvm/bin:/usr/bin${M}`) }); assert.equal(shellPath(), "/home/u/.nvm/bin:/usr/bin"); }); it("keeps PATH on error or missing delimiters", async () => { assert.equal(await hydrateShellPath({ spawn: stub("", new Error("timeout")) }), false); assert.equal(await hydrateShellPath({ spawn: stub("no markers") }), false); assert.equal( await hydrateShellPath({ spawn: () => { throw new Error("ENOENT"); }, }), false ); assert.equal(process.env.PATH, "/usr/bin:/bin"); }); it("does nothing with AGENTHUB_SHELL_PATH=0", async () => { process.env.AGENTHUB_SHELL_PATH = "0"; assert.equal(await hydrateShellPath({ spawn: stub(`${M}/x${M}`) }), false); assert.equal(process.env.PATH, "/usr/bin:/bin"); }); it("reads a real shell's PATH", async () => { const ok = await hydrateShellPath({ shell: "/bin/sh" }); assert.equal(ok, true); assert.ok(process.env.PATH.startsWith("/usr/bin:/bin")); }); });