import { describe, test, expect, beforeAll, afterAll } 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 { buildSvg } from "../src/render" import { loadFixture } from "./helpers/fixtures" const __dirname = path.dirname(fileURLToPath(import.meta.url)) const DRAW_IMAGE_DIR = path.resolve(__dirname, "..") const TMP = path.join(os.tmpdir(), `draw-image-optional-integration-${process.pid}`) beforeAll(() => { if (existsSync(TMP)) rmSync(TMP, { recursive: true, force: true }) mkdirSync(TMP, { recursive: true }) }) afterAll(() => { if (existsSync(TMP)) rmSync(TMP, { recursive: true, force: 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 }) } } function assertPng(filePath: string) { expect(existsSync(filePath), `PNG not found: ${filePath}`).toBe(true) const buf = readFileSync(filePath) 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) } describe("integration — optional subtitle and badge", () => { test("render without subtitle and without badge → valid PNG", () => { const brand = loadBrand(DRAW_IMAGE_DIR) const templateSvg = loadFixture("cover") const args = { template: "cover", title: "Bare" } const svg = buildSvg(templateSvg, brand, args, DRAW_IMAGE_DIR) const outPath = path.join(TMP, "bare.png") renderToPng(svg, outPath) assertPng(outPath) }) test("render with subtitle and badge → valid PNG", () => { const brand = loadBrand(DRAW_IMAGE_DIR) const templateSvg = loadFixture("cover") const args = { template: "cover", title: "Full", subtitle: "Sub Text", slots: { badge: "mic" }, } const svg = buildSvg(templateSvg, brand, args, DRAW_IMAGE_DIR) const outPath = path.join(TMP, "full.png") renderToPng(svg, outPath) assertPng(outPath) }) })