import { mkdir, readFile, rm, writeFile } from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { afterEach, describe, expect, it } from "vitest"; import { PDFDocument, StandardFonts } from "pdf-lib"; import { PNG } from "pngjs"; import { getHandler } from "../engine/registry"; import type { CatalogComponent, FlowNode } from "../types"; import type { RunContext } from "../engine/types"; import "./pdf"; const directories: string[] = []; const context = {} as RunContext; const component = {} as CatalogComponent; const node = (id: string): FlowNode => ({ id, componentId: id, position: { x: 0, y: 0 }, values: {}, options: {} }); async function run(id: string, args: Record) { const handler = getHandler(id); expect(handler, id).toBeTruthy(); return handler!(context, node(id), args, component); } afterEach(async () => Promise.all(directories.splice(0).map((directory) => rm(directory, { recursive: true, force: true })))); describe("PDF high-level capabilities", () => { it("creates a pdf fixture", async () => { const directory = await mkdtempSafe(); const pdf = await PDFDocument.create(); const page = pdf.addPage([220, 120]); const font = await pdf.embedFont(StandardFonts.Helvetica); const png = new PNG({ width: 8, height: 8 }); png.data.fill(255); png.data[0] = 20; png.data[1] = 90; png.data[2] = 200; png.data[3] = 255; page.drawImage(await pdf.embedPng(PNG.sync.write(png)), { x: 140, y: 70, width: 40, height: 40 }); for (const [value, x, y] of [["Name", 24, 90], ["Age", 120, 90], ["Alice", 24, 72], ["30", 120, 72]] as Array<[string, number, number]>) page.drawText(value, { x, y, size: 9, font }); await writeFile(path.join(directory, "source.pdf"), await pdf.save()); const filePath = path.join(directory, "source.pdf"); expect((await readFile(path.join(directory, "source.pdf"))).byteLength).toBeGreaterThan(0); const images = await run("PDF_GetPdfImg", { fileInPath: filePath, pdfRange: "all", pdfNum: "1", imgSavePath: directory, imageType: "png" }) as string[]; expect(images.length).toBeGreaterThan(0); expect((await readFile(images[0])).subarray(0, 4)).toEqual(Buffer.from([0x89, 0x50, 0x4e, 0x47])); await expect(run("PDF_GetPdfTable", { fileInPath: filePath, pdfRange: "all", pdfNum: "1" })).resolves.toEqual([["Name", "Age"], ["Alice", "30"]]); const encryptedPath = path.join(directory, "encrypted.pdf"); await writeFile(encryptedPath, await readFile(filePath)); await expect(run("PDF_PdfEncryption", { fileInPath: encryptedPath, passWord: "secret" })).resolves.toBe(encryptedPath); const pdfjs = await import("pdfjs-dist/legacy/build/pdf.mjs"); const opened = await pdfjs.getDocument({ data: new Uint8Array(await readFile(encryptedPath)), password: "secret" }).promise; expect(opened.numPages).toBe(1); }, 60000); }); async function mkdtempSafe(): Promise { const directory = await (await import("node:fs/promises")).mkdtemp(path.join(os.tmpdir(), "rpa-pdf-high-")); directories.push(directory); return directory; }