import { test } from "node:test"; import assert from "node:assert/strict"; import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import os from "node:os"; import path from "node:path"; import type { Paths } from "../lib/paths"; import { asBuiltStamp, asIndexStamp, builtStampPath, deployRecordFor, deployedPath, imageBuildFacts, indexStampPath, newStampId, readBuiltStamp, readDeployedFile, readIndexStamp, recordDeploy, writeBuiltStamp, writeIndexStamp, type DeployRecord, } from "./stamps"; import { builtStamp, indexStamp } from "./__fixtures__/stamps"; // Run with: // pnpm --filter yt-dlp-transcript-common test // // The publish stamps (release 18): a round trip through disk, and the // tolerance every `needs()` relies on — a missing, unparseable or // wrongly-shaped stamp reads as null (stale), never as half a stamp. function tmpPaths(): { root: string; paths: Paths } { const root = mkdtempSync(path.join(os.tmpdir(), "stamps-")); return { root, paths: { exportIndexDir: path.join(root, ".export-index"), exportBuildsDir: path.join(root, ".export-builds"), } as Paths, }; } test("the three stamps live where the plan says", () => { const p = { exportIndexDir: "/e/.export-index", exportBuildsDir: "/e/.export-builds" } as Paths; assert.equal(indexStampPath(p), "/e/.export-index/stamp.json"); assert.equal(builtStampPath(p, "jer"), "/e/.export-builds/jer/built.json"); assert.equal(builtStampPath(p, "_hub"), "/e/.export-builds/_hub/built.json"); assert.equal(deployedPath(p, "_homepage"), "/e/.export-builds/_homepage/deployed.json"); }); test("stamps round-trip through disk", async () => { const { root, paths } = tmpPaths(); try { assert.equal(await readIndexStamp(paths), null, "no stamp yet"); await writeIndexStamp(paths, indexStamp()); assert.deepEqual(await readIndexStamp(paths), indexStamp()); await writeBuiltStamp(paths, builtStamp({ sourceCommit: null })); assert.deepEqual(await readBuiltStamp(paths, "jer"), builtStamp({ sourceCommit: null })); assert.equal(await readBuiltStamp(paths, "other"), null); } finally { rmSync(root, { recursive: true, force: true }); } }); test("a malformed or wrongly-shaped stamp reads as null", async () => { const { root, paths } = tmpPaths(); try { mkdirSync(paths.exportIndexDir, { recursive: true }); writeFileSync(indexStampPath(paths), "{not json"); assert.equal(await readIndexStamp(paths), null); writeFileSync(indexStampPath(paths), JSON.stringify({ ...indexStamp(), v: 2 })); assert.equal(await readIndexStamp(paths), null, "another version"); writeFileSync(indexStampPath(paths), JSON.stringify({ ...indexStamp(), hubSig: 3 })); assert.equal(await readIndexStamp(paths), null, "a field of the wrong type"); } finally { rmSync(root, { recursive: true, force: true }); } assert.equal(asIndexStamp(null), null); assert.equal(asIndexStamp([]), null); assert.equal(asIndexStamp({ ...indexStamp(), sites: { x: { inputSig: 1 } } }), null); assert.equal(asIndexStamp({ ...indexStamp(), index: { ...indexStamp().index, heldChannels: [1] } }), null); assert.equal(asBuiltStamp({ ...builtStamp(), kind: "export" }), null); assert.equal(asBuiltStamp({ ...builtStamp(), runner: "podman" }), null); assert.equal(asBuiltStamp({ ...builtStamp(), files: "10" }), null); assert.equal(asBuiltStamp({ ...builtStamp(), sourceCommit: 5 }), null); const { stampId: _drop, ...noId } = builtStamp(); assert.equal(asBuiltStamp(noId), null); }); test("recordDeploy keeps every other record, and deployRecordFor finds each kind", async () => { const { root, paths } = tmpPaths(); const rec = (over: Partial): DeployRecord => ({ builtStampId: "b1", builtAt: 3_000, kind: "production", url: "https://x.pages.dev", at: 4_000, liveCheck: null, ...over, }); try { await recordDeploy(paths, "jer", rec({})); await recordDeploy(paths, "jer", rec({ kind: "preview", branch: "r18", url: "https://r18.x.pages.dev" })); await recordDeploy(paths, "jer", rec({ kind: "local", url: null })); await recordDeploy(paths, "jer", rec({ kind: "preview", branch: "r19", builtStampId: "b2" })); const file = await readDeployedFile(paths, "jer"); assert.equal(deployRecordFor(file, "production")?.url, "https://x.pages.dev"); assert.equal(deployRecordFor(file, "preview", "r18")?.url, "https://r18.x.pages.dev"); assert.equal(deployRecordFor(file, "preview", "r19")?.builtStampId, "b2"); assert.equal(deployRecordFor(file, "preview", "nope"), null); assert.equal(deployRecordFor(file, "preview"), null); assert.equal(deployRecordFor(file, "local")?.url, null); assert.equal(deployRecordFor(null, "production"), null); // A malformed file is replaced, not merged. writeFileSync(deployedPath(paths, "jer"), "[]"); assert.equal(await readDeployedFile(paths, "jer"), null); await recordDeploy(paths, "jer", rec({ builtStampId: "b3" })); const again = JSON.parse(readFileSync(deployedPath(paths, "jer"), "utf8")); assert.deepEqual(Object.keys(again.previews), []); assert.equal(again.production.builtStampId, "b3"); } finally { rmSync(root, { recursive: true, force: true }); } }); test("imageBuildFacts: the image's commit and branch, empty = null", () => { assert.deepEqual(imageBuildFacts({ ARCHILYZER_COMMIT: " abc ", ARCHILYZER_BRANCH: "" }), { commit: "abc", branch: null }); assert.deepEqual(imageBuildFacts({}), { commit: null, branch: null }); assert.deepEqual(imageBuildFacts({ ARCHILYZER_COMMIT: "c", ARCHILYZER_BRANCH: "main" }), { commit: "c", branch: "main" }); }); test("newStampId is unique and sorts by time", () => { const a = newStampId(1_000); const b = newStampId(2_000); assert.notEqual(newStampId(1_000), a); assert.ok(a < b); });