pdf.test.ts
1 import { StandardFonts } from "@cantoo/pdf-lib"; 2 import { describe, expect, mock, test } from "bun:test"; 3 import { div } from "~/elements/div"; 4 import { page } from "~/elements/page"; 5 import { PDF, pdf } from "~/elements/pdf"; 6 import { text } from "~/elements/text"; 7 import { font } from "~/utils/fonts"; 8 9 // Mock PDFDocument 10 const mockPDFDocument = { 11 addJavaScript: mock(() => {}), 12 addPage: mock(() => ({ 13 drawRectangle: mock(() => {}), 14 drawText: mock(() => {}), 15 getFont: mock(() => [{}]), 16 getHeight: mock(() => 841.8898), 17 getWidth: mock(() => 595.276), 18 setSize: mock(() => {}) 19 })), 20 embedFont: mock(async () => ({})), 21 save: mock(async () => new Uint8Array([1, 2, 3, 4])), 22 setAuthor: mock(() => {}) 23 }; 24 25 // Mock PDFDocument.create for each test 26 const mockPDFDocumentCreate = mock(async () => mockPDFDocument); 27 28 describe("PDF", () => { 29 describe("constructor and helper function", () => { 30 test("should create PDF instance", () => { 31 const pdfElement = new PDF(); 32 expect(pdfElement).toBeInstanceOf(PDF); 33 }); 34 35 test("should create PDF instance with helper function", () => { 36 const pdfElement = pdf(); 37 expect(pdfElement).toBeInstanceOf(PDF); 38 }); 39 }); 40 41 describe("author method", () => { 42 test("should set author and return instance for chaining", () => { 43 const pdfElement = pdf(); 44 const result = pdfElement.author("John Doe"); 45 46 expect(result).toBe(pdfElement); 47 }); 48 49 test("should chain multiple author calls", () => { 50 const pdfElement = pdf() 51 .author("John Doe") 52 .author("Jane Smith"); 53 54 expect(pdfElement).toBeInstanceOf(PDF); 55 }); 56 }); 57 58 describe("child management", () => { 59 test("should add page child and return instance for chaining", () => { 60 const pdfElement = pdf(); 61 const pageElement = page(); 62 63 const result = pdfElement.child(pageElement); 64 65 expect(result).toBe(pdfElement); 66 }); 67 68 test("should add multiple page children", () => { 69 const pdfElement = pdf(); 70 const page1 = page(); 71 const page2 = page(); 72 73 pdfElement.child(page1).child(page2); 74 75 expect(pdfElement).toBeInstanceOf(PDF); 76 }); 77 }); 78 79 describe("font management", () => { 80 test("should add font and return instance for chaining", () => { 81 const pdfElement = pdf(); 82 const memoryFont = font(StandardFonts.Helvetica); 83 84 const result = pdfElement.font(memoryFont); 85 86 expect(result).toBe(pdfElement); 87 }); 88 89 test("should add multiple fonts", () => { 90 const pdfElement = pdf(); 91 const font1 = font(StandardFonts.Helvetica); 92 const font2 = font(StandardFonts.TimesRoman); 93 94 pdfElement.font(font1).font(font2); 95 96 expect(pdfElement).toBeInstanceOf(PDF); 97 }); 98 }); 99 100 describe("script management", () => { 101 test("should add JavaScript and return instance for chaining", () => { 102 const pdfElement = pdf(); 103 const result = pdfElement.script("myScript", "console.log('Hello');"); 104 105 expect(result).toBe(pdfElement); 106 }); 107 108 test("should add multiple scripts", () => { 109 const pdfElement = pdf(); 110 111 pdfElement 112 .script("script1", "console.log('Script 1');") 113 .script("script2", "console.log('Script 2');"); 114 115 expect(pdfElement).toBeInstanceOf(PDF); 116 }); 117 }); 118 119 describe("renderToBytes", () => { 120 test("should be an async method that returns Promise<Uint8Array>", () => { 121 const pdfElement = pdf(); 122 123 const result = pdfElement.renderToBytes(); 124 125 expect(result).toBeInstanceOf(Promise); 126 }); 127 128 test("should handle empty PDF without throwing", async () => { 129 const pdfElement = pdf(); 130 131 // Test that the method doesn't throw - we can't easily test the actual PDF creation 132 // without complex mocking of the pdf-lib import 133 expect(() => pdfElement.renderToBytes()).not.toThrow(); 134 }); 135 }); 136 137 describe("method chaining", () => { 138 test("should support complete method chaining", () => { 139 const memoryFont = font(StandardFonts.Helvetica); 140 const pageElement = page() 141 .child(div().w(200).h(100).bg(0xFF0000)) 142 .child(text("Hello World")); 143 144 const pdfElement = pdf() 145 .author("Test Author") 146 .font(memoryFont) 147 .script("init", "console.log('PDF loaded');") 148 .child(pageElement) 149 .author("Updated Author"); // Should override 150 151 expect(pdfElement).toBeInstanceOf(PDF); 152 }); 153 }); 154 155 describe("integration scenarios", () => { 156 test("should handle complex PDF structure", () => { 157 const font1 = font(StandardFonts.Helvetica); 158 const font2 = font(StandardFonts.TimesRoman); 159 160 const page1 = page() 161 .size([600, 800]) 162 .child(text("Page 1 Header").font(font1)) 163 .child(div().w(500).h(200).bg(0x333333)); 164 165 const page2 = page() 166 .size([600, 800]) 167 .child(text("Page 2 Content").font(font2)) 168 .child(div().w(500).h(300).bg(0x666666)); 169 170 const pdfElement = pdf() 171 .author("Complex PDF Author") 172 .font(font1) 173 .font(font2) 174 .script("analytics", "trackPDFView();") 175 .child(page1) 176 .child(page2); 177 178 expect(pdfElement).toBeInstanceOf(PDF); 179 }); 180 }); 181 });