opencode-config/.opencode/draw-image/tests/render.optional.integration.test.ts
Sergey 8c00346b76
fix(draw-image): per-process temp dir in renderToPng test helpers (#184)
* fix(draw-image): per-process temp dir in renderToPng test helpers

* docs(handoff): add handoff and ADR for renderToPng temp dir fix

* docs(project-map): note per-process temp dir fix in renderToPng helpers

* docs(handoff): set PR number

* docs(handoff): replace PR number placeholder in frontmatter

---------

Co-authored-by: opencode-agent <agent@opencode.local>
2026-07-31 22:28:04 +03:00

71 lines
2.6 KiB
TypeScript

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 } from "../src/render"
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const DRAW_IMAGE_DIR = path.resolve(__dirname, "..")
const TMP = "/tmp/draw-image-optional-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 })
}
}
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 = loadTemplate(DRAW_IMAGE_DIR, "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 = loadTemplate(DRAW_IMAGE_DIR, "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)
})
})