liquid 4.0.1 → 5.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +142 -0
  3. data/README.md +10 -4
  4. data/lib/liquid/block.rb +31 -14
  5. data/lib/liquid/block_body.rb +169 -56
  6. data/lib/liquid/condition.rb +59 -23
  7. data/lib/liquid/context.rb +111 -52
  8. data/lib/liquid/document.rb +47 -9
  9. data/lib/liquid/drop.rb +4 -2
  10. data/lib/liquid/errors.rb +20 -18
  11. data/lib/liquid/expression.rb +29 -33
  12. data/lib/liquid/extensions.rb +2 -0
  13. data/lib/liquid/file_system.rb +6 -4
  14. data/lib/liquid/forloop_drop.rb +54 -4
  15. data/lib/liquid/i18n.rb +5 -3
  16. data/lib/liquid/interrupts.rb +3 -1
  17. data/lib/liquid/lexer.rb +31 -24
  18. data/lib/liquid/locales/en.yml +8 -5
  19. data/lib/liquid/parse_context.rb +20 -4
  20. data/lib/liquid/parse_tree_visitor.rb +42 -0
  21. data/lib/liquid/parser.rb +30 -18
  22. data/lib/liquid/parser_switching.rb +17 -3
  23. data/lib/liquid/partial_cache.rb +24 -0
  24. data/lib/liquid/profiler/hooks.rb +26 -14
  25. data/lib/liquid/profiler.rb +67 -86
  26. data/lib/liquid/range_lookup.rb +13 -3
  27. data/lib/liquid/registers.rb +51 -0
  28. data/lib/liquid/resource_limits.rb +47 -8
  29. data/lib/liquid/standardfilters.rb +616 -129
  30. data/lib/liquid/strainer_factory.rb +41 -0
  31. data/lib/liquid/strainer_template.rb +62 -0
  32. data/lib/liquid/tablerowloop_drop.rb +64 -5
  33. data/lib/liquid/tag/disableable.rb +22 -0
  34. data/lib/liquid/tag/disabler.rb +21 -0
  35. data/lib/liquid/tag.rb +28 -6
  36. data/lib/liquid/tags/assign.rb +44 -18
  37. data/lib/liquid/tags/break.rb +16 -3
  38. data/lib/liquid/tags/capture.rb +24 -18
  39. data/lib/liquid/tags/case.rb +69 -27
  40. data/lib/liquid/tags/comment.rb +18 -3
  41. data/lib/liquid/tags/continue.rb +16 -12
  42. data/lib/liquid/tags/cycle.rb +45 -25
  43. data/lib/liquid/tags/decrement.rb +22 -20
  44. data/lib/liquid/tags/echo.rb +41 -0
  45. data/lib/liquid/tags/for.rb +97 -89
  46. data/lib/liquid/tags/if.rb +61 -35
  47. data/lib/liquid/tags/ifchanged.rb +11 -10
  48. data/lib/liquid/tags/include.rb +56 -56
  49. data/lib/liquid/tags/increment.rb +23 -17
  50. data/lib/liquid/tags/inline_comment.rb +43 -0
  51. data/lib/liquid/tags/raw.rb +25 -11
  52. data/lib/liquid/tags/render.rb +109 -0
  53. data/lib/liquid/tags/table_row.rb +53 -19
  54. data/lib/liquid/tags/unless.rb +38 -19
  55. data/lib/liquid/template.rb +52 -72
  56. data/lib/liquid/template_factory.rb +9 -0
  57. data/lib/liquid/tokenizer.rb +18 -10
  58. data/lib/liquid/usage.rb +8 -0
  59. data/lib/liquid/utils.rb +13 -3
  60. data/lib/liquid/variable.rb +52 -41
  61. data/lib/liquid/variable_lookup.rb +24 -10
  62. data/lib/liquid/version.rb +3 -1
  63. data/lib/liquid.rb +19 -6
  64. metadata +21 -104
  65. data/lib/liquid/strainer.rb +0 -66
  66. data/test/fixtures/en_locale.yml +0 -9
  67. data/test/integration/assign_test.rb +0 -48
  68. data/test/integration/blank_test.rb +0 -106
  69. data/test/integration/block_test.rb +0 -12
  70. data/test/integration/capture_test.rb +0 -50
  71. data/test/integration/context_test.rb +0 -32
  72. data/test/integration/document_test.rb +0 -19
  73. data/test/integration/drop_test.rb +0 -273
  74. data/test/integration/error_handling_test.rb +0 -260
  75. data/test/integration/filter_test.rb +0 -178
  76. data/test/integration/hash_ordering_test.rb +0 -23
  77. data/test/integration/output_test.rb +0 -123
  78. data/test/integration/parsing_quirks_test.rb +0 -122
  79. data/test/integration/render_profiling_test.rb +0 -154
  80. data/test/integration/security_test.rb +0 -80
  81. data/test/integration/standard_filter_test.rb +0 -626
  82. data/test/integration/tags/break_tag_test.rb +0 -15
  83. data/test/integration/tags/continue_tag_test.rb +0 -15
  84. data/test/integration/tags/for_tag_test.rb +0 -410
  85. data/test/integration/tags/if_else_tag_test.rb +0 -188
  86. data/test/integration/tags/include_tag_test.rb +0 -245
  87. data/test/integration/tags/increment_tag_test.rb +0 -23
  88. data/test/integration/tags/raw_tag_test.rb +0 -31
  89. data/test/integration/tags/standard_tag_test.rb +0 -296
  90. data/test/integration/tags/statements_test.rb +0 -111
  91. data/test/integration/tags/table_row_test.rb +0 -64
  92. data/test/integration/tags/unless_else_tag_test.rb +0 -26
  93. data/test/integration/template_test.rb +0 -332
  94. data/test/integration/trim_mode_test.rb +0 -529
  95. data/test/integration/variable_test.rb +0 -96
  96. data/test/test_helper.rb +0 -116
  97. data/test/unit/block_unit_test.rb +0 -58
  98. data/test/unit/condition_unit_test.rb +0 -166
  99. data/test/unit/context_unit_test.rb +0 -489
  100. data/test/unit/file_system_unit_test.rb +0 -35
  101. data/test/unit/i18n_unit_test.rb +0 -37
  102. data/test/unit/lexer_unit_test.rb +0 -51
  103. data/test/unit/parser_unit_test.rb +0 -82
  104. data/test/unit/regexp_unit_test.rb +0 -44
  105. data/test/unit/strainer_unit_test.rb +0 -164
  106. data/test/unit/tag_unit_test.rb +0 -21
  107. data/test/unit/tags/case_tag_unit_test.rb +0 -10
  108. data/test/unit/tags/for_tag_unit_test.rb +0 -13
  109. data/test/unit/tags/if_tag_unit_test.rb +0 -8
  110. data/test/unit/template_unit_test.rb +0 -78
  111. data/test/unit/tokenizer_unit_test.rb +0 -55
  112. data/test/unit/variable_unit_test.rb +0 -162
