✨ (pagetop): Añade Grid y extrae Flex de Container
This commit is contained in:
parent
dfff12881f
commit
307ca6f62c
44 changed files with 2554 additions and 735 deletions
|
|
@ -1,7 +1,5 @@
|
|||
use pagetop::prelude::*;
|
||||
|
||||
// **< Container >**********************************************************************************
|
||||
|
||||
#[pagetop::test]
|
||||
async fn is_not_rendered_when_empty() {
|
||||
let mut container = Container::new();
|
||||
|
|
@ -33,183 +31,3 @@ async fn main_kind_renders_a_main_element() {
|
|||
assert!(html.starts_with("<main"));
|
||||
assert!(html.ends_with("</main>"));
|
||||
}
|
||||
|
||||
// **< Container + Flex >***************************************************************************
|
||||
|
||||
#[pagetop::test]
|
||||
async fn without_flex_no_style_attribute_is_added() {
|
||||
let mut container = Container::new().with_child(Lc::n("x"));
|
||||
let html = container
|
||||
.render(&mut Context::default())
|
||||
.await
|
||||
.into_string();
|
||||
|
||||
assert!(!html.contains("style="));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn default_flex_adds_only_display_flex() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Container::new()
|
||||
.with_flex(Flex::new())
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_flex_""#));
|
||||
assert!(assets.contains("_flex_{display:flex}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn column_direction_adds_flex_direction_style() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Container::new()
|
||||
.with_flex(Flex::new().with_direction(flex::Direction::Column))
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_flex_"));
|
||||
assert!(html.contains("_flex-direction_column_"));
|
||||
assert!(assets.contains("_flex_{display:flex}"));
|
||||
assert!(assets.contains("_flex-direction_column_{flex-direction:column}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn wrap_justify_and_align_add_their_matching_styles() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Container::new()
|
||||
.with_flex(
|
||||
Flex::new()
|
||||
.with_wrap(flex::Behavior::Wrap)
|
||||
.with_justify(flex::ContentJustify::Center)
|
||||
.with_align(flex::Align::Center)
|
||||
.with_align_content(flex::AlignContent::SpaceBetween),
|
||||
)
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_flex-wrap_wrap_"));
|
||||
assert!(html.contains("_flex-justify_center_"));
|
||||
assert!(html.contains("_flex-align-items_center_"));
|
||||
assert!(html.contains("_flex-align-content_space-between_"));
|
||||
assert!(assets.contains("_flex-wrap_wrap_{flex-wrap:wrap}"));
|
||||
assert!(assets.contains("_flex-justify_center_{justify-content:center}"));
|
||||
assert!(assets.contains("_flex-align-items_center_{align-items:center}"));
|
||||
assert!(assets.contains("_flex-align-content_space-between_{align-content:space-between}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn gap_both_adds_a_single_gap_style() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Container::new()
|
||||
.with_flex(Flex::new().with_gap(flex::Gap::Both(UnitValue::RelRem(0.5))))
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_flex-gap_0_5rem_"));
|
||||
assert!(assets.contains("_flex-gap_0_5rem_{gap:0.5rem}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn gap_distinct_adds_row_and_column_gap_styles() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Container::new()
|
||||
.with_flex(Flex::new().with_gap(flex::Gap::Distinct {
|
||||
row: UnitValue::Px(4),
|
||||
column: UnitValue::Px(8),
|
||||
}))
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_flex-row-gap_4px_"));
|
||||
assert!(html.contains("_flex-column-gap_8px_"));
|
||||
assert!(assets.contains("_flex-row-gap_4px_{row-gap:4px}"));
|
||||
assert!(assets.contains("_flex-column-gap_8px_{column-gap:8px}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn gap_none_adds_no_gap_style() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Container::new()
|
||||
.with_flex(Flex::new())
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(!html.contains("gap"));
|
||||
assert!(!assets.contains("gap"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn inline_flex_uses_its_own_display_value() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Container::new()
|
||||
.with_flex(Flex::inline())
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_inline-flex_""#));
|
||||
assert!(assets.contains("_inline-flex_{display:inline-flex}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn inline_flex_at_a_breakpoint_adds_its_suffix() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Container::new()
|
||||
.with_flex(Flex::inline_at(Breakpoint::Lg))
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_inline-flex_lg_""#));
|
||||
assert!(assets.contains("@media(min-width:992px){._inline-flex_lg_{display:inline-flex}}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn flex_and_flex_item_classes_keep_their_order() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Container::new()
|
||||
.with_prop(PropsOp::add_classes("own"))
|
||||
.with_flex(Flex::new().with_direction(flex::Direction::Column))
|
||||
.with_prop(FlexItem::new().with_grow(flex::ItemGrow::Is1))
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
|
||||
// The component's own classes come first, then those of `Flex`, then those of `FlexItem`,
|
||||
// which share a single accumulator in `Props::unpack_with_flex()`.
|
||||
assert!(html.contains(r#"class="own _flex_ _flex-direction_column_ _flex-item-grow_1_""#));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn flex_without_display_adds_no_class_of_its_own() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Container::new()
|
||||
.with_prop(PropsOp::add_classes("own"))
|
||||
.with_flex(Flex::default())
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
|
||||
assert!(html.contains(r#"class="own""#));
|
||||
assert!(cx.render_assets().into_string().is_empty());
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn breakpoints_add_their_suffix_and_wrap_rules_in_media_queries() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Container::new()
|
||||
.with_flex(
|
||||
Flex::at(Breakpoint::Md).with_direction_at(Breakpoint::Lg, flex::Direction::Column),
|
||||
)
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_flex_md_ _flex-direction_column_lg_""#));
|
||||
assert!(assets.contains("@media(min-width:768px){._flex_md_{display:flex}}"));
|
||||
assert!(assets.contains("@media(min-width:992px){._flex-direction_column_lg_"));
|
||||
}
|
||||
|
|
|
|||
187
tests/component_flex.rs
Normal file
187
tests/component_flex.rs
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
use pagetop::prelude::*;
|
||||
|
||||
// **< Flex >***************************************************************************************
|
||||
|
||||
#[pagetop::test]
|
||||
async fn is_not_rendered_when_empty() {
|
||||
let mut container = Flex::default();
|
||||
let html = container.render(&mut Context::default()).await;
|
||||
|
||||
assert!(html.is_empty());
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn renders_a_div_element() {
|
||||
let mut container = Flex::default().with_child(Lc::n("x"));
|
||||
let html = container
|
||||
.render(&mut Context::default())
|
||||
.await
|
||||
.into_string();
|
||||
|
||||
assert!(html.starts_with("<div"));
|
||||
assert!(html.ends_with("</div>"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn without_flex_no_style_attribute_is_added() {
|
||||
let mut container = Flex::default().with_child(Lc::n("x"));
|
||||
let html = container
|
||||
.render(&mut Context::default())
|
||||
.await
|
||||
.into_string();
|
||||
|
||||
assert!(!html.contains("style="));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn default_flex_adds_only_display_flex() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Flex::new().with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_flex_""#));
|
||||
assert!(assets.contains("_flex_{display:flex}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn column_direction_adds_flex_direction_style() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Flex::new()
|
||||
.with_direction(flex::Direction::Column)
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_flex_"));
|
||||
assert!(html.contains("_flex-direction_column_"));
|
||||
assert!(assets.contains("_flex_{display:flex}"));
|
||||
assert!(assets.contains("_flex-direction_column_{flex-direction:column}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn wrap_justify_and_align_add_their_matching_styles() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Flex::new()
|
||||
.with_wrap(flex::Behavior::Wrap)
|
||||
.with_justify(flex::ContentJustify::Center)
|
||||
.with_align(align::Items::Center)
|
||||
.with_align_content(align::Content::SpaceBetween)
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_flex-wrap_wrap_"));
|
||||
assert!(html.contains("_flex-justify_center_"));
|
||||
assert!(html.contains("_flex-align-items_center_"));
|
||||
assert!(html.contains("_flex-align-content_space-between_"));
|
||||
assert!(assets.contains("_flex-wrap_wrap_{flex-wrap:wrap}"));
|
||||
assert!(assets.contains("_flex-justify_center_{justify-content:center}"));
|
||||
assert!(assets.contains("_flex-align-items_center_{align-items:center}"));
|
||||
assert!(assets.contains("_flex-align-content_space-between_{align-content:space-between}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn gap_both_adds_a_single_gap_style() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Flex::new()
|
||||
.with_gap(align::Gap::Both(UnitValue::RelRem(0.5)))
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_flex-gap_0_5rem_"));
|
||||
assert!(assets.contains("_flex-gap_0_5rem_{gap:0.5rem}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn gap_distinct_adds_row_and_column_gap_styles() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Flex::new()
|
||||
.with_gap(align::Gap::Distinct {
|
||||
row: UnitValue::Px(4),
|
||||
column: UnitValue::Px(8),
|
||||
})
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_flex-row-gap_4px_"));
|
||||
assert!(html.contains("_flex-column-gap_8px_"));
|
||||
assert!(assets.contains("_flex-row-gap_4px_{row-gap:4px}"));
|
||||
assert!(assets.contains("_flex-column-gap_8px_{column-gap:8px}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn gap_none_adds_no_gap_style() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Flex::new().with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(!html.contains("gap"));
|
||||
assert!(!assets.contains("gap"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn inline_flex_uses_its_own_display_value() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Flex::inline().with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_inline-flex_""#));
|
||||
assert!(assets.contains("_inline-flex_{display:inline-flex}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn inline_flex_at_a_breakpoint_adds_its_suffix() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Flex::inline_at(Breakpoint::Lg).with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_inline-flex_lg_""#));
|
||||
assert!(assets.contains("@media(min-width:992px){._inline-flex_lg_{display:inline-flex}}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn flex_and_flex_item_classes_keep_their_order() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Flex::new()
|
||||
.with_direction(flex::Direction::Column)
|
||||
.with_prop(PropsOp::add_classes("own"))
|
||||
.with_prop(FlexItem::new().with_grow(flex::ItemGrow::Is1))
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
|
||||
// The component's own classes come first, then those of `Flex`, then those of `FlexItem`,
|
||||
// which share a single accumulator in `Props::unpack_with_classes()`.
|
||||
assert!(html.contains(r#"class="own _flex_ _flex-direction_column_ _flex-item-grow_1_""#));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn flex_without_display_adds_no_class_of_its_own() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Flex::default()
|
||||
.with_prop(PropsOp::add_classes("own"))
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
|
||||
assert!(html.contains(r#"class="own""#));
|
||||
assert!(cx.render_assets().into_string().is_empty());
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn breakpoints_add_their_suffix_and_wrap_rules_in_media_queries() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Flex::at(Breakpoint::Md)
|
||||
.with_direction_at(Breakpoint::Lg, flex::Direction::Column)
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_flex_md_ _flex-direction_column_lg_""#));
|
||||
assert!(assets.contains("@media(min-width:768px){._flex_md_{display:flex}}"));
|
||||
assert!(assets.contains("@media(min-width:992px){._flex-direction_column_lg_"));
|
||||
}
|
||||
223
tests/component_grid.rs
Normal file
223
tests/component_grid.rs
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
use pagetop::prelude::*;
|
||||
|
||||
// **< Grid >***************************************************************************************
|
||||
|
||||
#[pagetop::test]
|
||||
async fn is_not_rendered_when_empty() {
|
||||
let mut container = Grid::default();
|
||||
let html = container.render(&mut Context::default()).await;
|
||||
|
||||
assert!(html.is_empty());
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn renders_a_div_element() {
|
||||
let mut container = Grid::default().with_child(Lc::n("x"));
|
||||
let html = container
|
||||
.render(&mut Context::default())
|
||||
.await
|
||||
.into_string();
|
||||
|
||||
assert!(html.starts_with("<div"));
|
||||
assert!(html.ends_with("</div>"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn without_grid_no_style_attribute_is_added() {
|
||||
let mut container = Grid::default().with_child(Lc::n("x"));
|
||||
let html = container
|
||||
.render(&mut Context::default())
|
||||
.await
|
||||
.into_string();
|
||||
|
||||
assert!(!html.contains("style="));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn default_grid_adds_only_display_grid() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Grid::new().with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_grid_""#));
|
||||
assert!(assets.contains("_grid_{display:grid}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn columns_and_rows_add_their_matching_styles() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Grid::new()
|
||||
.with_columns(grid::Tracks::repeat(3, grid::AxisTrack::Fraction(1.0)))
|
||||
.with_rows(grid::Tracks::new().with_track(grid::AxisTrack::Fixed(UnitValue::Px(80))))
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_grid-columns_1fr-1fr-1fr_"));
|
||||
assert!(html.contains("_grid-rows_80px_"));
|
||||
assert!(assets.contains("_grid-columns_1fr-1fr-1fr_{grid-template-columns:1fr 1fr 1fr}"));
|
||||
assert!(assets.contains("_grid-rows_80px_{grid-template-rows:80px}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn auto_columns_and_auto_rows_add_their_matching_styles() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Grid::new()
|
||||
.with_auto_columns(grid::AxisTrack::MinContent)
|
||||
.with_auto_rows(grid::AxisTrack::Fixed(UnitValue::RelRem(3.0)))
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_grid-auto-columns_min-content_"));
|
||||
assert!(html.contains("_grid-auto-rows_3rem_"));
|
||||
assert!(assets.contains("_grid-auto-columns_min-content_{grid-auto-columns:min-content}"));
|
||||
assert!(assets.contains("_grid-auto-rows_3rem_{grid-auto-rows:3rem}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn auto_flow_dense_sanitizes_the_space_in_its_class_name() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Grid::new()
|
||||
.with_auto_flow(grid::AutoFlow::RowDense)
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
// `AutoFlow::RowDense` resolves to "row dense" (with a space); as a class name it must stay a
|
||||
// single, valid token (regression test: this used to split into two class list entries).
|
||||
assert!(html.contains(r#"class="_grid_ _grid-auto-flow_row-dense_""#));
|
||||
assert!(assets.contains("_grid-auto-flow_row-dense_{grid-auto-flow:row dense}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn justify_items_and_align_items_add_their_matching_styles() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Grid::new()
|
||||
.with_justify_items(grid::DefaultJustify::Center)
|
||||
.with_align_items(align::Items::Stretch)
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_grid-justify-items_center_"));
|
||||
assert!(html.contains("_grid-align-items_stretch_"));
|
||||
assert!(assets.contains("_grid-justify-items_center_{justify-items:center}"));
|
||||
assert!(assets.contains("_grid-align-items_stretch_{align-items:stretch}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn justify_content_and_align_content_add_their_matching_styles() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Grid::new()
|
||||
.with_justify_content(grid::ContentJustify::SpaceBetween)
|
||||
.with_align_content(align::Content::Center)
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_grid-justify-content_space-between_"));
|
||||
assert!(html.contains("_grid-align-content_center_"));
|
||||
assert!(assets.contains("_grid-justify-content_space-between_{justify-content:space-between}"));
|
||||
assert!(assets.contains("_grid-align-content_center_{align-content:center}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn gap_both_adds_a_single_gap_style() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Grid::new()
|
||||
.with_gap(align::Gap::Both(UnitValue::RelRem(0.5)))
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_grid-gap_0_5rem_"));
|
||||
assert!(assets.contains("_grid-gap_0_5rem_{gap:0.5rem}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn gap_distinct_adds_row_and_column_gap_styles() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Grid::new()
|
||||
.with_gap(align::Gap::Distinct {
|
||||
row: UnitValue::Px(4),
|
||||
column: UnitValue::Px(8),
|
||||
})
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_grid-row-gap_4px_"));
|
||||
assert!(html.contains("_grid-column-gap_8px_"));
|
||||
assert!(assets.contains("_grid-row-gap_4px_{row-gap:4px}"));
|
||||
assert!(assets.contains("_grid-column-gap_8px_{column-gap:8px}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn inline_grid_uses_its_own_display_value() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Grid::inline().with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_inline-grid_""#));
|
||||
assert!(assets.contains("_inline-grid_{display:inline-grid}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn inline_grid_at_a_breakpoint_adds_its_suffix() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Grid::inline_at(Breakpoint::Lg).with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_inline-grid_lg_""#));
|
||||
assert!(assets.contains("@media(min-width:992px){._inline-grid_lg_{display:inline-grid}}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn grid_and_grid_item_classes_keep_their_order() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Grid::new()
|
||||
.with_columns(grid::Tracks::repeat(2, grid::AxisTrack::Fraction(1.0)))
|
||||
.with_prop(PropsOp::add_classes("own"))
|
||||
.with_prop(GridItem::new().with_column(grid::ItemPlacement::Span(2)))
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
|
||||
// The component's own classes come first, then those of `Grid`, then those of `GridItem`,
|
||||
// which share a single accumulator in `Props::unpack_with_classes()`.
|
||||
assert!(
|
||||
html.contains(r#"class="own _grid_ _grid-columns_1fr-1fr_ _grid-item-column_span-2_""#)
|
||||
);
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn grid_without_display_adds_no_class_of_its_own() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Grid::default()
|
||||
.with_prop(PropsOp::add_classes("own"))
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
|
||||
assert!(html.contains(r#"class="own""#));
|
||||
assert!(cx.render_assets().into_string().is_empty());
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn grid_breakpoints_add_their_suffix_and_wrap_rules_in_media_queries() {
|
||||
let mut cx = Context::default();
|
||||
let mut container = Grid::at(Breakpoint::Md)
|
||||
.with_columns_at(
|
||||
Breakpoint::Lg,
|
||||
grid::Tracks::repeat(3, grid::AxisTrack::Fraction(1.0)),
|
||||
)
|
||||
.with_child(Lc::n("x"));
|
||||
let html = container.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_grid_md_ _grid-columns_1fr-1fr-1fr_lg_""#));
|
||||
assert!(assets.contains("@media(min-width:768px){._grid_md_{display:grid}}"));
|
||||
assert!(assets.contains("@media(min-width:992px){._grid-columns_1fr-1fr-1fr_lg_"));
|
||||
}
|
||||
|
|
@ -14,56 +14,6 @@ async fn is_not_rendered_when_empty() {
|
|||
assert!(html.is_empty());
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn nav_root_class_is_unaffected_by_content_flex() {
|
||||
let mut navbar = Navbar::simple()
|
||||
.with_flex(Flex::new().with_justify(flex::ContentJustify::End))
|
||||
.with_item(navbar::Item::nav(one_link_nav()));
|
||||
let html = navbar.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(html.contains(r#"class="navbar""#));
|
||||
}
|
||||
|
||||
// **< Navbar + Flex (content area) >***************************************************************
|
||||
|
||||
#[pagetop::test]
|
||||
async fn without_flex_content_area_has_no_style_attribute() {
|
||||
let mut navbar = Navbar::simple().with_item(navbar::Item::nav(one_link_nav()));
|
||||
let html = navbar.render(&mut Context::default()).await.into_string();
|
||||
|
||||
assert!(html.contains(r#"class="navbar-content""#));
|
||||
assert!(!html.contains("style="));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn flex_adds_its_styles_to_the_content_area() {
|
||||
let mut cx = Context::default();
|
||||
let mut navbar = Navbar::simple()
|
||||
.with_flex(Flex::new().with_justify(flex::ContentJustify::End))
|
||||
.with_item(navbar::Item::nav(one_link_nav()));
|
||||
let html = navbar.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("navbar-content"));
|
||||
assert!(html.contains("_flex_"));
|
||||
assert!(html.contains("_flex-justify_flex-end_"));
|
||||
assert!(assets.contains("_flex_{display:flex}"));
|
||||
assert!(assets.contains("_flex-justify_flex-end_{justify-content:flex-end}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn flex_gap_adds_a_style_to_the_content_area() {
|
||||
let mut cx = Context::default();
|
||||
let mut navbar = Navbar::simple()
|
||||
.with_flex(Flex::new().with_gap(align::Gap::Both(UnitValue::RelRem(0.5))))
|
||||
.with_item(navbar::Item::nav(one_link_nav()));
|
||||
let html = navbar.render(&mut cx).await.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_flex-gap_0_5rem_"));
|
||||
assert!(assets.contains("_flex-gap_0_5rem_{gap:0.5rem}"));
|
||||
}
|
||||
|
||||
// **< Navbar + FlexItem::push_end >****************************************************************
|
||||
|
||||
#[pagetop::test]
|
||||
|
|
|
|||
150
tests/html_props_grid_item.rs
Normal file
150
tests/html_props_grid_item.rs
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
use pagetop::prelude::*;
|
||||
|
||||
#[pagetop::test]
|
||||
async fn default_grid_item_adds_nothing() {
|
||||
let mut cx = Context::default();
|
||||
let props = Props::default().with_prop(GridItem::new());
|
||||
let html = html! { span (props.unpack(&mut cx)) {} }.into_string();
|
||||
|
||||
assert_eq!(html, "<span></span>");
|
||||
assert!(cx.render_assets().into_string().is_empty());
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn column_span_adds_grid_column_style() {
|
||||
let mut cx = Context::default();
|
||||
let props =
|
||||
Props::default().with_prop(GridItem::new().with_column(grid::ItemPlacement::Span(2)));
|
||||
let html = html! { span (props.unpack(&mut cx)) {} }.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_grid-item-column_span-2_""#));
|
||||
assert!(assets.contains("_grid-item-column_span-2_{grid-column:span 2}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn column_line_adds_grid_column_style() {
|
||||
let mut cx = Context::default();
|
||||
let props =
|
||||
Props::default().with_prop(GridItem::new().with_column(grid::ItemPlacement::Line(3)));
|
||||
let html = html! { span (props.unpack(&mut cx)) {} }.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_grid-item-column_3_""#));
|
||||
assert!(assets.contains("_grid-item-column_3_{grid-column:3}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn column_range_sanitizes_the_slash_and_space_in_its_class_name() {
|
||||
let mut cx = Context::default();
|
||||
let props =
|
||||
Props::default().with_prop(GridItem::new().with_column(grid::ItemPlacement::Range(2, 4)));
|
||||
let html = html! { span (props.unpack(&mut cx)) {} }.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
// "2 / 4" is a valid CSS value (with its spaces and slash), but not a valid class name
|
||||
// fragment: `value_to_token()` replaces both characters so the class stays a single token.
|
||||
assert!(html.contains(r#"class="_grid-item-column_2---4_""#));
|
||||
assert!(assets.contains("_grid-item-column_2---4_{grid-column:2 / 4}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn row_adds_grid_row_style() {
|
||||
let mut cx = Context::default();
|
||||
let props = Props::default().with_prop(GridItem::new().with_row(grid::ItemPlacement::Line(2)));
|
||||
let html = html! { span (props.unpack(&mut cx)) {} }.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_grid-item-row_2_""#));
|
||||
assert!(assets.contains("_grid-item-row_2_{grid-row:2}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn justify_self_adds_matching_style() {
|
||||
let mut cx = Context::default();
|
||||
let props =
|
||||
Props::default().with_prop(GridItem::new().with_justify_self(grid::ItemJustify::End));
|
||||
let html = html! { span (props.unpack(&mut cx)) {} }.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_grid-item-justify-self_end_""#));
|
||||
assert!(assets.contains("_grid-item-justify-self_end_{justify-self:end}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn align_self_adds_matching_style() {
|
||||
let mut cx = Context::default();
|
||||
let props =
|
||||
Props::default().with_prop(GridItem::new().with_align_self(align::ItemSelf::Center));
|
||||
let html = html! { span (props.unpack(&mut cx)) {} }.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_grid-item-align-self_center_""#));
|
||||
assert!(assets.contains("_grid-item-align-self_center_{align-self:center}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn combines_several_facets_in_one_call() {
|
||||
let mut cx = Context::default();
|
||||
let props = Props::default().with_prop(
|
||||
GridItem::new()
|
||||
.with_column(grid::ItemPlacement::Span(2))
|
||||
.with_row(grid::ItemPlacement::Line(2))
|
||||
.with_justify_self(grid::ItemJustify::Stretch)
|
||||
.with_align_self(align::ItemSelf::Start),
|
||||
);
|
||||
let html = html! { span (props.unpack(&mut cx)) {} }.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains("_grid-item-column_span-2_"));
|
||||
assert!(html.contains("_grid-item-row_2_"));
|
||||
assert!(html.contains("_grid-item-justify-self_stretch_"));
|
||||
assert!(html.contains("_grid-item-align-self_flex-start_"));
|
||||
assert!(assets.contains("_grid-item-column_span-2_{grid-column:span 2}"));
|
||||
assert!(assets.contains("_grid-item-row_2_{grid-row:2}"));
|
||||
assert!(assets.contains("_grid-item-justify-self_stretch_{justify-self:stretch}"));
|
||||
assert!(assets.contains("_grid-item-align-self_flex-start_{align-self:flex-start}"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn column_at_a_breakpoint_combines_token_and_suffix() {
|
||||
let mut cx = Context::default();
|
||||
let props = Props::default()
|
||||
.with_prop(GridItem::new().with_column_at(Breakpoint::Md, grid::ItemPlacement::Span(3)));
|
||||
let html = html! { span (props.unpack(&mut cx)) {} }.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_grid-item-column_span-3_md_""#));
|
||||
assert!(
|
||||
assets
|
||||
.contains("@media(min-width:768px){._grid-item-column_span-3_md_{grid-column:span 3}}")
|
||||
);
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn base_and_breakpoint_values_generate_one_class_each() {
|
||||
let mut cx = Context::default();
|
||||
let props = Props::default().with_prop(
|
||||
GridItem::new()
|
||||
.with_align_self(align::ItemSelf::Default)
|
||||
.with_column(grid::ItemPlacement::Span(2))
|
||||
.with_column_at(Breakpoint::Lg, grid::ItemPlacement::Span(4)),
|
||||
);
|
||||
let html = html! { span (props.unpack(&mut cx)) {} }.into_string();
|
||||
|
||||
// `ItemSelf::Default` resolves to an empty CSS value, so it adds no class at all.
|
||||
assert!(html.contains(r#"class="_grid-item-column_span-2_ _grid-item-column_span-4_lg_""#));
|
||||
assert!(!html.contains("_grid-item-align-self_"));
|
||||
}
|
||||
|
||||
#[pagetop::test]
|
||||
async fn from_grid_item_for_props_op() {
|
||||
let mut cx = Context::default();
|
||||
let item = GridItem::new().with_column(grid::ItemPlacement::Span(2));
|
||||
let props = Props::default().with_prop(item);
|
||||
let html = html! { span (props.unpack(&mut cx)) {} }.into_string();
|
||||
let assets = cx.render_assets().into_string();
|
||||
|
||||
assert!(html.contains(r#"class="_grid-item-column_span-2_""#));
|
||||
assert!(assets.contains("_grid-item-column_span-2_{grid-column:span 2}"));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue