1 use crate::parser::parse;
2 
assert_err_msg(input: &str, needles: &[&str])3 fn assert_err_msg(input: &str, needles: &[&str]) {
4     let res = parse(input);
5     assert!(res.is_err());
6     let err = res.unwrap_err();
7     let err_msg = err.to_string();
8     println!("{}", err_msg);
9     println!("Looking for:");
10     for needle in needles {
11         println!("{}", needle);
12         assert!(err_msg.contains(needle));
13     }
14 }
15 
16 #[test]
invalid_number()17 fn invalid_number() {
18     assert_err_msg(
19         "{{ 1.2.2 }}",
20         &[
21             "1:7",
22             "expected `or`, `and`, `not`, `<=`, `>=`, `<`, `>`, `==`, `!=`, `+`, `-`, `*`, `/`, `%`, a filter, or a variable end (`}}`)"
23         ],
24     );
25 }
26 
27 #[test]
invalid_op()28 fn invalid_op() {
29     assert_err_msg("{{ 1.2 >+ 3 }}", &["1:9", "expected an expression"]);
30 }
31 
32 #[test]
wrong_start_block()33 fn wrong_start_block() {
34     assert_err_msg(
35         "{{ if true %}",
36         &[
37             "1:7",
38             "expected `or`, `and`, `not`, `<=`, `>=`, `<`, `>`, `==`, `!=`, `+`, `-`, `*`, `/`, `%`, a filter, or a variable end (`}}`)"
39         ],
40     );
41 }
42 
43 #[test]
wrong_end_block()44 fn wrong_end_block() {
45     assert_err_msg(
46         "{{ hey %}",
47         &[
48             "1:9",
49             "expected an integer, a float, `true` or `false`, an identifier (must start with a-z), a dotted identifier (identifiers separated by `.`), a square bracketed identifier (identifiers separated by `.` or `[]`s), or an expression"
50         ],
51     );
52 }
53 
54 #[test]
unterminated_variable_block()55 fn unterminated_variable_block() {
56     assert_err_msg(
57         "{{ hey",
58         &[
59             "1:7",
60             "expected `or`, `and`, `not`, `<=`, `>=`, `<`, `>`, `==`, `!=`, `+`, `-`, `*`, `/`, `%`, a filter, or a variable end (`}}`)"
61         ],
62     );
63 }
64 
65 #[test]
unterminated_string()66 fn unterminated_string() {
67     assert_err_msg(r#"{{ "hey }}"#, &["1:4", "expected a value that can be negated"]);
68 }
69 
70 #[test]
unterminated_if_tag()71 fn unterminated_if_tag() {
72     assert_err_msg(r#"{% if true %}sd"#, &["1:16", r#"expected tag or some content"#]);
73 }
74 
75 #[test]
unterminated_filter_section()76 fn unterminated_filter_section() {
77     assert_err_msg(
78         r#"{% filter uppercase %}sd"#,
79         &["1:25", r#"expected tag or the filter section content"#],
80     );
81 }
82 
83 #[test]
invalid_filter_section_missing_name()84 fn invalid_filter_section_missing_name() {
85     assert_err_msg(
86         r#"{% filter %}sd{% endfilter %}"#,
87         &["1:11", "expected an identifier (must start with a-z)"],
88     );
89 }
90 
91 #[test]
invalid_macro_content()92 fn invalid_macro_content() {
93     assert_err_msg(
94         r#"
95 {% macro input(label, type) %}
96     {% macro nested() %}
97     {% endmacro nested %}
98 {% endmacro input %}
99     "#,
100         &["3:5", "unexpected tag; expected `{% endmacro %}` or the macro content"],
101     );
102 }
103 
104 #[test]
invalid_macro_default_arg_value()105 fn invalid_macro_default_arg_value() {
106     assert_err_msg(
107         r#"
108 {% macro input(label=something) %}
109 {% endmacro input %}
110     "#,
111         &["2:22", "expected an integer, a float, a string, or `true` or `false`"],
112     );
113 }
114 
115 #[test]
invalid_elif()116 fn invalid_elif() {
117     assert_err_msg(
118         r#"
119 {% if true %}
120 {% else %}
121 {% elif false %}
122 {% endif %}
123     "#,
124         &["4:1", "unexpected tag; expected an endif tag (`{% endif %}`) or some content"],
125     );
126 }
127 
128 #[test]
invalid_else()129 fn invalid_else() {
130     assert_err_msg(
131         r#"
132 {% if true %}
133 {% else %}
134 {% else %}
135 {% endif %}
136     "#,
137         &["4:1", "unexpected tag; expected an endif tag (`{% endif %}`) or some content"],
138     );
139 }
140 
141 #[test]
invalid_extends_position()142 fn invalid_extends_position() {
143     assert_err_msg(
144         r#"
145 hello
146 {% extends "hey.html" %}
147     "#,
148         &["3:1", "unexpected tag; expected end of input or some content"],
149     );
150 }
151 
152 #[test]
invalid_operator()153 fn invalid_operator() {
154     assert_err_msg(
155         "{{ hey =! }}",
156         &[
157             "1:8",
158             "expected `or`, `and`, `not`, `<=`, `>=`, `<`, `>`, `==`, `!=`, `+`, `-`, `*`, `/`, `%`, a filter, or a variable end (`}}`)"
159         ],
160     );
161 }
162 
163 #[test]
missing_expression_with_not()164 fn missing_expression_with_not() {
165     assert_err_msg("{% if not %}", &["1:11", "expected an expression"]);
166 }
167 
168 #[test]
missing_expression_in_if()169 fn missing_expression_in_if() {
170     assert_err_msg("{% if %}", &["1:7", "expected a value that can be negated"]);
171 }
172 
173 #[test]
missing_container_name_in_forloop()174 fn missing_container_name_in_forloop() {
175     assert_err_msg("{% for i in %}", &["1:13", "expected an expression or an array of values"]);
176 }
177 
178 #[test]
missing_variable_name_in_set()179 fn missing_variable_name_in_set() {
180     assert_err_msg("{% set = 1 %}", &["1:8", "expected an identifier (must start with a-z)"]);
181 }
182 
183 #[test]
missing_value_in_set()184 fn missing_value_in_set() {
185     assert_err_msg(
186         "{% set a =  %}",
187         &["1:13", "expected a value that can be negated or an array of values"],
188     );
189 }
190 
191 #[test]
unterminated_fn_call()192 fn unterminated_fn_call() {
193     assert_err_msg("{{ a | slice( }}", &["1:15", "expected an identifier (must start with a-z)"]);
194 }
195 
196 #[test]
invalid_fn_call_missing_value()197 fn invalid_fn_call_missing_value() {
198     assert_err_msg(
199         "{{ a | slice(start=) }}",
200         &["1:20", "expected a value that can be negated or an array of values"],
201     );
202 }
203 
204 #[test]
unterminated_macro_call()205 fn unterminated_macro_call() {
206     assert_err_msg("{{ my::macro( }}", &["1:15", "expected an identifier (must start with a-z)"]);
207 }
208 
209 #[test]
invalid_macro_call()210 fn invalid_macro_call() {
211     assert_err_msg(
212         "{{ my:macro() }}",
213         &[
214             "1:6",
215             "expected `or`, `and`, `not`, `<=`, `>=`, `<`, `>`, `==`, `!=`, `+`, `-`, `*`, `/`, `%`, a filter, or a variable end (`}}`)"
216         ],
217     );
218 }
219 
220 #[test]
unterminated_include()221 fn unterminated_include() {
222     assert_err_msg("{% include %}", &["1:12", "expected a string"]);
223 }
224 
225 #[test]
invalid_include_no_string()226 fn invalid_include_no_string() {
227     assert_err_msg("{% include 1 %}", &["1:12", "expected a string"]);
228 }
229 
230 #[test]
unterminated_extends()231 fn unterminated_extends() {
232     assert_err_msg("{% extends %}", &["1:12", "expected a string"]);
233 }
234 
235 #[test]
invalid_extends_no_string()236 fn invalid_extends_no_string() {
237     assert_err_msg("{% extends 1 %}", &["1:12", "expected a string"]);
238 }
239 
240 #[test]
invalid_import_macros_missing_filename()241 fn invalid_import_macros_missing_filename() {
242     assert_err_msg("{% import as macros %}", &["1:11", "expected a string"]);
243 }
244 
245 #[test]
invalid_import_macros_missing_namespace()246 fn invalid_import_macros_missing_namespace() {
247     assert_err_msg(
248         r#"{% import "hello" as %}"#,
249         &["1:22", "expected an identifier (must start with a-z)"],
250     );
251 }
252 
253 #[test]
invalid_block_missing_name()254 fn invalid_block_missing_name() {
255     assert_err_msg(r#"{% block %}"#, &["1:10", "expected an identifier (must start with a-z)"]);
256 }
257 
258 #[test]
unterminated_test()259 fn unterminated_test() {
260     assert_err_msg(
261         r#"{% if a is odd( %}"#,
262         &["1:17", "a test argument (any expressions including arrays)"],
263     );
264 }
265 
266 #[test]
invalid_test_argument()267 fn invalid_test_argument() {
268     assert_err_msg(
269         r#"{% if a is odd(key=1) %}"#,
270         &[
271             "1:19",
272             "expected `or`, `and`, `not`, `<=`, `>=`, `<`, `>`, `==`, `!=`, `+`, `-`, `*`, `/`, `%`, or a filter"
273         ],
274     );
275 }
276 
277 #[test]
unterminated_raw_tag()278 fn unterminated_raw_tag() {
279     assert_err_msg(r#"{% raw %}sd"#, &["1:12", "expected tag"]);
280 }
281 
282 #[test]
invalid_break_outside_loop()283 fn invalid_break_outside_loop() {
284     assert_err_msg(r#"{% break %}"#, &["1:1", "{% break %}", "expected a template"]);
285 }
286 
287 #[test]
invalid_continue_outside_loop()288 fn invalid_continue_outside_loop() {
289     assert_err_msg(r#"{% continue %}"#, &["1:1", "{% continue %}", "expected a template"]);
290 }
291