/** * Tests for src/modules/pdf-utils/injectPdfMetadata.ts * * Uses pdf-lib to create a real in-memory PDF and verifies * metadata injection behavior. */ import { describe, test, expect } from "bun:test"; import { PDFDocument } from "pdf-lib"; import { injectPdfMetadata, type DownloadMetadata, } from "../../src/modules/pdf-utils/injectPdfMetadata"; async function createBlankPdf(keywords?: string): Promise { const doc = await PDFDocument.create(); doc.addPage([612, 792]); if (keywords) { doc.setKeywords([keywords]); } return doc.save(); } describe("injectPdfMetadata", () => { test("injects required metadata keywords into a blank PDF", async () => { const pdfBytes = await createBlankPdf(); const metadata: DownloadMetadata = { downloadedAt: "2026-03-01T12:00:00Z", downloadedById: "user-42", }; const result = await injectPdfMetadata(pdfBytes, metadata); // Result should be a Uint8Array (valid PDF) expect(result).toBeInstanceOf(Uint8Array); expect(result.length).toBeGreaterThan(0); // Re-parse and check keywords const doc = await PDFDocument.load(result); const keywords = doc.getKeywords(); expect(keywords).toContain("downloadedAt:2026-03-01T12:00:00Z"); expect(keywords).toContain("downloadedById:user-42"); }); test("appends to existing keywords with separator", async () => { const existingKeywords = "createdBy:system; theme:default"; const pdfBytes = await createBlankPdf(existingKeywords); const metadata: DownloadMetadata = { downloadedAt: "2026-03-01T12:00:00Z", downloadedById: "user-42", }; const result = await injectPdfMetadata(pdfBytes, metadata); const doc = await PDFDocument.load(result); const keywords = doc.getKeywords() ?? ""; // Should start with existing keywords expect(keywords).toContain("createdBy:system; theme:default"); // Should have separator then new keywords expect(keywords).toContain("; downloadedAt:"); expect(keywords).toContain("downloadedById:user-42"); }); test("includes optional name and email when provided", async () => { const pdfBytes = await createBlankPdf(); const metadata: DownloadMetadata = { downloadedAt: "2026-03-01T12:00:00Z", downloadedById: "user-42", downloadedByName: "Jane Doe", downloadedByEmail: "jane@example.com", }; const result = await injectPdfMetadata(pdfBytes, metadata); const doc = await PDFDocument.load(result); const keywords = doc.getKeywords() ?? ""; expect(keywords).toContain("downloadedByName:Jane Doe"); expect(keywords).toContain("downloadedByEmail:jane@example.com"); }); test("omits optional name/email when not provided", async () => { const pdfBytes = await createBlankPdf(); const metadata: DownloadMetadata = { downloadedAt: "2026-03-01T12:00:00Z", downloadedById: "user-42", }; const result = await injectPdfMetadata(pdfBytes, metadata); const doc = await PDFDocument.load(result); const keywords = doc.getKeywords() ?? ""; expect(keywords).not.toContain("downloadedByName"); expect(keywords).not.toContain("downloadedByEmail"); }); test("updates ModificationDate (save() applies current time by default)", async () => { const pdfBytes = await createBlankPdf(); const metadata: DownloadMetadata = { downloadedAt: "2026-03-01T12:00:00Z", downloadedById: "user-42", }; const before = Date.now(); const result = await injectPdfMetadata(pdfBytes, metadata); const after = Date.now(); const doc = await PDFDocument.load(result); const modDate = doc.getModificationDate(); expect(modDate).toBeInstanceOf(Date); // pdf-lib's save() overrides ModificationDate with current time (updateMetadata defaults to true), // so we just verify the date is recent rather than matching downloadedAt exactly. expect(modDate!.getTime()).toBeGreaterThanOrEqual(before - 2000); expect(modDate!.getTime()).toBeLessThanOrEqual(after + 2000); }); test("works with Buffer input", async () => { const pdfBytes = await createBlankPdf(); const bufferInput = Buffer.from(pdfBytes); const metadata: DownloadMetadata = { downloadedAt: "2026-03-01T12:00:00Z", downloadedById: "user-1", }; const result = await injectPdfMetadata(bufferInput, metadata); expect(result).toBeInstanceOf(Uint8Array); const doc = await PDFDocument.load(result); const keywords = doc.getKeywords() ?? ""; expect(keywords).toContain("downloadedById:user-1"); }); });