Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105// E2E for `drawgent setup firefox` on Linux, with a fake `firefox` on PATH (it reports the// version we choose and logs what it is asked to open) and a throwaway HOME with a profile.// The embedded signed package → opened (permanent); --from-source on regular Firefox → temporary// add-on; on Nightly → unsigned allowed in the profile, then opened; a signed --xpi → opened;// a missing Firefox → a clear error.// node scripts/firefox-setup-e2e.mjs [path/to/drawgent]import { spawnSync } from "node:child_process";import fs from "node:fs";import os from "node:os";import path from "node:path";import zlib from "node:zlib";
const BIN = path.resolve(process.argv[2] || "./target/release/drawgent");const VERSION = JSON.parse(fs.readFileSync(new URL("../extension/manifest.json", import.meta.url), "utf8")).version;const checks = [];const ok = (name, cond, extra = "") => { checks.push(!!cond); console.log(`${cond ? "✓" : "✗"} ${name}${extra ? ` (${extra})` : ""}`); };
function sandbox(version) { const root = fs.mkdtempSync(path.join(os.tmpdir(), "dg-ff-")); const home = path.join(root, "home"), bin = path.join(root, "bin"), log = path.join(root, "opened.log"); const profile = path.join(home, ".mozilla/firefox/abcd.default-release"); fs.mkdirSync(profile, { recursive: true }); fs.mkdirSync(path.join(home, "Downloads")); fs.mkdirSync(bin); fs.writeFileSync(path.join(home, ".mozilla/firefox/profiles.ini"), "[Profile0]\nName=default-release\nIsRelative=1\nPath=abcd.default-release\n\n[Install4F96D1932A9F858E]\nDefault=abcd.default-release\nLocked=1\n"); const fake = path.join(bin, "firefox"); fs.writeFileSync(fake, `#!/bin/sh\nif [ "$1" = "--version" ]; then echo "Mozilla Firefox ${version}"; exit 0; fi\necho "$@" >> ${log}\n`, { mode: 0o755 }); const env = { ...process.env, HOME: home, PATH: `${bin}:/usr/bin:/bin`, DRAWGENT_CONFIG: path.join(root, "config.toml") }; const run = (...args) => spawnSync(BIN, ["setup", "firefox", ...args], { env, encoding: "utf8", timeout: 30000, stdio: ["ignore", "pipe", "pipe"] }); // setup hands things to Firefox without waiting for it: give the fake a moment to log. const opened = () => { const until = Date.now() + 3000; while (Date.now() < until && !fs.existsSync(log)) Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 50); Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 100); return fs.existsSync(log) ? fs.readFileSync(log, "utf8") : ""; }; const config = () => (fs.existsSync(env.DRAWGENT_CONFIG) ? fs.readFileSync(env.DRAWGENT_CONFIG, "utf8") : ""); return { root, home, profile, run, opened, config };}
/** File names in a zip (the central directory). */function zipNames(file) { const b = fs.readFileSync(file); const end = b.lastIndexOf(Buffer.from([0x50, 0x4b, 0x05, 0x06])); let o = b.readUInt32LE(end + 16); const names = []; while (b.readUInt32LE(o) === 0x02014b50) { const n = b.readUInt16LE(o + 28), x = b.readUInt16LE(o + 30), c = b.readUInt16LE(o + 32); names.push(b.slice(o + 46, o + 46 + n).toString()); o += 46 + n + x + c; } return names;}
// 1. Regular Firefox, with the signed package embedded in this build: permanent.{ const s = sandbox("131.0"); const r = s.run(); const xpi = path.join(s.home, `Downloads/drawgent-firefox-${VERSION}.xpi`); ok("regular Firefox: found, with its profile", r.status === 0 && r.stderr.includes("Mozilla Firefox 131.0") && r.stderr.includes("abcd.default-release"), r.stderr.split("\n").slice(0, 4).join(" / ")); ok("the signed package embedded in drawgent is used", r.stderr.includes("(signed)") && fs.existsSync(xpi) && zipNames(xpi).includes("META-INF/mozilla.rsa"), zipNames(xpi).filter((n) => n.startsWith("META-INF")).join(",")); ok("and opened in Firefox for a permanent install", s.opened().includes(xpi) && !s.opened().includes("about:debugging") && /install = "permanent"/.test(s.config())); ok("no preference is touched in the profile", !fs.existsSync(path.join(s.profile, "user.js")));}
// 1b. --from-source on regular Firefox: an unsigned build, so a temporary add-on.{ const s = sandbox("131.0"); const r = s.run("--from-source"); const xpi = path.join(s.home, `Downloads/drawgent-firefox-${VERSION}-unsigned.xpi`); ok("--from-source builds the package from the embedded sources into Downloads", fs.existsSync(xpi) && zipNames(xpi).includes("manifest.json") && !zipNames(xpi).some((n) => n.startsWith("META-INF")), zipNames(xpi).join(",")); ok("regular Firefox + unsigned: about:debugging for a temporary add-on, with the file to pick", s.opened().includes("about:debugging#/runtime/this-firefox") && r.stderr.includes("Load Temporary Add-on") && r.stderr.includes(xpi) && /install = "temporary"/.test(s.config()));}
// 2. Nightly: unsigned add-ons allowed in the profile, then the package is opened.{ const s = sandbox("132.0a1"); const r = s.run("--allow-unsigned", "--from-source"); const userjs = fs.existsSync(path.join(s.profile, "user.js")) ? fs.readFileSync(path.join(s.profile, "user.js"), "utf8") : ""; ok("Nightly: unsigned add-ons allowed in the profile's user.js", r.status === 0 && userjs.includes('user_pref("xpinstall.signatures.required", false);'), userjs.trim().split("\n").at(-1)); ok("then the package is opened in Firefox (permanent install)", s.opened().includes(`drawgent-firefox-${VERSION}-unsigned.xpi`) && /install = "permanent"/.test(s.config())); s.run("--allow-unsigned", "--from-source"); ok("running it again doesn't repeat the preference", fs.readFileSync(path.join(s.profile, "user.js"), "utf8").split("xpinstall.signatures.required").length === 2);}
// 3. A signed package: opened directly, whatever the edition.{ const s = sandbox("131.0"); const signed = path.join(s.root, "signed.xpi"); fs.writeFileSync(signed, zlib.gzipSync("pretend signed")); const r = s.run("--xpi", signed); ok("signed --xpi: opened in Firefox for a permanent install", r.status === 0 && s.opened().includes(`drawgent-firefox-${VERSION}.xpi`) && !s.opened().includes("about:debugging") && /install = "permanent"/.test(s.config()));}
// 4. A Firefox that isn't there (the machine may have a system Firefox, so name one).{ const s = sandbox("131.0"); const r = s.run("--firefox", path.join(s.root, "no-such-firefox")); ok("a missing Firefox: says so", r.status !== 0 && r.stderr.includes("doesn't run as Firefox"), r.stderr.trim().split("\n").at(-1));}
const failed = checks.filter((c) => !c).length;console.log(failed ? `FIREFOX SETUP E2E FAILED (${failed})` : "FIREFOX SETUP E2E OK");process.exit(failed ? 1 : 0);