#[cfg(feature = "serde_json")] #[macro_use] extern crate serde_json; use rinja::Template; #[cfg(feature = "serde_json")] use serde_json::Value; #[test] fn filter_escape() { #[derive(Template)] #[template(path = "filters.html")] struct TestTemplate { strvar: String, } let s = TestTemplate { strvar: "// my is \"unsafe\" & should be 'escaped'".to_string(), }; assert_eq!( s.render().unwrap(), "// my <html> is "unsafe" & \ should be 'escaped'" ); } #[test] fn filter_opt_escaper_none() { #[derive(Template)] #[template( source = "{{ \"

Foo Bar

\"|escape(\"none\") }} {{ \"

Foo Bar

\"|escape(\"html\") }} {{ \"

Foo Bar

\"|escape }} {{ \"

Foo Bar

\" }} ", ext = "txt", escape = "none" )] struct OptEscaperNoneTemplate; let t = OptEscaperNoneTemplate; assert_eq!( t.render().unwrap(), r#"

Foo Bar

<h1 class="title">Foo Bar</h1>

Foo Bar

Foo Bar

"# ); } #[test] fn filter_opt_escaper_html() { #[derive(Template)] #[template( source = "{{ \"

Foo Bar

\"|escape(\"none\") }} {{ \"

Foo Bar

\"|escape(\"html\") }} {{ \"

Foo Bar

\"|escape }} {{ \"

Foo Bar

\" }} ", ext = "txt", escape = "html" )] struct OptEscaperHtmlTemplate; let t = OptEscaperHtmlTemplate; assert_eq!( t.render().unwrap(), r#"

Foo Bar

<h1 class="title">Foo Bar</h1> <h1 class="title">Foo Bar</h1> <h1 class="title">Foo Bar</h1> "# ); } #[test] fn filter_format() { #[derive(Template)] #[template(path = "format.html", escape = "none")] struct FormatTemplate<'a> { var: &'a str, } let t = FormatTemplate { var: "formatted" }; assert_eq!(t.render().unwrap(), "\"formatted\""); } #[test] fn filter_fmt() { #[derive(Template)] #[template(source = "{{ var|fmt(\"{:?}\") }}", ext = "html", escape = "none")] struct FmtTemplate<'a> { var: &'a str, } let t = FmtTemplate { var: "formatted" }; assert_eq!(t.render().unwrap(), "\"formatted\""); } mod filters { pub fn myfilter(s: &str) -> ::rinja::Result { Ok(s.replace("oo", "aa")) } // for test_nested_filter_ref pub fn mytrim(s: &dyn (::std::fmt::Display)) -> ::rinja::Result { Ok(s.to_string().trim().to_owned()) } } #[test] fn test_my_filter() { #[derive(Template)] #[template(source = "{{ s|myfilter }}", ext = "txt")] struct MyFilterTemplate<'a> { s: &'a str, } let t = MyFilterTemplate { s: "foo" }; assert_eq!(t.render().unwrap(), "faa"); } #[test] fn test_join() { #[derive(Template)] #[template(path = "filters_join.html")] struct JoinTemplate<'a> { s: &'a [&'a str], } let t = JoinTemplate { s: &["foo", "bar", "bazz"], }; assert_eq!(t.render().unwrap(), "foo, bar, bazz"); } #[test] fn test_vec_join() { #[derive(Template)] #[template(path = "filters_join.html")] struct VecJoinTemplate { s: Vec, } let t = VecJoinTemplate { s: vec!["foo".into(), "bar".into(), "bazz".into()], }; assert_eq!(t.render().unwrap(), "foo, bar, bazz"); } #[cfg(feature = "serde_json")] #[test] fn test_json() { #[derive(Template)] #[template( source = r#"{ "foo": "{{ foo }}", "bar": {{ bar|json|safe }} }"#, ext = "txt" )] struct JsonTemplate<'a> { foo: &'a str, bar: &'a Value, } let val = json!({"arr": [ "one", 2, true, null ]}); let t = JsonTemplate { foo: "a", bar: &val, }; assert_eq!( t.render().unwrap(), r#"{ "foo": "a", "bar": {"arr":["one",2,true,null]} }"# ); } #[cfg(feature = "serde_json")] #[test] fn test_pretty_json() { #[derive(Template)] #[template( source = r#"{ "foo": "{{ foo }}", "bar": {{ bar|json(2)|safe }} }"#, ext = "txt" )] struct PrettyJsonTemplate<'a> { foo: &'a str, bar: &'a Value, } let val = json!({"arr": [ "one", 2, true, null ]}); let t = PrettyJsonTemplate { foo: "a", bar: &val, }; // Note: the json filter lacks a way to specify initial indentation assert_eq!( t.render().unwrap(), r#"{ "foo": "a", "bar": { "arr": [ "one", 2, true, null ] } }"# ); } #[cfg(feature = "serde_json")] #[test] fn test_dynamic_json() { #[derive(Template)] #[template(source = r#"{{ bar|json(indent)|safe }}"#, ext = "txt")] struct DynamicJsonTemplate<'a> { bar: &'a Value, indent: &'a str, } let val = json!({"arr": ["one", 2]}); let t = DynamicJsonTemplate { bar: &val, indent: "?", }; assert_eq!( t.render().unwrap(), r#"{ ?"arr": [ ??"one", ??2 ?] }"# ); } #[test] fn test_nested_filter_ref() { #[derive(Template)] #[template(source = "{{ x|mytrim|safe }}", ext = "html")] struct NestedFilterTemplate { x: String, } let t = NestedFilterTemplate { x: " floo & bar".to_string(), }; assert_eq!(t.render().unwrap(), "floo & bar"); } #[test] fn test_filter_let_filter() { #[derive(Template)] #[template( source = "{% let p = baz.print(foo.as_ref()) %}{{ p|upper }}", ext = "html" )] struct FilterLetFilterTemplate { foo: String, baz: Baz, } struct Baz {} impl Baz { fn print(&self, s: &str) -> String { s.trim().to_owned() } } let t = FilterLetFilterTemplate { foo: " bar ".to_owned(), baz: Baz {}, }; assert_eq!(t.render().unwrap(), "BAR"); } #[test] fn test_filter_truncate() { #[derive(Template)] #[template(source = "{{ foo|truncate(10) }}{{ foo|truncate(5) }}", ext = "txt")] struct TruncateFilter { foo: String, } let t = TruncateFilter { foo: "alpha bar".into(), }; assert_eq!(t.render().unwrap(), "alpha baralpha..."); } #[cfg(feature = "serde_json")] #[test] fn test_json_attribute() { #[derive(Template)] #[template(source = r#"
  • "#, ext = "html")] struct JsonAttributeTemplate<'a> { name: &'a str, } let t = JsonAttributeTemplate { name: r#"">"#, }; assert_eq!( t.render().unwrap(), r#"
  • "# ); } #[cfg(feature = "serde_json")] #[test] fn test_json_attribute2() { #[derive(Template)] #[template(source = r#"
  • "#, ext = "html")] struct JsonAttribute2Template<'a> { name: &'a str, } let t = JsonAttribute2Template { name: r"'>", }; assert_eq!( t.render().unwrap(), r#"
  • "# ); } #[cfg(feature = "serde_json")] #[test] fn test_json_script() { #[derive(Template)] #[template( source = r#""#, ext = "html" )] struct JsonScriptTemplate<'a> { name: &'a str, } let t = JsonScriptTemplate { name: r"", }; assert_eq!( t.render().unwrap(), r#""# ); } #[test] fn test_let_borrow() { #[derive(rinja::Template)] #[template( source = r#"{% let word = s|ref %}{{ word }} {%- let hello = String::from("hello") %} {%- if word|deref == hello %}1{% else %}2{% endif %}"#, ext = "html" )] struct LetBorrow { s: String, } let template = LetBorrow { s: "hello".to_owned(), }; assert_eq!(template.render().unwrap(), "hello1"); } #[test] fn test_linebreaks() { let s = ""; #[derive(Template)] #[template(source = r#"{{ s|linebreaks }}"#, ext = "html")] struct LineBreaks { s: &'static str, } assert_eq!( LineBreaks { s }.render().unwrap(), "

    <script>
    alert('Hello, world!')
    </script>

    ", ); #[derive(Template)] #[template(source = r#"{{ s|escape|linebreaks }}"#, ext = "html")] struct LineBreaksExtraEscape { s: &'static str, } assert_eq!( LineBreaksExtraEscape { s }.render().unwrap(), "

    <script>
    alert('Hello, world!')
    </script>

    ", ); #[derive(Template)] #[template(source = r#"{{ s|linebreaks|safe }}"#, ext = "html")] struct LineBreaksExtraSafe { s: &'static str, } assert_eq!( LineBreaksExtraSafe { s }.render().unwrap(), "

    <script>
    alert('Hello, world!')
    </script>

    ", ); #[derive(Template)] #[template(source = r#"{{ s|escape|linebreaks|safe }}"#, ext = "html")] struct LineBreaksExtraBoth { s: &'static str, } assert_eq!( LineBreaksExtraBoth { s }.render().unwrap(), "

    <script>
    alert('Hello, world!')
    </script>

    ", ); } // Regression tests for . #[test] fn test_filesizeformat() { #[derive(Template)] #[template( source = r#"{% if let Some(x) = s %}{{x|filesizeformat}}{% endif %}"#, ext = "html" )] struct S { s: Option, } assert_eq!(S { s: Some(12) }.render().unwrap(), "12 B"); } #[test] fn test_whitespace_around_filter_operator() { #[derive(Template)] #[template( source = r#"{{ 12 |safe }} {{ 8| safe }} {{ 4 | safe }}"#, ext = "html" )] struct S; assert_eq!(S.render().unwrap(), "12\n8\n4"); }