extern crate handlebars; #[macro_use] extern crate serde_json; use std::sync::atomic::{AtomicU16, Ordering}; use std::sync::Arc; use handlebars::{ Context, Handlebars, Helper, HelperDef, RenderContext, RenderError, RenderErrorReason, ScopedJson, }; #[test] fn test_subexpression() { let hbs = Handlebars::new(); let data = json!({"a": 1, "b": 0, "c": 2}); assert_eq!( hbs.render_template("{{#if (gt a b)}}Success{{else}}Failed{{/if}}", &data) .unwrap(), "Success" ); assert_eq!( hbs.render_template("{{#if (gt a c)}}Success{{else}}Failed{{/if}}", &data) .unwrap(), "Failed" ); assert_eq!( hbs.render_template("{{#if (not (gt a c))}}Success{{else}}Failed{{/if}}", &data) .unwrap(), "Success" ); assert_eq!( hbs.render_template("{{#if (not (gt a b))}}Success{{else}}Failed{{/if}}", &data) .unwrap(), "Failed" ); // no argument provided for not assert!(hbs .render_template("{{#if (not)}}Success{{else}}Failed{{/if}}", &data) .is_err()); // json literal assert_eq!( hbs.render_template("{{#if (not true)}}Success{{else}}Failed{{/if}}", &data) .unwrap(), "Failed" ); assert_eq!( hbs.render_template("{{#if (not false)}}Success{{else}}Failed{{/if}}", &data) .unwrap(), "Success" ); } #[test] fn test_strict_mode() { let mut hbs = Handlebars::new(); hbs.set_strict_mode(true); let data = json!({"a": 1}); assert!(hbs .render_template("{{#if (eq a 1)}}Success{{else}}Failed{{/if}}", &data) .is_ok()); assert!(hbs .render_template("{{#if (eq z 1)}}Success{{else}}Failed{{/if}}", &data) .is_err()); } #[test] fn invalid_json_path() { // The data here is not important let data = &Vec::<()>::new(); let hbs = Handlebars::new(); let error = hbs.render_template("{{x[]@this}}", &data).unwrap_err(); let cause = error.reason(); assert!(matches!(cause, RenderErrorReason::HelperNotFound(_))); } struct MyHelper; impl HelperDef for MyHelper { fn call_inner<'reg: 'rc, 'rc>( &self, _: &Helper<'rc>, _: &'reg Handlebars, _: &'rc Context, _: &mut RenderContext<'reg, 'rc>, ) -> Result, RenderError> { Ok(ScopedJson::Derived(json!({ "a": 1, "b": 2, }))) } } #[test] fn test_lookup_with_subexpression() { let mut registry = Handlebars::new(); registry.register_helper("myhelper", Box::new(MyHelper {})); registry .register_template_string("t", "{{ lookup (myhelper) \"a\" }}") .unwrap(); let result = registry.render("t", &json!({})).unwrap(); assert_eq!("1", result); } struct CallCounterHelper { pub(crate) c: Arc, } impl HelperDef for CallCounterHelper { fn call_inner<'reg: 'rc, 'rc>( &self, h: &Helper<'rc>, _: &'reg Handlebars, _: &'rc Context, _: &mut RenderContext<'reg, 'rc>, ) -> Result, RenderError> { // inc counter self.c.fetch_add(1, Ordering::SeqCst); if h.param(0).is_some() { Ok(json!({ "a": 1, }) .into()) } else { Ok(json!(null).into()) } } } #[test] fn test_helper_call_count() { let mut registry = Handlebars::new(); let counter = Arc::new(AtomicU16::new(0)); let helper = Box::new(CallCounterHelper { c: counter.clone() }); registry.register_helper("myhelper", helper); registry .render_template( "{{#if (myhelper a)}}something{{else}}nothing{{/if}}", &json!(null), ) // If returns true .unwrap(); assert_eq!(1, counter.load(Ordering::SeqCst)); registry .render_template( "{{#if (myhelper)}}something{{else}}nothing{{/if}}", &json!(null), ) // If returns false .unwrap(); assert_eq!(2, counter.load(Ordering::SeqCst)); }