import { test } from "node:test"; import assert from "node:assert/strict"; import { existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, symlinkSync, utimesSync, writeFileSync, } from "node:fs"; import { tmpdir } from "node:os"; import path from "node:path"; import { copyPublicFile, ownDir, writePublicFile } from "./_publicFile"; // Run with: // pnpm --filter yt-dlp-transcript-common test // // A worktree's export/public entries are symlinks into the primary checkout; a // compose run there must write into the worktree and leave the primary's files // exactly as they were. const OLD = new Date("2026-09-25T20:47:37Z"); // A "primary" dir holding the real file and dir, and a "worktree" public dir // whose entries are links to them. function fixture() { const root = mkdtempSync(path.join(tmpdir(), "public-file-")); const primary = path.join(root, "primary"); const worktree = path.join(root, "worktree"); mkdirSync(path.join(primary, "subs"), { recursive: true }); mkdirSync(worktree, { recursive: true }); writeFileSync(path.join(primary, "hub-sites.json"), "[live pool]"); writeFileSync(path.join(primary, "subs", "manifest.json"), "live subs"); utimesSync(path.join(primary, "hub-sites.json"), OLD, OLD); symlinkSync(path.join(primary, "hub-sites.json"), path.join(worktree, "hub-sites.json")); symlinkSync(path.join(primary, "subs"), path.join(worktree, "subs")); return { root, primary, worktree, cleanup: () => rmSync(root, { recursive: true, force: true }) }; } test("writePublicFile replaces a link with a file and leaves its target as it was", async () => { const { primary, worktree, cleanup } = fixture(); try { await writePublicFile(path.join(worktree, "hub-sites.json"), "[]"); const at = path.join(worktree, "hub-sites.json"); assert.ok(lstatSync(at).isFile()); assert.equal(readFileSync(at, "utf8"), "[]"); const target = path.join(primary, "hub-sites.json"); assert.equal(readFileSync(target, "utf8"), "[live pool]"); assert.equal(statSync(target).mtimeMs, OLD.getTime()); } finally { cleanup(); } }); test("writePublicFile over a real file or a dangling link just writes it", async () => { const { root, worktree, cleanup } = fixture(); try { const real = path.join(worktree, "corpus.json"); writeFileSync(real, "old"); await writePublicFile(real, "new"); assert.equal(readFileSync(real, "utf8"), "new"); const dangling = path.join(worktree, "llms.txt"); symlinkSync(path.join(root, "nowhere", "llms.txt"), dangling); await writePublicFile(dangling, "text"); assert.ok(lstatSync(dangling).isFile()); assert.equal(readFileSync(dangling, "utf8"), "text"); assert.ok(!existsSync(path.join(root, "nowhere"))); } finally { cleanup(); } }); test("copyPublicFile replaces a link with a copy and leaves its target as it was", async () => { const { root, primary, worktree, cleanup } = fixture(); try { const src = path.join(root, "sw-hub.js"); writeFileSync(src, "hub worker"); await copyPublicFile(src, path.join(worktree, "hub-sites.json")); assert.ok(lstatSync(path.join(worktree, "hub-sites.json")).isFile()); assert.equal(readFileSync(path.join(worktree, "hub-sites.json"), "utf8"), "hub worker"); assert.equal(readFileSync(path.join(primary, "hub-sites.json"), "utf8"), "[live pool]"); } finally { cleanup(); } }); test("ownDir replaces a linked dir with an empty real one, keeps a real one, creates a missing one", async () => { const { primary, worktree, cleanup } = fixture(); try { const linked = path.join(worktree, "subs"); await ownDir(linked); assert.ok(lstatSync(linked).isDirectory()); assert.deepEqual(readdirSync(linked), []); assert.equal(readFileSync(path.join(primary, "subs", "manifest.json"), "utf8"), "live subs"); writeFileSync(path.join(linked, "keep.json"), "{}"); await ownDir(linked); assert.deepEqual(readdirSync(linked), ["keep.json"]); const missing = path.join(worktree, "posts"); await ownDir(missing); assert.ok(lstatSync(missing).isDirectory()); } finally { cleanup(); } });