import assert from "node:assert/strict"; import { spawnSync } from "node:child_process"; import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import test from "node:test"; const workflowScripts = [ ["product-launch-video", new URL("./transitions.mjs", import.meta.url).pathname], ["pr-to-video", new URL("../../pr-to-video/scripts/transitions.mjs", import.meta.url).pathname], ]; function runInject(script, rootId) { const project = mkdtempSync(join(tmpdir(), "hf-transition-root-")); const framesDir = join(project, "compositions", "frames"); mkdirSync(framesDir, { recursive: true }); writeFileSync( join(project, "STORYBOARD.md"), `---\nformat: 1920x1080\n---\n\n## Frame 1 — First\n\n- duration: 3s\n- transition_in: cut\n- src: compositions/frames/frame-01.html\n\n## Frame 2 — Second\n\n- duration: 3s\n- transition_in: crossfade 0.5s\n- src: compositions/frames/frame-02.html\n`, ); writeFileSync( join(framesDir, "frame-01.html"), `
`, ); writeFileSync( join(framesDir, "frame-02.html"), '
', ); writeFileSync( join(project, "index.html"), `
`, ); const result = spawnSync( process.execPath, [script, "inject", "--storyboard", join(project, "STORYBOARD.md"), "--hyperframes", project], { encoding: "utf8" }, ); return { project, result, frameHtml: () => readFileSync(join(framesDir, "frame-01.html"), "utf8"), }; } for (const [workflow, script] of workflowScripts) { test(`${workflow} inserts duration on a valid durationless frame root`, () => { const fixture = runInject(script, "frame-01"); try { assert.equal(fixture.result.status, 0, fixture.result.stderr); assert.match(fixture.frameHtml(), /data-composition-id="frame-01"[^>]*data-duration="3\.5"/); } finally { rmSync(fixture.project, { recursive: true, force: true }); } }); test(`${workflow} still rejects a genuinely mismatched frame root`, () => { const fixture = runInject(script, "wrong-root"); try { assert.notEqual(fixture.result.status, 0); assert.match(fixture.result.stderr, /has no data-composition-id="frame-01" root/); } finally { rmSync(fixture.project, { recursive: true, force: true }); } }); }