liquid 4.0.0.rc3 → 5.0.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 +5 -5
- data/History.md +93 -2
- data/README.md +8 -0
- data/lib/liquid.rb +18 -5
- data/lib/liquid/block.rb +47 -20
- data/lib/liquid/block_body.rb +190 -76
- data/lib/liquid/condition.rb +69 -29
- data/lib/liquid/context.rb +122 -76
- data/lib/liquid/document.rb +47 -9
- data/lib/liquid/drop.rb +4 -2
- data/lib/liquid/errors.rb +20 -25
- data/lib/liquid/expression.rb +30 -31
- data/lib/liquid/extensions.rb +8 -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 +35 -26
- data/lib/liquid/locales/en.yml +4 -2
- data/lib/liquid/parse_context.rb +17 -4
- data/lib/liquid/parse_tree_visitor.rb +42 -0
- 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.rb +67 -86
- data/lib/liquid/profiler/hooks.rb +26 -14
- data/lib/liquid/range_lookup.rb +5 -3
- data/lib/liquid/register.rb +6 -0
- data/lib/liquid/resource_limits.rb +47 -8
- data/lib/liquid/standardfilters.rb +171 -57
- 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.rb +28 -6
- data/lib/liquid/tag/disableable.rb +22 -0
- data/lib/liquid/tag/disabler.rb +21 -0
- data/lib/liquid/tags/assign.rb +32 -10
- data/lib/liquid/tags/break.rb +8 -3
- data/lib/liquid/tags/capture.rb +11 -8
- data/lib/liquid/tags/case.rb +41 -27
- data/lib/liquid/tags/comment.rb +5 -3
- data/lib/liquid/tags/continue.rb +8 -3
- data/lib/liquid/tags/cycle.rb +35 -16
- data/lib/liquid/tags/decrement.rb +6 -3
- data/lib/liquid/tags/echo.rb +26 -0
- data/lib/liquid/tags/for.rb +79 -47
- data/lib/liquid/tags/if.rb +53 -30
- data/lib/liquid/tags/ifchanged.rb +11 -10
- data/lib/liquid/tags/include.rb +42 -44
- 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 +32 -20
- data/lib/liquid/tags/unless.rb +15 -15
- data/lib/liquid/template.rb +60 -71
- data/lib/liquid/template_factory.rb +9 -0
- data/lib/liquid/tokenizer.rb +17 -9
- data/lib/liquid/usage.rb +8 -0
- data/lib/liquid/utils.rb +6 -4
- data/lib/liquid/variable.rb +55 -38
- data/lib/liquid/variable_lookup.rb +14 -6
- data/lib/liquid/version.rb +3 -1
- data/test/integration/assign_test.rb +74 -5
- data/test/integration/blank_test.rb +11 -8
- data/test/integration/block_test.rb +58 -0
- data/test/integration/capture_test.rb +18 -10
- data/test/integration/context_test.rb +608 -5
- data/test/integration/document_test.rb +4 -2
- data/test/integration/drop_test.rb +67 -83
- data/test/integration/error_handling_test.rb +90 -60
- 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 +24 -8
- data/test/integration/{render_profiling_test.rb → profiler_test.rb} +84 -25
- data/test/integration/security_test.rb +41 -18
- data/test/integration/standard_filter_test.rb +523 -205
- 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 +109 -53
- data/test/integration/tags/if_else_tag_test.rb +5 -3
- data/test/integration/tags/include_tag_test.rb +83 -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 +128 -121
- data/test/integration/trim_mode_test.rb +82 -44
- data/test/integration/variable_test.rb +46 -31
- data/test/test_helper.rb +75 -23
- data/test/unit/block_unit_test.rb +19 -24
- data/test/unit/condition_unit_test.rb +82 -72
- 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 +12 -10
- data/test/unit/parse_tree_visitor_test.rb +247 -0
- 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 +19 -17
- data/test/unit/variable_unit_test.rb +51 -49
- metadata +83 -50
- data/lib/liquid/strainer.rb +0 -65
- data/test/unit/context_unit_test.rb +0 -483
- data/test/unit/strainer_unit_test.rb +0 -136
@@ -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,238 +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
|
-
def
|
207
|
+
def test_exception_renderer_that_returns_string
|
219
208
|
exception = nil
|
220
|
-
|
221
|
-
|
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)
|
222
218
|
end
|
223
219
|
|
224
|
-
def
|
220
|
+
def test_exception_renderer_that_raises
|
225
221
|
exception = nil
|
226
222
|
assert_raises(Liquid::ZeroDivisionError) do
|
227
|
-
Template.parse("{{ 1 | divided_by: 0 }}").render({},
|
223
|
+
Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_renderer: ->(e) {
|
224
|
+
exception = e
|
225
|
+
raise
|
226
|
+
})
|
228
227
|
end
|
229
|
-
assert
|
228
|
+
assert(exception.is_a?(Liquid::ZeroDivisionError))
|
230
229
|
end
|
231
230
|
|
232
231
|
def test_global_filter_option_on_render
|
233
232
|
global_filter_proc = ->(output) { "#{output} filtered" }
|
234
|
-
rendered_template
|
233
|
+
rendered_template = Template.parse("{{name}}").render({ "name" => "bob" }, global_filter: global_filter_proc)
|
235
234
|
|
236
|
-
assert_equal
|
235
|
+
assert_equal('bob filtered', rendered_template)
|
237
236
|
end
|
238
237
|
|
239
238
|
def test_global_filter_option_when_native_filters_exist
|
240
239
|
global_filter_proc = ->(output) { "#{output} filtered" }
|
241
|
-
rendered_template
|
240
|
+
rendered_template = Template.parse("{{name | upcase}}").render({ "name" => "bob" }, global_filter: global_filter_proc)
|
242
241
|
|
243
|
-
assert_equal
|
242
|
+
assert_equal('BOB filtered', rendered_template)
|
244
243
|
end
|
245
244
|
|
246
245
|
def test_undefined_variables
|
247
|
-
t
|
248
|
-
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)
|
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)
|
249
262
|
|
250
|
-
assert_equal
|
251
|
-
assert_equal
|
252
|
-
assert_instance_of Liquid::UndefinedVariable, t.errors[0]
|
253
|
-
assert_equal 'Liquid error: undefined variable y', t.errors[0].message
|
254
|
-
assert_instance_of Liquid::UndefinedVariable, t.errors[1]
|
255
|
-
assert_equal 'Liquid error: undefined variable b', t.errors[1].message
|
256
|
-
assert_instance_of Liquid::UndefinedVariable, t.errors[2]
|
257
|
-
assert_equal 'Liquid error: undefined variable d', t.errors[2].message
|
263
|
+
assert_equal(0, t.errors.count)
|
264
|
+
assert_equal('something', result)
|
258
265
|
end
|
259
266
|
|
260
267
|
def test_undefined_variables_raise
|
261
268
|
t = Template.parse("{{x}} {{y}} {{z.a}} {{z.b}} {{z.c.d}}")
|
262
269
|
|
263
|
-
assert_raises
|
264
|
-
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)
|
265
272
|
end
|
266
273
|
end
|
267
274
|
|
268
275
|
def test_undefined_drop_methods
|
269
276
|
d = DropWithUndefinedMethod.new
|
270
277
|
t = Template.new.parse('{{ foo }} {{ woot }}')
|
271
|
-
result = t.render(d,
|
278
|
+
result = t.render(d, strict_variables: true)
|
272
279
|
|
273
|
-
assert_equal
|
274
|
-
assert_equal
|
275
|
-
assert_instance_of
|
280
|
+
assert_equal('foo ', result)
|
281
|
+
assert_equal(1, t.errors.count)
|
282
|
+
assert_instance_of(Liquid::UndefinedDropMethod, t.errors[0])
|
276
283
|
end
|
277
284
|
|
278
285
|
def test_undefined_drop_methods_raise
|
279
286
|
d = DropWithUndefinedMethod.new
|
280
287
|
t = Template.new.parse('{{ foo }} {{ woot }}')
|
281
288
|
|
282
|
-
assert_raises
|
283
|
-
t.render!(d,
|
289
|
+
assert_raises(UndefinedDropMethod) do
|
290
|
+
t.render!(d, strict_variables: true)
|
284
291
|
end
|
285
292
|
end
|
286
293
|
|
@@ -291,29 +298,29 @@ class TemplateTest < Minitest::Test
|
|
291
298
|
"-#{v}-"
|
292
299
|
end
|
293
300
|
end
|
294
|
-
result = t.render({ 'a' => 123, 'x' => 'foo' },
|
301
|
+
result = t.render({ 'a' => 123, 'x' => 'foo' }, filters: [filters], strict_filters: true)
|
295
302
|
|
296
|
-
assert_equal
|
297
|
-
assert_equal
|
298
|
-
assert_instance_of
|
299
|
-
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)
|
300
307
|
end
|
301
308
|
|
302
309
|
def test_undefined_filters_raise
|
303
310
|
t = Template.parse("{{x | somefilter1 | upcase | somefilter2}}")
|
304
311
|
|
305
|
-
assert_raises
|
306
|
-
t.render!({ 'x' => 'foo' },
|
312
|
+
assert_raises(UndefinedFilter) do
|
313
|
+
t.render!({ 'x' => 'foo' }, strict_filters: true)
|
307
314
|
end
|
308
315
|
end
|
309
316
|
|
310
317
|
def test_using_range_literal_works_as_expected
|
311
318
|
t = Template.parse("{% assign foo = (x..y) %}{{ foo }}")
|
312
|
-
result = t.render(
|
313
|
-
assert_equal
|
319
|
+
result = t.render('x' => 1, 'y' => 5)
|
320
|
+
assert_equal('1..5', result)
|
314
321
|
|
315
322
|
t = Template.parse("{% assign nums = (x..y) %}{% for num in nums %}{{ num }}{% endfor %}")
|
316
|
-
result = t.render(
|
317
|
-
assert_equal
|
323
|
+
result = t.render('x' => 1, 'y' => 5)
|
324
|
+
assert_equal('12345', result)
|
318
325
|
end
|
319
326
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'test_helper'
|
2
4
|
|
3
5
|
class TrimModeTest < Minitest::Test
|
@@ -67,7 +69,7 @@ class TrimModeTest < Minitest::Test
|
|
67
69
|
# Make sure the trim isn't applied to standard tags
|
68
70
|
def test_standard_tags
|
69
71
|
whitespace = ' '
|
70
|
-
text
|
72
|
+
text = <<-END_TEMPLATE
|
71
73
|
<div>
|
72
74
|
<p>
|
73
75
|
{% if true %}
|
@@ -76,14 +78,14 @@ class TrimModeTest < Minitest::Test
|
|
76
78
|
</p>
|
77
79
|
</div>
|
78
80
|
END_TEMPLATE
|
79
|
-
expected =
|
80
|
-
|
81
|
-
|
82
|
-
#{whitespace}
|
83
|
-
|
84
|
-
#{whitespace}
|
85
|
-
|
86
|
-
|
81
|
+
expected = <<~END_EXPECTED
|
82
|
+
<div>
|
83
|
+
<p>
|
84
|
+
#{whitespace}
|
85
|
+
yes
|
86
|
+
#{whitespace}
|
87
|
+
</p>
|
88
|
+
</div>
|
87
89
|
END_EXPECTED
|
88
90
|
assert_template_result(expected, text)
|
89
91
|
|
@@ -96,70 +98,70 @@ class TrimModeTest < Minitest::Test
|
|
96
98
|
</p>
|
97
99
|
</div>
|
98
100
|
END_TEMPLATE
|
99
|
-
expected =
|
100
|
-
|
101
|
-
|
102
|
-
#{whitespace}
|
103
|
-
|
104
|
-
|
101
|
+
expected = <<~END_EXPECTED
|
102
|
+
<div>
|
103
|
+
<p>
|
104
|
+
#{whitespace}
|
105
|
+
</p>
|
106
|
+
</div>
|
105
107
|
END_EXPECTED
|
106
108
|
assert_template_result(expected, text)
|
107
109
|
end
|
108
110
|
|
109
111
|
# Make sure the trim isn't too agressive
|
110
112
|
def test_no_trim_output
|
111
|
-
text
|
113
|
+
text = '<p>{{- \'John\' -}}</p>'
|
112
114
|
expected = '<p>John</p>'
|
113
115
|
assert_template_result(expected, text)
|
114
116
|
end
|
115
117
|
|
116
118
|
# Make sure the trim isn't too agressive
|
117
119
|
def test_no_trim_tags
|
118
|
-
text
|
120
|
+
text = '<p>{%- if true -%}yes{%- endif -%}</p>'
|
119
121
|
expected = '<p>yes</p>'
|
120
122
|
assert_template_result(expected, text)
|
121
123
|
|
122
|
-
text
|
124
|
+
text = '<p>{%- if false -%}no{%- endif -%}</p>'
|
123
125
|
expected = '<p></p>'
|
124
126
|
assert_template_result(expected, text)
|
125
127
|
end
|
126
128
|
|
127
129
|
def test_single_line_outer_tag
|
128
|
-
text
|
130
|
+
text = '<p> {%- if true %} yes {% endif -%} </p>'
|
129
131
|
expected = '<p> yes </p>'
|
130
132
|
assert_template_result(expected, text)
|
131
133
|
|
132
|
-
text
|
134
|
+
text = '<p> {%- if false %} no {% endif -%} </p>'
|
133
135
|
expected = '<p></p>'
|
134
136
|
assert_template_result(expected, text)
|
135
137
|
end
|
136
138
|
|
137
139
|
def test_single_line_inner_tag
|
138
|
-
text
|
140
|
+
text = '<p> {% if true -%} yes {%- endif %} </p>'
|
139
141
|
expected = '<p> yes </p>'
|
140
142
|
assert_template_result(expected, text)
|
141
143
|
|
142
|
-
text
|
144
|
+
text = '<p> {% if false -%} no {%- endif %} </p>'
|
143
145
|
expected = '<p> </p>'
|
144
146
|
assert_template_result(expected, text)
|
145
147
|
end
|
146
148
|
|
147
149
|
def test_single_line_post_tag
|
148
|
-
text
|
150
|
+
text = '<p> {% if true -%} yes {% endif -%} </p>'
|
149
151
|
expected = '<p> yes </p>'
|
150
152
|
assert_template_result(expected, text)
|
151
153
|
|
152
|
-
text
|
154
|
+
text = '<p> {% if false -%} no {% endif -%} </p>'
|
153
155
|
expected = '<p> </p>'
|
154
156
|
assert_template_result(expected, text)
|
155
157
|
end
|
156
158
|
|
157
159
|
def test_single_line_pre_tag
|
158
|
-
text
|
160
|
+
text = '<p> {%- if true %} yes {%- endif %} </p>'
|
159
161
|
expected = '<p> yes </p>'
|
160
162
|
assert_template_result(expected, text)
|
161
163
|
|
162
|
-
text
|
164
|
+
text = '<p> {%- if false %} no {%- endif %} </p>'
|
163
165
|
expected = '<p> </p>'
|
164
166
|
assert_template_result(expected, text)
|
165
167
|
end
|
@@ -328,7 +330,7 @@ class TrimModeTest < Minitest::Test
|
|
328
330
|
assert_template_result(expected, text)
|
329
331
|
|
330
332
|
whitespace = ' '
|
331
|
-
text
|
333
|
+
text = <<-END_TEMPLATE
|
332
334
|
<div>
|
333
335
|
<p>
|
334
336
|
{% if false -%}
|
@@ -337,12 +339,12 @@ class TrimModeTest < Minitest::Test
|
|
337
339
|
</p>
|
338
340
|
</div>
|
339
341
|
END_TEMPLATE
|
340
|
-
expected =
|
341
|
-
|
342
|
-
|
343
|
-
#{whitespace}
|
344
|
-
|
345
|
-
|
342
|
+
expected = <<~END_EXPECTED
|
343
|
+
<div>
|
344
|
+
<p>
|
345
|
+
#{whitespace}
|
346
|
+
</p>
|
347
|
+
</div>
|
346
348
|
END_EXPECTED
|
347
349
|
assert_template_result(expected, text)
|
348
350
|
end
|
@@ -496,9 +498,13 @@ class TrimModeTest < Minitest::Test
|
|
496
498
|
assert_template_result(expected, text)
|
497
499
|
end
|
498
500
|
|
501
|
+
def test_right_trim_followed_by_tag
|
502
|
+
assert_template_result('ab c', '{{ "a" -}}{{ "b" }} c')
|
503
|
+
end
|
504
|
+
|
499
505
|
def test_raw_output
|
500
506
|
whitespace = ' '
|
501
|
-
text
|
507
|
+
text = <<-END_TEMPLATE
|
502
508
|
<div>
|
503
509
|
{% raw %}
|
504
510
|
{%- if true -%}
|
@@ -509,17 +515,49 @@ class TrimModeTest < Minitest::Test
|
|
509
515
|
{% endraw %}
|
510
516
|
</div>
|
511
517
|
END_TEMPLATE
|
512
|
-
expected =
|
513
|
-
|
514
|
-
#{whitespace}
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
#{whitespace}
|
521
|
-
|
518
|
+
expected = <<~END_EXPECTED
|
519
|
+
<div>
|
520
|
+
#{whitespace}
|
521
|
+
{%- if true -%}
|
522
|
+
<p>
|
523
|
+
{{- 'John' -}}
|
524
|
+
</p>
|
525
|
+
{%- endif -%}
|
526
|
+
#{whitespace}
|
527
|
+
</div>
|
522
528
|
END_EXPECTED
|
523
529
|
assert_template_result(expected, text)
|
524
530
|
end
|
531
|
+
|
532
|
+
def test_pre_trim_blank_preceding_text
|
533
|
+
template = Liquid::Template.parse("\n{%- raw %}{% endraw %}")
|
534
|
+
assert_equal("", template.render)
|
535
|
+
|
536
|
+
template = Liquid::Template.parse("\n{%- if true %}{% endif %}")
|
537
|
+
assert_equal("", template.render)
|
538
|
+
|
539
|
+
template = Liquid::Template.parse("{{ 'B' }} \n{%- if true %}C{% endif %}")
|
540
|
+
assert_equal("BC", template.render)
|
541
|
+
end
|
542
|
+
|
543
|
+
def test_bug_compatible_pre_trim
|
544
|
+
template = Liquid::Template.parse("\n {%- raw %}{% endraw %}", bug_compatible_whitespace_trimming: true)
|
545
|
+
assert_equal("\n", template.render)
|
546
|
+
|
547
|
+
template = Liquid::Template.parse("\n {%- if true %}{% endif %}", bug_compatible_whitespace_trimming: true)
|
548
|
+
assert_equal("\n", template.render)
|
549
|
+
|
550
|
+
template = Liquid::Template.parse("{{ 'B' }} \n{%- if true %}C{% endif %}", bug_compatible_whitespace_trimming: true)
|
551
|
+
assert_equal("B C", template.render)
|
552
|
+
|
553
|
+
template = Liquid::Template.parse("B\n {%- raw %}{% endraw %}", bug_compatible_whitespace_trimming: true)
|
554
|
+
assert_equal("B", template.render)
|
555
|
+
|
556
|
+
template = Liquid::Template.parse("B\n {%- if true %}{% endif %}", bug_compatible_whitespace_trimming: true)
|
557
|
+
assert_equal("B", template.render)
|
558
|
+
end
|
559
|
+
|
560
|
+
def test_trim_blank
|
561
|
+
assert_template_result('foobar', 'foo {{-}} bar')
|
562
|
+
end
|
525
563
|
end # TrimModeTest
|