@@ -1,410 +0,0 @@
1
- require 'test_helper'
2
-
3
- class ThingWithValue < Liquid::Drop
4
- def value
5
- 3
6
- end
7
- end
8
-
9
- class ForTagTest < Minitest::Test
10
- include Liquid
11
-
12
- def test_for
13
- assert_template_result(' yo yo yo yo ', '{%for item in array%} yo {%endfor%}', 'array' => [1, 2, 3, 4])
14
- assert_template_result('yoyo', '{%for item in array%}yo{%endfor%}', 'array' => [1, 2])
15
- assert_template_result(' yo ', '{%for item in array%} yo {%endfor%}', 'array' => [1])
16
- assert_template_result('', '{%for item in array%}{%endfor%}', 'array' => [1, 2])
17
- expected = <<HERE
18
-
19
- yo
20
-
21
- yo
22
-
23
- yo
24
-
25
- HERE
26
- template = <<HERE
27
- {%for item in array%}
28
- yo
29
- {%endfor%}
30
- HERE
31
- assert_template_result(expected, template, 'array' => [1, 2, 3])
32
- end
33
-
34
- def test_for_reversed
35
- assigns = { 'array' => [ 1, 2, 3] }
36
- assert_template_result('321', '{%for item in array reversed %}{{item}}{%endfor%}', assigns)
37
- end
38
-
39
- def test_for_with_range
40
- assert_template_result(' 1 2 3 ', '{%for item in (1..3) %} {{item}} {%endfor%}')
41
-
42
- assert_raises(Liquid::ArgumentError) do
43
- Template.parse('{% for i in (a..2) %}{% endfor %}').render!("a" => [1, 2])
44
- end
45
-
46
- assert_template_result(' 0 1 2 3 ', '{% for item in (a..3) %} {{item}} {% endfor %}', "a" => "invalid integer")
47
- end
48
-
49
- def test_for_with_variable_range
50
- assert_template_result(' 1 2 3 ', '{%for item in (1..foobar) %} {{item}} {%endfor%}', "foobar" => 3)
51
- end
52
-
53
- def test_for_with_hash_value_range
54
- foobar = { "value" => 3 }
55
- assert_template_result(' 1 2 3 ', '{%for item in (1..foobar.value) %} {{item}} {%endfor%}', "foobar" => foobar)
56
- end
57
-
58
- def test_for_with_drop_value_range
59
- foobar = ThingWithValue.new
60
- assert_template_result(' 1 2 3 ', '{%for item in (1..foobar.value) %} {{item}} {%endfor%}', "foobar" => foobar)
61
- end
62
-
63
- def test_for_with_variable
64
- assert_template_result(' 1 2 3 ', '{%for item in array%} {{item}} {%endfor%}', 'array' => [1, 2, 3])
65
- assert_template_result('123', '{%for item in array%}{{item}}{%endfor%}', 'array' => [1, 2, 3])
66
- assert_template_result('123', '{% for item in array %}{{item}}{% endfor %}', 'array' => [1, 2, 3])
67
- assert_template_result('abcd', '{%for item in array%}{{item}}{%endfor%}', 'array' => ['a', 'b', 'c', 'd'])
68
- assert_template_result('a b c', '{%for item in array%}{{item}}{%endfor%}', 'array' => ['a', ' ', 'b', ' ', 'c'])
69
- assert_template_result('abc', '{%for item in array%}{{item}}{%endfor%}', 'array' => ['a', '', 'b', '', 'c'])
70
- end
71
-
72
- def test_for_helpers
73
- assigns = { 'array' => [1, 2, 3] }
74
- assert_template_result(' 1/3 2/3 3/3 ',
75
- '{%for item in array%} {{forloop.index}}/{{forloop.length}} {%endfor%}',
76
- assigns)
77
- assert_template_result(' 1 2 3 ', '{%for item in array%} {{forloop.index}} {%endfor%}', assigns)
78
- assert_template_result(' 0 1 2 ', '{%for item in array%} {{forloop.index0}} {%endfor%}', assigns)
79
- assert_template_result(' 2 1 0 ', '{%for item in array%} {{forloop.rindex0}} {%endfor%}', assigns)
80
- assert_template_result(' 3 2 1 ', '{%for item in array%} {{forloop.rindex}} {%endfor%}', assigns)
81
- assert_template_result(' true false false ', '{%for item in array%} {{forloop.first}} {%endfor%}', assigns)
82
- assert_template_result(' false false true ', '{%for item in array%} {{forloop.last}} {%endfor%}', assigns)
83
- end
84
-
85
- def test_for_and_if
86
- assigns = { 'array' => [1, 2, 3] }
87
- assert_template_result('+--',
88
- '{%for item in array%}{% if forloop.first %}+{% else %}-{% endif %}{%endfor%}',
89
- assigns)
90
- end
91
-
92
- def test_for_else
93
- assert_template_result('+++', '{%for item in array%}+{%else%}-{%endfor%}', 'array' => [1, 2, 3])
94
- assert_template_result('-', '{%for item in array%}+{%else%}-{%endfor%}', 'array' => [])
95
- assert_template_result('-', '{%for item in array%}+{%else%}-{%endfor%}', 'array' => nil)
96
- end
97
-
98
- def test_limiting
99
- assigns = { 'array' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] }
100
- assert_template_result('12', '{%for i in array limit:2 %}{{ i }}{%endfor%}', assigns)
101
- assert_template_result('1234', '{%for i in array limit:4 %}{{ i }}{%endfor%}', assigns)
102
- assert_template_result('3456', '{%for i in array limit:4 offset:2 %}{{ i }}{%endfor%}', assigns)
103
- assert_template_result('3456', '{%for i in array limit: 4 offset: 2 %}{{ i }}{%endfor%}', assigns)
104
- end
105
-
106
- def test_dynamic_variable_limiting
107
- assigns = { 'array' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] }
108
- assigns['limit'] = 2
109
- assigns['offset'] = 2
110
-
111
- assert_template_result('34', '{%for i in array limit: limit offset: offset %}{{ i }}{%endfor%}', assigns)
112
- end
113
-
114
- def test_nested_for
115
- assigns = { 'array' => [[1, 2], [3, 4], [5, 6]] }
116
- assert_template_result('123456', '{%for item in array%}{%for i in item%}{{ i }}{%endfor%}{%endfor%}', assigns)
117
- end
118
-
119
- def test_offset_only
120
- assigns = { 'array' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] }
121
- assert_template_result('890', '{%for i in array offset:7 %}{{ i }}{%endfor%}', assigns)
122
- end
123
-
124
- def test_pause_resume
125
- assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] } }
126
- markup = <<-MKUP
127
- {%for i in array.items limit: 3 %}{{i}}{%endfor%}
128
- next
129
- {%for i in array.items offset:continue limit: 3 %}{{i}}{%endfor%}
130
- next
131
- {%for i in array.items offset:continue limit: 3 %}{{i}}{%endfor%}
132
- MKUP
133
- expected = <<-XPCTD
134
- 123
135
- next
136
- 456
137
- next
138
- 789
139
- XPCTD
140
- assert_template_result(expected, markup, assigns)
141
- end
142
-
143
- def test_pause_resume_limit
144
- assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] } }
145
- markup = <<-MKUP
146
- {%for i in array.items limit:3 %}{{i}}{%endfor%}
147
- next
148
- {%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
149
- next
150
- {%for i in array.items offset:continue limit:1 %}{{i}}{%endfor%}
151
- MKUP
152
- expected = <<-XPCTD
153
- 123
154
- next
155
- 456
156
- next
157
- 7
158
- XPCTD
159
- assert_template_result(expected, markup, assigns)
160
- end
161
-
162
- def test_pause_resume_big_limit
163
- assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] } }
164
- markup = <<-MKUP
165
- {%for i in array.items limit:3 %}{{i}}{%endfor%}
166
- next
167
- {%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
168
- next
169
- {%for i in array.items offset:continue limit:1000 %}{{i}}{%endfor%}
170
- MKUP
171
- expected = <<-XPCTD
172
- 123
173
- next
174
- 456
175
- next
176
- 7890
177
- XPCTD
178
- assert_template_result(expected, markup, assigns)
179
- end
180
-
181
- def test_pause_resume_big_offset
182
- assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] } }
183
- markup = '{%for i in array.items limit:3 %}{{i}}{%endfor%}
184
- next
185
- {%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
186
- next
187
- {%for i in array.items offset:continue limit:3 offset:1000 %}{{i}}{%endfor%}'
188
- expected = '123
189
- next
190
- 456
191
- next
192
- '
193
- assert_template_result(expected, markup, assigns)
194
- end
195
-
196
- def test_for_with_break
197
- assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] } }
198
-
199
- markup = '{% for i in array.items %}{% break %}{% endfor %}'
200
- expected = ""
201
- assert_template_result(expected, markup, assigns)
202
-
203
- markup = '{% for i in array.items %}{{ i }}{% break %}{% endfor %}'
204
- expected = "1"
205
- assert_template_result(expected, markup, assigns)
206
-
207
- markup = '{% for i in array.items %}{% break %}{{ i }}{% endfor %}'
208
- expected = ""
209
- assert_template_result(expected, markup, assigns)
210
-
211
- markup = '{% for i in array.items %}{{ i }}{% if i > 3 %}{% break %}{% endif %}{% endfor %}'
212
- expected = "1234"
213
- assert_template_result(expected, markup, assigns)
214
-
215
- # tests to ensure it only breaks out of the local for loop
216
- # and not all of them.
217
- assigns = { 'array' => [[1, 2], [3, 4], [5, 6]] }
218
- markup = '{% for item in array %}' \
219
- '{% for i in item %}' \
220
- '{% if i == 1 %}' \
221
- '{% break %}' \
222
- '{% endif %}' \
223
- '{{ i }}' \
224
- '{% endfor %}' \
225
- '{% endfor %}'
226
- expected = '3456'
227
- assert_template_result(expected, markup, assigns)
228
-
229
- # test break does nothing when unreached
230
- assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5] } }
231
- markup = '{% for i in array.items %}{% if i == 9999 %}{% break %}{% endif %}{{ i }}{% endfor %}'
232
- expected = '12345'
233
- assert_template_result(expected, markup, assigns)
234
- end
235
-
236
- def test_for_with_continue
237
- assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5] } }
238
-
239
- markup = '{% for i in array.items %}{% continue %}{% endfor %}'
240
- expected = ""
241
- assert_template_result(expected, markup, assigns)
242
-
243
- markup = '{% for i in array.items %}{{ i }}{% continue %}{% endfor %}'
244
- expected = "12345"
245
- assert_template_result(expected, markup, assigns)
246
-
247
- markup = '{% for i in array.items %}{% continue %}{{ i }}{% endfor %}'
248
- expected = ""
249
- assert_template_result(expected, markup, assigns)
250
-
251
- markup = '{% for i in array.items %}{% if i > 3 %}{% continue %}{% endif %}{{ i }}{% endfor %}'
252
- expected = "123"
253
- assert_template_result(expected, markup, assigns)
254
-
255
- markup = '{% for i in array.items %}{% if i == 3 %}{% continue %}{% else %}{{ i }}{% endif %}{% endfor %}'
256
- expected = "1245"
257
- assert_template_result(expected, markup, assigns)
258
-
259
- # tests to ensure it only continues the local for loop and not all of them.
260
- assigns = { 'array' => [[1, 2], [3, 4], [5, 6]] }
261
- markup = '{% for item in array %}' \
262
- '{% for i in item %}' \
263
- '{% if i == 1 %}' \
264
- '{% continue %}' \
265
- '{% endif %}' \
266
- '{{ i }}' \
267
- '{% endfor %}' \
268
- '{% endfor %}'
269
- expected = '23456'
270
- assert_template_result(expected, markup, assigns)
271
-
272
- # test continue does nothing when unreached
273
- assigns = { 'array' => { 'items' => [1, 2, 3, 4, 5] } }
274
- markup = '{% for i in array.items %}{% if i == 9999 %}{% continue %}{% endif %}{{ i }}{% endfor %}'
275
- expected = '12345'
276
- assert_template_result(expected, markup, assigns)
277
- end
278
-
279
- def test_for_tag_string
280
- # ruby 1.8.7 "String".each => Enumerator with single "String" element.
281
- # ruby 1.9.3 no longer supports .each on String though we mimic
282
- # the functionality for backwards compatibility
283
-
284
- assert_template_result('test string',
285
- '{%for val in string%}{{val}}{%endfor%}',
286
- 'string' => "test string")
287
-
288
- assert_template_result('test string',
289
- '{%for val in string limit:1%}{{val}}{%endfor%}',
290
- 'string' => "test string")
291
-
292
- assert_template_result('val-string-1-1-0-1-0-true-true-test string',
293
- '{%for val in string%}' \
294
- '{{forloop.name}}-' \
295
- '{{forloop.index}}-' \
296
- '{{forloop.length}}-' \
297
- '{{forloop.index0}}-' \
298
- '{{forloop.rindex}}-' \
299
- '{{forloop.rindex0}}-' \
300
- '{{forloop.first}}-' \
301
- '{{forloop.last}}-' \
302
- '{{val}}{%endfor%}',
303
- 'string' => "test string")
304
- end
305
-
306
- def test_for_parentloop_references_parent_loop
307
- assert_template_result('1.1 1.2 1.3 2.1 2.2 2.3 ',
308
- '{% for inner in outer %}{% for k in inner %}' \
309
- '{{ forloop.parentloop.index }}.{{ forloop.index }} ' \
310
- '{% endfor %}{% endfor %}',
311
- 'outer' => [[1, 1, 1], [1, 1, 1]])
312
- end
313
-
314
- def test_for_parentloop_nil_when_not_present
315
- assert_template_result('.1 .2 ',
316
- '{% for inner in outer %}' \
317
- '{{ forloop.parentloop.index }}.{{ forloop.index }} ' \
318
- '{% endfor %}',
319
- 'outer' => [[1, 1, 1], [1, 1, 1]])
320
- end
321
-
322
- def test_inner_for_over_empty_input
323
- assert_template_result 'oo', '{% for a in (1..2) %}o{% for b in empty %}{% endfor %}{% endfor %}'
324
- end
325
-
326
- def test_blank_string_not_iterable
327
- assert_template_result('', "{% for char in characters %}I WILL NOT BE OUTPUT{% endfor %}", 'characters' => '')
328
- end
329
-
330
- def test_bad_variable_naming_in_for_loop
331
- assert_raises(Liquid::SyntaxError) do
332
- Liquid::Template.parse('{% for a/b in x %}{% endfor %}')
333
- end
334
- end
335
-
336
- def test_spacing_with_variable_naming_in_for_loop
337
- expected = '12345'
338
- template = '{% for item in items %}{{item}}{% endfor %}'
339
- assigns = { 'items' => [1, 2, 3, 4, 5] }
340
- assert_template_result(expected, template, assigns)
341
- end
342
-
343
- class LoaderDrop < Liquid::Drop
344
- attr_accessor :each_called, :load_slice_called
345
-
346
- def initialize(data)
347
- @data = data
348
- end
349
-
350
- def each
351
- @each_called = true
352
- @data.each { |el| yield el }
353
- end
354
-
355
- def load_slice(from, to)
356
- @load_slice_called = true
357
- @data[(from..to - 1)]
358
- end
359
- end
360
-
361
- def test_iterate_with_each_when_no_limit_applied
362
- loader = LoaderDrop.new([1, 2, 3, 4, 5])
363
- assigns = { 'items' => loader }
364
- expected = '12345'
365
- template = '{% for item in items %}{{item}}{% endfor %}'
366
- assert_template_result(expected, template, assigns)
367
- assert loader.each_called
368
- assert !loader.load_slice_called
369
- end
370
-
371
- def test_iterate_with_load_slice_when_limit_applied
372
- loader = LoaderDrop.new([1, 2, 3, 4, 5])
373
- assigns = { 'items' => loader }
374
- expected = '1'
375
- template = '{% for item in items limit:1 %}{{item}}{% endfor %}'
376
- assert_template_result(expected, template, assigns)
377
- assert !loader.each_called
378
- assert loader.load_slice_called
379
- end
380
-
381
- def test_iterate_with_load_slice_when_limit_and_offset_applied
382
- loader = LoaderDrop.new([1, 2, 3, 4, 5])
383
- assigns = { 'items' => loader }
384
- expected = '34'
385
- template = '{% for item in items offset:2 limit:2 %}{{item}}{% endfor %}'
386
- assert_template_result(expected, template, assigns)
387
- assert !loader.each_called
388
- assert loader.load_slice_called
389
- end
390
-
391
- def test_iterate_with_load_slice_returns_same_results_as_without
392
- loader = LoaderDrop.new([1, 2, 3, 4, 5])
393
- loader_assigns = { 'items' => loader }
394
- array_assigns = { 'items' => [1, 2, 3, 4, 5] }
395
- expected = '34'
396
- template = '{% for item in items offset:2 limit:2 %}{{item}}{% endfor %}'
397
- assert_template_result(expected, template, loader_assigns)
398
- assert_template_result(expected, template, array_assigns)
399
- end
400
-
401
- def test_for_cleans_up_registers
402
- context = Context.new(ErrorDrop.new)
403
-
404
- assert_raises(StandardError) do
405
- Liquid::Template.parse('{% for i in (1..2) %}{{ standard_error }}{% endfor %}').render!(context)
406
- end
407
-
408
- assert context.registers[:for_stack].empty?
409
- end
410
- end
@@ -1,188 +0,0 @@
1
- require 'test_helper'
2
-
3
- class IfElseTagTest < Minitest::Test
4
- include Liquid
5
-
6
- def test_if
7
- assert_template_result(' ', ' {% if false %} this text should not go into the output {% endif %} ')
8
- assert_template_result(' this text should go into the output ',
9
- ' {% if true %} this text should go into the output {% endif %} ')
10
- assert_template_result(' you rock ?', '{% if false %} you suck {% endif %} {% if true %} you rock {% endif %}?')
11
- end
12
-
13
- def test_literal_comparisons
14
- assert_template_result(' NO ', '{% assign v = false %}{% if v %} YES {% else %} NO {% endif %}')
15
- assert_template_result(' YES ', '{% assign v = nil %}{% if v == nil %} YES {% else %} NO {% endif %}')
16
- end
17
-
18
- def test_if_else
19
- assert_template_result(' YES ', '{% if false %} NO {% else %} YES {% endif %}')
20
- assert_template_result(' YES ', '{% if true %} YES {% else %} NO {% endif %}')
21
- assert_template_result(' YES ', '{% if "foo" %} YES {% else %} NO {% endif %}')
22
- end
23
-
24
- def test_if_boolean
25
- assert_template_result(' YES ', '{% if var %} YES {% endif %}', 'var' => true)
26
- end
27
-
28
- def test_if_or
29
- assert_template_result(' YES ', '{% if a or b %} YES {% endif %}', 'a' => true, 'b' => true)
30
- assert_template_result(' YES ', '{% if a or b %} YES {% endif %}', 'a' => true, 'b' => false)
31
- assert_template_result(' YES ', '{% if a or b %} YES {% endif %}', 'a' => false, 'b' => true)
32
- assert_template_result('', '{% if a or b %} YES {% endif %}', 'a' => false, 'b' => false)
33
-
34
- assert_template_result(' YES ', '{% if a or b or c %} YES {% endif %}', 'a' => false, 'b' => false, 'c' => true)
35
- assert_template_result('', '{% if a or b or c %} YES {% endif %}', 'a' => false, 'b' => false, 'c' => false)
36
- end
37
-
38
- def test_if_or_with_operators
39
- assert_template_result(' YES ', '{% if a == true or b == true %} YES {% endif %}', 'a' => true, 'b' => true)
40
- assert_template_result(' YES ', '{% if a == true or b == false %} YES {% endif %}', 'a' => true, 'b' => true)
41
- assert_template_result('', '{% if a == false or b == false %} YES {% endif %}', 'a' => true, 'b' => true)
42
- end
43
-
44
- def test_comparison_of_strings_containing_and_or_or
45
- awful_markup = "a == 'and' and b == 'or' and c == 'foo and bar' and d == 'bar or baz' and e == 'foo' and foo and bar"
46
- assigns = { 'a' => 'and', 'b' => 'or', 'c' => 'foo and bar', 'd' => 'bar or baz', 'e' => 'foo', 'foo' => true, 'bar' => true }
47
- assert_template_result(' YES ', "{% if #{awful_markup} %} YES {% endif %}", assigns)
48
- end
49
-
50
- def test_comparison_of_expressions_starting_with_and_or_or
51
- assigns = { 'order' => { 'items_count' => 0 }, 'android' => { 'name' => 'Roy' } }
52
- assert_template_result("YES",
53
- "{% if android.name == 'Roy' %}YES{% endif %}",
54
- assigns)
55
- assert_template_result("YES",
56
- "{% if order.items_count == 0 %}YES{% endif %}",
57
- assigns)
58
- end
59
-
60
- def test_if_and
61
- assert_template_result(' YES ', '{% if true and true %} YES {% endif %}')
62
- assert_template_result('', '{% if false and true %} YES {% endif %}')
63
- assert_template_result('', '{% if false and true %} YES {% endif %}')
64
- end
65
-
66
- def test_hash_miss_generates_false
67
- assert_template_result('', '{% if foo.bar %} NO {% endif %}', 'foo' => {})
68
- end
69
-
70
- def test_if_from_variable
71
- assert_template_result('', '{% if var %} NO {% endif %}', 'var' => false)
72
- assert_template_result('', '{% if var %} NO {% endif %}', 'var' => nil)
73
- assert_template_result('', '{% if foo.bar %} NO {% endif %}', 'foo' => { 'bar' => false })
74
- assert_template_result('', '{% if foo.bar %} NO {% endif %}', 'foo' => {})
75
- assert_template_result('', '{% if foo.bar %} NO {% endif %}', 'foo' => nil)
76
- assert_template_result('', '{% if foo.bar %} NO {% endif %}', 'foo' => true)
77
-
78
- assert_template_result(' YES ', '{% if var %} YES {% endif %}', 'var' => "text")
79
- assert_template_result(' YES ', '{% if var %} YES {% endif %}', 'var' => true)
80
- assert_template_result(' YES ', '{% if var %} YES {% endif %}', 'var' => 1)
81
- assert_template_result(' YES ', '{% if var %} YES {% endif %}', 'var' => {})
82
- assert_template_result(' YES ', '{% if var %} YES {% endif %}', 'var' => [])
83
- assert_template_result(' YES ', '{% if "foo" %} YES {% endif %}')
84
- assert_template_result(' YES ', '{% if foo.bar %} YES {% endif %}', 'foo' => { 'bar' => true })
85
- assert_template_result(' YES ', '{% if foo.bar %} YES {% endif %}', 'foo' => { 'bar' => "text" })
86
- assert_template_result(' YES ', '{% if foo.bar %} YES {% endif %}', 'foo' => { 'bar' => 1 })
87
- assert_template_result(' YES ', '{% if foo.bar %} YES {% endif %}', 'foo' => { 'bar' => {} })
88
- assert_template_result(' YES ', '{% if foo.bar %} YES {% endif %}', 'foo' => { 'bar' => [] })
89
-
90
- assert_template_result(' YES ', '{% if var %} NO {% else %} YES {% endif %}', 'var' => false)
91
- assert_template_result(' YES ', '{% if var %} NO {% else %} YES {% endif %}', 'var' => nil)
92
- assert_template_result(' YES ', '{% if var %} YES {% else %} NO {% endif %}', 'var' => true)
93
- assert_template_result(' YES ', '{% if "foo" %} YES {% else %} NO {% endif %}', 'var' => "text")
94
-
95
- assert_template_result(' YES ', '{% if foo.bar %} NO {% else %} YES {% endif %}', 'foo' => { 'bar' => false })
96
- assert_template_result(' YES ', '{% if foo.bar %} YES {% else %} NO {% endif %}', 'foo' => { 'bar' => true })
97
- assert_template_result(' YES ', '{% if foo.bar %} YES {% else %} NO {% endif %}', 'foo' => { 'bar' => "text" })
98
- assert_template_result(' YES ', '{% if foo.bar %} NO {% else %} YES {% endif %}', 'foo' => { 'notbar' => true })
99
- assert_template_result(' YES ', '{% if foo.bar %} NO {% else %} YES {% endif %}', 'foo' => {})
100
- assert_template_result(' YES ', '{% if foo.bar %} NO {% else %} YES {% endif %}', 'notfoo' => { 'bar' => true })
101
- end
102
-
103
- def test_nested_if
104
- assert_template_result('', '{% if false %}{% if false %} NO {% endif %}{% endif %}')
105
- assert_template_result('', '{% if false %}{% if true %} NO {% endif %}{% endif %}')
106
- assert_template_result('', '{% if true %}{% if false %} NO {% endif %}{% endif %}')
107
- assert_template_result(' YES ', '{% if true %}{% if true %} YES {% endif %}{% endif %}')
108
-
109
- assert_template_result(' YES ', '{% if true %}{% if true %} YES {% else %} NO {% endif %}{% else %} NO {% endif %}')
110
- assert_template_result(' YES ', '{% if true %}{% if false %} NO {% else %} YES {% endif %}{% else %} NO {% endif %}')
111
- assert_template_result(' YES ', '{% if false %}{% if true %} NO {% else %} NONO {% endif %}{% else %} YES {% endif %}')
112
- end
113
-
114
- def test_comparisons_on_null
115
- assert_template_result('', '{% if null < 10 %} NO {% endif %}')
116
- assert_template_result('', '{% if null <= 10 %} NO {% endif %}')
117
- assert_template_result('', '{% if null >= 10 %} NO {% endif %}')
118
- assert_template_result('', '{% if null > 10 %} NO {% endif %}')
119
-
120
- assert_template_result('', '{% if 10 < null %} NO {% endif %}')
121
- assert_template_result('', '{% if 10 <= null %} NO {% endif %}')
122
- assert_template_result('', '{% if 10 >= null %} NO {% endif %}')
123
- assert_template_result('', '{% if 10 > null %} NO {% endif %}')
124
- end
125
-
126
- def test_else_if
127
- assert_template_result('0', '{% if 0 == 0 %}0{% elsif 1 == 1%}1{% else %}2{% endif %}')
128
- assert_template_result('1', '{% if 0 != 0 %}0{% elsif 1 == 1%}1{% else %}2{% endif %}')
129
- assert_template_result('2', '{% if 0 != 0 %}0{% elsif 1 != 1%}1{% else %}2{% endif %}')
130
-
131
- assert_template_result('elsif', '{% if false %}if{% elsif true %}elsif{% endif %}')
132
- end
133
-
134
- def test_syntax_error_no_variable
135
- assert_raises(SyntaxError){ assert_template_result('', '{% if jerry == 1 %}') }
136
- end
137
-
138
- def test_syntax_error_no_expression
139
- assert_raises(SyntaxError) { assert_template_result('', '{% if %}') }
140
- end
141
-
142
- def test_if_with_custom_condition
143
- original_op = Condition.operators['contains']
144
- Condition.operators['contains'] = :[]
145
-
146
- assert_template_result('yes', %({% if 'bob' contains 'o' %}yes{% endif %}))
147
- assert_template_result('no', %({% if 'bob' contains 'f' %}yes{% else %}no{% endif %}))
148
- ensure
149
- Condition.operators['contains'] = original_op
150
- end
151
-
152
- def test_operators_are_ignored_unless_isolated
153
- original_op = Condition.operators['contains']
154
- Condition.operators['contains'] = :[]
155
-
156
- assert_template_result('yes',
157
- %({% if 'gnomeslab-and-or-liquid' contains 'gnomeslab-and-or-liquid' %}yes{% endif %}))
158
- ensure
159
- Condition.operators['contains'] = original_op
160
- end
161
-
162
- def test_operators_are_whitelisted
163
- assert_raises(SyntaxError) do
164
- assert_template_result('', %({% if 1 or throw or or 1 %}yes{% endif %}))
165
- end
166
- end
167
-
168
- def test_multiple_conditions
169
- tpl = "{% if a or b and c %}true{% else %}false{% endif %}"
170
-
171
- tests = {
172
- [true, true, true] => true,
173
- [true, true, false] => true,
174
- [true, false, true] => true,
175
- [true, false, false] => true,
176
- [false, true, true] => true,
177
- [false, true, false] => false,
178
- [false, false, true] => false,
179
- [false, false, false] => false,
180
- }
181
-
182
- tests.each do |vals, expected|
183
- a, b, c = vals
184
- assigns = { 'a' => a, 'b' => b, 'c' => c }
185
- assert_template_result expected.to_s, tpl, assigns, assigns.to_s
186
- end
187
- end
188
- end