Files
healer-man/scripts/content/content-objects.test.mjs
T
2026-09-20 19:27:37 -04:00

54 lines
3.6 KiB
JavaScript

import assert from "node:assert/strict";
import { createHash } from "node:crypto";
import { mkdtemp, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import test from "node:test";
import { gunzipSync } from "node:zlib";
import { prepareContentObjects } from "./content-objects.mjs";
import { selectBootstrapContent } from "./prepare-bootstrap.mjs";
import { createContentManifest } from "./publish-content.mjs";
import contentPolicy from "../../shared/content-policy.json" with { type: "json" };
test("ships one lossless object for identical assets and verifies original bytes", async () => {
const directory = await mkdtemp(path.join(os.tmpdir(), "healer-content-compression-"));
try {
const sourcePath = path.join(directory, "original.glb");
const original = Buffer.from("original geometry, textures, and animation\n".repeat(4096));
await writeFile(sourcePath, original);
const common = { sourcePath, bytes: original.length, sha256: createHash("sha256").update(original).digest("hex"), extension: ".glb" };
const files = ["first", "second"].map((id) => ({ ...common, logicalPath: `assets/creatures/${id}/model.glb`, packId: `creatures:${id}` }));
const result = await prepareContentObjects(files, { directory: path.join(directory, "objects"), baseUrl: "/content/bundled" });
assert.equal(result.uniqueObjects, 1);
assert.equal(result.uniqueBytes, original.length);
assert.equal(result.logicalBytes, original.length * 2);
assert.ok(result.storedBytes < original.length / 10);
assert.equal((await readdir(path.join(directory, "objects"))).length, 1);
assert.deepEqual(result.files[0].download, result.files[1].download);
assert.ok(result.files[0].download.url.endsWith(".gzip"), "avoid Android's automatic .gz expansion");
const stored = await readFile(path.join(directory, "objects", path.basename(result.files[0].download.url)));
assert.deepEqual(gunzipSync(stored), original);
assert.deepEqual(await readFile(sourcePath), original);
const again = await prepareContentObjects(files, { directory: path.join(directory, "objects"), baseUrl: "/content/bundled" });
assert.equal(again.writtenObjects, 0);
assert.equal(createContentManifest(result.files).version, createContentManifest(again.files).version);
await writeFile(sourcePath, "changed");
await assert.rejects(prepareContentObjects(files, { directory: path.join(directory, "objects"), baseUrl: "/content/bundled" }), /changed during packaging/);
} finally { await rm(directory, { recursive: true, force: true }); }
});
test("bundles only starter packs and their exact dependencies", () => {
const ids = [...contentPolicy.bootstrapPackIds, "dungeon:second", "shared:creatures", "manastorm:shared-map", "manastorm:optional-map", "characters:extra"];
const files = ids.map((packId, index) => ({ logicalPath: `assets/${index}.glb`, packId, sha256: String(index).repeat(64), bytes: 100, extension: ".glb" }));
const result = selectBootstrapContent(files, [
{ id: "dungeon:second", dependencies: [] },
]);
assert.deepEqual(result.files.map((file) => file.packId), contentPolicy.bootstrapPackIds);
const packs = new Map(result.packDefinitions.map((pack) => [pack.id, pack]));
assert.deepEqual([...packs.keys()].sort(), [...contentPolicy.bootstrapPackIds].sort());
assert.equal([...packs.values()].every((pack) => pack.bundledOnAndroid), true);
assert.equal(packs.has("dungeon:second"), false);
assert.equal(packs.has("manastorm:shared-map"), false);
assert.equal(packs.has("manastorm:optional-map"), false);
});