const assert = require("node:assert/strict"); const { test } = require("node:test"); const fs = require("node:fs/promises"); const os = require("node:os"); const path = require("node:path"); const vm = require("node:vm"); const { writeOutput } = require("../scripts/write-output.cjs"); test("build output keeps the previous script available until complete replacement", async t => { const folder = await fs.mkdtemp(path.join(os.tmpdir(), "opportunities-build-")); t.after(() => fs.rm(folder, { recursive: true, force: true })); const file = path.join(folder, "background.js"); await writeOutput(file, "old script"); await writeOutput(file, "new script", { ...fs, async rename(from, to) { assert.equal(await fs.readFile(to, "utf8"), "old script"); assert.equal(await fs.readFile(from, "utf8"), "new script"); return fs.rename(from, to); } }); assert.equal(await fs.readFile(file, "utf8"), "new script"); await writeOutput(file, "new script", { ...fs, writeFile() { assert.fail("Unchanged scripts must not be rewritten"); } }); for (const operation of ["writeFile", "rename"]) { await assert.rejects(writeOutput(file, "failed update", { ...fs, async [operation]() { throw new Error("Synthetic publication failure"); } }), /Synthetic publication failure/); assert.equal(await fs.readFile(file, "utf8"), "new script"); assert.deepEqual(await fs.readdir(folder), ["background.js"]); } }); test("packaged background scripts start and register listeners without DOM or network", async () => { for (const target of ["chromium", "firefox"]) { const folder = path.join(__dirname, "../dist", target); const manifest = JSON.parse(await fs.readFile(path.join(folder, "manifest.json"), "utf8")); const files = manifest.background.scripts || [manifest.background.service_worker]; const listeners = []; const api = { runtime: { onMessage: { addListener: handler => listeners.push(handler) } } }; const context = vm.createContext({ [target === "firefox" ? "browser" : "chrome"]: api, setTimeout, fetch() { assert.fail("No startup network requests"); } }); for (const file of files) { new vm.Script(await fs.readFile(path.join(folder, file), "utf8"), { filename: file }).runInContext(context); } assert.equal(listeners.length, 1, target); for (const entry of manifest.content_scripts) { for (const file of entry.js) new vm.Script(await fs.readFile(path.join(folder, file), "utf8")); } } });