Files
NetMesh/electron/bridges/terminalBridge.windowsAppsAlias.test.cjs

162 lines
5.0 KiB
JavaScript
Raw Permalink Normal View History

const test = require("node:test");
const assert = require("node:assert/strict");
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");
const Module = require("node:module");
const childProcess = require("node:child_process");
function loadBridgeWithFakePty() {
const bridgePath = require.resolve("./terminalBridge.cjs");
delete require.cache[bridgePath];
const originalLoad = Module._load;
Module._load = function patchedLoad(request) {
if (request === "node-pty") {
return {
spawn() {
throw new Error("node-pty spawn is not exercised by this suite");
},
};
}
return originalLoad.apply(this, arguments);
};
try {
return require("./terminalBridge.cjs");
} finally {
Module._load = originalLoad;
}
}
const bridge = loadBridgeWithFakePty();
function withWin32Platform(fn) {
const platformDescriptor = Object.getOwnPropertyDescriptor(process, "platform");
Object.defineProperty(process, "platform", { ...platformDescriptor, value: "win32" });
try {
return fn();
} finally {
Object.defineProperty(process, "platform", platformDescriptor);
}
}
// findExecutable() re-requires child_process inside the call, so patching the
// module object's execFileSync at runtime intercepts its `where.exe` probes.
function withWhereFake(resultsByname, fn) {
const realExecFileSync = childProcess.execFileSync;
childProcess.execFileSync = function fakeExecFileSync(file, args) {
const argv0 = String(file).toLowerCase();
const isWhere =
argv0 === "where.exe" || argv0.endsWith("\\where.exe") || argv0.endsWith("/where.exe");
if (isWhere) {
const lines = resultsByname.get(args[0]);
if (lines !== undefined) {
if (lines === null) {
throw new Error("not found");
}
return lines.join("\r\n");
}
}
throw new Error(`unexpected execFileSync call: ${file} ${JSON.stringify(args)}`);
};
try {
return fn();
} finally {
childProcess.execFileSync = realExecFileSync;
}
}
// Hide machine-specific fallback paths (e.g. an MSI pwsh under Program Files)
// so the tests behave identically regardless of what the host has installed.
function withExistsSyncAllowlist(allowed, fn) {
const realExistsSync = fs.existsSync;
fs.existsSync = (p) => allowed.has(String(p));
try {
return fn();
} finally {
fs.existsSync = realExistsSync;
}
}
function makeHarness(t) {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-local-shell-"));
t.after(() => fs.rmSync(tmp, { recursive: true, force: true }));
const previousLocalAppData = process.env.LOCALAPPDATA;
process.env.LOCALAPPDATA = tmp;
t.after(() => {
if (previousLocalAppData === undefined) {
delete process.env.LOCALAPPDATA;
} else {
process.env.LOCALAPPDATA = previousLocalAppData;
}
});
const aliasPath = path.join(tmp, "Microsoft", "WindowsApps", "pwsh.exe");
// Intentionally not created on disk: real App Execution Aliases fail
// fs.statSync() with EACCES, so existsSync() is false for them anyway.
const realPwshPath = path.join(tmp, "PowerShell", "7", "pwsh.exe");
fs.mkdirSync(path.dirname(realPwshPath), { recursive: true });
fs.writeFileSync(realPwshPath, "");
const windowsPowerShellPath = path.join(tmp, "WindowsPowerShell", "v1.0", "powershell.exe");
fs.mkdirSync(path.dirname(windowsPowerShellPath), { recursive: true });
fs.writeFileSync(windowsPowerShellPath, "");
return { tmp, aliasPath, realPwshPath, windowsPowerShellPath };
}
test("getDefaultLocalShell resolves an MSIX pwsh execution alias", (t) => {
const { aliasPath } = makeHarness(t);
withWin32Platform(() =>
withWhereFake(new Map([["pwsh", [aliasPath]]]), () => {
assert.equal(bridge.getDefaultLocalShell(), aliasPath);
}),
);
});
test("findExecutable prefers a regular executable listed after an execution alias", (t) => {
const { aliasPath, realPwshPath } = makeHarness(t);
withWin32Platform(() =>
withWhereFake(new Map([["pwsh", [aliasPath, realPwshPath]]]), () => {
assert.equal(bridge.findExecutable("pwsh"), realPwshPath);
}),
);
});
test("getDefaultLocalShell still falls back to Windows PowerShell when no pwsh exists", (t) => {
const { windowsPowerShellPath } = makeHarness(t);
withWin32Platform(() =>
withWhereFake(
new Map([
["pwsh", null],
["powershell", [windowsPowerShellPath]],
]),
() =>
withExistsSyncAllowlist(new Set([windowsPowerShellPath]), () => {
assert.equal(bridge.getDefaultLocalShell(), windowsPowerShellPath);
}),
),
);
});
test("getDefaultLocalShell keeps the powershell.exe last-resort fallback", (t) => {
makeHarness(t);
withWin32Platform(() =>
withWhereFake(
new Map([
["pwsh", null],
["powershell", null],
]),
() =>
withExistsSyncAllowlist(new Set(), () => {
assert.equal(bridge.getDefaultLocalShell(), "powershell.exe");
}),
),
);
});