use azul_layout::solver3::calc::*;
use azul_css::props::basic::{FloatValue, PixelValue, SizeMetric, DEFAULT_FONT_SIZE};
use azul_css::props::layout::{CalcAstItem, CalcAstItemVec};
fn pv(metric: SizeMetric, number: f32) -> PixelValue {
PixelValue {
metric,
number: FloatValue::new(number),
}
}
fn items(v: Vec<CalcAstItem>) -> CalcAstItemVec {
v.into()
}
fn ctx(ast: Vec<CalcAstItem>) -> CalcResolveContext {
CalcResolveContext {
items: items(ast),
em_size: DEFAULT_FONT_SIZE,
rem_size: DEFAULT_FONT_SIZE,
}
}
fn ctx_with_fonts(ast: Vec<CalcAstItem>, em: f32, rem: f32) -> CalcResolveContext {
CalcResolveContext {
items: items(ast),
em_size: em,
rem_size: rem,
}
}
#[test]
fn single_px_value() {
let c = ctx(vec![CalcAstItem::Value(pv(SizeMetric::Px, 100.0))]);
assert_eq!(evaluate_calc(&c, 0.0), 100.0);
}
#[test]
fn single_percent_value() {
let c = ctx(vec![CalcAstItem::Value(pv(SizeMetric::Percent, 50.0))]);
assert_eq!(evaluate_calc(&c, 400.0), 200.0);
}
#[test]
fn single_pt_value() {
let c = ctx(vec![CalcAstItem::Value(pv(SizeMetric::Pt, 12.0))]);
let result = evaluate_calc(&c, 0.0);
assert!((result - 16.0).abs() < 0.01);
}
#[test]
fn simple_addition() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Px, 100.0)),
CalcAstItem::Add,
CalcAstItem::Value(pv(SizeMetric::Px, 50.0)),
]);
assert_eq!(evaluate_calc(&c, 0.0), 150.0);
}
#[test]
fn simple_subtraction() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Px, 200.0)),
CalcAstItem::Sub,
CalcAstItem::Value(pv(SizeMetric::Px, 50.0)),
]);
assert_eq!(evaluate_calc(&c, 0.0), 150.0);
}
#[test]
fn percent_minus_px() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Percent, 100.0)),
CalcAstItem::Sub,
CalcAstItem::Value(pv(SizeMetric::Px, 20.0)),
]);
assert_eq!(evaluate_calc(&c, 300.0), 280.0);
}
#[test]
fn thirds_calc() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Percent, 33.333)),
CalcAstItem::Sub,
CalcAstItem::Value(pv(SizeMetric::Px, 10.0)),
]);
let result = evaluate_calc(&c, 900.0);
assert!((result - 289.997).abs() < 0.01);
}
#[test]
fn simple_multiplication() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Px, 50.0)),
CalcAstItem::Mul,
CalcAstItem::Value(pv(SizeMetric::Px, 3.0)),
]);
assert_eq!(evaluate_calc(&c, 0.0), 150.0);
}
#[test]
fn simple_division() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Px, 300.0)),
CalcAstItem::Div,
CalcAstItem::Value(pv(SizeMetric::Px, 4.0)),
]);
assert_eq!(evaluate_calc(&c, 0.0), 75.0);
}
#[test]
fn division_by_zero() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Px, 100.0)),
CalcAstItem::Div,
CalcAstItem::Value(pv(SizeMetric::Px, 0.0)),
]);
assert_eq!(evaluate_calc(&c, 0.0), 0.0);
}
#[test]
fn precedence_mul_before_add() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Px, 10.0)),
CalcAstItem::Add,
CalcAstItem::Value(pv(SizeMetric::Px, 5.0)),
CalcAstItem::Mul,
CalcAstItem::Value(pv(SizeMetric::Px, 3.0)),
]);
assert_eq!(evaluate_calc(&c, 0.0), 25.0);
}
#[test]
fn precedence_div_before_sub() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Px, 100.0)),
CalcAstItem::Sub,
CalcAstItem::Value(pv(SizeMetric::Px, 60.0)),
CalcAstItem::Div,
CalcAstItem::Value(pv(SizeMetric::Px, 3.0)),
]);
assert_eq!(evaluate_calc(&c, 0.0), 80.0);
}
#[test]
fn precedence_complex() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Px, 2.0)),
CalcAstItem::Mul,
CalcAstItem::Value(pv(SizeMetric::Px, 3.0)),
CalcAstItem::Add,
CalcAstItem::Value(pv(SizeMetric::Px, 4.0)),
CalcAstItem::Mul,
CalcAstItem::Value(pv(SizeMetric::Px, 5.0)),
]);
assert_eq!(evaluate_calc(&c, 0.0), 26.0);
}
#[test]
fn simple_parens() {
let c = ctx(vec![
CalcAstItem::BraceOpen,
CalcAstItem::Value(pv(SizeMetric::Px, 10.0)),
CalcAstItem::Add,
CalcAstItem::Value(pv(SizeMetric::Px, 20.0)),
CalcAstItem::BraceClose,
]);
assert_eq!(evaluate_calc(&c, 0.0), 30.0);
}
#[test]
fn parens_override_precedence() {
let c = ctx(vec![
CalcAstItem::BraceOpen,
CalcAstItem::Value(pv(SizeMetric::Px, 10.0)),
CalcAstItem::Add,
CalcAstItem::Value(pv(SizeMetric::Px, 5.0)),
CalcAstItem::BraceClose,
CalcAstItem::Mul,
CalcAstItem::Value(pv(SizeMetric::Px, 3.0)),
]);
assert_eq!(evaluate_calc(&c, 0.0), 45.0);
}
#[test]
fn nested_parens() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Px, 100.0)),
CalcAstItem::Sub,
CalcAstItem::BraceOpen,
CalcAstItem::Value(pv(SizeMetric::Px, 20.0)),
CalcAstItem::Add,
CalcAstItem::BraceOpen,
CalcAstItem::Value(pv(SizeMetric::Px, 5.0)),
CalcAstItem::Mul,
CalcAstItem::Value(pv(SizeMetric::Px, 2.0)),
CalcAstItem::BraceClose,
CalcAstItem::BraceClose,
]);
assert_eq!(evaluate_calc(&c, 0.0), 70.0);
}
#[test]
fn em_with_default_font_size() {
let c = ctx(vec![CalcAstItem::Value(pv(SizeMetric::Em, 2.0))]);
assert_eq!(evaluate_calc(&c, 0.0), DEFAULT_FONT_SIZE * 2.0);
}
#[test]
fn em_with_custom_font_size() {
let c = ctx_with_fonts(
vec![CalcAstItem::Value(pv(SizeMetric::Em, 2.0))],
24.0,
16.0,
);
assert_eq!(evaluate_calc(&c, 0.0), 48.0);
}
#[test]
fn rem_with_custom_root_font_size() {
let c = ctx_with_fonts(
vec![CalcAstItem::Value(pv(SizeMetric::Rem, 1.5))],
16.0,
20.0,
);
assert_eq!(evaluate_calc(&c, 0.0), 30.0);
}
#[test]
fn em_and_rem_differ() {
let c = ctx_with_fonts(
vec![
CalcAstItem::Value(pv(SizeMetric::Em, 1.0)),
CalcAstItem::Add,
CalcAstItem::Value(pv(SizeMetric::Rem, 1.0)),
],
24.0,
20.0,
);
assert_eq!(evaluate_calc(&c, 0.0), 44.0);
}
#[test]
fn em_percent_mixed() {
let c = ctx_with_fonts(
vec![
CalcAstItem::Value(pv(SizeMetric::Percent, 50.0)),
CalcAstItem::Add,
CalcAstItem::Value(pv(SizeMetric::Em, 2.0)),
],
12.0,
16.0,
);
assert_eq!(evaluate_calc(&c, 200.0), 124.0);
}
#[test]
fn flexbox_three_column() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Percent, 33.333)),
CalcAstItem::Sub,
CalcAstItem::Value(pv(SizeMetric::Px, 10.0)),
]);
let result = evaluate_calc(&c, 600.0);
assert!((result - 189.998).abs() < 0.01);
}
#[test]
fn sidebar_main_layout() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Percent, 100.0)),
CalcAstItem::Sub,
CalcAstItem::Value(pv(SizeMetric::Px, 250.0)),
]);
assert_eq!(evaluate_calc(&c, 1024.0), 774.0);
}
#[test]
fn responsive_padding() {
let c = ctx_with_fonts(
vec![
CalcAstItem::Value(pv(SizeMetric::Rem, 1.0)),
CalcAstItem::Add,
CalcAstItem::Value(pv(SizeMetric::Percent, 2.0)),
],
16.0,
16.0,
);
assert_eq!(evaluate_calc(&c, 800.0), 32.0);
}
#[test]
fn empty_expression() {
let c = ctx(vec![]);
assert_eq!(evaluate_calc(&c, 100.0), 0.0);
}
#[test]
fn only_operator_no_values() {
let c = ctx(vec![CalcAstItem::Add]);
assert_eq!(evaluate_calc(&c, 100.0), 0.0);
}
#[test]
fn multiple_additions() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Px, 10.0)),
CalcAstItem::Add,
CalcAstItem::Value(pv(SizeMetric::Px, 20.0)),
CalcAstItem::Add,
CalcAstItem::Value(pv(SizeMetric::Px, 30.0)),
]);
assert_eq!(evaluate_calc(&c, 0.0), 60.0);
}
#[test]
fn cm_unit() {
let c = ctx(vec![CalcAstItem::Value(pv(SizeMetric::Cm, 2.54))]);
let result = evaluate_calc(&c, 0.0);
assert!((result - 96.0).abs() < 0.01);
}
#[test]
fn mm_unit() {
let c = ctx(vec![CalcAstItem::Value(pv(SizeMetric::Mm, 25.4))]);
let result = evaluate_calc(&c, 0.0);
assert!((result - 96.0).abs() < 0.01);
}
#[test]
fn in_unit() {
let c = ctx(vec![CalcAstItem::Value(pv(SizeMetric::In, 1.0))]);
assert_eq!(evaluate_calc(&c, 0.0), 96.0);
}
#[test]
fn chained_mul_div() {
let c = ctx(vec![
CalcAstItem::Value(pv(SizeMetric::Px, 100.0)),
CalcAstItem::Mul,
CalcAstItem::Value(pv(SizeMetric::Px, 2.0)),
CalcAstItem::Div,
CalcAstItem::Value(pv(SizeMetric::Px, 4.0)),
]);
assert_eq!(evaluate_calc(&c, 0.0), 50.0);
}
#[test]
fn resolve_px() {
assert_eq!(resolve_pixel_value(&pv(SizeMetric::Px, 42.0), 0.0, 16.0, 16.0), 42.0);
}
#[test]
fn resolve_percent() {
assert_eq!(resolve_pixel_value(&pv(SizeMetric::Percent, 25.0), 400.0, 16.0, 16.0), 100.0);
}
#[test]
fn resolve_em_custom() {
assert_eq!(resolve_pixel_value(&pv(SizeMetric::Em, 2.0), 0.0, 20.0, 16.0), 40.0);
}
#[test]
fn resolve_rem_custom() {
assert_eq!(resolve_pixel_value(&pv(SizeMetric::Rem, 2.0), 0.0, 20.0, 18.0), 36.0);
}