/ tests / elements / div.test.ts
div.test.ts
  1  import { describe, expect, mock, test } from "bun:test";
  2  import { Align, Display, FlexDirection, Justify, Overflow, PositionType } from "yoga-layout";
  3  import { Div, div } from "~/elements/div";
  4  
  5  // Mock PDFPage for testing
  6  const mockPDFPage = {
  7    drawRectangle: mock(() => {}),
  8    getHeight: mock(() => 800)
  9  };
 10  
 11  describe("Div", () => {
 12    describe("constructor and helper function", () => {
 13      test("should create Div instance", () => {
 14        const divElement = new Div();
 15        expect(divElement).toBeInstanceOf(Div);
 16      });
 17  
 18      test("should create Div instance with helper function", () => {
 19        const divElement = div();
 20        expect(divElement).toBeInstanceOf(Div);
 21      });
 22    });
 23  
 24    describe("children management", () => {
 25      test("should have empty children array initially", () => {
 26        const divElement = div();
 27        expect(divElement.children).toEqual([]);
 28      });
 29  
 30      test("should add child and return instance for chaining", () => {
 31        const parent = div();
 32        const child = div();
 33  
 34        const result = parent.child(child);
 35  
 36        expect(result).toBe(parent);
 37        expect(parent.children).toContain(child);
 38      });
 39  
 40      test("should add multiple children", () => {
 41        const parent = div();
 42        const child1 = div();
 43        const child2 = div();
 44  
 45        parent.child(child1).child(child2);
 46  
 47        expect(parent.children).toEqual([child1, child2]);
 48      });
 49    });
 50  
 51    describe("positioning methods", () => {
 52      test("should set absolute positioning", () => {
 53        const divElement = div();
 54        const result = divElement.absolute();
 55  
 56        expect(result).toBe(divElement);
 57      });
 58  
 59      test("should set relative positioning", () => {
 60        const divElement = div();
 61        const result = divElement.relative();
 62  
 63        expect(result).toBe(divElement);
 64      });
 65    });
 66  
 67    describe("background color", () => {
 68      test("should set background color", () => {
 69        const divElement = div();
 70        const result = divElement.bg(0xFF0000); // Red
 71  
 72        expect(result).toBe(divElement);
 73      });
 74  
 75      test("should chain background color calls", () => {
 76        const divElement = div()
 77          .bg(0xFF0000)
 78          .bg(0x00FF00)
 79          .bg(0x0000FF);
 80  
 81        expect(divElement).toBeInstanceOf(Div);
 82      });
 83    });
 84  
 85    describe("display methods", () => {
 86      test("should set flex display", () => {
 87        const divElement = div();
 88        const result = divElement.flex();
 89  
 90        expect(result).toBe(divElement);
 91      });
 92    });
 93  
 94    describe("flex direction methods", () => {
 95      test("should set flex row direction", () => {
 96        const divElement = div();
 97        const result = divElement.flexRow();
 98  
 99        expect(result).toBe(divElement);
100      });
101  
102      test("should set flex row reverse direction", () => {
103        const divElement = div();
104        const result = divElement.flexRowReverse();
105  
106        expect(result).toBe(divElement);
107      });
108  
109      test("should set flex column direction", () => {
110        const divElement = div();
111        const result = divElement.flexCol();
112  
113        expect(result).toBe(divElement);
114      });
115  
116      test("should set flex column reverse direction", () => {
117        const divElement = div();
118        const result = divElement.flexColReverse();
119  
120        expect(result).toBe(divElement);
121      });
122    });
123  
124    describe("alignment methods", () => {
125      test("should set items center alignment", () => {
126        const divElement = div();
127        const result = divElement.itemsCenter();
128  
129        expect(result).toBe(divElement);
130      });
131  
132      test("should set items start alignment", () => {
133        const divElement = div();
134        const result = divElement.itemsStart();
135  
136        expect(result).toBe(divElement);
137      });
138  
139      test("should set justify center", () => {
140        const divElement = div();
141        const result = divElement.justifyCenter();
142  
143        expect(result).toBe(divElement);
144      });
145  
146      test("should set justify start", () => {
147        const divElement = div();
148        const result = divElement.justifyStart();
149  
150        expect(result).toBe(divElement);
151      });
152    });
153  
154    describe("size methods", () => {
155      test("should set width", () => {
156        const divElement = div();
157        const result = divElement.w(200);
158  
159        expect(result).toBe(divElement);
160      });
161  
162      test("should set full width", () => {
163        const divElement = div();
164        const result = divElement.wFull();
165  
166        expect(result).toBe(divElement);
167      });
168  
169      test("should set height", () => {
170        const divElement = div();
171        const result = divElement.h(150);
172  
173        expect(result).toBe(divElement);
174      });
175  
176      test("should set full height", () => {
177        const divElement = div();
178        const result = divElement.hFull();
179  
180        expect(result).toBe(divElement);
181      });
182    });
183  
184    describe("flex properties", () => {
185      test("should set grow to 1", () => {
186        const divElement = div();
187        const result = divElement.grow1();
188  
189        expect(result).toBe(divElement);
190      });
191  
192      test("should set shrink to 0", () => {
193        const divElement = div();
194        const result = divElement.shrink0();
195  
196        expect(result).toBe(divElement);
197      });
198  
199      test("should set shrink to 1", () => {
200        const divElement = div();
201        const result = divElement.shrink1();
202  
203        expect(result).toBe(divElement);
204      });
205    });
206  
207    describe("overflow methods", () => {
208      test("should set overflow hidden", () => {
209        const divElement = div();
210        const result = divElement.overflowHidden();
211  
212        expect(result).toBe(divElement);
213      });
214    });
215  
216    describe("getLayoutNode", () => {
217      test("should create and return layout node", () => {
218        const divElement = div();
219        const fonts = new Map();
220  
221        const node = divElement.getLayoutNode(mockPDFPage as any, fonts);
222  
223        expect(node).toBeDefined();
224        expect(typeof node.free).toBe("function");
225  
226        node.free();
227      });
228  
229      test("should return same node on subsequent calls", () => {
230        const divElement = div();
231        const fonts = new Map();
232  
233        const node1 = divElement.getLayoutNode(mockPDFPage as any, fonts);
234        const node2 = divElement.getLayoutNode(mockPDFPage as any, fonts);
235  
236        expect(node1).toBe(node2);
237  
238        node1.free();
239      });
240  
241      test("should handle children layout nodes", () => {
242        const parent = div();
243        const child = div();
244        parent.child(child);
245  
246        const fonts = new Map();
247        const node = parent.getLayoutNode(mockPDFPage as any, fonts);
248  
249        expect(node).toBeDefined();
250        expect(node.getChildCount()).toBe(1);
251  
252        node.free();
253      });
254    });
255  
256    describe("draw", () => {
257      test("should call drawRectangle when background color is set", () => {
258        const divElement = div().bg(0xFF0000);
259        const fonts = new Map();
260  
261        // Create layout node first
262        const node = divElement.getLayoutNode(mockPDFPage as any, fonts);
263  
264        // Mock the computed dimensions
265        node.getComputedWidth = mock(() => 200);
266        node.getComputedHeight = mock(() => 100);
267  
268        divElement.draw(mockPDFPage as any, fonts);
269  
270        expect(mockPDFPage.drawRectangle).toHaveBeenCalled();
271  
272        node.free();
273      });
274  
275      test("should draw children elements", () => {
276        const parent = div();
277        const child = div().bg(0x00FF00);
278        parent.child(child);
279  
280        const fonts = new Map();
281  
282        // Create layout nodes
283        const parentNode = parent.getLayoutNode(mockPDFPage as any, fonts);
284        parentNode.getComputedWidth = mock(() => 300);
285        parentNode.getComputedHeight = mock(() => 200);
286  
287        parent.draw(mockPDFPage as any, fonts);
288  
289        // Should be called at least once for the child
290        expect(mockPDFPage.drawRectangle).toHaveBeenCalled();
291  
292        parentNode.free();
293      });
294    });
295  
296    describe("method chaining", () => {
297      test("should support complex method chaining", () => {
298        const divElement = div()
299          .flex()
300          .flexRow()
301          .itemsCenter()
302          .justifyCenter()
303          .w(200)
304          .h(100)
305          .bg(0x123456)
306          .grow1()
307          .shrink0()
308          .absolute()
309          .overflowHidden();
310  
311        expect(divElement).toBeInstanceOf(Div);
312      });
313  
314      test("should chain with children", () => {
315        const child1 = div().w(50).h(50).bg(0xFF0000);
316        const child2 = div().w(50).h(50).bg(0x00FF00);
317  
318        const parent = div()
319          .flex()
320          .flexRow()
321          .child(child1)
322          .child(child2)
323          .w(200)
324          .h(100);
325  
326        expect(parent).toBeInstanceOf(Div);
327        expect(parent.children).toHaveLength(2);
328      });
329    });
330  });