1pub mod border;
6pub mod column;
7pub mod grid;
8pub mod types;
9
10pub use types::{
11 BorderCollapse, CellCollapsedBorders, CollapsedBorder, ColumnInfo, ColumnWidth, GridCell,
12 TableLayout, TableLayoutMode,
13};
14
15#[cfg(test)]
16mod tests {
17 use super::*;
18 use crate::area::{AreaId, AreaTree};
19 use fop_types::Length;
20
21 #[test]
22 fn test_table_layout_creation() {
23 let layout = TableLayout::new(Length::from_pt(500.0));
24 assert_eq!(layout.available_width, Length::from_pt(500.0));
25 }
26
27 #[test]
28 fn test_fixed_width_single_column() {
29 let layout = TableLayout::new(Length::from_pt(500.0));
30 let columns = vec![ColumnWidth::Fixed(Length::from_pt(200.0))];
31
32 let widths = layout.compute_fixed_widths(&columns);
33
34 assert_eq!(widths.len(), 1);
35 assert_eq!(widths[0], Length::from_pt(200.0));
36 }
37
38 #[test]
39 fn test_fixed_width_proportional() {
40 let layout = TableLayout::new(Length::from_pt(500.0));
41 let columns = vec![
42 ColumnWidth::Proportional(1.0),
43 ColumnWidth::Proportional(2.0),
44 ];
45
46 let widths = layout.compute_fixed_widths(&columns);
47
48 assert_eq!(widths.len(), 2);
49 assert!(widths[0].to_pt() < widths[1].to_pt());
52 }
53
54 #[test]
55 fn test_fixed_width_mixed() {
56 let layout = TableLayout::new(Length::from_pt(500.0));
57 let columns = vec![
58 ColumnWidth::Fixed(Length::from_pt(100.0)),
59 ColumnWidth::Proportional(1.0),
60 ColumnWidth::Proportional(1.0),
61 ];
62
63 let widths = layout.compute_fixed_widths(&columns);
64
65 assert_eq!(widths.len(), 3);
66 assert_eq!(widths[0], Length::from_pt(100.0));
67 assert_eq!(widths[1], widths[2]);
69 }
70
71 #[test]
72 fn test_create_grid() {
73 let layout = TableLayout::new(Length::from_pt(500.0));
74 let grid = layout.create_grid(3, 4);
75
76 assert_eq!(grid.len(), 3);
77 assert_eq!(grid[0].len(), 4);
78 assert!(grid[0][0].is_none());
79 }
80
81 #[test]
82 fn test_place_cell() {
83 let layout = TableLayout::new(Length::from_pt(500.0));
84 let mut grid = layout.create_grid(3, 3);
85
86 let cell = GridCell {
87 row: 0,
88 col: 0,
89 rowspan: 1,
90 colspan: 1,
91 content_id: None,
92 };
93
94 layout
95 .place_cell(&mut grid, cell)
96 .expect("test: should succeed");
97 assert!(grid[0][0].is_some());
98 }
99
100 #[test]
101 fn test_place_cell_with_colspan() {
102 let layout = TableLayout::new(Length::from_pt(500.0));
103 let mut grid = layout.create_grid(3, 3);
104
105 let cell = GridCell {
106 row: 0,
107 col: 0,
108 rowspan: 1,
109 colspan: 2,
110 content_id: None,
111 };
112
113 layout
114 .place_cell(&mut grid, cell)
115 .expect("test: should succeed");
116 assert!(grid[0][0].is_some());
117 assert!(grid[0][1].is_some()); assert!(grid[0][2].is_none()); }
120
121 #[test]
122 fn test_auto_width_with_column_info() {
123 let layout = TableLayout::new(Length::from_pt(500.0));
124 let column_info = vec![
125 ColumnInfo {
126 width_spec: ColumnWidth::Auto,
127 computed_width: Length::ZERO,
128 min_width: Length::from_pt(50.0),
129 max_width: Length::from_pt(150.0),
130 },
131 ColumnInfo {
132 width_spec: ColumnWidth::Fixed(Length::from_pt(200.0)),
133 computed_width: Length::ZERO,
134 min_width: Length::from_pt(200.0),
135 max_width: Length::from_pt(200.0),
136 },
137 ];
138
139 let widths = layout.compute_auto_widths(&column_info);
140
141 assert_eq!(widths.len(), 2);
142 assert_eq!(widths[1], Length::from_pt(200.0)); assert!(widths[0] > Length::ZERO); }
145
146 #[test]
147 fn test_table_layout_mode_default() {
148 let layout = TableLayout::new(Length::from_pt(500.0));
149 assert_eq!(layout.layout_mode(), TableLayoutMode::Fixed);
150 }
151
152 #[test]
153 fn test_table_layout_mode_auto() {
154 let layout =
155 TableLayout::new(Length::from_pt(500.0)).with_layout_mode(TableLayoutMode::Auto);
156 assert_eq!(layout.layout_mode(), TableLayoutMode::Auto);
157 }
158
159 #[test]
160 fn test_column_info_new() {
161 let info = ColumnInfo::new(ColumnWidth::Auto);
162 assert!(matches!(info.width_spec, ColumnWidth::Auto));
163 assert_eq!(info.min_width, Length::ZERO);
164 assert_eq!(info.max_width, Length::ZERO);
165 }
166
167 #[test]
168 fn test_column_info_with_widths() {
169 let info = ColumnInfo::with_widths(
170 ColumnWidth::Auto,
171 Length::from_pt(50.0),
172 Length::from_pt(200.0),
173 );
174 assert_eq!(info.min_width, Length::from_pt(50.0));
175 assert_eq!(info.max_width, Length::from_pt(200.0));
176 }
177
178 #[test]
179 fn test_auto_width_plenty_of_space() {
180 let layout = TableLayout::new(Length::from_pt(1000.0));
181 let column_info = vec![
182 ColumnInfo::with_widths(
183 ColumnWidth::Auto,
184 Length::from_pt(50.0),
185 Length::from_pt(100.0),
186 ),
187 ColumnInfo::with_widths(
188 ColumnWidth::Auto,
189 Length::from_pt(60.0),
190 Length::from_pt(120.0),
191 ),
192 ];
193
194 let widths = layout.compute_auto_widths(&column_info);
195
196 assert_eq!(widths[0], Length::from_pt(100.0));
198 assert_eq!(widths[1], Length::from_pt(120.0));
199 }
200
201 #[test]
202 fn test_auto_width_tight_space() {
203 let layout = TableLayout::new(Length::from_pt(200.0));
204 let column_info = vec![
205 ColumnInfo::with_widths(
206 ColumnWidth::Auto,
207 Length::from_pt(50.0),
208 Length::from_pt(100.0),
209 ),
210 ColumnInfo::with_widths(
211 ColumnWidth::Auto,
212 Length::from_pt(60.0),
213 Length::from_pt(120.0),
214 ),
215 ];
216
217 let widths = layout.compute_auto_widths(&column_info);
218
219 assert!(widths[0] >= Length::from_pt(50.0));
221 assert!(widths[0] <= Length::from_pt(100.0));
222 assert!(widths[1] >= Length::from_pt(60.0));
223 assert!(widths[1] <= Length::from_pt(120.0));
224 }
225
226 #[test]
227 fn test_auto_width_with_fixed_columns() {
228 let layout = TableLayout::new(Length::from_pt(500.0));
229 let column_info = vec![
230 ColumnInfo::with_widths(
231 ColumnWidth::Fixed(Length::from_pt(150.0)),
232 Length::ZERO,
233 Length::ZERO,
234 ),
235 ColumnInfo::with_widths(
236 ColumnWidth::Auto,
237 Length::from_pt(50.0),
238 Length::from_pt(200.0),
239 ),
240 ColumnInfo::with_widths(
241 ColumnWidth::Auto,
242 Length::from_pt(50.0),
243 Length::from_pt(200.0),
244 ),
245 ];
246
247 let widths = layout.compute_auto_widths(&column_info);
248
249 assert_eq!(widths[0], Length::from_pt(150.0));
251 assert!(widths[1] > Length::ZERO);
253 assert!(widths[2] > Length::ZERO);
254 }
255
256 #[test]
257 fn test_measure_column_widths() {
258 let layout = TableLayout::new(Length::from_pt(500.0));
259 let grid = layout.create_grid(2, 3);
260
261 let (min, max) = layout.measure_column_widths(&grid, 0);
262
263 assert!(min >= Length::ZERO);
265 assert!(max >= min);
266 }
267
268 #[test]
269 fn test_update_column_info_from_grid() {
270 let layout = TableLayout::new(Length::from_pt(500.0));
271 let mut column_info = vec![
272 ColumnInfo::new(ColumnWidth::Auto),
273 ColumnInfo::new(ColumnWidth::Fixed(Length::from_pt(100.0))),
274 ];
275 let mut grid = layout.create_grid(2, 2);
276
277 let cell = GridCell {
279 row: 0,
280 col: 0,
281 rowspan: 1,
282 colspan: 1,
283 content_id: None,
284 };
285 layout
286 .place_cell(&mut grid, cell)
287 .expect("test: should succeed");
288
289 layout.update_column_info_from_grid(&mut column_info, &grid);
290
291 assert!(column_info[0].min_width > Length::ZERO);
293 assert!(column_info[0].max_width >= column_info[0].min_width);
294 assert_eq!(column_info[1].min_width, Length::ZERO);
296 }
297
298 #[test]
299 fn test_distribute_colspan_widths() {
300 let layout = TableLayout::new(Length::from_pt(500.0));
301 let mut column_info = vec![
302 ColumnInfo::new(ColumnWidth::Auto),
303 ColumnInfo::new(ColumnWidth::Auto),
304 ];
305
306 let mut grid = layout.create_grid(1, 2);
307 let cell = GridCell {
308 row: 0,
309 col: 0,
310 rowspan: 1,
311 colspan: 2,
312 content_id: None,
313 };
314 layout
315 .place_cell(&mut grid, cell)
316 .expect("test: should succeed");
317
318 layout.distribute_colspan_widths(&mut column_info, &grid);
319
320 assert!(column_info[0].min_width > Length::ZERO);
322 assert!(column_info[1].min_width > Length::ZERO);
323 }
324
325 #[test]
326 fn test_border_collapse_default() {
327 let layout = TableLayout::new(Length::from_pt(500.0));
328 assert_eq!(layout.border_collapse(), BorderCollapse::Separate);
329 }
330
331 #[test]
332 fn test_border_collapse_setting() {
333 let layout =
334 TableLayout::new(Length::from_pt(500.0)).with_border_collapse(BorderCollapse::Collapse);
335 assert_eq!(layout.border_collapse(), BorderCollapse::Collapse);
336 }
337
338 #[test]
339 fn test_fixed_widths_with_collapsed_borders() {
340 let layout =
341 TableLayout::new(Length::from_pt(500.0)).with_border_collapse(BorderCollapse::Collapse);
342 let columns = vec![
343 ColumnWidth::Fixed(Length::from_pt(100.0)),
344 ColumnWidth::Fixed(Length::from_pt(200.0)),
345 ];
346
347 let widths = layout.compute_fixed_widths(&columns);
348
349 assert_eq!(widths[0], Length::from_pt(100.0));
352 assert_eq!(widths[1], Length::from_pt(200.0));
353 }
354
355 #[test]
356 fn test_fixed_widths_with_separate_borders() {
357 let layout = TableLayout::new(Length::from_pt(500.0))
358 .with_border_spacing(Length::from_pt(5.0))
359 .with_border_collapse(BorderCollapse::Separate);
360 let columns = vec![
361 ColumnWidth::Fixed(Length::from_pt(100.0)),
362 ColumnWidth::Fixed(Length::from_pt(200.0)),
363 ];
364
365 let widths = layout.compute_fixed_widths(&columns);
366
367 assert_eq!(widths[0], Length::from_pt(100.0));
369 assert_eq!(widths[1], Length::from_pt(200.0));
370 }
371
372 #[test]
373 fn test_border_conflict_resolution_hidden() {
374 use crate::area::BorderStyle;
375 let layout = TableLayout::new(Length::from_pt(500.0));
376
377 let border1 = CollapsedBorder::new(
378 Length::from_pt(2.0),
379 fop_types::Color::RED,
380 BorderStyle::Hidden,
381 );
382 let border2 = CollapsedBorder::new(
383 Length::from_pt(5.0),
384 fop_types::Color::BLUE,
385 BorderStyle::Solid,
386 );
387
388 let result = layout.resolve_border_conflict(border1, border2);
389 assert_eq!(result.style, BorderStyle::Hidden);
391 }
392
393 #[test]
394 fn test_border_conflict_resolution_width() {
395 use crate::area::BorderStyle;
396 let layout = TableLayout::new(Length::from_pt(500.0));
397
398 let border1 = CollapsedBorder::new(
399 Length::from_pt(5.0),
400 fop_types::Color::RED,
401 BorderStyle::Solid,
402 );
403 let border2 = CollapsedBorder::new(
404 Length::from_pt(2.0),
405 fop_types::Color::BLUE,
406 BorderStyle::Solid,
407 );
408
409 let result = layout.resolve_border_conflict(border1, border2);
410 assert_eq!(result.width, Length::from_pt(5.0));
412 assert_eq!(result.color, fop_types::Color::RED);
413 }
414
415 #[test]
416 fn test_border_conflict_resolution_style() {
417 use crate::area::BorderStyle;
418 let layout = TableLayout::new(Length::from_pt(500.0));
419
420 let border1 = CollapsedBorder::new(
421 Length::from_pt(2.0),
422 fop_types::Color::RED,
423 BorderStyle::Double,
424 );
425 let border2 = CollapsedBorder::new(
426 Length::from_pt(2.0),
427 fop_types::Color::BLUE,
428 BorderStyle::Dashed,
429 );
430
431 let result = layout.resolve_border_conflict(border1, border2);
432 assert_eq!(result.style, BorderStyle::Double);
434 assert_eq!(result.color, fop_types::Color::RED);
435 }
436
437 #[test]
438 fn test_border_conflict_resolution_none() {
439 use crate::area::BorderStyle;
440 let layout = TableLayout::new(Length::from_pt(500.0));
441
442 let border1 = CollapsedBorder::new(
443 Length::from_pt(2.0),
444 fop_types::Color::RED,
445 BorderStyle::None,
446 );
447 let border2 = CollapsedBorder::new(
448 Length::from_pt(2.0),
449 fop_types::Color::BLUE,
450 BorderStyle::Solid,
451 );
452
453 let result = layout.resolve_border_conflict(border1, border2);
454 assert_eq!(result.style, BorderStyle::Solid);
456 assert_eq!(result.color, fop_types::Color::BLUE);
457 }
458
459 #[test]
460 fn test_collapsed_border_visible() {
461 use crate::area::BorderStyle;
462
463 let visible = CollapsedBorder::new(
464 Length::from_pt(2.0),
465 fop_types::Color::RED,
466 BorderStyle::Solid,
467 );
468 assert!(visible.is_visible());
469
470 let invisible_none = CollapsedBorder::new(
471 Length::from_pt(2.0),
472 fop_types::Color::RED,
473 BorderStyle::None,
474 );
475 assert!(!invisible_none.is_visible());
476
477 let invisible_hidden = CollapsedBorder::new(
478 Length::from_pt(2.0),
479 fop_types::Color::RED,
480 BorderStyle::Hidden,
481 );
482 assert!(!invisible_hidden.is_visible());
483
484 let invisible_zero =
485 CollapsedBorder::new(Length::ZERO, fop_types::Color::RED, BorderStyle::Solid);
486 assert!(!invisible_zero.is_visible());
487 }
488
489 #[test]
490 fn test_border_collapse_display() {
491 assert_eq!(format!("{}", BorderCollapse::Separate), "separate");
492 assert_eq!(format!("{}", BorderCollapse::Collapse), "collapse");
493 }
494
495 #[test]
504 fn test_table_layout_default_border_spacing() {
505 let layout = TableLayout::new(Length::from_pt(400.0));
506 assert_eq!(layout.border_spacing, Length::from_pt(2.0));
508 }
509
510 #[test]
511 fn test_table_layout_with_border_spacing_getter() {
512 let layout =
513 TableLayout::new(Length::from_pt(400.0)).with_border_spacing(Length::from_pt(8.0));
514 assert_eq!(layout.border_spacing, Length::from_pt(8.0));
515 }
516
517 #[test]
518 fn test_table_layout_available_width_stored() {
519 let layout = TableLayout::new(Length::from_pt(720.0));
520 assert_eq!(layout.available_width, Length::from_pt(720.0));
521 }
522
523 #[test]
524 fn test_table_layout_chained_builder() {
525 let layout = TableLayout::new(Length::from_pt(500.0))
526 .with_border_spacing(Length::from_pt(4.0))
527 .with_layout_mode(TableLayoutMode::Auto)
528 .with_border_collapse(BorderCollapse::Collapse);
529 assert_eq!(layout.layout_mode(), TableLayoutMode::Auto);
530 assert_eq!(layout.border_collapse(), BorderCollapse::Collapse);
531 assert_eq!(layout.border_spacing, Length::from_pt(4.0));
532 }
533
534 #[test]
539 fn test_fixed_widths_empty_columns() {
540 let layout = TableLayout::new(Length::from_pt(500.0));
541 let widths = layout.compute_fixed_widths(&[]);
542 assert!(widths.is_empty());
543 }
544
545 #[test]
546 fn test_fixed_widths_three_equal_fixed_columns() {
547 let layout = TableLayout::new(Length::from_pt(600.0))
548 .with_border_spacing(Length::ZERO)
549 .with_border_collapse(BorderCollapse::Collapse);
550 let columns = vec![
551 ColumnWidth::Fixed(Length::from_pt(100.0)),
552 ColumnWidth::Fixed(Length::from_pt(200.0)),
553 ColumnWidth::Fixed(Length::from_pt(150.0)),
554 ];
555 let widths = layout.compute_fixed_widths(&columns);
556 assert_eq!(widths.len(), 3);
557 assert_eq!(widths[0], Length::from_pt(100.0));
558 assert_eq!(widths[1], Length::from_pt(200.0));
559 assert_eq!(widths[2], Length::from_pt(150.0));
560 }
561
562 #[test]
563 fn test_fixed_widths_auto_columns_share_remaining() {
564 let layout =
566 TableLayout::new(Length::from_pt(500.0)).with_border_collapse(BorderCollapse::Collapse);
567 let columns = vec![
568 ColumnWidth::Fixed(Length::from_pt(200.0)),
569 ColumnWidth::Auto,
570 ColumnWidth::Auto,
571 ];
572 let widths = layout.compute_fixed_widths(&columns);
573 assert_eq!(widths.len(), 3);
574 assert_eq!(widths[0], Length::from_pt(200.0));
575 assert_eq!(widths[1], widths[2]);
577 assert!((widths[1].to_pt() - 150.0).abs() < 0.01);
578 }
579
580 #[test]
581 fn test_fixed_widths_single_auto_column_takes_all_remaining() {
582 let layout =
583 TableLayout::new(Length::from_pt(500.0)).with_border_collapse(BorderCollapse::Collapse);
584 let columns = vec![
585 ColumnWidth::Fixed(Length::from_pt(100.0)),
586 ColumnWidth::Auto,
587 ];
588 let widths = layout.compute_fixed_widths(&columns);
589 assert!((widths[1].to_pt() - 400.0).abs() < 0.01);
590 }
591
592 #[test]
593 fn test_fixed_widths_proportional_single() {
594 let layout =
596 TableLayout::new(Length::from_pt(400.0)).with_border_collapse(BorderCollapse::Collapse);
597 let columns = vec![ColumnWidth::Proportional(1.0)];
598 let widths = layout.compute_fixed_widths(&columns);
599 assert_eq!(widths.len(), 1);
600 assert!((widths[0].to_pt() - 400.0).abs() < 0.01);
602 }
603
604 #[test]
605 fn test_fixed_widths_proportional_3_1_ratio() {
606 let layout =
607 TableLayout::new(Length::from_pt(400.0)).with_border_collapse(BorderCollapse::Collapse);
608 let columns = vec![
609 ColumnWidth::Proportional(3.0),
610 ColumnWidth::Proportional(1.0),
611 ];
612 let widths = layout.compute_fixed_widths(&columns);
613 assert!((widths[0].to_pt() - 300.0).abs() < 0.01);
615 assert!((widths[1].to_pt() - 100.0).abs() < 0.01);
616 }
617
618 #[test]
623 fn test_auto_widths_empty_columns() {
624 let layout = TableLayout::new(Length::from_pt(500.0));
625 let widths = layout.compute_auto_widths(&[]);
626 assert!(widths.is_empty());
627 }
628
629 #[test]
630 fn test_auto_widths_all_fixed() {
631 let layout =
632 TableLayout::new(Length::from_pt(500.0)).with_border_collapse(BorderCollapse::Collapse);
633 let infos = vec![
634 ColumnInfo::with_widths(
635 ColumnWidth::Fixed(Length::from_pt(120.0)),
636 Length::ZERO,
637 Length::ZERO,
638 ),
639 ColumnInfo::with_widths(
640 ColumnWidth::Fixed(Length::from_pt(80.0)),
641 Length::ZERO,
642 Length::ZERO,
643 ),
644 ];
645 let widths = layout.compute_auto_widths(&infos);
646 assert_eq!(widths[0], Length::from_pt(120.0));
647 assert_eq!(widths[1], Length::from_pt(80.0));
648 }
649
650 #[test]
651 fn test_auto_widths_proportional_columns() {
652 let layout =
653 TableLayout::new(Length::from_pt(400.0)).with_border_collapse(BorderCollapse::Collapse);
654 let infos = vec![
655 ColumnInfo::new(ColumnWidth::Proportional(1.0)),
656 ColumnInfo::new(ColumnWidth::Proportional(1.0)),
657 ];
658 let widths = layout.compute_auto_widths(&infos);
659 assert!((widths[0].to_pt() - 200.0).abs() < 0.01);
661 assert!((widths[1].to_pt() - 200.0).abs() < 0.01);
662 }
663
664 #[test]
665 fn test_auto_widths_tight_all_min() {
666 let layout =
668 TableLayout::new(Length::from_pt(50.0)).with_border_collapse(BorderCollapse::Collapse);
669 let infos = vec![
670 ColumnInfo::with_widths(
671 ColumnWidth::Auto,
672 Length::from_pt(40.0),
673 Length::from_pt(100.0),
674 ),
675 ColumnInfo::with_widths(
676 ColumnWidth::Auto,
677 Length::from_pt(40.0),
678 Length::from_pt(100.0),
679 ),
680 ];
681 let widths = layout.compute_auto_widths(&infos);
682 assert!(widths[0] > Length::ZERO);
684 assert!(widths[1] > Length::ZERO);
685 let total = widths[0].to_pt() + widths[1].to_pt();
686 assert!(total <= 50.0 + 0.01);
687 }
688
689 #[test]
690 fn test_auto_widths_between_min_and_max_interpolation() {
691 let layout =
693 TableLayout::new(Length::from_pt(200.0)).with_border_collapse(BorderCollapse::Collapse);
694 let infos = vec![
695 ColumnInfo::with_widths(
696 ColumnWidth::Auto,
697 Length::from_pt(50.0),
698 Length::from_pt(150.0),
699 ),
700 ColumnInfo::with_widths(
701 ColumnWidth::Auto,
702 Length::from_pt(50.0),
703 Length::from_pt(150.0),
704 ),
705 ];
706 let widths = layout.compute_auto_widths(&infos);
707 assert!(widths[0] >= Length::from_pt(50.0));
709 assert!(widths[0] <= Length::from_pt(150.0));
710 assert!(widths[1] >= Length::from_pt(50.0));
711 assert!(widths[1] <= Length::from_pt(150.0));
712 }
713
714 #[test]
715 fn test_auto_widths_same_min_max_uses_max_widths() {
716 let layout =
719 TableLayout::new(Length::from_pt(300.0)).with_border_collapse(BorderCollapse::Collapse);
720 let infos = vec![
721 ColumnInfo::with_widths(
722 ColumnWidth::Auto,
723 Length::from_pt(80.0),
724 Length::from_pt(80.0),
725 ),
726 ColumnInfo::with_widths(
727 ColumnWidth::Auto,
728 Length::from_pt(80.0),
729 Length::from_pt(80.0),
730 ),
731 ];
732 let widths = layout.compute_auto_widths(&infos);
734 assert!((widths[0].to_pt() - 80.0).abs() < 0.01);
735 assert!((widths[1].to_pt() - 80.0).abs() < 0.01);
736 }
737
738 #[test]
743 fn test_grid_cell_rowspan_marks_spanned_rows() {
744 let layout = TableLayout::new(Length::from_pt(500.0));
745 let mut grid = layout.create_grid(3, 2);
746 let cell = GridCell {
747 row: 0,
748 col: 0,
749 rowspan: 3,
750 colspan: 1,
751 content_id: None,
752 };
753 layout
754 .place_cell(&mut grid, cell)
755 .expect("test: should succeed");
756 let top = grid[0][0].as_ref().expect("test: should succeed");
758 assert_eq!(top.rowspan, 3);
759 let marker1 = grid[1][0].as_ref().expect("test: should succeed");
761 assert_eq!(marker1.rowspan, 0);
762 let marker2 = grid[2][0].as_ref().expect("test: should succeed");
763 assert_eq!(marker2.rowspan, 0);
764 assert!(grid[0][1].is_none());
766 }
767
768 #[test]
769 fn test_grid_cell_colspan_marks_spanned_cols() {
770 let layout = TableLayout::new(Length::from_pt(500.0));
771 let mut grid = layout.create_grid(2, 4);
772 let cell = GridCell {
773 row: 0,
774 col: 1,
775 rowspan: 1,
776 colspan: 3,
777 content_id: None,
778 };
779 layout
780 .place_cell(&mut grid, cell)
781 .expect("test: should succeed");
782 assert_eq!(
784 grid[0][1].as_ref().expect("test: should succeed").colspan,
785 3
786 );
787 assert_eq!(
789 grid[0][2].as_ref().expect("test: should succeed").colspan,
790 0
791 );
792 assert_eq!(
793 grid[0][3].as_ref().expect("test: should succeed").colspan,
794 0
795 );
796 assert!(grid[0][0].is_none());
798 }
799
800 #[test]
801 fn test_grid_cell_rowspan_colspan_combined() {
802 let layout = TableLayout::new(Length::from_pt(500.0));
803 let mut grid = layout.create_grid(3, 3);
804 let cell = GridCell {
805 row: 0,
806 col: 0,
807 rowspan: 2,
808 colspan: 2,
809 content_id: None,
810 };
811 layout
812 .place_cell(&mut grid, cell)
813 .expect("test: should succeed");
814 let real = grid[0][0].as_ref().expect("test: should succeed");
816 assert_eq!(real.rowspan, 2);
817 assert_eq!(real.colspan, 2);
818 assert_eq!(
820 grid[0][1].as_ref().expect("test: should succeed").rowspan,
821 0
822 );
823 assert_eq!(
824 grid[1][0].as_ref().expect("test: should succeed").rowspan,
825 0
826 );
827 assert_eq!(
828 grid[1][1].as_ref().expect("test: should succeed").rowspan,
829 0
830 );
831 assert!(grid[0][2].is_none());
833 assert!(grid[2][0].is_none());
834 }
835
836 #[test]
837 fn test_place_cell_out_of_bounds_row() {
838 let layout = TableLayout::new(Length::from_pt(500.0));
839 let mut grid = layout.create_grid(2, 2);
840 let cell = GridCell {
841 row: 5,
842 col: 0,
843 rowspan: 1,
844 colspan: 1,
845 content_id: None,
846 };
847 assert!(layout.place_cell(&mut grid, cell).is_err());
848 }
849
850 #[test]
851 fn test_place_cell_out_of_bounds_col() {
852 let layout = TableLayout::new(Length::from_pt(500.0));
853 let mut grid = layout.create_grid(2, 2);
854 let cell = GridCell {
855 row: 0,
856 col: 5,
857 rowspan: 1,
858 colspan: 1,
859 content_id: None,
860 };
861 assert!(layout.place_cell(&mut grid, cell).is_err());
862 }
863
864 #[test]
865 fn test_place_cell_span_clamped_at_bounds() {
866 let layout = TableLayout::new(Length::from_pt(500.0));
868 let mut grid = layout.create_grid(2, 3);
869 let cell = GridCell {
870 row: 0,
871 col: 1,
872 rowspan: 5, colspan: 5, content_id: None,
875 };
876 layout
878 .place_cell(&mut grid, cell)
879 .expect("test: should succeed");
880 }
881
882 #[test]
883 fn test_grid_cell_with_content_id() {
884 let layout = TableLayout::new(Length::from_pt(500.0));
885 let mut grid = layout.create_grid(1, 1);
886 let area_id = AreaId::from_index(42);
887 let cell = GridCell {
888 row: 0,
889 col: 0,
890 rowspan: 1,
891 colspan: 1,
892 content_id: Some(area_id),
893 };
894 layout
895 .place_cell(&mut grid, cell)
896 .expect("test: should succeed");
897 let stored = grid[0][0].as_ref().expect("test: should succeed");
898 assert_eq!(stored.content_id, Some(area_id));
899 }
900
901 #[test]
906 fn test_border_conflict_both_hidden() {
907 use crate::area::BorderStyle;
908 let layout = TableLayout::new(Length::from_pt(500.0));
909 let b1 = CollapsedBorder::new(
910 Length::from_pt(1.0),
911 fop_types::Color::BLACK,
912 BorderStyle::Hidden,
913 );
914 let b2 = CollapsedBorder::new(
915 Length::from_pt(3.0),
916 fop_types::Color::RED,
917 BorderStyle::Hidden,
918 );
919 let result = layout.resolve_border_conflict(b1, b2);
921 assert!(matches!(result.style, BorderStyle::Hidden));
922 }
923
924 #[test]
925 fn test_border_conflict_both_none() {
926 use crate::area::BorderStyle;
927 let layout = TableLayout::new(Length::from_pt(500.0));
928 let b1 = CollapsedBorder::new(
929 Length::from_pt(1.0),
930 fop_types::Color::BLACK,
931 BorderStyle::None,
932 );
933 let b2 = CollapsedBorder::new(
934 Length::from_pt(1.0),
935 fop_types::Color::RED,
936 BorderStyle::None,
937 );
938 let result = layout.resolve_border_conflict(b1, b2);
939 assert!(matches!(result.style, BorderStyle::None));
940 }
941
942 #[test]
943 fn test_border_conflict_equal_width_style_precedence() {
944 use crate::area::BorderStyle;
945 let layout = TableLayout::new(Length::from_pt(500.0));
946 let b1 = CollapsedBorder::new(
948 Length::from_pt(2.0),
949 fop_types::Color::BLACK,
950 BorderStyle::Dotted,
951 );
952 let b2 = CollapsedBorder::new(
953 Length::from_pt(2.0),
954 fop_types::Color::RED,
955 BorderStyle::Solid,
956 );
957 let result = layout.resolve_border_conflict(b1, b2);
958 assert!(matches!(result.style, BorderStyle::Solid));
959 }
960
961 #[test]
962 fn test_border_conflict_double_vs_solid() {
963 use crate::area::BorderStyle;
964 let layout = TableLayout::new(Length::from_pt(500.0));
965 let b1 = CollapsedBorder::new(
966 Length::from_pt(2.0),
967 fop_types::Color::BLACK,
968 BorderStyle::Solid,
969 );
970 let b2 = CollapsedBorder::new(
971 Length::from_pt(2.0),
972 fop_types::Color::RED,
973 BorderStyle::Double,
974 );
975 let result = layout.resolve_border_conflict(b1, b2);
976 assert!(matches!(result.style, BorderStyle::Double));
977 }
978
979 #[test]
980 fn test_border_conflict_groove_inset_precedence() {
981 use crate::area::BorderStyle;
982 let layout = TableLayout::new(Length::from_pt(500.0));
983 let b1 = CollapsedBorder::new(
985 Length::from_pt(2.0),
986 fop_types::Color::BLACK,
987 BorderStyle::Groove,
988 );
989 let b2 = CollapsedBorder::new(
990 Length::from_pt(2.0),
991 fop_types::Color::RED,
992 BorderStyle::Inset,
993 );
994 let result = layout.resolve_border_conflict(b1, b2);
995 assert!(matches!(result.style, BorderStyle::Groove));
996 }
997
998 #[test]
999 fn test_border_conflict_wider_wins_over_better_style() {
1000 use crate::area::BorderStyle;
1001 let layout = TableLayout::new(Length::from_pt(500.0));
1002 let b1 = CollapsedBorder::new(
1004 Length::from_pt(1.0),
1005 fop_types::Color::BLACK,
1006 BorderStyle::Double,
1007 );
1008 let b2 = CollapsedBorder::new(
1009 Length::from_pt(5.0),
1010 fop_types::Color::BLUE,
1011 BorderStyle::Dotted,
1012 );
1013 let result = layout.resolve_border_conflict(b1, b2);
1014 assert_eq!(result.width, Length::from_pt(5.0));
1015 assert!(matches!(result.style, BorderStyle::Dotted));
1016 }
1017
1018 #[test]
1019 fn test_collapsed_border_none_factory() {
1020 let b = CollapsedBorder::none();
1021 assert_eq!(b.width, Length::ZERO);
1022 assert!(!b.is_visible());
1023 }
1024
1025 #[test]
1026 fn test_cell_collapsed_borders_default() {
1027 let borders = CellCollapsedBorders::default();
1028 assert!(!borders.top.is_visible());
1029 assert!(!borders.right.is_visible());
1030 assert!(!borders.bottom.is_visible());
1031 assert!(!borders.left.is_visible());
1032 }
1033
1034 #[test]
1035 fn test_separate_border_spacing_affects_available_width() {
1036 let layout = TableLayout::new(Length::from_pt(500.0))
1038 .with_border_spacing(Length::from_pt(10.0))
1039 .with_border_collapse(BorderCollapse::Separate);
1040 let columns = vec![
1042 ColumnWidth::Auto,
1043 ColumnWidth::Auto,
1044 ColumnWidth::Auto,
1045 ColumnWidth::Auto,
1046 ];
1047 let widths = layout.compute_fixed_widths(&columns);
1048 for w in &widths {
1050 assert!((w.to_pt() - 112.5).abs() < 0.01);
1051 }
1052 }
1053
1054 #[test]
1055 fn test_collapse_model_no_spacing_deducted() {
1056 let layout = TableLayout::new(Length::from_pt(400.0))
1057 .with_border_spacing(Length::from_pt(10.0))
1058 .with_border_collapse(BorderCollapse::Collapse);
1059 let columns = vec![ColumnWidth::Auto, ColumnWidth::Auto];
1061 let widths = layout.compute_fixed_widths(&columns);
1062 for w in &widths {
1064 assert!((w.to_pt() - 200.0).abs() < 0.01);
1065 }
1066 }
1067
1068 #[test]
1073 fn test_column_info_computed_width_initial_zero() {
1074 let info = ColumnInfo::new(ColumnWidth::Fixed(Length::from_pt(100.0)));
1075 assert_eq!(info.computed_width, Length::ZERO);
1076 }
1077
1078 #[test]
1079 fn test_column_info_with_widths_computed_still_zero() {
1080 let info = ColumnInfo::with_widths(
1081 ColumnWidth::Proportional(2.0),
1082 Length::from_pt(30.0),
1083 Length::from_pt(90.0),
1084 );
1085 assert_eq!(info.computed_width, Length::ZERO);
1086 assert_eq!(info.min_width, Length::from_pt(30.0));
1087 assert_eq!(info.max_width, Length::from_pt(90.0));
1088 }
1089
1090 #[test]
1091 fn test_column_info_width_spec_variants() {
1092 let fixed = ColumnInfo::new(ColumnWidth::Fixed(Length::from_pt(50.0)));
1093 assert!(matches!(fixed.width_spec, ColumnWidth::Fixed(_)));
1094
1095 let prop = ColumnInfo::new(ColumnWidth::Proportional(1.5));
1096 assert!(matches!(prop.width_spec, ColumnWidth::Proportional(_)));
1097
1098 let auto = ColumnInfo::new(ColumnWidth::Auto);
1099 assert!(matches!(auto.width_spec, ColumnWidth::Auto));
1100 }
1101
1102 #[test]
1107 fn test_grid_cell_end_column_computed() {
1108 let cell = GridCell {
1109 row: 0,
1110 col: 2,
1111 rowspan: 1,
1112 colspan: 3,
1113 content_id: None,
1114 };
1115 assert_eq!(cell.col + cell.colspan - 1, 4);
1117 }
1118
1119 #[test]
1120 fn test_grid_cell_single_cell_span() {
1121 let cell = GridCell {
1122 row: 0,
1123 col: 0,
1124 rowspan: 1,
1125 colspan: 1,
1126 content_id: None,
1127 };
1128 assert_eq!(cell.rowspan, 1);
1129 assert_eq!(cell.colspan, 1);
1130 }
1131
1132 #[test]
1133 fn test_grid_cell_marker_zeroed_spans() {
1134 let layout = TableLayout::new(Length::from_pt(500.0));
1135 let mut grid = layout.create_grid(2, 2);
1136 let cell = GridCell {
1137 row: 0,
1138 col: 0,
1139 rowspan: 2,
1140 colspan: 2,
1141 content_id: None,
1142 };
1143 layout
1144 .place_cell(&mut grid, cell)
1145 .expect("test: should succeed");
1146 for &(r, c) in &[(0usize, 1usize), (1, 0), (1, 1)] {
1148 let marker = grid[r][c].as_ref().expect("test: should succeed");
1149 assert_eq!(marker.rowspan, 0, "row={r} col={c} should be marker");
1150 assert_eq!(marker.colspan, 0, "row={r} col={c} should be marker");
1151 }
1152 }
1153
1154 #[test]
1155 fn test_grid_cell_marker_points_to_origin() {
1156 let layout = TableLayout::new(Length::from_pt(500.0));
1157 let mut grid = layout.create_grid(2, 2);
1158 let cell = GridCell {
1159 row: 1,
1160 col: 1,
1161 rowspan: 1,
1162 colspan: 1,
1163 content_id: None,
1164 };
1165 layout
1166 .place_cell(&mut grid, cell)
1167 .expect("test: should succeed");
1168 let stored = grid[1][1].as_ref().expect("test: should succeed");
1169 assert_eq!(stored.row, 1);
1170 assert_eq!(stored.col, 1);
1171 }
1172
1173 #[test]
1178 fn test_empty_table_zero_columns() {
1179 let layout = TableLayout::new(Length::from_pt(500.0));
1180 let widths = layout.compute_fixed_widths(&[]);
1181 assert!(widths.is_empty());
1182 }
1183
1184 #[test]
1185 fn test_single_cell_table() {
1186 let layout =
1187 TableLayout::new(Length::from_pt(300.0)).with_border_collapse(BorderCollapse::Collapse);
1188 let mut grid = layout.create_grid(1, 1);
1189 let cell = GridCell {
1190 row: 0,
1191 col: 0,
1192 rowspan: 1,
1193 colspan: 1,
1194 content_id: None,
1195 };
1196 layout
1197 .place_cell(&mut grid, cell)
1198 .expect("test: should succeed");
1199 assert!(grid[0][0].is_some());
1200 let widths = layout.compute_fixed_widths(&[ColumnWidth::Auto]);
1202 assert_eq!(widths.len(), 1);
1203 assert!((widths[0].to_pt() - 300.0).abs() < 0.01);
1204 }
1205
1206 #[test]
1207 fn test_one_column_table_many_rows() {
1208 let layout =
1209 TableLayout::new(Length::from_pt(200.0)).with_border_collapse(BorderCollapse::Collapse);
1210 let mut grid = layout.create_grid(5, 1);
1211 for r in 0..5 {
1212 let cell = GridCell {
1213 row: r,
1214 col: 0,
1215 rowspan: 1,
1216 colspan: 1,
1217 content_id: None,
1218 };
1219 layout
1220 .place_cell(&mut grid, cell)
1221 .expect("test: should succeed");
1222 }
1223 for row in grid.iter().take(5) {
1224 assert!(row[0].is_some());
1225 }
1226 let widths = layout.compute_fixed_widths(&[ColumnWidth::Auto]);
1227 assert_eq!(widths.len(), 1);
1228 assert!((widths[0].to_pt() - 200.0).abs() < 0.01);
1229 }
1230
1231 #[test]
1232 fn test_one_row_table_many_columns() {
1233 let layout =
1234 TableLayout::new(Length::from_pt(600.0)).with_border_collapse(BorderCollapse::Collapse);
1235 let n = 6;
1236 let mut grid = layout.create_grid(1, n);
1237 for c in 0..n {
1238 let cell = GridCell {
1239 row: 0,
1240 col: c,
1241 rowspan: 1,
1242 colspan: 1,
1243 content_id: None,
1244 };
1245 layout
1246 .place_cell(&mut grid, cell)
1247 .expect("test: should succeed");
1248 }
1249 let col_specs: Vec<ColumnWidth> = (0..n).map(|_| ColumnWidth::Auto).collect();
1250 let widths = layout.compute_fixed_widths(&col_specs);
1251 assert_eq!(widths.len(), n);
1252 for w in &widths {
1253 assert!(
1254 (w.to_pt() - 100.0).abs() < 0.01,
1255 "expected 100pt, got {}pt",
1256 w.to_pt()
1257 );
1258 }
1259 }
1260
1261 #[test]
1262 fn test_single_proportional_column_zero_proportional_sum() {
1263 let layout =
1265 TableLayout::new(Length::from_pt(300.0)).with_border_collapse(BorderCollapse::Collapse);
1266 let columns = vec![ColumnWidth::Proportional(0.0)];
1267 let widths = layout.compute_fixed_widths(&columns);
1268 assert_eq!(widths[0], Length::ZERO);
1270 }
1271
1272 #[test]
1277 fn test_fixed_widths_fit_within_available_width() {
1278 let available = Length::from_pt(500.0);
1279 let layout = TableLayout::new(available).with_border_collapse(BorderCollapse::Collapse);
1280 let columns = vec![
1281 ColumnWidth::Proportional(1.0),
1282 ColumnWidth::Proportional(1.0),
1283 ColumnWidth::Proportional(1.0),
1284 ];
1285 let widths = layout.compute_fixed_widths(&columns);
1286 let total: f64 = widths.iter().map(|w| w.to_pt()).sum();
1287 assert!(
1288 total <= available.to_pt() + 0.01,
1289 "total {total} > available {}",
1290 available.to_pt()
1291 );
1292 }
1293
1294 #[test]
1295 fn test_auto_widths_fit_within_available_width() {
1296 let available = Length::from_pt(400.0);
1297 let layout = TableLayout::new(available).with_border_collapse(BorderCollapse::Collapse);
1298 let infos = vec![
1299 ColumnInfo::with_widths(
1300 ColumnWidth::Auto,
1301 Length::from_pt(60.0),
1302 Length::from_pt(180.0),
1303 ),
1304 ColumnInfo::with_widths(
1305 ColumnWidth::Auto,
1306 Length::from_pt(60.0),
1307 Length::from_pt(180.0),
1308 ),
1309 ];
1310 let widths = layout.compute_auto_widths(&infos);
1311 let total: f64 = widths.iter().map(|w| w.to_pt()).sum();
1312 assert!(total <= available.to_pt() + 0.01);
1313 }
1314
1315 #[test]
1316 fn test_table_layout_separates_border_spacing_in_auto_widths() {
1317 let layout = TableLayout::new(Length::from_pt(500.0))
1318 .with_border_spacing(Length::from_pt(5.0))
1319 .with_border_collapse(BorderCollapse::Separate);
1320 let infos = vec![
1321 ColumnInfo::with_widths(
1322 ColumnWidth::Auto,
1323 Length::from_pt(10.0),
1324 Length::from_pt(500.0),
1325 ),
1326 ColumnInfo::with_widths(
1327 ColumnWidth::Auto,
1328 Length::from_pt(10.0),
1329 Length::from_pt(500.0),
1330 ),
1331 ];
1332 let widths = layout.compute_auto_widths(&infos);
1335 let total: f64 = widths.iter().map(|w| w.to_pt()).sum();
1336 assert!(total <= 500.0 + 0.01);
1338 }
1339
1340 #[test]
1345 fn test_column_width_fixed_variant() {
1346 let cw = ColumnWidth::Fixed(Length::from_pt(75.0));
1347 if let ColumnWidth::Fixed(l) = cw {
1348 assert!((l.to_pt() - 75.0).abs() < 0.01);
1349 } else {
1350 panic!("Expected Fixed variant");
1351 }
1352 }
1353
1354 #[test]
1355 fn test_column_width_proportional_variant() {
1356 let cw = ColumnWidth::Proportional(2.5);
1357 if let ColumnWidth::Proportional(p) = cw {
1358 assert!((p - 2.5).abs() < 0.001);
1359 } else {
1360 panic!("Expected Proportional variant");
1361 }
1362 }
1363
1364 #[test]
1365 fn test_column_width_auto_variant() {
1366 let cw = ColumnWidth::Auto;
1367 assert!(matches!(cw, ColumnWidth::Auto));
1368 }
1369
1370 #[test]
1371 fn test_column_width_equality() {
1372 assert_eq!(ColumnWidth::Auto, ColumnWidth::Auto);
1373 assert_eq!(
1374 ColumnWidth::Fixed(Length::from_pt(10.0)),
1375 ColumnWidth::Fixed(Length::from_pt(10.0))
1376 );
1377 assert_ne!(ColumnWidth::Auto, ColumnWidth::Fixed(Length::from_pt(0.0)));
1378 }
1379
1380 #[test]
1385 fn test_table_layout_mode_equality() {
1386 assert_eq!(TableLayoutMode::Fixed, TableLayoutMode::Fixed);
1387 assert_eq!(TableLayoutMode::Auto, TableLayoutMode::Auto);
1388 assert_ne!(TableLayoutMode::Fixed, TableLayoutMode::Auto);
1389 }
1390
1391 #[test]
1392 fn test_table_layout_mode_default_is_fixed() {
1393 assert_eq!(TableLayoutMode::default(), TableLayoutMode::Fixed);
1394 }
1395
1396 #[test]
1401 fn test_border_collapse_equality() {
1402 assert_eq!(BorderCollapse::Separate, BorderCollapse::Separate);
1403 assert_eq!(BorderCollapse::Collapse, BorderCollapse::Collapse);
1404 assert_ne!(BorderCollapse::Separate, BorderCollapse::Collapse);
1405 }
1406
1407 #[test]
1408 fn test_border_collapse_default_is_separate() {
1409 assert_eq!(BorderCollapse::default(), BorderCollapse::Separate);
1410 }
1411
1412 #[test]
1417 fn test_collapsed_border_dotted_visible() {
1418 use crate::area::BorderStyle;
1419 let b = CollapsedBorder::new(
1420 Length::from_pt(1.0),
1421 fop_types::Color::BLACK,
1422 BorderStyle::Dotted,
1423 );
1424 assert!(b.is_visible());
1425 }
1426
1427 #[test]
1428 fn test_collapsed_border_dashed_visible() {
1429 use crate::area::BorderStyle;
1430 let b = CollapsedBorder::new(
1431 Length::from_pt(0.5),
1432 fop_types::Color::BLACK,
1433 BorderStyle::Dashed,
1434 );
1435 assert!(b.is_visible());
1436 }
1437
1438 #[test]
1439 fn test_collapsed_border_double_visible() {
1440 use crate::area::BorderStyle;
1441 let b = CollapsedBorder::new(
1442 Length::from_pt(3.0),
1443 fop_types::Color::RED,
1444 BorderStyle::Double,
1445 );
1446 assert!(b.is_visible());
1447 }
1448
1449 #[test]
1450 fn test_collapsed_border_groove_visible() {
1451 use crate::area::BorderStyle;
1452 let b = CollapsedBorder::new(
1453 Length::from_pt(2.0),
1454 fop_types::Color::BLACK,
1455 BorderStyle::Groove,
1456 );
1457 assert!(b.is_visible());
1458 }
1459
1460 #[test]
1461 fn test_collapsed_border_ridge_visible() {
1462 use crate::area::BorderStyle;
1463 let b = CollapsedBorder::new(
1464 Length::from_pt(2.0),
1465 fop_types::Color::BLACK,
1466 BorderStyle::Ridge,
1467 );
1468 assert!(b.is_visible());
1469 }
1470
1471 #[test]
1476 fn test_create_grid_zero_rows() {
1477 let layout = TableLayout::new(Length::from_pt(500.0));
1478 let grid = layout.create_grid(0, 4);
1479 assert_eq!(grid.len(), 0);
1480 }
1481
1482 #[test]
1483 fn test_create_grid_zero_cols() {
1484 let layout = TableLayout::new(Length::from_pt(500.0));
1485 let grid = layout.create_grid(3, 0);
1486 assert_eq!(grid.len(), 3);
1487 assert_eq!(grid[0].len(), 0);
1488 }
1489
1490 #[test]
1491 fn test_create_grid_all_cells_initially_none() {
1492 let layout = TableLayout::new(Length::from_pt(500.0));
1493 let grid = layout.create_grid(4, 5);
1494 for row in &grid {
1495 for cell in row {
1496 assert!(cell.is_none());
1497 }
1498 }
1499 }
1500
1501 #[test]
1506 fn test_distribute_colspan_three_cols_one_span() {
1507 let layout = TableLayout::new(Length::from_pt(500.0));
1508 let mut column_info = vec![
1509 ColumnInfo::new(ColumnWidth::Auto),
1510 ColumnInfo::new(ColumnWidth::Auto),
1511 ColumnInfo::new(ColumnWidth::Auto),
1512 ];
1513 let mut grid = layout.create_grid(1, 3);
1514 let cell = GridCell {
1515 row: 0,
1516 col: 0,
1517 rowspan: 1,
1518 colspan: 3,
1519 content_id: None,
1520 };
1521 layout
1522 .place_cell(&mut grid, cell)
1523 .expect("test: should succeed");
1524 layout.distribute_colspan_widths(&mut column_info, &grid);
1525 for info in &column_info {
1527 assert!(info.min_width > Length::ZERO);
1528 }
1529 }
1530
1531 #[test]
1532 fn test_distribute_colspan_fixed_column_unaffected() {
1533 let layout = TableLayout::new(Length::from_pt(500.0));
1534 let mut column_info = vec![
1535 ColumnInfo::with_widths(
1536 ColumnWidth::Fixed(Length::from_pt(100.0)),
1537 Length::from_pt(100.0),
1538 Length::from_pt(100.0),
1539 ),
1540 ColumnInfo::new(ColumnWidth::Auto),
1541 ];
1542 let mut grid = layout.create_grid(1, 2);
1543 let cell = GridCell {
1544 row: 0,
1545 col: 0,
1546 rowspan: 1,
1547 colspan: 2,
1548 content_id: None,
1549 };
1550 layout
1551 .place_cell(&mut grid, cell)
1552 .expect("test: should succeed");
1553 layout.distribute_colspan_widths(&mut column_info, &grid);
1554 assert_eq!(column_info[0].min_width, Length::from_pt(100.0));
1556 }
1557
1558 #[test]
1563 fn test_measure_column_widths_with_cell_returns_nonzero() {
1564 let layout = TableLayout::new(Length::from_pt(500.0));
1565 let mut grid = layout.create_grid(2, 2);
1566 let cell = GridCell {
1567 row: 0,
1568 col: 0,
1569 rowspan: 1,
1570 colspan: 1,
1571 content_id: None,
1572 };
1573 layout
1574 .place_cell(&mut grid, cell)
1575 .expect("test: should succeed");
1576 let (min, max) = layout.measure_column_widths(&grid, 0);
1577 assert!((min.to_pt() - 30.0).abs() < 0.01);
1579 assert!((max.to_pt() - 200.0).abs() < 0.01);
1580 }
1581
1582 #[test]
1583 fn test_measure_column_widths_empty_column_returns_zero() {
1584 let layout = TableLayout::new(Length::from_pt(500.0));
1585 let grid = layout.create_grid(3, 3);
1586 let (min, max) = layout.measure_column_widths(&grid, 1);
1587 assert_eq!(min, Length::ZERO);
1588 assert_eq!(max, Length::ZERO);
1589 }
1590
1591 #[test]
1592 fn test_measure_column_widths_max_gte_min() {
1593 let layout = TableLayout::new(Length::from_pt(500.0));
1594 let mut grid = layout.create_grid(1, 1);
1595 let cell = GridCell {
1596 row: 0,
1597 col: 0,
1598 rowspan: 1,
1599 colspan: 1,
1600 content_id: None,
1601 };
1602 layout
1603 .place_cell(&mut grid, cell)
1604 .expect("test: should succeed");
1605 let (min, max) = layout.measure_column_widths(&grid, 0);
1606 assert!(max >= min);
1607 }
1608
1609 #[test]
1614 fn test_layout_table_returns_area_id() {
1615 let layout = TableLayout::new(Length::from_pt(500.0));
1616 let mut tree = AreaTree::new();
1617 let column_widths = vec![Length::from_pt(100.0), Length::from_pt(200.0)];
1618 let grid = layout.create_grid(2, 2);
1619 let result = layout.layout_table(&mut tree, &column_widths, &grid, Length::ZERO);
1620 assert!(result.is_ok());
1621 }
1622
1623 #[test]
1624 fn test_layout_table_empty_grid() {
1625 let layout = TableLayout::new(Length::from_pt(500.0));
1626 let mut tree = AreaTree::new();
1627 let column_widths: Vec<Length> = vec![];
1628 let grid: Vec<Vec<Option<GridCell>>> = vec![];
1629 let result = layout.layout_table(&mut tree, &column_widths, &grid, Length::ZERO);
1630 assert!(result.is_ok());
1631 }
1632
1633 #[test]
1634 fn test_layout_table_with_y_offset() {
1635 let layout = TableLayout::new(Length::from_pt(500.0));
1636 let mut tree = AreaTree::new();
1637 let column_widths = vec![Length::from_pt(200.0)];
1638 let grid = layout.create_grid(1, 1);
1639 let y = Length::from_pt(50.0);
1640 let result = layout.layout_table(&mut tree, &column_widths, &grid, y);
1641 assert!(result.is_ok());
1642 }
1643}