mirror of
https://github.com/askama-rs/askama.git
synced 2025-10-02 15:25:19 +00:00
Add tests for if (not) defined
feature
This commit is contained in:
parent
0372dac003
commit
fcf1a97d9d
@ -8,13 +8,19 @@ use similar::{Algorithm, ChangeTag, TextDiffConfig};
|
||||
|
||||
use crate::build_template;
|
||||
|
||||
#[test]
|
||||
fn check_if_let() {
|
||||
// This function makes it much easier to compare expected code by adding the wrapping around
|
||||
// the code we want to check.
|
||||
#[track_caller]
|
||||
fn compare(jinja: &str, expected: &str, size_hint: usize) {
|
||||
let jinja = format!(r#"#[template(source = {jinja:?}, ext = "txt")] struct Foo;"#);
|
||||
fn compare(jinja: &str, expected: &str, fields: &[(&str, &str)], size_hint: usize) {
|
||||
let jinja = format!(
|
||||
r##"#[template(source = {jinja:?}, ext = "txt")]
|
||||
struct Foo {{ {} }}"##,
|
||||
fields
|
||||
.iter()
|
||||
.map(|(name, type_)| format!("{name}: {type_}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(","),
|
||||
);
|
||||
let generated = build_template(&syn::parse_str::<syn::DeriveInput>(&jinja).unwrap())
|
||||
.unwrap()
|
||||
.parse()
|
||||
@ -100,6 +106,8 @@ fn check_if_let() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_if_let() {
|
||||
// In this test, we ensure that `query` never is `self.query`.
|
||||
compare(
|
||||
"{% if let Some(query) = s && !query.is_empty() %}{{query}}{% endif %}",
|
||||
@ -110,6 +118,7 @@ fn check_if_let() {
|
||||
expr0 = &(&&::rinja::filters::AutoEscaper::new(&(query), ::rinja::filters::Text)).rinja_auto_escape()?,
|
||||
)?;
|
||||
}"#,
|
||||
&[],
|
||||
3,
|
||||
);
|
||||
|
||||
@ -124,6 +133,7 @@ fn check_if_let() {
|
||||
expr0 = &(&&::rinja::filters::AutoEscaper::new(&(s), ::rinja::filters::Text)).rinja_auto_escape()?,
|
||||
)?;
|
||||
}"#,
|
||||
&[],
|
||||
3,
|
||||
);
|
||||
|
||||
@ -138,6 +148,7 @@ fn check_if_let() {
|
||||
expr0 = &(&&::rinja::filters::AutoEscaper::new(&(s), ::rinja::filters::Text)).rinja_auto_escape()?,
|
||||
)?;
|
||||
}"#,
|
||||
&[],
|
||||
3,
|
||||
);
|
||||
|
||||
@ -157,6 +168,161 @@ fn check_if_let() {
|
||||
writer.write_str("3")?;
|
||||
writer.write_str("3")?;"#
|
||||
),
|
||||
&[],
|
||||
4,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_is_defined() {
|
||||
// Checks that it removes conditions if we know at compile-time that they always return false.
|
||||
//
|
||||
// We're forced to add `bla` otherwise `compare` assert fails in weird ways...
|
||||
compare(
|
||||
"{% if y is defined %}{{query}}{% endif %}bla",
|
||||
r#"writer.write_str("bla")?;"#,
|
||||
&[],
|
||||
3,
|
||||
);
|
||||
compare(
|
||||
"{% if x is not defined %}{{query}}{% endif %}bla",
|
||||
r#"writer.write_str("bla")?;"#,
|
||||
&[("x", "u32")],
|
||||
3,
|
||||
);
|
||||
compare(
|
||||
"{% if y is defined && x is not defined %}{{query}}{% endif %}bla",
|
||||
r#"writer.write_str("bla")?;"#,
|
||||
&[("x", "u32")],
|
||||
3,
|
||||
);
|
||||
|
||||
// Same with declared variables.
|
||||
compare(
|
||||
"{% set y = 12 %}
|
||||
{%- if y is not defined %}{{query}}{% endif %}bla",
|
||||
r#"let y = 12;
|
||||
writer.write_str("bla")?;"#,
|
||||
&[],
|
||||
3,
|
||||
);
|
||||
compare(
|
||||
"{% set y = 12 %}
|
||||
{%- if y is not defined && x is defined %}{{query}}{% endif %}bla",
|
||||
r#"let y = 12;
|
||||
writer.write_str("bla")?;"#,
|
||||
&[],
|
||||
3,
|
||||
);
|
||||
|
||||
// Checks that if the condition is always `true` at compile-time, then we keep the code but
|
||||
// remove the condition.
|
||||
compare(
|
||||
"{% if y is defined %}bla{% endif %}",
|
||||
r#"writer.write_str("bla")?;"#,
|
||||
&[("y", "u32")],
|
||||
3,
|
||||
);
|
||||
compare(
|
||||
"{% if x is not defined %}bla{% endif %}",
|
||||
r#"writer.write_str("bla")?;"#,
|
||||
&[],
|
||||
3,
|
||||
);
|
||||
// Same with declared variables.
|
||||
compare(
|
||||
"{% set y = 12 %}
|
||||
{%- if y is defined %}bla{% endif %}",
|
||||
r#"let y = 12;
|
||||
writer.write_str("bla")?;"#,
|
||||
&[],
|
||||
3,
|
||||
);
|
||||
|
||||
// If the always `true` condition is followed by more `else if`/`else`, check that they are
|
||||
// removed as well.
|
||||
compare(
|
||||
"{% if x is defined %}bli
|
||||
{%- else if x == 12 %}12{% endif %}bla",
|
||||
r#"writer.write_str("bli")?;
|
||||
writer.write_str("bla")?;"#,
|
||||
&[("x", "u32")],
|
||||
6,
|
||||
);
|
||||
compare(
|
||||
"{% if x is defined %}bli
|
||||
{%- else if x == 12 %}12
|
||||
{%- else %}nope{% endif %}bla",
|
||||
r#"writer.write_str("bli")?;
|
||||
writer.write_str("bla")?;"#,
|
||||
&[("x", "u32")],
|
||||
6,
|
||||
);
|
||||
// If it's not the first one.
|
||||
compare(
|
||||
"{% if x == 12 %}bli
|
||||
{%- else if x is defined %}12
|
||||
{%- else %}nope{% endif %}",
|
||||
r#"if *(&(self.x == 12) as &bool) {
|
||||
writer.write_str("bli")?;
|
||||
} else {
|
||||
writer.write_str("12")?;
|
||||
}"#,
|
||||
&[("x", "u32")],
|
||||
5,
|
||||
);
|
||||
|
||||
// Checking that it doesn't remove the condition if other non-"if (not) defined" checks
|
||||
// are present.
|
||||
compare(
|
||||
"{% if y is defined || x == 12 %}{{x}}{% endif %}",
|
||||
r#"if *(&(false || self.x == 12) as &bool) {
|
||||
::std::write!(writer, "{expr0}",
|
||||
expr0 = &(&&::rinja::filters::AutoEscaper::new(&(self.x), ::rinja::filters::Text)).rinja_auto_escape()?,
|
||||
)?;
|
||||
}
|
||||
"#,
|
||||
&[("x", "u32")],
|
||||
3,
|
||||
);
|
||||
compare(
|
||||
"{% if y is defined || x == 12 %}{{x}}{% endif %}",
|
||||
r#"if *(&(true || self.x == 12) as &bool) {
|
||||
::std::write!(writer, "{expr0}",
|
||||
expr0 = &(&&::rinja::filters::AutoEscaper::new(&(self.x), ::rinja::filters::Text)).rinja_auto_escape()?,
|
||||
)?;
|
||||
}
|
||||
"#,
|
||||
&[("y", "u32"), ("x", "u32")],
|
||||
3,
|
||||
);
|
||||
|
||||
// Checking some funny cases.
|
||||
|
||||
// This one is a bit useless because you can use `is not defined` but I suppose it's possible
|
||||
// to encounter cases like that in the wild so better have a check.
|
||||
compare(
|
||||
"{% if !(y is defined) %}bla{% endif %}",
|
||||
r#"writer.write_str("bla")?;"#,
|
||||
&[],
|
||||
3,
|
||||
);
|
||||
compare(
|
||||
"{% if !(y is not defined) %}bli{% endif %}bla",
|
||||
r#"writer.write_str("bla")?;"#,
|
||||
&[],
|
||||
3,
|
||||
);
|
||||
compare(
|
||||
"{% if !(y is defined) %}bli{% endif %}bla",
|
||||
r#"writer.write_str("bla")?;"#,
|
||||
&[("y", "u32")],
|
||||
3,
|
||||
);
|
||||
compare(
|
||||
"{% if !(y is not defined) %}bla{% endif %}",
|
||||
r#"writer.write_str("bla")?;"#,
|
||||
&[("y", "u32")],
|
||||
3,
|
||||
);
|
||||
}
|
||||
|
33
testing/tests/is_defined.rs
Normal file
33
testing/tests/is_defined.rs
Normal file
@ -0,0 +1,33 @@
|
||||
use rinja::Template;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(
|
||||
source = r#"<script>
|
||||
const x = {{ x is defined }};
|
||||
const y = {{ y is not defined }};
|
||||
const z = {{ y is defined }};
|
||||
const w = {{ x is not defined }};
|
||||
const v = {{ y }};
|
||||
</script>"#,
|
||||
ext = "html"
|
||||
)]
|
||||
struct IsDefined {
|
||||
y: u32,
|
||||
}
|
||||
|
||||
// This test ensures that `include` are correctly working inside filter blocks and that external
|
||||
// variables are used correctly.
|
||||
#[test]
|
||||
fn is_defined_in_expr() {
|
||||
let s = IsDefined { y: 0 };
|
||||
assert_eq!(
|
||||
s.render().unwrap(),
|
||||
r#"<script>
|
||||
const x = false;
|
||||
const y = false;
|
||||
const z = true;
|
||||
const w = true;
|
||||
const v = 0;
|
||||
</script>"#
|
||||
);
|
||||
}
|
46
testing/tests/ui/is_defined.rs
Normal file
46
testing/tests/ui/is_defined.rs
Normal file
@ -0,0 +1,46 @@
|
||||
use rinja::Template;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(
|
||||
ext = "html",
|
||||
source = r#"{% if x.y is defined %}{% endif %}"#,
|
||||
)]
|
||||
struct A;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(
|
||||
ext = "html",
|
||||
source = r#"{% if true is defined %}{% endif %}"#,
|
||||
)]
|
||||
struct B;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(
|
||||
ext = "html",
|
||||
source = r#"{% if true is %}{% endif %}"#,
|
||||
)]
|
||||
struct C;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(
|
||||
ext = "html",
|
||||
source = r#"{% if x is %}{% endif %}"#,
|
||||
)]
|
||||
struct D;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(
|
||||
ext = "html",
|
||||
source = r#"{% if x is blue %}{% endif %}"#,
|
||||
)]
|
||||
struct E;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(
|
||||
ext = "html",
|
||||
source = r#"{% if x is blue.red %}{% endif %}"#,
|
||||
)]
|
||||
struct F;
|
||||
|
||||
fn main() {
|
||||
}
|
59
testing/tests/ui/is_defined.stderr
Normal file
59
testing/tests/ui/is_defined.stderr
Normal file
@ -0,0 +1,59 @@
|
||||
error: `is defined` operator can only be used on variables, not on their fields
|
||||
failed to parse template source at row 1, column 6 near:
|
||||
"x.y is defined %}{% endif %}"
|
||||
--> tests/ui/is_defined.rs:3:10
|
||||
|
|
||||
3 | #[derive(Template)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: `is defined` operator can only be used on variables
|
||||
failed to parse template source at row 1, column 6 near:
|
||||
"true is defined %}{% endif %}"
|
||||
--> tests/ui/is_defined.rs:10:10
|
||||
|
|
||||
10 | #[derive(Template)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: expected `defined` or `not defined` after `is`
|
||||
failed to parse template source at row 1, column 6 near:
|
||||
"true is %}{% endif %}"
|
||||
--> tests/ui/is_defined.rs:17:10
|
||||
|
|
||||
17 | #[derive(Template)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: expected `defined` or `not defined` after `is`
|
||||
failed to parse template source at row 1, column 6 near:
|
||||
"x is %}{% endif %}"
|
||||
--> tests/ui/is_defined.rs:24:10
|
||||
|
|
||||
24 | #[derive(Template)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: expected `defined` or `not defined` after `is`
|
||||
failed to parse template source at row 1, column 6 near:
|
||||
"x is blue %}{% endif %}"
|
||||
--> tests/ui/is_defined.rs:31:10
|
||||
|
|
||||
31 | #[derive(Template)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: expected `defined` or `not defined` after `is`
|
||||
failed to parse template source at row 1, column 6 near:
|
||||
"x is blue.red %}{% endif %}"
|
||||
--> tests/ui/is_defined.rs:38:10
|
||||
|
|
||||
38 | #[derive(Template)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
|
Loading…
x
Reference in New Issue
Block a user