mod common;
use common::*;
use zenith_core::default_provider;
use zenith_scene::compile;
#[test]
fn grid_two_by_three_positions_children_with_gutters() {
let src = r##"zenith version=1 {
project id="proj.grid1" name="Grid1"
tokens format="zenith-token-v1" {
token id="color.k" type="color" value="#000000"
token id="space.gap" type="dimension" value=(px)20
}
styles {
style id="style.grid" {
gap (token)"space.gap"
}
}
document id="doc.grid1" title="Grid1" {
page id="page.grid1" w=(px)400 h=(px)400 {
frame id="frame.grid" x=(px)0 y=(px)0 w=(px)320 h=(px)300 layout="grid" columns=2 rows=3 style="style.grid" {
rect id="r0" fill=(token)"color.k"
rect id="r1" fill=(token)"color.k"
rect id="r2" fill=(token)"color.k"
rect id="r3" fill=(token)"color.k"
rect id="r4" fill=(token)"color.k"
rect id="r5" fill=(token)"color.k"
}
}
}
}
"##;
let doc = parse(src);
let result = compile(&doc, &default_provider());
assert!(
result.diagnostics.is_empty(),
"unexpected diagnostics: {:?}",
result.diagnostics
);
let rects = fill_rects(&result);
assert_eq!(
rects.len(),
6,
"expected six child FillRects; got {rects:?}"
);
let gap = 20.0;
let col_w = (320.0 - gap) / 2.0; let row_h = (300.0 - 2.0 * gap) / 3.0;
for (i, (x, y, w, h)) in rects.iter().enumerate() {
let col = (i % 2) as f64;
let row = (i / 2) as f64;
let exp_x = col * (col_w + gap);
let exp_y = row * (row_h + gap);
assert!(
(*x - exp_x).abs() < 1e-9,
"cell {i}: x expected {exp_x}; got {x}"
);
assert!(
(*y - exp_y).abs() < 1e-9,
"cell {i}: y expected {exp_y}; got {y}"
);
assert!(
(*w - col_w).abs() < 1e-9,
"cell {i}: w expected {col_w}; got {w}"
);
assert!(
(*h - row_h).abs() < 1e-9,
"cell {i}: h expected {row_h}; got {h}"
);
}
let (x0, _, w0, _) = rects[0];
let (x1, _, _, _) = rects[1];
assert!(
(x1 - (x0 + w0) - gap).abs() < 1e-9,
"horizontal gutter must equal gap ({gap})"
);
let (_, y0, _, h0) = rects[0];
let (_, y2, _, _) = rects[2];
assert!(
(y2 - (y0 + h0) - gap).abs() < 1e-9,
"vertical gutter must equal gap ({gap})"
);
}
#[test]
fn grid_default_columns_is_one() {
let src = r##"zenith version=1 {
project id="proj.grid2" name="Grid2"
tokens format="zenith-token-v1" {
token id="color.k" type="color" value="#000000"
}
styles {}
document id="doc.grid2" title="Grid2" {
page id="page.grid2" w=(px)400 h=(px)400 {
frame id="frame.grid" x=(px)0 y=(px)0 w=(px)300 h=(px)300 layout="grid" {
rect id="r0" fill=(token)"color.k"
rect id="r1" fill=(token)"color.k"
}
}
}
}
"##;
let doc = parse(src);
let result = compile(&doc, &default_provider());
let rects = fill_rects(&result);
assert_eq!(
rects.len(),
2,
"expected two child FillRects; got {rects:?}"
);
let (x0, _, w0, _) = rects[0];
let (x1, _, w1, _) = rects[1];
assert_eq!(x0, 0.0, "single-column child0 x must be content_left (0)");
assert_eq!(x1, 0.0, "single-column child1 x must be content_left (0)");
assert_eq!(w0, 300.0, "single column width must be full content width");
assert_eq!(w1, 300.0, "single column width must be full content width");
let (_, y0, _, _) = rects[0];
let (_, y1, _, _) = rects[1];
assert!(y1 > y0, "child1 must sit below child0 in a single column");
let report = zenith_core::validate(&doc);
assert!(
report
.diagnostics
.iter()
.any(|d| d.code == "grid.missing_columns"),
"expected grid.missing_columns advisory; codes: {:?}",
report
.diagnostics
.iter()
.map(|d| &d.code)
.collect::<Vec<_>>()
);
}
#[test]
fn grid_derived_rows_from_child_count() {
let src = r##"zenith version=1 {
project id="proj.grid3" name="Grid3"
tokens format="zenith-token-v1" {
token id="color.k" type="color" value="#000000"
}
styles {}
document id="doc.grid3" title="Grid3" {
page id="page.grid3" w=(px)400 h=(px)400 {
frame id="frame.grid" x=(px)0 y=(px)0 w=(px)300 h=(px)300 layout="grid" columns=2 {
rect id="r0" fill=(token)"color.k"
rect id="r1" fill=(token)"color.k"
rect id="r2" fill=(token)"color.k"
}
}
}
}
"##;
let doc = parse(src);
let result = compile(&doc, &default_provider());
assert!(
result.diagnostics.is_empty(),
"unexpected diagnostics: {:?}",
result.diagnostics
);
let rects = fill_rects(&result);
assert_eq!(
rects.len(),
3,
"expected three child FillRects; got {rects:?}"
);
let (x0, y0, w0, h0) = rects[0];
let (x1, y1, _, _) = rects[1];
let (x2, y2, _, _) = rects[2];
assert_eq!((x0, y0, w0, h0), (0.0, 0.0, 150.0, 150.0));
assert_eq!((x1, y1), (150.0, 0.0));
assert_eq!((x2, y2), (0.0, 150.0));
}
#[test]
fn non_grid_frame_byte_identical() {
let abs_src = r##"zenith version=1 {
project id="proj.grid4" name="Grid4"
tokens format="zenith-token-v1" {
token id="color.k" type="color" value="#000000"
}
styles {}
document id="doc.grid4" title="Grid4" {
page id="page.grid4" w=(px)200 h=(px)200 {
frame id="frame.abs" x=(px)20 y=(px)30 w=(px)160 h=(px)160 {
rect id="rect.a" x=(px)50 y=(px)60 w=(px)40 h=(px)30 fill=(token)"color.k"
}
}
}
}
"##;
let abs = compile(&parse(abs_src), &default_provider());
assert_eq!(fill_rects(&abs), vec![(50.0, 60.0, 40.0, 30.0)]);
let flow_src = r##"zenith version=1 {
project id="proj.grid5" name="Grid5"
tokens format="zenith-token-v1" {
token id="color.k" type="color" value="#000000"
}
styles {}
document id="doc.grid5" title="Grid5" {
page id="page.grid5" w=(px)200 h=(px)200 {
frame id="frame.flow" x=(px)0 y=(px)0 w=(px)160 h=(px)160 layout="flow" {
rect id="rect.a" h=(px)30 fill=(token)"color.k"
rect id="rect.b" h=(px)30 fill=(token)"color.k"
}
}
}
}
"##;
let flow = compile(&parse(flow_src), &default_provider());
let rects = fill_rects(&flow);
assert_eq!(rects.len(), 2);
assert_eq!(rects[0].0, rects[1].0, "flow children share x (stacked)");
assert!(rects[1].1 > rects[0].1, "flow child2 below child1");
}