import { test, after } from "node:test";
import assert from "node:assert/strict";
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
import os from "node:os";
import path from "node:path";
import { SourceRefusal } from "./sourceAudit";
import { escapeHtml, hrefFor, renderTreeIndex, sortEntries, writeTreeIndexes } from "./sourceTree";
// Run with:
// pnpm --filter yt-dlp-transcript-common test
//
// The raw tree's directory pages (sourceTree.ts): hrefs a static host can
// resolve for the repo's real bracketed names, escaped labels, the order,
// the relative breadcrumbs, and the refusals.
const TMP = mkdtempSync(path.join(os.tmpdir(), "source-tree-"));
after(() => rmSync(TMP, { recursive: true, force: true }));
const META = { mirrorHead: "0123456789abcdef0123456789abcdef01234567", generatedAt: "2026-09-28T12:00:00.000Z" };
test("hrefs are URL-encoded, a directory's with a trailing slash — the repo's brackets included", () => {
assert.equal(hrefFor({ name: "[slug]", dir: true }), "%5Bslug%5D/");
assert.equal(hrefFor({ name: "Archivo[wdth,wght].ttf", dir: false }), "Archivo%5Bwdth%2Cwght%5D.ttf");
assert.equal(hrefFor({ name: "a b#c?.md", dir: false }), "a%20b%23c%3F.md");
assert.equal(hrefFor({ name: "page.tsx", dir: false }), "page.tsx");
});
test("names are escaped wherever they are printed", () => {
assert.equal(escapeHtml(`&'`), "<a href="x">&'</a>");
const html = renderTreeIndex({
relDir: "x",
entries: [{ name: "");
await assert.rejects(
writeTreeIndexes(with404, META),
(e) => e instanceof SourceRefusal && /docs\/deep\/404\.html; Pages would serve it, as HTML/.test(e.message),
);
const withLink = path.join(TMP, "t3");
mkdirSync(withLink);
symlinkSync("/etc/hostname", path.join(withLink, "leak"));
await assert.rejects(writeTreeIndexes(withLink, META), (e) => e instanceof SourceRefusal && /symlink/.test(e.message));
});