Files
glagolify/tests/package-extension.test.js
2026-08-08 19:39:47 +02:00

87 lines
3.2 KiB
JavaScript

"use strict";
const test = require("node:test");
const assert = require("node:assert/strict");
const { createHash } = require("node:crypto");
const { mkdtemp, readFile, rm } = require("node:fs/promises");
const os = require("node:os");
const path = require("node:path");
const { inflateRawSync } = require("node:zlib");
const {
ARCHIVE_FILES,
normalizeVersion,
packageExtension
} = require("../scripts/package-extension.js");
function readZipEntries(archive) {
const entries = new Map();
let offset = 0;
while (archive.readUInt32LE(offset) === 0x04034b50) {
const method = archive.readUInt16LE(offset + 8);
const compressedSize = archive.readUInt32LE(offset + 18);
const nameLength = archive.readUInt16LE(offset + 26);
const extraLength = archive.readUInt16LE(offset + 28);
const nameStart = offset + 30;
const dataStart = nameStart + nameLength + extraLength;
const name = archive.subarray(nameStart, nameStart + nameLength).toString("utf8");
const compressed = archive.subarray(dataStart, dataStart + compressedSize);
assert.equal(method, 8, `${name} should use DEFLATE compression`);
entries.set(name, inflateRawSync(compressed));
offset = dataStart + compressedSize;
}
assert.equal(archive.readUInt32LE(offset), 0x02014b50, "central directory is present");
return entries;
}
test("normalizes release tags and rejects versions Firefox cannot publish", () => {
assert.equal(normalizeVersion("1.2.3"), "1.2.3");
assert.equal(normalizeVersion("v2.0"), "2.0");
assert.equal(normalizeVersion("V3"), "3");
for (const version of ["", "v", "1.2.3.4.5", "1.02", "1.0-beta", "1000000000"]) {
assert.throws(() => normalizeVersion(version), /Invalid Mozilla extension version|required/);
}
});
test("builds a deterministic unsigned XPI with the release version and runtime files only", async (context) => {
const rootDirectory = path.resolve(__dirname, "..");
const firstOutput = await mkdtemp(path.join(os.tmpdir(), "glagolify-package-"));
const secondOutput = await mkdtemp(path.join(os.tmpdir(), "glagolify-package-"));
context.after(async () => {
await Promise.all([
rm(firstOutput, { recursive: true, force: true }),
rm(secondOutput, { recursive: true, force: true })
]);
});
const first = await packageExtension({
rootDirectory,
outputDirectory: firstOutput,
version: "v9.8.7"
});
const second = await packageExtension({
rootDirectory,
outputDirectory: secondOutput,
version: "9.8.7"
});
const firstArchive = await readFile(first.archivePath);
const secondArchive = await readFile(second.archivePath);
const entries = readZipEntries(firstArchive);
assert.equal(first.archiveName, "glagolify-9.8.7.xpi");
assert.deepEqual([...entries.keys()], [...ARCHIVE_FILES]);
assert.equal(JSON.parse(entries.get("manifest.json")).version, "9.8.7");
assert.equal(entries.has("package.json"), false);
assert.equal(entries.has("tests/package-extension.test.js"), false);
assert.deepEqual(firstArchive, secondArchive);
const digest = createHash("sha256").update(firstArchive).digest("hex");
assert.equal(
await readFile(first.checksumPath, "utf8"),
`${digest} glagolify-9.8.7.xpi\n`
);
});