import { test } from "node:test"; import assert from "node:assert/strict"; import path from "node:path"; import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import type { Paths } from "../lib/paths"; import { CUES_JSON_FILENAME, LIVE_CHAT_CUES_FILENAME, LIVE_CHAT_FILENAME, META_FILENAME, VTT_FILENAME, } from "../lib/videoStatus"; import { DUPLICATES_FILENAME } from "../lib/duplicates"; import { MEDIA_SCAN_FILENAME } from "../lib/mediaScan"; import { normalizeTranscript } from "./normalizeTranscript"; import { normalizeLiveChat } from "./normalizeLiveChat"; import { detectDuplicateShorts } from "./duplicateShorts"; import { scanCorruptMedia } from "./scanCorruptMedia"; // THE FOUR COMPACT WRITERS keep their historical bytes after the fold onto // writeJsonAtomic (release 4 slice W): each wrote `JSON.stringify(x)` — no // indent, NO trailing newline — and a reader-side diff (the phase-3 numbers // tools, a site's published bytes) would move if that changed. Each test pins // that the file on disk is exactly `JSON.stringify` of its own parse. async function withDir(fn: (dir: string) => Promise): Promise { const dir = await mkdtemp(path.join(tmpdir(), "compact-writers-")); try { await fn(dir); } finally { await rm(dir, { recursive: true, force: true }); } } function assertCompact(text: string, what: string): void { assert.ok(!text.endsWith("\n"), `${what}: no trailing newline`); assert.equal(text, JSON.stringify(JSON.parse(text)), `${what}: compact`); } async function videoDir(dir: string): Promise { const v = path.join(dir, "vid1"); await mkdir(v, { recursive: true }); await writeFile( path.join(v, META_FILENAME), JSON.stringify({ id: "vid1", title: "A video", duration: 60 }), ); return v; } test("normalizeTranscript writes transcript.cues.json compact, no newline", async () => { await withDir(async (dir) => { const v = await videoDir(dir); await writeFile( path.join(v, VTT_FILENAME), "WEBVTT\n\n00:00:00.000 --> 00:00:05.000\nhello\n", ); const out = await normalizeTranscript({ videoDir: v, channelSlug: "c" }); assert.equal(out.status, "wrote"); assertCompact(await readFile(path.join(v, CUES_JSON_FILENAME), "utf8"), "cues"); }); }); test("normalizeLiveChat writes the live-chat cues compact, no newline", async () => { await withDir(async (dir) => { const v = await videoDir(dir); await writeFile(path.join(v, LIVE_CHAT_FILENAME), ""); const out = await normalizeLiveChat({ videoDir: v, channelSlug: "c" }); assert.equal(out.status, "wrote"); assertCompact( await readFile(path.join(v, LIVE_CHAT_CUES_FILENAME), "utf8"), "live chat cues", ); }); }); function emptyCorpus(dir: string): Paths { return { transcriptsDir: dir, channelsDir: path.join(dir, "channels"), } as Paths; } test("detectDuplicateShorts writes duplicates.json compact, no newline", async () => { await withDir(async (dir) => { await mkdir(path.join(dir, "channels"), { recursive: true }); await detectDuplicateShorts({ paths: emptyCorpus(dir), onLog: () => {} }); assertCompact(await readFile(path.join(dir, DUPLICATES_FILENAME), "utf8"), "duplicates"); }); }); test("scanCorruptMedia writes media-scan.json compact, no newline", async () => { await withDir(async (dir) => { await mkdir(path.join(dir, "channels"), { recursive: true }); await scanCorruptMedia({ paths: emptyCorpus(dir), onLog: () => {} }); assertCompact(await readFile(path.join(dir, MEDIA_SCAN_FILENAME), "utf8"), "media scan"); }); });