import { describe, test, expect, beforeAll } from "vitest" import { existsSync, readFileSync, rmSync, mkdirSync, writeFileSync, mkdtempSync } from "node:fs" import path from "node:path" import os from "node:os" import { fileURLToPath } from "node:url" import { spawnSync } from "node:child_process" import { loadBrand } from "../src/config" import { loadTemplate, buildSvg, computeHash } from "../src/render" const __dirname = path.dirname(fileURLToPath(import.meta.url)) const DRAW_IMAGE_DIR = path.resolve(__dirname, "..") const TMP = "/tmp/draw-image-integration" beforeAll(() => { if (existsSync(TMP)) rmSync(TMP, { recursive: true, force: true }) mkdirSync(TMP, { recursive: true }) }) function renderToPng(svg: string, outPath: string): void { const tmpDir = mkdtempSync(path.join(os.tmpdir(), `draw-image-test-${process.pid}-`)) const tmpSvg = path.join(tmpDir, "input.svg") try { writeFileSync(tmpSvg, svg) const r = spawnSync("node", [path.join(DRAW_IMAGE_DIR, "render.mjs"), tmpSvg, outPath], { encoding: "utf-8", }) if (r.status !== 0) throw new Error(`render.mjs failed: ${r.stderr || r.stdout}`) } finally { if (existsSync(tmpDir)) rmSync(tmpDir, { recursive: true, force: true }) } } describe("integration — render pipeline", () => { test("renders valid PNG 1024x1024", () => { const brand = loadBrand(DRAW_IMAGE_DIR) const templateSvg = loadTemplate(DRAW_IMAGE_DIR, "cover") const args = { template: "cover", title: "Test", out: path.join(TMP, "cover.png") } const hash = computeHash(brand, templateSvg, args) const svg = buildSvg(templateSvg, brand, args, DRAW_IMAGE_DIR) const outPath = path.join(TMP, "cover.png") renderToPng(svg, outPath) expect(existsSync(outPath)).toBe(true) const buf = readFileSync(outPath) expect(buf[0]).toBe(0x89) expect(buf[1]).toBe(0x50) expect(buf[2]).toBe(0x4e) expect(buf[3]).toBe(0x47) const width = buf.readUInt32BE(16) const height = buf.readUInt32BE(20) expect(width, `PNG width should be 1024, got ${width}`).toBe(1024) expect(height, `PNG height should be 1024, got ${height}`).toBe(1024) expect(hash).toHaveLength(64) }) test("creates output directory recursively", () => { const brand = loadBrand(DRAW_IMAGE_DIR) const templateSvg = loadTemplate(DRAW_IMAGE_DIR, "cover") const args = { template: "cover", title: "Deep", out: path.join(TMP, "a", "b", "c", "cover.png") } const svg = buildSvg(templateSvg, brand, args, DRAW_IMAGE_DIR) const outPath = path.join(TMP, "a", "b", "c", "cover.png") renderToPng(svg, outPath) expect(existsSync(outPath)).toBe(true) }) })