| 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<ScopedJson<'rc>, 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<AtomicU16>, |
| } |
| |
| impl HelperDef for CallCounterHelper { |
| fn call_inner<'reg: 'rc, 'rc>( |
| &self, |
| h: &Helper<'rc>, |
| _: &'reg Handlebars, |
| _: &'rc Context, |
| _: &mut RenderContext<'reg, 'rc>, |
| ) -> Result<ScopedJson<'rc>, RenderError> { |
| // inc counter |
| self.c.fetch_add(1, Ordering::SeqCst); |
| |
| if let Some(_) = h.param(0) { |
| 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)); |
| } |