import test from "node:test"; import assert from "node:assert/strict"; import { chmod, mkdir, mkdtemp, rm, writeFile } from "node:fs/promises"; import os from "node:os"; import path from "node:path"; // Run with: // pnpm -C editor exec tsx --test "app/api/media/fetch-window/route.test.ts" // // The refusals that come before any action runs, and the two cached answers — // both read the disk only, so a temp corpus and a stand-in ffprobe are the // whole world: no job is queued and nothing is fetched. const ROOT = await mkdtemp(path.join(os.tmpdir(), "fetch-window-route-")); const SLUG = "demo-channel"; const VIDEO_DIR = path.join(ROOT, "channels", SLUG, "data", "abc123"); // Set before the route (and getPaths, which caches) is first imported. process.env.WORKER_TOKEN = "test-token"; process.env.TRANSCRIPTS_DIR = ROOT; process.env.SETTINGS_FILE = path.join(ROOT, "settings.json"); process.env.FFPROBE_BIN = path.join(ROOT, "ffprobe"); await writeFile(process.env.FFPROBE_BIN, "#!/bin/sh\necho 1080\n"); await chmod(process.env.FFPROBE_BIN, 0o755); await mkdir(path.join(VIDEO_DIR, "clips"), { recursive: true }); await writeFile( path.join(ROOT, "channels", SLUG, "config.json"), JSON.stringify({ name: "Demo", handling: "youtube", url: "https://www.youtube.com/@demo" }), ); const { POST } = await import("./route"); test.after(() => rm(ROOT, { recursive: true, force: true })); function post(body: Record): Promise { return POST( new Request("http://localhost/api/media/fetch-window", { method: "POST", headers: { authorization: "Bearer test-token", "content-type": "application/json", }, body: JSON.stringify(body), }), ); } const base = { channelSlug: "demo-channel", videoId: "abc123", requestedBy: "test", from: 10, to: 20, }; test("maxHeight out of range, fractional or not a number is refused with 400", async () => { for (const maxHeight of [143, 2161, 720.5, "720", 0, -1]) { for (const full of [false, true]) { const res = await post({ ...base, full, maxHeight }); assert.equal(res.status, 400, `${JSON.stringify(maxHeight)} full=${full}`); const body = (await res.json()) as { error: string }; assert.match(body.error, /maxHeight must be a whole number of pixels from 144 to 2160/); } } }); test("a cached window answers with its probed height", async () => { await writeFile(path.join(VIDEO_DIR, "clips", "5.00-25.00.mp4"), "not really an mp4"); const res = await post({ ...base, maxHeight: 720 }); assert.equal(res.status, 200); const body = (await res.json()) as Record; assert.equal(body.cached, true); assert.equal(body.from, 5); assert.equal(body.to, 25); // Taller than the cap asked for: the answer says so, it does not refetch. assert.equal(body.height, 1080); }); test("a cached whole recording answers with the height its persist recorded", async () => { const store = path.join(ROOT, "saved-videos", SLUG, "abc123"); await mkdir(store, { recursive: true }); await writeFile(path.join(store, "abc123.mp4"), "x"); const pointer = (format?: unknown) => writeFile( path.join(VIDEO_DIR, "saved-video.json"), JSON.stringify({ storedAt: "", dir: store, file: "abc123.mp4", bytes: 1, format }), ); await pointer({ preset: "original", height: 1080, vcodec: "avc1" }); let res = await post({ ...base, full: true, maxHeight: 720 }); assert.equal(res.status, 200); let body = (await res.json()) as Record; assert.equal(body.file, path.join(store, "abc123.mp4")); assert.equal(body.height, 1080); // A pointer from before formats were recorded: no height, rather than a guess. await pointer(undefined); res = await post({ ...base, full: true }); body = (await res.json()) as Record; assert.equal(res.status, 200); assert.equal("height" in body, false); }); test("an ask for a window a queued job will already write answers that job, and starts none", async () => { // A fabricated fetch-window job for 295–330 of abc123, held queued behind a // running holder on its queue (release 19, A5). const { getRegistry } = await import("yt-dlp-transcript-common/jobs/registry"); const reg = getRegistry(); const make = (id: string, params: Record) => { const record = { id, kind: "fetch-window", queueKey: "clips:youtube", channelSlug: SLUG, status: "queued" as const, queuedAt: Date.now(), logPath: "/dev/null", spec: { kind: "fetch-window", slug: SLUG, params }, }; reg.register(record); reg.enqueue(record, { start: () => {}, onCancel: () => {} }); }; make("HOLD", { videoId: "zzz", from: 0, to: 1 }); make("WIN5", { videoId: "abc123", from: 295, to: 330 }); const before = reg.list().length; try { const res = await post({ ...base, from: 300, to: 310 }); assert.equal(res.status, 202); const body = (await res.json()) as Record; assert.equal(body.jobId, "WIN5"); assert.equal(body.existing, true); assert.equal(body.from, 295); assert.equal(body.to, 330); assert.match(String(body.file), /clips\/295\.00-330\.00\.mp4$/); assert.equal(reg.list().length, before, "no second job"); } finally { reg.cancel("WIN5"); reg.forceRelease("HOLD"); } });