liquid 4.0.2 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.md +59 -0
- data/README.md +6 -0
- data/lib/liquid/block.rb +31 -14
- data/lib/liquid/block_body.rb +166 -53
- data/lib/liquid/condition.rb +41 -20
- data/lib/liquid/context.rb +107 -52
- data/lib/liquid/document.rb +47 -9
- data/lib/liquid/drop.rb +4 -2
- data/lib/liquid/errors.rb +20 -18
- data/lib/liquid/expression.rb +29 -34
- data/lib/liquid/extensions.rb +2 -0
- data/lib/liquid/file_system.rb +6 -4
- data/lib/liquid/forloop_drop.rb +11 -4
- data/lib/liquid/i18n.rb +5 -3
- data/lib/liquid/interrupts.rb +3 -1
- data/lib/liquid/lexer.rb +30 -23
- data/lib/liquid/locales/en.yml +3 -1
- data/lib/liquid/parse_context.rb +20 -4
- data/lib/liquid/parse_tree_visitor.rb +2 -2
- data/lib/liquid/parser.rb +30 -18
- data/lib/liquid/parser_switching.rb +17 -3
- data/lib/liquid/partial_cache.rb +24 -0
- data/lib/liquid/profiler/hooks.rb +26 -14
- data/lib/liquid/profiler.rb +67 -86
- data/lib/liquid/range_lookup.rb +13 -3
- data/lib/liquid/register.rb +6 -0
- data/lib/liquid/resource_limits.rb +47 -8
- data/lib/liquid/standardfilters.rb +95 -46
- data/lib/liquid/static_registers.rb +44 -0
- data/lib/liquid/strainer_factory.rb +36 -0
- data/lib/liquid/strainer_template.rb +53 -0
- data/lib/liquid/tablerowloop_drop.rb +6 -4
- data/lib/liquid/tag/disableable.rb +22 -0
- data/lib/liquid/tag/disabler.rb +21 -0
- data/lib/liquid/tag.rb +28 -6
- data/lib/liquid/tags/assign.rb +24 -10
- data/lib/liquid/tags/break.rb +8 -3
- data/lib/liquid/tags/capture.rb +11 -8
- data/lib/liquid/tags/case.rb +40 -27
- data/lib/liquid/tags/comment.rb +5 -3
- data/lib/liquid/tags/continue.rb +8 -3
- data/lib/liquid/tags/cycle.rb +25 -14
- data/lib/liquid/tags/decrement.rb +6 -3
- data/lib/liquid/tags/echo.rb +34 -0
- data/lib/liquid/tags/for.rb +68 -44
- data/lib/liquid/tags/if.rb +39 -23
- data/lib/liquid/tags/ifchanged.rb +11 -10
- data/lib/liquid/tags/include.rb +34 -47
- data/lib/liquid/tags/increment.rb +7 -3
- data/lib/liquid/tags/raw.rb +14 -11
- data/lib/liquid/tags/render.rb +84 -0
- data/lib/liquid/tags/table_row.rb +23 -19
- data/lib/liquid/tags/unless.rb +23 -15
- data/lib/liquid/template.rb +53 -72
- data/lib/liquid/template_factory.rb +9 -0
- data/lib/liquid/tokenizer.rb +18 -10
- data/lib/liquid/usage.rb +8 -0
- data/lib/liquid/utils.rb +13 -3
- data/lib/liquid/variable.rb +46 -41
- data/lib/liquid/variable_lookup.rb +11 -6
- data/lib/liquid/version.rb +2 -1
- data/lib/liquid.rb +17 -5
- data/test/integration/assign_test.rb +74 -5
- data/test/integration/blank_test.rb +11 -8
- data/test/integration/block_test.rb +47 -1
- data/test/integration/capture_test.rb +18 -10
- data/test/integration/context_test.rb +609 -5
- data/test/integration/document_test.rb +4 -2
- data/test/integration/drop_test.rb +67 -83
- data/test/integration/error_handling_test.rb +73 -61
- data/test/integration/expression_test.rb +46 -0
- data/test/integration/filter_test.rb +53 -42
- data/test/integration/hash_ordering_test.rb +5 -3
- data/test/integration/output_test.rb +26 -24
- data/test/integration/parsing_quirks_test.rb +19 -7
- data/test/integration/{render_profiling_test.rb → profiler_test.rb} +84 -25
- data/test/integration/security_test.rb +30 -21
- data/test/integration/standard_filter_test.rb +385 -281
- data/test/integration/tag/disableable_test.rb +59 -0
- data/test/integration/tag_test.rb +45 -0
- data/test/integration/tags/break_tag_test.rb +4 -2
- data/test/integration/tags/continue_tag_test.rb +4 -2
- data/test/integration/tags/echo_test.rb +13 -0
- data/test/integration/tags/for_tag_test.rb +107 -51
- data/test/integration/tags/if_else_tag_test.rb +5 -3
- data/test/integration/tags/include_tag_test.rb +76 -52
- data/test/integration/tags/increment_tag_test.rb +4 -2
- data/test/integration/tags/liquid_tag_test.rb +116 -0
- data/test/integration/tags/raw_tag_test.rb +14 -11
- data/test/integration/tags/render_tag_test.rb +213 -0
- data/test/integration/tags/standard_tag_test.rb +38 -31
- data/test/integration/tags/statements_test.rb +23 -21
- data/test/integration/tags/table_row_test.rb +2 -0
- data/test/integration/tags/unless_else_tag_test.rb +4 -2
- data/test/integration/template_test.rb +132 -124
- data/test/integration/trim_mode_test.rb +78 -44
- data/test/integration/variable_test.rb +74 -32
- data/test/test_helper.rb +113 -22
- data/test/unit/block_unit_test.rb +19 -24
- data/test/unit/condition_unit_test.rb +79 -77
- data/test/unit/file_system_unit_test.rb +6 -4
- data/test/unit/i18n_unit_test.rb +7 -5
- data/test/unit/lexer_unit_test.rb +11 -9
- data/test/{integration → unit}/parse_tree_visitor_test.rb +16 -2
- data/test/unit/parser_unit_test.rb +37 -35
- data/test/unit/partial_cache_unit_test.rb +128 -0
- data/test/unit/regexp_unit_test.rb +17 -15
- data/test/unit/static_registers_unit_test.rb +156 -0
- data/test/unit/strainer_factory_unit_test.rb +100 -0
- data/test/unit/strainer_template_unit_test.rb +82 -0
- data/test/unit/tag_unit_test.rb +5 -3
- data/test/unit/tags/case_tag_unit_test.rb +3 -1
- data/test/unit/tags/for_tag_unit_test.rb +4 -2
- data/test/unit/tags/if_tag_unit_test.rb +3 -1
- data/test/unit/template_factory_unit_test.rb +12 -0
- data/test/unit/template_unit_test.rb +19 -10
- data/test/unit/tokenizer_unit_test.rb +26 -19
- data/test/unit/variable_unit_test.rb +51 -49
- metadata +76 -50
- data/lib/liquid/strainer.rb +0 -66
- data/lib/liquid/truffle.rb +0 -5
- data/test/truffle/truffle_test.rb +0 -9
- data/test/unit/context_unit_test.rb +0 -489
- data/test/unit/strainer_unit_test.rb +0 -164
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'test_helper'
|
2
4
|
|
3
5
|
class UnlessElseTagTest < Minitest::Test
|
@@ -17,10 +19,10 @@ class UnlessElseTagTest < Minitest::Test
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def test_unless_in_loop
|
20
|
-
assert_template_result
|
22
|
+
assert_template_result('23', '{% for i in choices %}{% unless i %}{{ forloop.index }}{% endunless %}{% endfor %}', 'choices' => [1, nil, false])
|
21
23
|
end
|
22
24
|
|
23
25
|
def test_unless_else_in_loop
|
24
|
-
assert_template_result
|
26
|
+
assert_template_result(' TRUE 2 3 ', '{% for i in choices %}{% unless i %} {{ forloop.index }} {% else %} TRUE {% endunless %}{% endfor %}', 'choices' => [1, nil, false])
|
25
27
|
end
|
26
28
|
end # UnlessElseTest
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'test_helper'
|
2
4
|
require 'timeout'
|
3
5
|
|
@@ -38,8 +40,8 @@ class TemplateTest < Minitest::Test
|
|
38
40
|
|
39
41
|
def test_instance_assigns_persist_on_same_template_object_between_parses
|
40
42
|
t = Template.new
|
41
|
-
assert_equal
|
42
|
-
assert_equal
|
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!)
|
43
45
|
end
|
44
46
|
|
45
47
|
def test_warnings_is_not_exponential_time
|
@@ -49,251 +51,243 @@ class TemplateTest < Minitest::Test
|
|
49
51
|
end
|
50
52
|
|
51
53
|
t = Template.parse(str)
|
52
|
-
assert_equal
|
54
|
+
assert_equal([], Timeout.timeout(1) { t.warnings })
|
53
55
|
end
|
54
56
|
|
55
57
|
def test_instance_assigns_persist_on_same_template_parsing_between_renders
|
56
58
|
t = Template.new.parse("{{ foo }}{% assign foo = 'foo' %}{{ foo }}")
|
57
|
-
assert_equal
|
58
|
-
assert_equal
|
59
|
+
assert_equal('foo', t.render!)
|
60
|
+
assert_equal('foofoo', t.render!)
|
59
61
|
end
|
60
62
|
|
61
63
|
def test_custom_assigns_do_not_persist_on_same_template
|
62
64
|
t = Template.new
|
63
|
-
assert_equal
|
64
|
-
assert_equal
|
65
|
+
assert_equal('from custom assigns', t.parse("{{ foo }}").render!('foo' => 'from custom assigns'))
|
66
|
+
assert_equal('', t.parse("{{ foo }}").render!)
|
65
67
|
end
|
66
68
|
|
67
69
|
def test_custom_assigns_squash_instance_assigns
|
68
70
|
t = Template.new
|
69
|
-
assert_equal
|
70
|
-
assert_equal
|
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'))
|
71
73
|
end
|
72
74
|
|
73
75
|
def test_persistent_assigns_squash_instance_assigns
|
74
76
|
t = Template.new
|
75
|
-
assert_equal
|
77
|
+
assert_equal('from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render!)
|
76
78
|
t.assigns['foo'] = 'from persistent assigns'
|
77
|
-
assert_equal
|
79
|
+
assert_equal('from persistent assigns', t.parse("{{ foo }}").render!)
|
78
80
|
end
|
79
81
|
|
80
82
|
def test_lambda_is_called_once_from_persistent_assigns_over_multiple_parses_and_renders
|
81
83
|
t = Template.new
|
82
|
-
t.assigns['number'] = -> {
|
83
|
-
|
84
|
-
|
85
|
-
|
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!)
|
86
91
|
@global = nil
|
87
92
|
end
|
88
93
|
|
89
94
|
def test_lambda_is_called_once_from_custom_assigns_over_multiple_parses_and_renders
|
90
95
|
t = Template.new
|
91
|
-
assigns = { 'number' => -> {
|
92
|
-
|
93
|
-
|
94
|
-
|
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))
|
95
103
|
@global = nil
|
96
104
|
end
|
97
105
|
|
98
106
|
def test_resource_limits_works_with_custom_length_method
|
99
107
|
t = Template.parse("{% assign foo = bar %}")
|
100
108
|
t.resource_limits.render_length_limit = 42
|
101
|
-
assert_equal
|
109
|
+
assert_equal("", t.render!("bar" => SomethingWithLength.new))
|
102
110
|
end
|
103
111
|
|
104
112
|
def test_resource_limits_render_length
|
105
113
|
t = Template.parse("0123456789")
|
106
|
-
t.resource_limits.render_length_limit =
|
107
|
-
assert_equal
|
108
|
-
assert
|
114
|
+
t.resource_limits.render_length_limit = 9
|
115
|
+
assert_equal("Liquid error: Memory limits exceeded", t.render)
|
116
|
+
assert(t.resource_limits.reached?)
|
109
117
|
|
110
118
|
t.resource_limits.render_length_limit = 10
|
111
|
-
assert_equal
|
112
|
-
refute_nil t.resource_limits.render_length
|
119
|
+
assert_equal("0123456789", t.render!)
|
113
120
|
end
|
114
121
|
|
115
122
|
def test_resource_limits_render_score
|
116
123
|
t = Template.parse("{% for a in (1..10) %} {% for a in (1..10) %} foo {% endfor %} {% endfor %}")
|
117
124
|
t.resource_limits.render_score_limit = 50
|
118
|
-
assert_equal
|
119
|
-
assert
|
125
|
+
assert_equal("Liquid error: Memory limits exceeded", t.render)
|
126
|
+
assert(t.resource_limits.reached?)
|
120
127
|
|
121
128
|
t = Template.parse("{% for a in (1..100) %} foo {% endfor %}")
|
122
129
|
t.resource_limits.render_score_limit = 50
|
123
|
-
assert_equal
|
124
|
-
assert
|
130
|
+
assert_equal("Liquid error: Memory limits exceeded", t.render)
|
131
|
+
assert(t.resource_limits.reached?)
|
125
132
|
|
126
133
|
t.resource_limits.render_score_limit = 200
|
127
|
-
assert_equal
|
128
|
-
refute_nil
|
129
|
-
end
|
130
|
-
|
131
|
-
def test_resource_limits_assign_score
|
132
|
-
t = Template.parse("{% assign foo = 42 %}{% assign bar = 23 %}")
|
133
|
-
t.resource_limits.assign_score_limit = 1
|
134
|
-
assert_equal "Liquid error: Memory limits exceeded", t.render
|
135
|
-
assert t.resource_limits.reached?
|
136
|
-
|
137
|
-
t.resource_limits.assign_score_limit = 2
|
138
|
-
assert_equal "", t.render!
|
139
|
-
refute_nil t.resource_limits.assign_score
|
140
|
-
end
|
141
|
-
|
142
|
-
def test_resource_limits_assign_score_nested
|
143
|
-
t = Template.parse("{% assign foo = 'aaaa' | reverse %}")
|
144
|
-
|
145
|
-
t.resource_limits.assign_score_limit = 3
|
146
|
-
assert_equal "Liquid error: Memory limits exceeded", t.render
|
147
|
-
assert t.resource_limits.reached?
|
148
|
-
|
149
|
-
t.resource_limits.assign_score_limit = 5
|
150
|
-
assert_equal "", t.render!
|
134
|
+
assert_equal((" foo " * 100), t.render!)
|
135
|
+
refute_nil(t.resource_limits.render_score)
|
151
136
|
end
|
152
137
|
|
153
138
|
def test_resource_limits_aborts_rendering_after_first_error
|
154
139
|
t = Template.parse("{% for a in (1..100) %} foo1 {% endfor %} bar {% for a in (1..100) %} foo2 {% endfor %}")
|
155
140
|
t.resource_limits.render_score_limit = 50
|
156
|
-
assert_equal
|
157
|
-
assert
|
141
|
+
assert_equal("Liquid error: Memory limits exceeded", t.render)
|
142
|
+
assert(t.resource_limits.reached?)
|
158
143
|
end
|
159
144
|
|
160
145
|
def test_resource_limits_hash_in_template_gets_updated_even_if_no_limits_are_set
|
161
|
-
t = Template.parse("{% for a in (1..100) %}
|
146
|
+
t = Template.parse("{% for a in (1..100) %}x{% assign foo = 1 %} {% endfor %}")
|
162
147
|
t.render!
|
163
|
-
assert
|
164
|
-
assert
|
165
|
-
assert t.resource_limits.render_length > 0
|
148
|
+
assert(t.resource_limits.assign_score > 0)
|
149
|
+
assert(t.resource_limits.render_score > 0)
|
166
150
|
end
|
167
151
|
|
168
152
|
def test_render_length_persists_between_blocks
|
169
153
|
t = Template.parse("{% if true %}aaaa{% endif %}")
|
170
|
-
t.resource_limits.render_length_limit =
|
171
|
-
assert_equal
|
172
|
-
t.resource_limits.render_length_limit =
|
173
|
-
assert_equal
|
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)
|
174
158
|
|
175
159
|
t = Template.parse("{% if true %}aaaa{% endif %}{% if true %}bbb{% endif %}")
|
176
|
-
t.resource_limits.render_length_limit =
|
177
|
-
assert_equal
|
178
|
-
t.resource_limits.render_length_limit =
|
179
|
-
assert_equal
|
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)
|
180
164
|
|
181
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 %}")
|
182
166
|
t.resource_limits.render_length_limit = 5
|
183
|
-
assert_equal
|
184
|
-
t.resource_limits.render_length_limit =
|
185
|
-
assert_equal
|
186
|
-
|
187
|
-
|
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)
|
188
178
|
end
|
189
179
|
|
190
180
|
def test_default_resource_limits_unaffected_by_render_with_context
|
191
181
|
context = Context.new
|
192
|
-
t = Template.parse("{% for a in (1..100) %}
|
182
|
+
t = Template.parse("{% for a in (1..100) %}x{% assign foo = 1 %} {% endfor %}")
|
193
183
|
t.render!(context)
|
194
|
-
assert
|
195
|
-
assert
|
196
|
-
assert context.resource_limits.render_length > 0
|
184
|
+
assert(context.resource_limits.assign_score > 0)
|
185
|
+
assert(context.resource_limits.render_score > 0)
|
197
186
|
end
|
198
187
|
|
199
188
|
def test_can_use_drop_as_context
|
200
189
|
t = Template.new
|
201
190
|
t.registers['lulz'] = 'haha'
|
202
191
|
drop = TemplateContextDrop.new
|
203
|
-
assert_equal
|
204
|
-
assert_equal
|
205
|
-
assert_equal
|
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))
|
206
195
|
end
|
207
196
|
|
208
197
|
def test_render_bang_force_rethrow_errors_on_passed_context
|
209
|
-
context = Context.new(
|
198
|
+
context = Context.new('drop' => ErroneousDrop.new)
|
210
199
|
t = Template.new.parse('{{ drop.bad_method }}')
|
211
200
|
|
212
|
-
e = assert_raises
|
201
|
+
e = assert_raises(RuntimeError) do
|
213
202
|
t.render!(context)
|
214
203
|
end
|
215
|
-
assert_equal
|
204
|
+
assert_equal('ruby error in drop', e.message)
|
216
205
|
end
|
217
206
|
|
218
207
|
def test_exception_renderer_that_returns_string
|
219
208
|
exception = nil
|
220
|
-
handler
|
209
|
+
handler = ->(e) {
|
210
|
+
exception = e
|
211
|
+
'<!-- error -->'
|
212
|
+
}
|
221
213
|
|
222
214
|
output = Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_renderer: handler)
|
223
215
|
|
224
|
-
assert
|
225
|
-
assert_equal
|
216
|
+
assert(exception.is_a?(Liquid::ZeroDivisionError))
|
217
|
+
assert_equal('<!-- error -->', output)
|
226
218
|
end
|
227
219
|
|
228
220
|
def test_exception_renderer_that_raises
|
229
221
|
exception = nil
|
230
222
|
assert_raises(Liquid::ZeroDivisionError) do
|
231
|
-
Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_renderer: ->(e) {
|
223
|
+
Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_renderer: ->(e) {
|
224
|
+
exception = e
|
225
|
+
raise
|
226
|
+
})
|
232
227
|
end
|
233
|
-
assert
|
228
|
+
assert(exception.is_a?(Liquid::ZeroDivisionError))
|
234
229
|
end
|
235
230
|
|
236
231
|
def test_global_filter_option_on_render
|
237
232
|
global_filter_proc = ->(output) { "#{output} filtered" }
|
238
|
-
rendered_template
|
233
|
+
rendered_template = Template.parse("{{name}}").render({ "name" => "bob" }, global_filter: global_filter_proc)
|
239
234
|
|
240
|
-
assert_equal
|
235
|
+
assert_equal('bob filtered', rendered_template)
|
241
236
|
end
|
242
237
|
|
243
238
|
def test_global_filter_option_when_native_filters_exist
|
244
239
|
global_filter_proc = ->(output) { "#{output} filtered" }
|
245
|
-
rendered_template
|
240
|
+
rendered_template = Template.parse("{{name | upcase}}").render({ "name" => "bob" }, global_filter: global_filter_proc)
|
246
241
|
|
247
|
-
assert_equal
|
242
|
+
assert_equal('BOB filtered', rendered_template)
|
248
243
|
end
|
249
244
|
|
250
245
|
def test_undefined_variables
|
251
|
-
t
|
252
|
-
result = t.render({ 'x' => 33, 'z' => { 'a' => 32, 'c' => { 'e' => 31 } } },
|
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)
|
253
248
|
|
254
|
-
assert_equal
|
255
|
-
assert_equal
|
256
|
-
assert_instance_of
|
257
|
-
assert_equal
|
258
|
-
assert_instance_of
|
259
|
-
assert_equal
|
260
|
-
assert_instance_of
|
261
|
-
assert_equal
|
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)
|
262
257
|
end
|
263
258
|
|
264
259
|
def test_nil_value_does_not_raise
|
265
|
-
|
266
|
-
t = Template.parse("some{{x}}thing")
|
260
|
+
t = Template.parse("some{{x}}thing", error_mode: :strict)
|
267
261
|
result = t.render!({ 'x' => nil }, strict_variables: true)
|
268
262
|
|
269
|
-
assert_equal
|
270
|
-
assert_equal
|
263
|
+
assert_equal(0, t.errors.count)
|
264
|
+
assert_equal('something', result)
|
271
265
|
end
|
272
266
|
|
273
267
|
def test_undefined_variables_raise
|
274
268
|
t = Template.parse("{{x}} {{y}} {{z.a}} {{z.b}} {{z.c.d}}")
|
275
269
|
|
276
|
-
assert_raises
|
277
|
-
t.render!({ 'x' => 33, 'z' => { 'a' => 32, 'c' => { 'e' => 31 } } },
|
270
|
+
assert_raises(UndefinedVariable) do
|
271
|
+
t.render!({ 'x' => 33, 'z' => { 'a' => 32, 'c' => { 'e' => 31 } } }, strict_variables: true)
|
278
272
|
end
|
279
273
|
end
|
280
274
|
|
281
275
|
def test_undefined_drop_methods
|
282
276
|
d = DropWithUndefinedMethod.new
|
283
277
|
t = Template.new.parse('{{ foo }} {{ woot }}')
|
284
|
-
result = t.render(d,
|
278
|
+
result = t.render(d, strict_variables: true)
|
285
279
|
|
286
|
-
assert_equal
|
287
|
-
assert_equal
|
288
|
-
assert_instance_of
|
280
|
+
assert_equal('foo ', result)
|
281
|
+
assert_equal(1, t.errors.count)
|
282
|
+
assert_instance_of(Liquid::UndefinedDropMethod, t.errors[0])
|
289
283
|
end
|
290
284
|
|
291
285
|
def test_undefined_drop_methods_raise
|
292
286
|
d = DropWithUndefinedMethod.new
|
293
287
|
t = Template.new.parse('{{ foo }} {{ woot }}')
|
294
288
|
|
295
|
-
assert_raises
|
296
|
-
t.render!(d,
|
289
|
+
assert_raises(UndefinedDropMethod) do
|
290
|
+
t.render!(d, strict_variables: true)
|
297
291
|
end
|
298
292
|
end
|
299
293
|
|
@@ -304,29 +298,43 @@ class TemplateTest < Minitest::Test
|
|
304
298
|
"-#{v}-"
|
305
299
|
end
|
306
300
|
end
|
307
|
-
result = t.render({ 'a' => 123, 'x' => 'foo' },
|
301
|
+
result = t.render({ 'a' => 123, 'x' => 'foo' }, filters: [filters], strict_filters: true)
|
308
302
|
|
309
|
-
assert_equal
|
310
|
-
assert_equal
|
311
|
-
assert_instance_of
|
312
|
-
assert_equal
|
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)
|
313
307
|
end
|
314
308
|
|
315
309
|
def test_undefined_filters_raise
|
316
310
|
t = Template.parse("{{x | somefilter1 | upcase | somefilter2}}")
|
317
311
|
|
318
|
-
assert_raises
|
319
|
-
t.render!({ 'x' => 'foo' },
|
312
|
+
assert_raises(UndefinedFilter) do
|
313
|
+
t.render!({ 'x' => 'foo' }, strict_filters: true)
|
320
314
|
end
|
321
315
|
end
|
322
316
|
|
323
317
|
def test_using_range_literal_works_as_expected
|
324
318
|
t = Template.parse("{% assign foo = (x..y) %}{{ foo }}")
|
325
|
-
result = t.render(
|
326
|
-
assert_equal
|
319
|
+
result = t.render('x' => 1, 'y' => 5)
|
320
|
+
assert_equal('1..5', result)
|
327
321
|
|
328
322
|
t = Template.parse("{% assign nums = (x..y) %}{% for num in nums %}{{ num }}{% endfor %}")
|
329
|
-
result = t.render(
|
330
|
-
assert_equal
|
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)
|
331
339
|
end
|
332
340
|
end
|