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