1 use std::borrow;
2
3 use liquid::ValueView;
4
5 #[derive(Default, Debug, Clone, Copy)]
6 struct TestFileSystem;
7
8 impl liquid::partials::PartialSource for TestFileSystem {
contains(&self, _name: &str) -> bool9 fn contains(&self, _name: &str) -> bool {
10 true
11 }
12
names(&self) -> Vec<&str>13 fn names(&self) -> Vec<&str> {
14 vec![]
15 }
16
try_get<'a>(&'a self, name: &str) -> Option<borrow::Cow<'a, str>>17 fn try_get<'a>(&'a self, name: &str) -> Option<borrow::Cow<'a, str>> {
18 let template = match name {
19 "product" => "Product: {{ product.title }} ".into(),
20 "locale_variables" => "Locale: {{echo1}} {{echo2}}".into(),
21 "variant" => "Variant: {{ variant.title }}".into(),
22 "nested_template" => {
23 "{% include 'header' %} {% include 'body' %} {% include 'footer' %}".into()
24 }
25 "body" => "body {% include 'body_detail' %}".into(),
26 "nested_product_template" => {
27 "Product: {{ nested_product_template.title }} {%include 'details'%} ".into()
28 }
29 "recursively_nested_template" => "-{% include 'recursively_nested_template' %}".into(),
30 "pick_a_source" => "from TestFileSystem".into(),
31 "assignments" => "{% assign foo = 'bar' %}".into(),
32 _ => name.to_owned().into(),
33 };
34 Some(template)
35 }
36 }
37
liquid() -> liquid::Parser38 fn liquid() -> liquid::Parser {
39 liquid::ParserBuilder::with_stdlib()
40 .partials(liquid::partials::OnDemandCompiler::<TestFileSystem>::empty())
41 .build()
42 .unwrap()
43 }
44
45 #[test]
46 #[should_panic]
test_include_tag_looks_for_file_system_in_registers_first()47 fn test_include_tag_looks_for_file_system_in_registers_first() {
48 panic!("Implementation specific: exposing of registers API");
49 }
50
51 #[test]
52 #[should_panic] // liquid-rust#237
test_include_tag_with()53 fn test_include_tag_with() {
54 assert_template_result!(
55 "Product: Draft 151cm ",
56 "{% include 'product' with products[0] %}",
57 o!({"products": [ { "title": "Draft 151cm" }, { "title": "Element 155cm" } ]}),
58 liquid()
59 );
60 }
61
62 #[test]
test_include_tag_with_default_name()63 fn test_include_tag_with_default_name() {
64 assert_template_result!(
65 "Product: Draft 151cm ",
66 "{% include 'product' %}",
67 o!({"product": { "title": "Draft 151cm" }}),
68 liquid()
69 );
70 }
71
72 #[test]
73 #[should_panic] // liquid-rust#237
test_include_tag_for()74 fn test_include_tag_for() {
75 assert_template_result!(
76 "Product: Draft 151cm Product: Element 155cm ",
77 "{% include 'product' for products %}",
78 o!({"products": [ { "title": "Draft 151cm" }, { "title": "Element 155cm" } ]}),
79 liquid()
80 );
81 }
82
83 #[test]
84 #[should_panic] // fails due to strict_variables
test_include_tag_with_local_variables()85 fn test_include_tag_with_local_variables() {
86 assert_template_result!(
87 "Locale: test123 ",
88 "{% include 'locale_variables' echo1: 'test123' %}",
89 o!({}),
90 liquid()
91 );
92 }
93
94 #[test]
test_include_tag_with_multiple_local_variables()95 fn test_include_tag_with_multiple_local_variables() {
96 assert_template_result!(
97 "Locale: test123 test321",
98 "{% include 'locale_variables' echo1: 'test123', echo2: 'test321' %}",
99 o!({}),
100 liquid()
101 );
102 }
103
104 #[test]
test_include_tag_with_multiple_local_variables_from_runtime()105 fn test_include_tag_with_multiple_local_variables_from_runtime() {
106 assert_template_result!(
107 "Locale: test123 test321",
108 "{% include 'locale_variables' echo1: echo1, echo2: more_echos.echo2 %}",
109 o!({"echo1": "test123", "more_echos": { "echo2": "test321" }}),
110 liquid()
111 );
112 }
113
114 #[test]
test_included_templates_assigns_variables()115 fn test_included_templates_assigns_variables() {
116 assert_template_result!(
117 "bar",
118 "{% include 'assignments' %}{{ foo }}",
119 o!({}),
120 liquid()
121 );
122 }
123
124 #[test]
test_nested_include_tag()125 fn test_nested_include_tag() {
126 assert_template_result!("body body_detail", "{% include 'body' %}", o!({}), liquid());
127
128 assert_template_result!(
129 "header body body_detail footer",
130 "{% include 'nested_template' %}",
131 o!({}),
132 liquid()
133 );
134 }
135
136 #[test]
137 #[should_panic] // liquid-rust#237
test_nested_include_with_variable()138 fn test_nested_include_with_variable() {
139 assert_template_result!(
140 "Product: Draft 151cm details ",
141 "{% include 'nested_product_template' with product %}",
142 o!({"product": { "title": "Draft 151cm" }}),
143 liquid()
144 );
145
146 assert_template_result!(
147 "Product: Draft 151cm details Product: Element 155cm details ",
148 "{% include 'nested_product_template' for products %}",
149 o!({"products": [{ "title": "Draft 151cm" }, { "title": "Element 155cm" }]}),
150 liquid()
151 );
152 }
153
154 #[derive(Default, Debug, Clone, Copy)]
155 struct InfiniteFileSystem;
156
157 impl liquid::partials::PartialSource for InfiniteFileSystem {
contains(&self, _name: &str) -> bool158 fn contains(&self, _name: &str) -> bool {
159 true
160 }
161
names(&self) -> Vec<&str>162 fn names(&self) -> Vec<&str> {
163 vec![]
164 }
165
try_get<'a>(&'a self, _name: &str) -> Option<borrow::Cow<'a, str>>166 fn try_get<'a>(&'a self, _name: &str) -> Option<borrow::Cow<'a, str>> {
167 Some("-{% include 'loop' %}".into())
168 }
169 }
170
171 #[test]
172 #[should_panic] // liquid-rust#300
test_recursively_included_template_does_not_produce_endless_loop()173 fn test_recursively_included_template_does_not_produce_endless_loop() {
174 panic!("We don't check recursion depth");
175 /*
176 liquid::ParserBuilder::with_stdlib()
177 .partials(liquid::partials::OnDemandCompiler::<TestFileSystem>::empty())
178 .build()
179 .unwrap()
180 parser.parse("{% include 'loop' %}").unwrap();
181 */
182 }
183
184 #[test]
185 #[should_panic] // liquid-rust#275
test_dynamically_chosen_template()186 fn test_dynamically_chosen_template() {
187 assert_template_result!(
188 "Test123",
189 "{% include template %}",
190 o!({"template": "Test123"}),
191 liquid()
192 );
193 assert_template_result!(
194 "Test321",
195 "{% include template %}",
196 o!({"template": "Test321"}),
197 liquid()
198 );
199
200 assert_template_result!(
201 "Product: Draft 151cm ",
202 "{% include template for product %}",
203 o!({"template": "product", "product": { "title": "Draft 151cm" }}),
204 liquid()
205 );
206 }
207
208 #[test]
209 #[should_panic]
test_include_tag_caches_second_read_of_same_partial()210 fn test_include_tag_caches_second_read_of_same_partial() {
211 panic!("Implementation specific: caching policies");
212 }
213
214 #[test]
215 #[should_panic]
test_include_tag_doesnt_cache_partials_across_renders()216 fn test_include_tag_doesnt_cache_partials_across_renders() {
217 panic!("Implementation specific: caching policies");
218 }
219
220 #[test]
test_include_tag_within_if_statement()221 fn test_include_tag_within_if_statement() {
222 assert_template_result!(
223 "foo_if_true",
224 "{% if true %}{% include 'foo_if_true' %}{% endif %}",
225 o!({}),
226 liquid()
227 );
228 }
229
230 #[test]
231 #[should_panic]
test_custom_include_tag()232 fn test_custom_include_tag() {
233 panic!("Implementation specific: API customization");
234 }
235
236 #[test]
237 #[should_panic]
test_custom_include_tag_within_if_statement()238 fn test_custom_include_tag_within_if_statement() {
239 panic!("Implementation specific: API customization");
240 }
241
242 #[test]
test_does_not_add_error_in_strict_mode_for_missing_variable()243 fn test_does_not_add_error_in_strict_mode_for_missing_variable() {
244 let template = liquid()
245 .parse(r#" {% include "nested_template" %}"#)
246 .unwrap();
247 template.render(o!({}).as_object().unwrap()).unwrap();
248 }
249
250 #[test]
251 #[should_panic]
test_passing_options_to_included_templates()252 fn test_passing_options_to_included_templates() {
253 panic!("Implementation specific: API options");
254 }
255
256 #[test]
test_render_raise_argument_error_when_template_is_undefined()257 fn test_render_raise_argument_error_when_template_is_undefined() {
258 let parser = liquid();
259 let data = liquid::Object::new();
260
261 let template = parser.parse("{% include undefined_variable %}").unwrap();
262 template.render(&data).unwrap_err();
263
264 let template = parser.parse("{% include nil %}").unwrap();
265 template.render(&data).unwrap_err();
266 }
267
268 #[test]
269 #[should_panic] // liquid-rust#275
test_including_via_variable_value()270 fn test_including_via_variable_value() {
271 assert_template_result!(
272 "from TestFileSystem",
273 "{% assign page = 'pick_a_source' %}{% include page %}",
274 o!({}),
275 liquid()
276 );
277
278 assert_template_result!(
279 "Product: Draft 151cm ",
280 "{% assign page = 'product' %}{% include page %}",
281 o!({"product": { "title": "Draft 151cm" }}),
282 liquid()
283 );
284
285 assert_template_result!(
286 "Product: Draft 151cm ",
287 "{% assign page = 'product' %}{% include page for foo %}",
288 o!({"foo": { "title": "Draft 151cm" }}),
289 liquid()
290 );
291 }
292
293 #[test]
test_including_with_strict_variables()294 fn test_including_with_strict_variables() {
295 let template = liquid().parse("{% include 'simple' %}").unwrap();
296 template.render(&o!({})).unwrap();
297 }
298