import assert from 'node:assert/strict'; import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import test from 'node:test'; import { detectExecutableArch, expectedArch, isComplete, main, platformPath, repair, resolveElectronPackageDir, } from './ensure-electron.mjs'; const FAIL_SCRIPT = 'process.exit(1);\n'; function headerBytesForArch(arch) { const platform = process.platform; if (platform === 'darwin') { const cputype = { arm64: 0x0100000c, x64: 0x01000007, ia32: 0x00000007, arm: 0x0000000c }[arch]; const buf = Buffer.alloc(8); buf.writeUInt32LE(0xfeedfacf, 0); buf.writeUInt32LE(cputype, 4); return buf; } if (platform === 'linux') { const machine = { arm64: 183, x64: 62, ia32: 3, arm: 40 }[arch]; const buf = Buffer.alloc(20); buf[0] = 0x7f; buf[1] = 0x45; buf[2] = 0x4c; buf[3] = 0x46; buf.writeUInt16LE(machine, 18); return buf; } if (platform === 'win32') { const peOffset = 0x80; const machine = { arm64: 0xaa64, x64: 0x8664, ia32: 0x014c }[arch]; const buf = Buffer.alloc(peOffset + 6); buf.write('MZ', 0, 'latin1'); buf.writeUInt32LE(peOffset, 0x3c); buf.write('PE\0\0', peOffset, 'latin1'); buf.writeUInt16LE(machine, peOffset + 4); return buf; } throw new Error(`unsupported test platform: ${platform}`); } function installScriptContent({ arch = expectedArch(), platform = platformPath(), version = '41.2.1', exitCode = 0, } = {}) { const headerHex = headerBytesForArch(arch).toString('hex'); return [ "const fs = require('node:fs');", "const path = require('node:path');", `const platformPath = ${JSON.stringify(platform)};`, `const header = Buffer.from('${headerHex}', 'hex');`, "const exe = path.join(__dirname, 'dist', platformPath);", 'fs.mkdirSync(path.dirname(exe), { recursive: true });', `fs.writeFileSync(path.join(__dirname, 'dist', 'version'), ${JSON.stringify(version)});`, "fs.writeFileSync(path.join(__dirname, 'path.txt'), platformPath);", 'fs.writeFileSync(exe, header);', `process.exit(${exitCode});`, ].join('\n'); } function makeFixture({ version = '41.2.1', complete = false, distVersion, arch, installScripts = {}, } = {}) { const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'electron-ensure-')); fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ name: 'electron', version })); if (complete) { const platform = platformPath(); fs.mkdirSync(path.join(dir, 'dist', path.dirname(platform)), { recursive: true }); fs.writeFileSync(path.join(dir, 'dist', 'version'), distVersion ?? version); fs.writeFileSync(path.join(dir, 'path.txt'), platform); fs.writeFileSync(path.join(dir, 'dist', platform), headerBytesForArch(arch ?? expectedArch())); } for (const [name, content] of Object.entries(installScripts)) { fs.writeFileSync(path.join(dir, name), content); } return dir; } function withFixture(t, options) { const dir = makeFixture(options); t.after(() => fs.rmSync(dir, { recursive: true, force: true })); return dir; } test('isComplete accepts a healthy same-version, same-arch install', (t) => { const dir = withFixture(t, { complete: true }); assert.equal(isComplete(dir), true); }); test('isComplete rejects a missing dist directory', (t) => { const dir = withFixture(t); assert.equal(isComplete(dir), false); }); test('isComplete rejects a stale/mismatched version', (t) => { const dir = withFixture(t, { complete: true, distVersion: '41.1.0' }); assert.equal(isComplete(dir), false); }); test('isComplete rejects a missing path.txt', (t) => { const dir = withFixture(t, { complete: true }); fs.rmSync(path.join(dir, 'path.txt')); assert.equal(isComplete(dir), false); }); test('isComplete rejects a binary of the wrong architecture', (t) => { const hostArch = expectedArch(); const otherArch = hostArch === 'arm64' ? 'x64' : 'arm64'; const dir = withFixture(t, { complete: true, arch: otherArch }); assert.equal(isComplete(dir), false); // With an expected arch matching the fixture the same install passes. assert.equal(isComplete(dir, otherArch), true); }); test('detectExecutableArch reads the header for both architectures', (t) => { const hostArch = expectedArch(); const otherArch = hostArch === 'arm64' ? 'x64' : 'arm64'; const hostDir = withFixture(t, { complete: true }); assert.equal(detectExecutableArch(path.join(hostDir, 'dist', platformPath())), hostArch); const otherDir = withFixture(t, { complete: true, arch: otherArch }); assert.equal(detectExecutableArch(path.join(otherDir, 'dist', platformPath())), otherArch); }); test('detectExecutableArch returns null for a non-executable file', (t) => { const dir = withFixture(t); const junk = path.join(dir, 'junk.bin'); fs.writeFileSync(junk, 'not a binary'); assert.equal(detectExecutableArch(junk), null); assert.equal(detectExecutableArch(path.join(dir, 'missing')), null); }); test('resolveElectronPackageDir locates the electron package in the monorepo', () => { const dir = resolveElectronPackageDir(); assert.ok(dir); const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8')); assert.equal(pkg.name, 'electron'); }); test('main returns 0 for a healthy install without attempting repair', async (t) => { const dir = withFixture(t, { complete: true, installScripts: { 'install.js': FAIL_SCRIPT } }); const env = { ...process.env, OPENCHAMBER_ELECTRON_PKG_DIR: dir, OPENCHAMBER_ELECTRON_INSTALL_COMMANDS: '[["node",["install.js"]]]', }; assert.equal(await main([], env), 0); // The failing install script never ran: dist was not rewritten. assert.equal(fs.readFileSync(path.join(dir, 'path.txt'), 'utf8').trim(), platformPath()); }); test('main repairs an incomplete install via the injected command', async (t) => { const dir = withFixture(t, { installScripts: { 'install.js': installScriptContent() } }); const env = { ...process.env, OPENCHAMBER_ELECTRON_PKG_DIR: dir, OPENCHAMBER_ELECTRON_INSTALL_COMMANDS: '[["node",["install.js"]]]', }; assert.equal(await main([], env), 0); assert.equal(isComplete(dir), true); }); test('main falls back from a failing first command to a succeeding second', async (t) => { const dir = withFixture(t, { installScripts: { 'install-fail.js': FAIL_SCRIPT, 'install-ok.js': installScriptContent(), }, }); const env = { ...process.env, OPENCHAMBER_ELECTRON_PKG_DIR: dir, OPENCHAMBER_ELECTRON_INSTALL_COMMANDS: '[["bun",["install-fail.js"]],["node",["install-ok.js"]]]', }; assert.equal(await main([], env), 0); assert.equal(isComplete(dir), true); }); test('main returns 1 when every repair command fails', async (t) => { const dir = withFixture(t, { installScripts: { 'install-fail-1.js': FAIL_SCRIPT, 'install-fail-2.js': FAIL_SCRIPT, }, }); const env = { ...process.env, OPENCHAMBER_ELECTRON_PKG_DIR: dir, OPENCHAMBER_ELECTRON_INSTALL_COMMANDS: '[["node",["install-fail-1.js"]],["node",["install-fail-2.js"]]]', }; assert.equal(await main([], env), 1); }); test('main --best-effort returns 0 when repair is impossible', async (t) => { const dir = withFixture(t, { installScripts: { 'install-fail.js': FAIL_SCRIPT } }); const env = { ...process.env, OPENCHAMBER_ELECTRON_PKG_DIR: dir, OPENCHAMBER_ELECTRON_INSTALL_COMMANDS: '[["node",["install-fail.js"]]]', }; assert.equal(await main(['--best-effort'], env), 0); }); test('main honors ELECTRON_SKIP_BINARY_DOWNLOAD and skips repair', async (t) => { const dir = withFixture(t, { installScripts: { 'install.js': installScriptContent() } }); const env = { ...process.env, OPENCHAMBER_ELECTRON_PKG_DIR: dir, OPENCHAMBER_ELECTRON_INSTALL_COMMANDS: '[["node",["install.js"]]]', ELECTRON_SKIP_BINARY_DOWNLOAD: '1', }; assert.equal(await main([], env), 1); assert.equal(fs.existsSync(path.join(dir, 'dist')), false); assert.equal(await main(['--best-effort'], env), 0); assert.equal(fs.existsSync(path.join(dir, 'dist')), false); }); test('main reports a missing electron package', async () => { const env = { ...process.env, OPENCHAMBER_ELECTRON_PKG_DIR: path.join(os.tmpdir(), 'does-not-exist-electron-pkg'), }; assert.equal(await main([], env), 1); assert.equal(await main(['--best-effort'], env), 0); }); test('repair skips a command whose runner errors and keeps trying the rest', (t) => { const dir = withFixture(t); const calls = []; const commands = [['bun', ['install.js']], ['node', ['install.js']]]; const result = repair(dir, { runner: (bin, args) => { calls.push([bin, args]); return { error: new Error('spawn failed') }; }, commands, }); assert.equal(result, false); // Exactly the injected commands were invoked, in order. assert.deepEqual(calls, commands); }); test('repair resolves Bun before invoking the install command', (t) => { const dir = withFixture(t); const calls = []; const resolvedBun = 'C:\\npm\\node_modules\\bun\\bin\\bun.exe'; const result = repair(dir, { env: { TEST_ENV: 'present' }, bunResolver: ({ env }) => { assert.equal(env.TEST_ENV, 'present'); return resolvedBun; }, runner: (bin, args, options) => { calls.push([bin, args, options.windowsHide]); if (bin !== resolvedBun) return { status: 1 }; const platform = platformPath(); fs.mkdirSync(path.join(dir, 'dist', path.dirname(platform)), { recursive: true }); fs.writeFileSync(path.join(dir, 'dist', 'version'), '41.2.1'); fs.writeFileSync(path.join(dir, 'path.txt'), platform); fs.writeFileSync(path.join(dir, 'dist', platform), headerBytesForArch(expectedArch())); return { status: 0 }; }, }); assert.equal(result, true); assert.deepEqual(calls, [[resolvedBun, ['install.js'], true]]); }); test('repair returns false when the runner reports a failure status for every command', (t) => { const dir = withFixture(t); const calls = []; const commands = [['bun', ['install.js']], ['node', ['install.js']]]; const result = repair(dir, { runner: (bin, args) => { calls.push([bin, args]); return { status: 1 }; }, commands, }); assert.equal(result, false); assert.deepEqual(calls, commands); }); test('repair runs injected commands in order and stops after the first success', (t) => { const dir = withFixture(t); const calls = []; const commands = [ ['bun', ['install-fail.js']], ['node', ['install-ok.js']], ['node', ['install-never.js']], ]; const result = repair(dir, { runner: (bin, args) => { calls.push([bin, args]); if (args[0] === 'install-ok.js') { // Simulate a successful postinstall: materialize a complete install so // isComplete() sees a healthy dist right after the command. const platform = platformPath(); fs.mkdirSync(path.join(dir, 'dist', path.dirname(platform)), { recursive: true }); fs.writeFileSync(path.join(dir, 'dist', 'version'), '41.2.1'); fs.writeFileSync(path.join(dir, 'path.txt'), platform); fs.writeFileSync(path.join(dir, 'dist', platform), headerBytesForArch(expectedArch())); return { status: 0 }; } return { status: 1 }; }, commands, }); assert.equal(result, true); // Only the failing and succeeding commands ran; the trailing one was skipped. assert.deepEqual(calls, commands.slice(0, 2)); assert.equal(isComplete(dir), true); });