liquid 5.3.0 → 5.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +16 -1
  3. data/README.md +2 -2
  4. data/lib/liquid/block_body.rb +4 -4
  5. data/lib/liquid/context.rb +6 -2
  6. data/lib/liquid/forloop_drop.rb +44 -1
  7. data/lib/liquid/locales/en.yml +6 -5
  8. data/lib/liquid/partial_cache.rb +3 -3
  9. data/lib/liquid/{static_registers.rb → registers.rb} +13 -10
  10. data/lib/liquid/standardfilters.rb +406 -57
  11. data/lib/liquid/strainer_factory.rb +4 -0
  12. data/lib/liquid/strainer_template.rb +4 -0
  13. data/lib/liquid/tablerowloop_drop.rb +58 -1
  14. data/lib/liquid/tags/assign.rb +12 -8
  15. data/lib/liquid/tags/break.rb +8 -0
  16. data/lib/liquid/tags/capture.rb +13 -10
  17. data/lib/liquid/tags/case.rb +21 -0
  18. data/lib/liquid/tags/comment.rb +13 -0
  19. data/lib/liquid/tags/continue.rb +8 -9
  20. data/lib/liquid/tags/cycle.rb +12 -11
  21. data/lib/liquid/tags/decrement.rb +16 -17
  22. data/lib/liquid/tags/echo.rb +16 -9
  23. data/lib/liquid/tags/for.rb +22 -43
  24. data/lib/liquid/tags/if.rb +11 -9
  25. data/lib/liquid/tags/include.rb +15 -13
  26. data/lib/liquid/tags/increment.rb +16 -14
  27. data/lib/liquid/tags/inline_comment.rb +43 -0
  28. data/lib/liquid/tags/raw.rb +11 -0
  29. data/lib/liquid/tags/render.rb +29 -4
  30. data/lib/liquid/tags/table_row.rb +22 -0
  31. data/lib/liquid/tags/unless.rb +15 -4
  32. data/lib/liquid/template.rb +2 -3
  33. data/lib/liquid/variable.rb +4 -4
  34. data/lib/liquid/variable_lookup.rb +10 -7
  35. data/lib/liquid/version.rb +1 -1
  36. data/lib/liquid.rb +2 -2
  37. metadata +7 -123
  38. data/lib/liquid/register.rb +0 -6
  39. data/test/fixtures/en_locale.yml +0 -9
  40. data/test/integration/assign_test.rb +0 -117
  41. data/test/integration/blank_test.rb +0 -109
  42. data/test/integration/block_test.rb +0 -58
  43. data/test/integration/capture_test.rb +0 -58
  44. data/test/integration/context_test.rb +0 -634
  45. data/test/integration/document_test.rb +0 -21
  46. data/test/integration/drop_test.rb +0 -257
  47. data/test/integration/error_handling_test.rb +0 -272
  48. data/test/integration/expression_test.rb +0 -46
  49. data/test/integration/filter_kwarg_test.rb +0 -24
  50. data/test/integration/filter_test.rb +0 -189
  51. data/test/integration/hash_ordering_test.rb +0 -25
  52. data/test/integration/output_test.rb +0 -125
  53. data/test/integration/parsing_quirks_test.rb +0 -134
  54. data/test/integration/profiler_test.rb +0 -240
  55. data/test/integration/security_test.rb +0 -89
  56. data/test/integration/standard_filter_test.rb +0 -925
  57. data/test/integration/tag/disableable_test.rb +0 -59
  58. data/test/integration/tag_test.rb +0 -45
  59. data/test/integration/tags/break_tag_test.rb +0 -17
  60. data/test/integration/tags/continue_tag_test.rb +0 -17
  61. data/test/integration/tags/echo_test.rb +0 -13
  62. data/test/integration/tags/for_tag_test.rb +0 -466
  63. data/test/integration/tags/if_else_tag_test.rb +0 -190
  64. data/test/integration/tags/include_tag_test.rb +0 -269
  65. data/test/integration/tags/increment_tag_test.rb +0 -25
  66. data/test/integration/tags/liquid_tag_test.rb +0 -116
  67. data/test/integration/tags/raw_tag_test.rb +0 -34
  68. data/test/integration/tags/render_tag_test.rb +0 -213
  69. data/test/integration/tags/standard_tag_test.rb +0 -303
  70. data/test/integration/tags/statements_test.rb +0 -113
  71. data/test/integration/tags/table_row_test.rb +0 -66
  72. data/test/integration/tags/unless_else_tag_test.rb +0 -28
  73. data/test/integration/template_test.rb +0 -340
  74. data/test/integration/trim_mode_test.rb +0 -563
  75. data/test/integration/variable_test.rb +0 -138
  76. data/test/test_helper.rb +0 -207
  77. data/test/unit/block_unit_test.rb +0 -53
  78. data/test/unit/condition_unit_test.rb +0 -181
  79. data/test/unit/file_system_unit_test.rb +0 -37
  80. data/test/unit/i18n_unit_test.rb +0 -39
  81. data/test/unit/lexer_unit_test.rb +0 -53
  82. data/test/unit/parse_tree_visitor_test.rb +0 -261
  83. data/test/unit/parser_unit_test.rb +0 -84
  84. data/test/unit/partial_cache_unit_test.rb +0 -128
  85. data/test/unit/regexp_unit_test.rb +0 -46
  86. data/test/unit/static_registers_unit_test.rb +0 -156
  87. data/test/unit/strainer_factory_unit_test.rb +0 -101
  88. data/test/unit/strainer_template_unit_test.rb +0 -82
  89. data/test/unit/tag_unit_test.rb +0 -23
  90. data/test/unit/tags/case_tag_unit_test.rb +0 -12
  91. data/test/unit/tags/for_tag_unit_test.rb +0 -15
  92. data/test/unit/tags/if_tag_unit_test.rb +0 -10
  93. data/test/unit/template_factory_unit_test.rb +0 -12
  94. data/test/unit/template_unit_test.rb +0 -87
  95. data/test/unit/tokenizer_unit_test.rb +0 -62
  96. data/test/unit/variable_unit_test.rb +0 -164
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class TableRowTest < Minitest::Test
6
- include Liquid
7
-
8
- class ArrayDrop < Liquid::Drop
9
- include Enumerable
10
-
11
- def initialize(array)
12
- @array = array
13
- end
14
-
15
- def each(&block)
16
- @array.each(&block)
17
- end
18
- end
19
-
20
- def test_table_row
21
- assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
22
- '{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
23
- 'numbers' => [1, 2, 3, 4, 5, 6])
24
-
25
- assert_template_result("<tr class=\"row1\">\n</tr>\n",
26
- '{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
27
- 'numbers' => [])
28
- end
29
-
30
- def test_table_row_with_different_cols
31
- assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td><td class=\"col4\"> 4 </td><td class=\"col5\"> 5 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 6 </td></tr>\n",
32
- '{% tablerow n in numbers cols:5%} {{n}} {% endtablerow %}',
33
- 'numbers' => [1, 2, 3, 4, 5, 6])
34
- end
35
-
36
- def test_table_col_counter
37
- assert_template_result("<tr class=\"row1\">\n<td class=\"col1\">1</td><td class=\"col2\">2</td></tr>\n<tr class=\"row2\"><td class=\"col1\">1</td><td class=\"col2\">2</td></tr>\n<tr class=\"row3\"><td class=\"col1\">1</td><td class=\"col2\">2</td></tr>\n",
38
- '{% tablerow n in numbers cols:2%}{{tablerowloop.col}}{% endtablerow %}',
39
- 'numbers' => [1, 2, 3, 4, 5, 6])
40
- end
41
-
42
- def test_quoted_fragment
43
- assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
44
- "{% tablerow n in collections.frontpage cols:3%} {{n}} {% endtablerow %}",
45
- 'collections' => { 'frontpage' => [1, 2, 3, 4, 5, 6] })
46
- assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
47
- "{% tablerow n in collections['frontpage'] cols:3%} {{n}} {% endtablerow %}",
48
- 'collections' => { 'frontpage' => [1, 2, 3, 4, 5, 6] })
49
- end
50
-
51
- def test_enumerable_drop
52
- assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
53
- '{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
54
- 'numbers' => ArrayDrop.new([1, 2, 3, 4, 5, 6]))
55
- end
56
-
57
- def test_offset_and_limit
58
- assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
59
- '{% tablerow n in numbers cols:3 offset:1 limit:6%} {{n}} {% endtablerow %}',
60
- 'numbers' => [0, 1, 2, 3, 4, 5, 6, 7])
61
- end
62
-
63
- def test_blank_string_not_iterable
64
- assert_template_result("<tr class=\"row1\">\n</tr>\n", "{% tablerow char in characters cols:3 %}I WILL NOT BE OUTPUT{% endtablerow %}", 'characters' => '')
65
- end
66
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class UnlessElseTagTest < Minitest::Test
6
- include Liquid
7
-
8
- def test_unless
9
- assert_template_result(' ', ' {% unless true %} this text should not go into the output {% endunless %} ')
10
- assert_template_result(' this text should go into the output ',
11
- ' {% unless false %} this text should go into the output {% endunless %} ')
12
- assert_template_result(' you rock ?', '{% unless true %} you suck {% endunless %} {% unless false %} you rock {% endunless %}?')
13
- end
14
-
15
- def test_unless_else
16
- assert_template_result(' YES ', '{% unless true %} NO {% else %} YES {% endunless %}')
17
- assert_template_result(' YES ', '{% unless false %} YES {% else %} NO {% endunless %}')
18
- assert_template_result(' YES ', '{% unless "foo" %} NO {% else %} YES {% endunless %}')
19
- end
20
-
21
- def test_unless_in_loop
22
- assert_template_result('23', '{% for i in choices %}{% unless i %}{{ forloop.index }}{% endunless %}{% endfor %}', 'choices' => [1, nil, false])
23
- end
24
-
25
- def test_unless_else_in_loop
26
- assert_template_result(' TRUE 2 3 ', '{% for i in choices %}{% unless i %} {{ forloop.index }} {% else %} TRUE {% endunless %}{% endfor %}', 'choices' => [1, nil, false])
27
- end
28
- end # UnlessElseTest
@@ -1,340 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
- require 'timeout'
5
-
6
- class TemplateContextDrop < Liquid::Drop
7
- def liquid_method_missing(method)
8
- method
9
- end
10
-
11
- def foo
12
- 'fizzbuzz'
13
- end
14
-
15
- def baz
16
- @context.registers['lulz']
17
- end
18
- end
19
-
20
- class SomethingWithLength < Liquid::Drop
21
- def length
22
- nil
23
- end
24
- end
25
-
26
- class ErroneousDrop < Liquid::Drop
27
- def bad_method
28
- raise 'ruby error in drop'
29
- end
30
- end
31
-
32
- class DropWithUndefinedMethod < Liquid::Drop
33
- def foo
34
- 'foo'
35
- end
36
- end
37
-
38
- class TemplateTest < Minitest::Test
39
- include Liquid
40
-
41
- def test_instance_assigns_persist_on_same_template_object_between_parses
42
- t = Template.new
43
- assert_equal('from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render!)
44
- assert_equal('from instance assigns', t.parse("{{ foo }}").render!)
45
- end
46
-
47
- def test_warnings_is_not_exponential_time
48
- str = "false"
49
- 100.times do
50
- str = "{% if true %}true{% else %}#{str}{% endif %}"
51
- end
52
-
53
- t = Template.parse(str)
54
- assert_equal([], Timeout.timeout(1) { t.warnings })
55
- end
56
-
57
- def test_instance_assigns_persist_on_same_template_parsing_between_renders
58
- t = Template.new.parse("{{ foo }}{% assign foo = 'foo' %}{{ foo }}")
59
- assert_equal('foo', t.render!)
60
- assert_equal('foofoo', t.render!)
61
- end
62
-
63
- def test_custom_assigns_do_not_persist_on_same_template
64
- t = Template.new
65
- assert_equal('from custom assigns', t.parse("{{ foo }}").render!('foo' => 'from custom assigns'))
66
- assert_equal('', t.parse("{{ foo }}").render!)
67
- end
68
-
69
- def test_custom_assigns_squash_instance_assigns
70
- t = Template.new
71
- assert_equal('from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render!)
72
- assert_equal('from custom assigns', t.parse("{{ foo }}").render!('foo' => 'from custom assigns'))
73
- end
74
-
75
- def test_persistent_assigns_squash_instance_assigns
76
- t = Template.new
77
- assert_equal('from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render!)
78
- t.assigns['foo'] = 'from persistent assigns'
79
- assert_equal('from persistent assigns', t.parse("{{ foo }}").render!)
80
- end
81
-
82
- def test_lambda_is_called_once_from_persistent_assigns_over_multiple_parses_and_renders
83
- t = Template.new
84
- t.assigns['number'] = -> {
85
- @global ||= 0
86
- @global += 1
87
- }
88
- assert_equal('1', t.parse("{{number}}").render!)
89
- assert_equal('1', t.parse("{{number}}").render!)
90
- assert_equal('1', t.render!)
91
- @global = nil
92
- end
93
-
94
- def test_lambda_is_called_once_from_custom_assigns_over_multiple_parses_and_renders
95
- t = Template.new
96
- assigns = { 'number' => -> {
97
- @global ||= 0
98
- @global += 1
99
- } }
100
- assert_equal('1', t.parse("{{number}}").render!(assigns))
101
- assert_equal('1', t.parse("{{number}}").render!(assigns))
102
- assert_equal('1', t.render!(assigns))
103
- @global = nil
104
- end
105
-
106
- def test_resource_limits_works_with_custom_length_method
107
- t = Template.parse("{% assign foo = bar %}")
108
- t.resource_limits.render_length_limit = 42
109
- assert_equal("", t.render!("bar" => SomethingWithLength.new))
110
- end
111
-
112
- def test_resource_limits_render_length
113
- t = Template.parse("0123456789")
114
- t.resource_limits.render_length_limit = 9
115
- assert_equal("Liquid error: Memory limits exceeded", t.render)
116
- assert(t.resource_limits.reached?)
117
-
118
- t.resource_limits.render_length_limit = 10
119
- assert_equal("0123456789", t.render!)
120
- end
121
-
122
- def test_resource_limits_render_score
123
- t = Template.parse("{% for a in (1..10) %} {% for a in (1..10) %} foo {% endfor %} {% endfor %}")
124
- t.resource_limits.render_score_limit = 50
125
- assert_equal("Liquid error: Memory limits exceeded", t.render)
126
- assert(t.resource_limits.reached?)
127
-
128
- t = Template.parse("{% for a in (1..100) %} foo {% endfor %}")
129
- t.resource_limits.render_score_limit = 50
130
- assert_equal("Liquid error: Memory limits exceeded", t.render)
131
- assert(t.resource_limits.reached?)
132
-
133
- t.resource_limits.render_score_limit = 200
134
- assert_equal((" foo " * 100), t.render!)
135
- refute_nil(t.resource_limits.render_score)
136
- end
137
-
138
- def test_resource_limits_aborts_rendering_after_first_error
139
- t = Template.parse("{% for a in (1..100) %} foo1 {% endfor %} bar {% for a in (1..100) %} foo2 {% endfor %}")
140
- t.resource_limits.render_score_limit = 50
141
- assert_equal("Liquid error: Memory limits exceeded", t.render)
142
- assert(t.resource_limits.reached?)
143
- end
144
-
145
- def test_resource_limits_hash_in_template_gets_updated_even_if_no_limits_are_set
146
- t = Template.parse("{% for a in (1..100) %}x{% assign foo = 1 %} {% endfor %}")
147
- t.render!
148
- assert(t.resource_limits.assign_score > 0)
149
- assert(t.resource_limits.render_score > 0)
150
- end
151
-
152
- def test_render_length_persists_between_blocks
153
- t = Template.parse("{% if true %}aaaa{% endif %}")
154
- t.resource_limits.render_length_limit = 3
155
- assert_equal("Liquid error: Memory limits exceeded", t.render)
156
- t.resource_limits.render_length_limit = 4
157
- assert_equal("aaaa", t.render)
158
-
159
- t = Template.parse("{% if true %}aaaa{% endif %}{% if true %}bbb{% endif %}")
160
- t.resource_limits.render_length_limit = 6
161
- assert_equal("Liquid error: Memory limits exceeded", t.render)
162
- t.resource_limits.render_length_limit = 7
163
- assert_equal("aaaabbb", t.render)
164
-
165
- t = Template.parse("{% if true %}a{% endif %}{% if true %}b{% endif %}{% if true %}a{% endif %}{% if true %}b{% endif %}{% if true %}a{% endif %}{% if true %}b{% endif %}")
166
- t.resource_limits.render_length_limit = 5
167
- assert_equal("Liquid error: Memory limits exceeded", t.render)
168
- t.resource_limits.render_length_limit = 6
169
- assert_equal("ababab", t.render)
170
- end
171
-
172
- def test_render_length_uses_number_of_bytes_not_characters
173
- t = Template.parse("{% if true %}すごい{% endif %}")
174
- t.resource_limits.render_length_limit = 8
175
- assert_equal("Liquid error: Memory limits exceeded", t.render)
176
- t.resource_limits.render_length_limit = 9
177
- assert_equal("すごい", t.render)
178
- end
179
-
180
- def test_default_resource_limits_unaffected_by_render_with_context
181
- context = Context.new
182
- t = Template.parse("{% for a in (1..100) %}x{% assign foo = 1 %} {% endfor %}")
183
- t.render!(context)
184
- assert(context.resource_limits.assign_score > 0)
185
- assert(context.resource_limits.render_score > 0)
186
- end
187
-
188
- def test_can_use_drop_as_context
189
- t = Template.new
190
- t.registers['lulz'] = 'haha'
191
- drop = TemplateContextDrop.new
192
- assert_equal('fizzbuzz', t.parse('{{foo}}').render!(drop))
193
- assert_equal('bar', t.parse('{{bar}}').render!(drop))
194
- assert_equal('haha', t.parse("{{baz}}").render!(drop))
195
- end
196
-
197
- def test_render_bang_force_rethrow_errors_on_passed_context
198
- context = Context.new('drop' => ErroneousDrop.new)
199
- t = Template.new.parse('{{ drop.bad_method }}')
200
-
201
- e = assert_raises(RuntimeError) do
202
- t.render!(context)
203
- end
204
- assert_equal('ruby error in drop', e.message)
205
- end
206
-
207
- def test_exception_renderer_that_returns_string
208
- exception = nil
209
- handler = ->(e) {
210
- exception = e
211
- '<!-- error -->'
212
- }
213
-
214
- output = Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_renderer: handler)
215
-
216
- assert(exception.is_a?(Liquid::ZeroDivisionError))
217
- assert_equal('<!-- error -->', output)
218
- end
219
-
220
- def test_exception_renderer_that_raises
221
- exception = nil
222
- assert_raises(Liquid::ZeroDivisionError) do
223
- Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_renderer: ->(e) {
224
- exception = e
225
- raise
226
- })
227
- end
228
- assert(exception.is_a?(Liquid::ZeroDivisionError))
229
- end
230
-
231
- def test_global_filter_option_on_render
232
- global_filter_proc = ->(output) { "#{output} filtered" }
233
- rendered_template = Template.parse("{{name}}").render({ "name" => "bob" }, global_filter: global_filter_proc)
234
-
235
- assert_equal('bob filtered', rendered_template)
236
- end
237
-
238
- def test_global_filter_option_when_native_filters_exist
239
- global_filter_proc = ->(output) { "#{output} filtered" }
240
- rendered_template = Template.parse("{{name | upcase}}").render({ "name" => "bob" }, global_filter: global_filter_proc)
241
-
242
- assert_equal('BOB filtered', rendered_template)
243
- end
244
-
245
- def test_undefined_variables
246
- t = Template.parse("{{x}} {{y}} {{z.a}} {{z.b}} {{z.c.d}}")
247
- result = t.render({ 'x' => 33, 'z' => { 'a' => 32, 'c' => { 'e' => 31 } } }, strict_variables: true)
248
-
249
- assert_equal('33 32 ', result)
250
- assert_equal(3, t.errors.count)
251
- assert_instance_of(Liquid::UndefinedVariable, t.errors[0])
252
- assert_equal('Liquid error: undefined variable y', t.errors[0].message)
253
- assert_instance_of(Liquid::UndefinedVariable, t.errors[1])
254
- assert_equal('Liquid error: undefined variable b', t.errors[1].message)
255
- assert_instance_of(Liquid::UndefinedVariable, t.errors[2])
256
- assert_equal('Liquid error: undefined variable d', t.errors[2].message)
257
- end
258
-
259
- def test_nil_value_does_not_raise
260
- t = Template.parse("some{{x}}thing", error_mode: :strict)
261
- result = t.render!({ 'x' => nil }, strict_variables: true)
262
-
263
- assert_equal(0, t.errors.count)
264
- assert_equal('something', result)
265
- end
266
-
267
- def test_undefined_variables_raise
268
- t = Template.parse("{{x}} {{y}} {{z.a}} {{z.b}} {{z.c.d}}")
269
-
270
- assert_raises(UndefinedVariable) do
271
- t.render!({ 'x' => 33, 'z' => { 'a' => 32, 'c' => { 'e' => 31 } } }, strict_variables: true)
272
- end
273
- end
274
-
275
- def test_undefined_drop_methods
276
- d = DropWithUndefinedMethod.new
277
- t = Template.new.parse('{{ foo }} {{ woot }}')
278
- result = t.render(d, strict_variables: true)
279
-
280
- assert_equal('foo ', result)
281
- assert_equal(1, t.errors.count)
282
- assert_instance_of(Liquid::UndefinedDropMethod, t.errors[0])
283
- end
284
-
285
- def test_undefined_drop_methods_raise
286
- d = DropWithUndefinedMethod.new
287
- t = Template.new.parse('{{ foo }} {{ woot }}')
288
-
289
- assert_raises(UndefinedDropMethod) do
290
- t.render!(d, strict_variables: true)
291
- end
292
- end
293
-
294
- def test_undefined_filters
295
- t = Template.parse("{{a}} {{x | upcase | somefilter1 | somefilter2 | somefilter3}}")
296
- filters = Module.new do
297
- def somefilter3(v)
298
- "-#{v}-"
299
- end
300
- end
301
- result = t.render({ 'a' => 123, 'x' => 'foo' }, filters: [filters], strict_filters: true)
302
-
303
- assert_equal('123 ', result)
304
- assert_equal(1, t.errors.count)
305
- assert_instance_of(Liquid::UndefinedFilter, t.errors[0])
306
- assert_equal('Liquid error: undefined filter somefilter1', t.errors[0].message)
307
- end
308
-
309
- def test_undefined_filters_raise
310
- t = Template.parse("{{x | somefilter1 | upcase | somefilter2}}")
311
-
312
- assert_raises(UndefinedFilter) do
313
- t.render!({ 'x' => 'foo' }, strict_filters: true)
314
- end
315
- end
316
-
317
- def test_using_range_literal_works_as_expected
318
- t = Template.parse("{% assign foo = (x..y) %}{{ foo }}")
319
- result = t.render('x' => 1, 'y' => 5)
320
- assert_equal('1..5', result)
321
-
322
- t = Template.parse("{% assign nums = (x..y) %}{% for num in nums %}{{ num }}{% endfor %}")
323
- result = t.render('x' => 1, 'y' => 5)
324
- assert_equal('12345', result)
325
- end
326
-
327
- def test_source_string_subclass
328
- string_subclass = Class.new(String) do
329
- # E.g. ActiveSupport::SafeBuffer does this, so don't just rely on to_s to return a String
330
- def to_s
331
- self
332
- end
333
- end
334
- source = string_subclass.new("{% assign x = 2 -%} x= {{- x }}")
335
- assert_instance_of(string_subclass, source)
336
- output = Template.parse(source).render!
337
- assert_equal("x=2", output)
338
- assert_instance_of(String, output)
339
- end
340
- end