/ tests / elements / text.test.ts
text.test.ts
  1  import { StandardFonts, TextAlignment } from "@cantoo/pdf-lib";
  2  import { describe, expect, mock, test } from "bun:test";
  3  import { Text, text } from "~/elements/text";
  4  import { font } from "~/utils/fonts";
  5  
  6  // Mock PDFPage and PDFFont for testing
  7  const mockPDFFont = {
  8    heightAtSize: mock((size: number) => size),
  9    widthOfTextAtSize: mock((t: string, size: number) => t.length * size * 0.6)
 10  };
 11  
 12  const mockPDFPage = {
 13    doc: {
 14      defaultWordBreaks: /\s/g
 15    },
 16    drawText: mock(() => {}),
 17    getFont: mock(() => [mockPDFFont]),
 18    getHeight: mock(() => 800)
 19  };
 20  
 21  describe("Text", () => {
 22    describe("constructor", () => {
 23      test("should create Text instance with value", () => {
 24        const textElement = new Text("Hello World");
 25        expect(textElement).toBeInstanceOf(Text);
 26      });
 27    });
 28  
 29    describe("text helper function", () => {
 30      test("should create Text instance", () => {
 31        const textElement = text("Hello World");
 32        expect(textElement).toBeInstanceOf(Text);
 33      });
 34  
 35      test("should work with empty string", () => {
 36        const textElement = text("");
 37        expect(textElement).toBeInstanceOf(Text);
 38      });
 39  
 40      test("should work with multiline text", () => {
 41        const textElement = text("Line 1\nLine 2\nLine 3");
 42        expect(textElement).toBeInstanceOf(Text);
 43      });
 44    });
 45  
 46    describe("font method", () => {
 47      test("should set font and return instance for chaining", () => {
 48        const memoryFont = font(StandardFonts.Helvetica);
 49        const textElement = text("Hello");
 50        const result = textElement.font(memoryFont);
 51  
 52        expect(result).toBe(textElement);
 53      });
 54    });
 55  
 56    describe("text alignment methods", () => {
 57      test("should set text center alignment", () => {
 58        const textElement = text("Hello");
 59        const result = textElement.textCenter();
 60  
 61        expect(result).toBe(textElement);
 62      });
 63  
 64      test("should set text left alignment", () => {
 65        const textElement = text("Hello");
 66        const result = textElement.textLeft();
 67  
 68        expect(result).toBe(textElement);
 69      });
 70  
 71      test("should set text right alignment", () => {
 72        const textElement = text("Hello");
 73        const result = textElement.textRight();
 74  
 75        expect(result).toBe(textElement);
 76      });
 77  
 78      test("should chain alignment methods", () => {
 79        const textElement = text("Hello")
 80          .textCenter()
 81          .textLeft()
 82          .textRight();
 83  
 84        expect(textElement).toBeInstanceOf(Text);
 85      });
 86    });
 87  
 88    describe("leading methods", () => {
 89      test("should set line height with leading method", () => {
 90        const textElement = text("Hello");
 91        const result = textElement.leading(1.5);
 92  
 93        expect(result).toBe(textElement);
 94      });
 95  
 96      test("should set line height to 1 with leadingNone", () => {
 97        const textElement = text("Hello");
 98        const result = textElement.leadingNone();
 99  
100        expect(result).toBe(textElement);
101      });
102  
103      test("should chain leading methods", () => {
104        const textElement = text("Hello")
105          .leading(2.0)
106          .leadingNone()
107          .leading(1.2);
108  
109        expect(textElement).toBeInstanceOf(Text);
110      });
111    });
112  
113    describe("getLayoutNode", () => {
114      test("should create and return layout node", () => {
115        const textElement = text("Hello World");
116        const fonts = new Map();
117  
118        const node = textElement.getLayoutNode(mockPDFPage as any, fonts);
119  
120        expect(node).toBeDefined();
121        expect(typeof node.free).toBe("function");
122  
123        node.free();
124      });
125  
126      test("should return same node on subsequent calls", () => {
127        const textElement = text("Hello World");
128        const fonts = new Map();
129  
130        const node1 = textElement.getLayoutNode(mockPDFPage as any, fonts);
131        const node2 = textElement.getLayoutNode(mockPDFPage as any, fonts);
132  
133        expect(node1).toBe(node2);
134  
135        node1.free();
136      });
137  
138      test("should handle empty text", () => {
139        const textElement = text("");
140        const fonts = new Map();
141  
142        const node = textElement.getLayoutNode(mockPDFPage as any, fonts);
143  
144        expect(node).toBeDefined();
145  
146        node.free();
147      });
148    });
149  
150    describe("draw", () => {
151      test("should call drawText on page", () => {
152        const textElement = text("Hello World");
153        const fonts = new Map();
154  
155        // Create layout node first
156        const node = textElement.getLayoutNode(mockPDFPage as any, fonts);
157  
158        // Mock the computed dimensions
159        node.getComputedWidth = mock(() => 200);
160        node.getComputedHeight = mock(() => 50);
161  
162        textElement.draw(mockPDFPage as any, fonts);
163  
164        expect(mockPDFPage.drawText).toHaveBeenCalled();
165  
166        node.free();
167      });
168    });
169  
170    describe("method chaining", () => {
171      test("should support complete method chaining", () => {
172        const memoryFont = font(StandardFonts.Helvetica);
173  
174        const textElement = text("Hello World")
175          .font(memoryFont)
176          .textCenter()
177          .leading(1.5)
178          .leadingNone()
179          .textLeft()
180          .textRight();
181  
182        expect(textElement).toBeInstanceOf(Text);
183      });
184    });
185  });