askama/testing/tests/calls.rs
2025-05-22 22:50:40 +02:00

316 lines
6.2 KiB
Rust

use askama::Template;
#[test]
fn test_one_func() {
#[derive(Template)]
#[template(source = "{{ b(value) }}", ext = "txt")]
struct OneFunction {
value: u32,
}
impl OneFunction {
fn b(&self, x: &u32) -> u32 {
self.value + x
}
}
let t = OneFunction { value: 10 };
assert_eq!(t.render().unwrap(), "20");
}
#[test]
fn test_one_func_self() {
#[derive(Template)]
#[template(source = "{{ self.func(value) }}", ext = "txt")]
struct OneFunctionSelf {
value: i32,
}
impl OneFunctionSelf {
fn func(&self, i: &i32) -> i32 {
2 * i
}
}
let t = OneFunctionSelf { value: 123 };
assert_eq!(t.render().unwrap(), "246");
}
#[test]
fn test_one_func_index() {
#[derive(Template)]
#[template(source = "{{ func[index](value) }}", ext = "txt")]
struct OneFunctionIndex<'a> {
func: &'a [fn(&i32) -> i32],
value: i32,
index: usize,
}
let t = OneFunctionIndex {
func: &[|_| panic!(), |&i| 2 * i, |_| panic!(), |_| panic!()],
value: 123,
index: 1,
};
assert_eq!(t.render().unwrap(), "246");
}
#[test]
fn test_one_func_binop() {
struct AddToGetAFunction;
impl std::ops::Add<usize> for &AddToGetAFunction {
type Output = fn(&i32) -> i32;
fn add(self, rhs: usize) -> Self::Output {
assert_eq!(rhs, 1);
|&i| 2 * i
}
}
#[derive(Template)]
#[template(source = "{{ (func + index)(value) }}", ext = "txt")]
struct OneFunctionBinop<'a> {
func: &'a AddToGetAFunction,
value: i32,
index: usize,
}
let t = OneFunctionBinop {
func: &AddToGetAFunction,
value: 123,
index: 1,
};
assert_eq!(t.render().unwrap(), "246");
}
mod test_double_attr_arg {
use askama::Template;
fn double_attr_arg_helper(x: u32) -> u32 {
x * x + x
}
#[derive(askama::Template)]
#[template(
source = "{{ self::double_attr_arg_helper(self.x.0 + 2) }}",
ext = "txt"
)]
struct DoubleAttrArg {
x: (u32,),
}
#[test]
fn test_double_attr_arg() {
let t = DoubleAttrArg { x: (10,) };
assert_eq!(t.render().unwrap(), "156");
}
}
// This test ensures that whitespace characters are removed when `endcall` ends
// with `-%}`.
#[test]
fn test_caller() {
#[derive(Template)]
#[template(
source = r#"
{%- macro test() -%}
{{- caller() -}}
{%- endmacro -%}
{%- call() test() %}
nested
{% endcall -%}
"#,
ext = "html"
)]
struct CallerEmpty;
assert_eq!(CallerEmpty.render().unwrap(), "\nnested\n");
}
// This test ensures that whitespace characters are NOT removed when `endcall` ends
// with `%}`.
#[test]
fn test_caller2() {
#[derive(Template)]
#[template(
source = r#"
{%- macro test() -%}
{{- caller() -}}
{%- endmacro -%}
{%- call() test() %}
nested
{% endcall %}
"#,
ext = "html"
)]
struct CallerEmpty;
assert_eq!(CallerEmpty.render().unwrap(), "\nnested\n\n");
}
#[test]
fn test_caller_struct() {
struct TestInput<'a> {
a: &'a str,
b: &'a str,
}
#[derive(Template)]
#[template(
source = r#"
{%- macro test(a) -%}
{{- caller(a) -}}
{%- endmacro -%}
{%- call(value) test(a) -%}
a: {{value.a}}
b: {{value.b}}
{%- endcall -%}
"#,
ext = "txt"
)]
struct Tmpl<'a> {
a: TestInput<'a>,
}
let x = Tmpl {
a: TestInput { a: "one", b: "two" },
};
assert_eq!(x.render().unwrap(), "a: one\nb: two");
}
#[test]
fn test_caller_args() {
#[derive(Template)]
#[template(
source = r#"
{%- macro test() -%}
{{~ caller("test") ~}}
{{~ caller(1) ~}}
{%- endmacro -%}
{%- call(value) test() -%}
nested {{value}}
{%- endcall -%}
"#,
ext = "html"
)]
struct CallerEmpty {}
let x = CallerEmpty {};
assert_eq!(x.render().unwrap(), "nested test\nnested 1");
}
// Ensures that fields are not moved when calling a jinja macro.
#[test]
fn test_do_not_move_fields() {
#[derive(Template)]
#[template(
source = "
{%- macro package_navigation(title, show) -%}
{%- if show -%}
{{title}}
{%- else -%}
no show
{%- endif -%}
{%- endmacro -%}
{%- call package_navigation(title=title, show=true) -%}{%- endcall -%}
",
ext = "html"
)]
struct DoNotMoveFields {
title: String,
}
let x = DoNotMoveFields {
title: "a".to_string(),
};
assert_eq!(x.render().unwrap(), "a");
}
#[test]
fn test_closure_field() {
#[derive(Template)]
#[template(source = "{{ (func)(value) }}", ext = "txt")]
struct ClosureField {
func: fn(&i32) -> i32,
value: i32,
}
let t = ClosureField {
func: |&i| 2 * i,
value: 123,
};
assert_eq!(t.render().unwrap(), "246");
}
mod test_not_method {
use askama::Template;
fn single() -> &'static str {
"a"
}
mod sub_mod {
pub fn sub_fn(v: i32) -> i32 {
v * 2
}
}
#[derive(Template)]
#[template(
source = "
{{- self::single() -}}
{{- sub_mod::sub_fn(3) -}}
",
ext = "txt"
)]
struct NotMethod;
#[test]
fn test_not_method() {
assert_eq!(NotMethod.render().unwrap(), "a6");
}
}
mod test_deref_method_arg {
use askama::Template;
#[derive(Template)]
#[template(
source = "
{{- bar(x) -}}
{{- bar(&*x) -}}
{{- foo(*x) -}}
{{- foo(*&*x) -}}
{# #} {{+ extra_fn::bar(x) -}}
{{- extra_fn::bar(&*x) -}}
{{- extra_fn::foo(*x) -}}
{{- extra_fn::foo(*&*x) -}}
",
ext = "txt"
)]
struct DerefMethodArg {
x: u32,
}
mod extra_fn {
pub fn bar(x: &u32) -> u32 {
*x + 4
}
pub fn foo(x: u32) -> u32 {
x + 5
}
}
impl DerefMethodArg {
fn bar(&self, x: &u32) -> u32 {
*x + 1
}
fn foo(&self, x: u32) -> u32 {
x
}
}
// This test ensures that the `*`/`&` operators are correctly placed on method/function arguments.
#[test]
fn test_deref_method_arg() {
let x = DerefMethodArg { x: 2 };
assert_eq!(x.render().unwrap(), "3322 6677");
}
}