|
| 1 | +import assert from "node:assert/strict"; |
| 2 | +import { existsSync, mkdirSync, mkdtempSync, writeFileSync } from "node:fs"; |
| 3 | +import { tmpdir } from "node:os"; |
| 4 | +import { join } from "node:path"; |
| 5 | +import test from "node:test"; |
| 6 | +import { stageAssets } from "./lib/assets.mjs"; |
| 7 | + |
| 8 | +// ── captured SVGs are stageable ────────────────────────────────────────────── |
| 9 | +// Regression: `hyperframes capture` extracts inline SVGs into capture/assets/svgs/ |
| 10 | +// (assetDownloader.ts), and the capture manifest advertises them to the agent as |
| 11 | +// `assets/svgs/<name>.svg`, so a frame names one in `asset_candidates` exactly as |
| 12 | +// it names a screenshot. stageAssets only searched capture/{assets,assets/videos, |
| 13 | +// screenshots}, so every captured SVG resolved to nothing — reported as a |
| 14 | +// non-fatal anomaly, and the frame 404'd the logo it had been told to use. |
| 15 | + |
| 16 | +function projectWithCapturedSvg() { |
| 17 | + const dir = mkdtempSync(join(tmpdir(), "product-launch-stage-assets-")); |
| 18 | + mkdirSync(join(dir, "capture/assets/svgs"), { recursive: true }); |
| 19 | + mkdirSync(join(dir, "capture/screenshots"), { recursive: true }); |
| 20 | + writeFileSync(join(dir, "capture/assets/svgs/brand-mark.svg"), "<svg/>"); |
| 21 | + writeFileSync(join(dir, "capture/screenshots/hero.png"), "png"); |
| 22 | + return dir; |
| 23 | +} |
| 24 | + |
| 25 | +const frames = [ |
| 26 | + { extra: { asset_candidates: "assets/svgs/brand-mark.svg — the mark; assets/hero.png — hero" } }, |
| 27 | +]; |
| 28 | + |
| 29 | +test("stages an SVG that capture wrote into capture/assets/svgs/", () => { |
| 30 | + const dir = projectWithCapturedSvg(); |
| 31 | + |
| 32 | + const { staged, wanted, anomalies } = stageAssets({ hyperframesDir: dir, frames }); |
| 33 | + |
| 34 | + assert.equal(wanted.size, 2); |
| 35 | + assert.equal(staged, 2, `expected both assets staged, got anomalies: ${anomalies.join("; ")}`); |
| 36 | + assert.deepEqual(anomalies, []); |
| 37 | + assert.ok(existsSync(join(dir, "assets/brand-mark.svg"))); |
| 38 | + assert.ok(existsSync(join(dir, "assets/hero.png"))); |
| 39 | +}); |
| 40 | + |
| 41 | +test("still reports an asset that exists nowhere under capture/", () => { |
| 42 | + const dir = projectWithCapturedSvg(); |
| 43 | + |
| 44 | + const { staged, anomalies } = stageAssets({ |
| 45 | + hyperframesDir: dir, |
| 46 | + frames: [{ extra: { asset_candidates: "assets/svgs/absent.svg — never captured" } }], |
| 47 | + }); |
| 48 | + |
| 49 | + assert.equal(staged, 0); |
| 50 | + assert.equal(anomalies.length, 1); |
| 51 | + assert.match(anomalies[0], /absent\.svg/); |
| 52 | +}); |
0 commit comments