use guiduck_component_core::expr::Expr; use guiduck_core::component::DynSignal; use guiduck_core::signals::Signal; use super::*; fn expr(source: &str) -> Expr { let doc = guiduck_component_core::sexpr::read(source).expect("reads"); guiduck_component_core::expr::from_sexpr(&doc.values[0], source).expect("valid") } fn cx_with(count: i32, busy: bool) -> DynCx { let mut cx = DynCx::default(); cx.signals .insert("count".into(), DynSignal::I32(Signal::new(count))); cx.signals .insert("busy".into(), DynSignal::Bool(Signal::new(busy))); cx.props .insert("step".into(), DynSignal::I64(Signal::new(3))); cx.props .insert("label".into(), DynSignal::Str(Signal::new("Items".into()))); cx } #[test] fn arithmetic_and_comparison() { let cx = cx_with(7, false); assert_eq!(eval(&expr("(+ count step)"), &cx), Value::I64(10)); assert_eq!(eval(&expr("(* count 2)"), &cx), Value::I64(14)); assert_eq!(eval(&expr("(> count 5)"), &cx), Value::Bool(true)); assert_eq!(eval(&expr("(= count 7)"), &cx), Value::Bool(true)); assert_eq!( eval(&expr("(/ count 0)"), &cx), Value::I64(0), "no div-by-zero panic" ); assert_eq!(eval(&expr("(+ 1.5 count)"), &cx), Value::F64(8.5)); } #[test] fn boolean_logic_short_circuits() { let cx = cx_with(1, true); assert_eq!( eval(&expr("(and busy (> count 0))"), &cx), Value::Bool(true) ); assert_eq!(eval(&expr("(not busy)"), &cx), Value::Bool(false)); assert_eq!(eval(&expr("(or busy (/ 1 0))"), &cx), Value::Bool(true)); } #[test] fn templates_interpolate() { let cx = cx_with(4, false); assert_eq!( eval(&expr(r#""{label}: {count} of {step}""#), &cx), Value::Str("Items: 4 of 3".into()) ); } #[test] fn if_selects_branches() { let cx = cx_with(0, true); assert_eq!( eval(&expr(r##"(if busy "#111111" "#222222")"##), &cx), Value::Str("#111111".into()) ); }