























@@ -108,6 +108,59 @@ describe("install.sh", () => {
108108expect(output).toContain(`path=${nvmNode}`);
109109expect(output).toContain("version=v22.22.1");
110110});
111+112+it("warns before redirecting an unwritable npm prefix", () => {
113+const tmp = mkdtempSync(join(tmpdir(), "openclaw-install-npm-prefix-"));
114+const home = join(tmp, "home");
115+const events = join(tmp, "events.log");
116+mkdirSync(home, { recursive: true });
117+118+let result: ReturnType<typeof runInstallShell> | undefined;
119+try {
120+result = runInstallShell(`
121+ set -euo pipefail
122+ source "${SCRIPT_PATH}"
123+ OS=linux
124+ HOME=${JSON.stringify(home)}
125+ prefix=${JSON.stringify(join(tmp, "root-owned-prefix"))}
126+ events=${JSON.stringify(events)}
127+ npm() {
128+ if [[ "$1" == "config" && "$2" == "get" && "$3" == "prefix" ]]; then
129+ printf '%s\\n' "$prefix"
130+ return 0
131+ fi
132+ if [[ "$1" == "config" && "$2" == "set" && "$3" == "prefix" ]]; then
133+ printf 'npm-set:%s\\n' "$4" >> "$events"
134+ return 0
135+ fi
136+ return 1
137+ }
138+ ui_info() { printf 'info:%s\\n' "$*" >> "$events"; }
139+ ui_warn() { printf 'warn:%s\\n' "$*" >> "$events"; }
140+ ui_success() { printf 'success:%s\\n' "$*" >> "$events"; }
141+ fix_npm_permissions
142+ cat "$events"
143+ `);
144+} finally {
145+rmSync(tmp, { force: true, recursive: true });
146+}
147+148+expect(result?.status).toBe(0);
149+const lines = (result?.stdout ?? "").trim().split("\n");
150+const warningIndex = lines.findIndex((line) =>
151+line.includes("The installer will switch npm's user prefix"),
152+);
153+const npmSetIndex = lines.findIndex((line) => line.startsWith("npm-set:"));
154+const noSudoWarningIndex = lines.findIndex((line) => line.includes("Avoid sudo npm i -g"));
155+expect(warningIndex).toBeGreaterThanOrEqual(0);
156+expect(npmSetIndex).toBeGreaterThan(warningIndex);
157+expect(noSudoWarningIndex).toBeGreaterThan(npmSetIndex);
158+expect(result?.stdout).toContain("npm global prefix is not writable");
159+expect(result?.stdout).toContain("npm normally writes that setting to ~/.npmrc");
160+expect(result?.stdout).toContain("npm i -g openclaw@latest");
161+expect(result?.stdout).toContain("using this user prefix");
162+expect(result?.stdout).not.toContain("has been saved");
163+});
111164});
112165113166describe("install.sh macOS Homebrew Node behavior", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。