// Regression for a real incident (2026-09-02): syncLibrary()'s rebuild path // only carried `likes` forward from the old record, silently resetting // playCount/lastPlayedAt to "never played" on every periodic sync (every // 5 min in server.js) for any clip that hadn't been touched in admin.html // (i.e. wasn't `edited: true`). Run: node --test ingest.test.js const test = require("node:test"); const assert = require("node:assert/strict"); const fs = require("node:fs"); const path = require("node:path"); const os = require("node:os"); const http = require("node:http"); function startMockH3(jobs) { return new Promise((resolve) => { const server = http.createServer((req, res) => { if (req.method === "GET" && req.url.startsWith("/v1/videos")) { res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ jobs })); return; } res.writeHead(404); res.end(); }); server.listen(0, () => resolve(server)); }); } test("syncLibrary: carries playCount/lastPlayedAt forward for non-edited clips, not just likes", async () => { const job = { id: "clip-1", status: "done", download: true, created_at: 1700000000, partition: "text", req: { prompt: "a long enough real prompt that will not match the isTestJob short-circuit ".repeat(3), width: 480, height: 832, frames: 240 }, }; const mockH3 = await startMockH3([job]); const mockH3Port = mockH3.address().port; const cwd = fs.mkdtempSync(path.join(os.tmpdir(), "ingest-test-")); fs.writeFileSync( path.join(cwd, "library.json"), JSON.stringify([{ id: "clip-1", source: "h3console", prompt: "old", fullPrompt: "old", edited: false, width: 480, height: 832, duration: 10, partition: "text", likes: 3, createdAt: 1000, lastPlayedAt: 123456, playCount: 7 }]) ); fs.copyFileSync(path.join(__dirname, "ingest.js"), path.join(cwd, "ingest.js")); process.env.H3_CONSOLE_BASE = `http://localhost:${mockH3Port}`; process.env.H3_CONSOLE_TOKEN = "mock-token"; delete require.cache[path.join(cwd, "ingest.js")]; const { syncLibrary } = require(path.join(cwd, "ingest.js")); const cwdBefore = process.cwd(); process.chdir(cwd); try { await syncLibrary(); } finally { process.chdir(cwdBefore); mockH3.close(); } const library = JSON.parse(fs.readFileSync(path.join(cwd, "library.json"), "utf8")); const clip = library.find((c) => c.id === "clip-1"); assert.equal(clip.likes, 3, "likes was already carried forward correctly"); assert.equal(clip.lastPlayedAt, 123456, "lastPlayedAt must survive a sync, not reset to unplayed"); assert.equal(clip.playCount, 7, "playCount must survive a sync, not reset to 0"); fs.rmSync(cwd, { recursive: true, force: true }); }); test("syncLibrary: a never-played clip stays without playCount/lastPlayedAt fields (no false '0 plays')", async () => { const job = { id: "clip-2", status: "done", download: true, created_at: 1700000000, partition: "text", req: { prompt: "a long enough real prompt that will not match the isTestJob short-circuit ".repeat(3), width: 480, height: 832, frames: 240 }, }; const mockH3 = await startMockH3([job]); const mockH3Port = mockH3.address().port; const cwd = fs.mkdtempSync(path.join(os.tmpdir(), "ingest-test-")); fs.writeFileSync(path.join(cwd, "library.json"), JSON.stringify([])); fs.copyFileSync(path.join(__dirname, "ingest.js"), path.join(cwd, "ingest.js")); process.env.H3_CONSOLE_BASE = `http://localhost:${mockH3Port}`; process.env.H3_CONSOLE_TOKEN = "mock-token"; delete require.cache[path.join(cwd, "ingest.js")]; const { syncLibrary } = require(path.join(cwd, "ingest.js")); const cwdBefore = process.cwd(); process.chdir(cwd); try { await syncLibrary(); } finally { process.chdir(cwdBefore); mockH3.close(); } const library = JSON.parse(fs.readFileSync(path.join(cwd, "library.json"), "utf8")); const clip = library.find((c) => c.id === "clip-2"); assert.equal("lastPlayedAt" in clip, false); assert.equal("playCount" in clip, false); fs.rmSync(cwd, { recursive: true, force: true }); });