liquid 3.0.6 → 4.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +89 -58
- data/{MIT-LICENSE → LICENSE} +0 -0
- data/lib/liquid.rb +7 -6
- data/lib/liquid/block.rb +31 -124
- data/lib/liquid/block_body.rb +54 -57
- data/lib/liquid/condition.rb +23 -22
- data/lib/liquid/context.rb +50 -42
- data/lib/liquid/document.rb +19 -9
- data/lib/liquid/drop.rb +12 -13
- data/lib/liquid/errors.rb +16 -17
- data/lib/liquid/expression.rb +15 -3
- data/lib/liquid/extensions.rb +7 -7
- data/lib/liquid/file_system.rb +3 -3
- data/lib/liquid/forloop_drop.rb +42 -0
- data/lib/liquid/i18n.rb +5 -5
- data/lib/liquid/interrupts.rb +1 -2
- data/lib/liquid/lexer.rb +6 -4
- data/lib/liquid/locales/en.yml +3 -1
- data/lib/liquid/parse_context.rb +37 -0
- data/lib/liquid/parser_switching.rb +4 -4
- data/lib/liquid/profiler.rb +18 -19
- data/lib/liquid/profiler/hooks.rb +7 -7
- data/lib/liquid/range_lookup.rb +16 -1
- data/lib/liquid/resource_limits.rb +23 -0
- data/lib/liquid/standardfilters.rb +101 -56
- data/lib/liquid/strainer.rb +4 -5
- data/lib/liquid/tablerowloop_drop.rb +62 -0
- data/lib/liquid/tag.rb +9 -8
- data/lib/liquid/tags/assign.rb +5 -4
- data/lib/liquid/tags/break.rb +0 -3
- data/lib/liquid/tags/capture.rb +1 -1
- data/lib/liquid/tags/case.rb +19 -12
- data/lib/liquid/tags/comment.rb +2 -2
- data/lib/liquid/tags/cycle.rb +6 -6
- data/lib/liquid/tags/decrement.rb +1 -4
- data/lib/liquid/tags/for.rb +93 -75
- data/lib/liquid/tags/if.rb +49 -44
- data/lib/liquid/tags/ifchanged.rb +0 -2
- data/lib/liquid/tags/include.rb +60 -52
- data/lib/liquid/tags/raw.rb +26 -4
- data/lib/liquid/tags/table_row.rb +12 -30
- data/lib/liquid/tags/unless.rb +3 -4
- data/lib/liquid/template.rb +23 -50
- data/lib/liquid/tokenizer.rb +31 -0
- data/lib/liquid/utils.rb +48 -8
- data/lib/liquid/variable.rb +46 -45
- data/lib/liquid/variable_lookup.rb +3 -3
- data/lib/liquid/version.rb +1 -1
- data/test/integration/assign_test.rb +8 -8
- data/test/integration/blank_test.rb +14 -14
- data/test/integration/context_test.rb +2 -2
- data/test/integration/document_test.rb +19 -0
- data/test/integration/drop_test.rb +42 -40
- data/test/integration/error_handling_test.rb +64 -45
- data/test/integration/filter_test.rb +60 -20
- data/test/integration/output_test.rb +26 -27
- data/test/integration/parsing_quirks_test.rb +15 -13
- data/test/integration/render_profiling_test.rb +20 -20
- data/test/integration/security_test.rb +5 -7
- data/test/integration/standard_filter_test.rb +119 -37
- data/test/integration/tags/break_tag_test.rb +1 -2
- data/test/integration/tags/continue_tag_test.rb +0 -1
- data/test/integration/tags/for_tag_test.rb +133 -98
- data/test/integration/tags/if_else_tag_test.rb +75 -77
- data/test/integration/tags/include_tag_test.rb +23 -30
- data/test/integration/tags/increment_tag_test.rb +10 -11
- data/test/integration/tags/raw_tag_test.rb +7 -1
- data/test/integration/tags/standard_tag_test.rb +121 -122
- data/test/integration/tags/statements_test.rb +3 -5
- data/test/integration/tags/table_row_test.rb +20 -19
- data/test/integration/tags/unless_else_tag_test.rb +6 -6
- data/test/integration/template_test.rb +91 -45
- data/test/integration/variable_test.rb +23 -13
- data/test/test_helper.rb +33 -5
- data/test/unit/block_unit_test.rb +6 -5
- data/test/unit/condition_unit_test.rb +82 -77
- data/test/unit/context_unit_test.rb +48 -57
- data/test/unit/file_system_unit_test.rb +3 -3
- data/test/unit/i18n_unit_test.rb +2 -2
- data/test/unit/lexer_unit_test.rb +11 -8
- data/test/unit/parser_unit_test.rb +2 -2
- data/test/unit/regexp_unit_test.rb +1 -1
- data/test/unit/strainer_unit_test.rb +13 -2
- data/test/unit/tag_unit_test.rb +7 -2
- data/test/unit/tags/case_tag_unit_test.rb +1 -1
- data/test/unit/tags/for_tag_unit_test.rb +2 -2
- data/test/unit/tags/if_tag_unit_test.rb +1 -1
- data/test/unit/template_unit_test.rb +6 -5
- data/test/unit/tokenizer_unit_test.rb +24 -7
- data/test/unit/variable_unit_test.rb +60 -43
- metadata +44 -41
- data/lib/liquid/module_ex.rb +0 -62
- data/lib/liquid/token.rb +0 -18
- data/test/unit/module_ex_unit_test.rb +0 -87
@@ -37,7 +37,6 @@ class StatementsTest < Minitest::Test
|
|
37
37
|
text = ' {% if null <= 0 %} true {% else %} false {% endif %} '
|
38
38
|
assert_template_result ' false ', text
|
39
39
|
|
40
|
-
|
41
40
|
text = ' {% if 0 <= null %} true {% else %} false {% endif %} '
|
42
41
|
assert_template_result ' false ', text
|
43
42
|
end
|
@@ -72,18 +71,17 @@ class StatementsTest < Minitest::Test
|
|
72
71
|
assert_template_result ' true ', text, 'var' => 'hello there!'
|
73
72
|
end
|
74
73
|
|
75
|
-
|
76
74
|
def test_var_and_long_string_are_equal_backwards
|
77
75
|
text = " {% if 'hello there!' == var %} true {% else %} false {% endif %} "
|
78
76
|
assert_template_result ' true ', text, 'var' => 'hello there!'
|
79
77
|
end
|
80
78
|
|
81
|
-
#def test_is_nil
|
79
|
+
# def test_is_nil
|
82
80
|
# text = %| {% if var != nil %} true {% else %} false {% end %} |
|
83
81
|
# @template.assigns = { 'var' => 'hello there!'}
|
84
82
|
# expected = %| true |
|
85
83
|
# assert_equal expected, @template.parse(text)
|
86
|
-
#end
|
84
|
+
# end
|
87
85
|
|
88
86
|
def test_is_collection_empty
|
89
87
|
text = ' {% if array == empty %} true {% else %} false {% endif %} '
|
@@ -92,7 +90,7 @@ class StatementsTest < Minitest::Test
|
|
92
90
|
|
93
91
|
def test_is_not_collection_empty
|
94
92
|
text = ' {% if array == empty %} true {% else %} false {% endif %} '
|
95
|
-
assert_template_result ' false ', text, 'array' => [1,2,3]
|
93
|
+
assert_template_result ' false ', text, 'array' => [1, 2, 3]
|
96
94
|
end
|
97
95
|
|
98
96
|
def test_nil
|
@@ -16,48 +16,49 @@ class TableRowTest < Minitest::Test
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def test_table_row
|
19
|
-
|
20
19
|
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",
|
21
|
-
|
22
|
-
|
20
|
+
'{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
|
21
|
+
'numbers' => [1, 2, 3, 4, 5, 6])
|
23
22
|
|
24
23
|
assert_template_result("<tr class=\"row1\">\n</tr>\n",
|
25
|
-
|
26
|
-
|
24
|
+
'{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
|
25
|
+
'numbers' => [])
|
27
26
|
end
|
28
27
|
|
29
28
|
def test_table_row_with_different_cols
|
30
29
|
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",
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
'{% tablerow n in numbers cols:5%} {{n}} {% endtablerow %}',
|
31
|
+
'numbers' => [1, 2, 3, 4, 5, 6])
|
34
32
|
end
|
35
33
|
|
36
34
|
def test_table_col_counter
|
37
35
|
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
|
-
|
39
|
-
|
36
|
+
'{% tablerow n in numbers cols:2%}{{tablerowloop.col}}{% endtablerow %}',
|
37
|
+
'numbers' => [1, 2, 3, 4, 5, 6])
|
40
38
|
end
|
41
39
|
|
42
40
|
def test_quoted_fragment
|
43
41
|
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
|
-
|
45
|
-
|
42
|
+
"{% tablerow n in collections.frontpage cols:3%} {{n}} {% endtablerow %}",
|
43
|
+
'collections' => { 'frontpage' => [1, 2, 3, 4, 5, 6] })
|
46
44
|
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
|
-
|
48
|
-
|
49
|
-
|
45
|
+
"{% tablerow n in collections['frontpage'] cols:3%} {{n}} {% endtablerow %}",
|
46
|
+
'collections' => { 'frontpage' => [1, 2, 3, 4, 5, 6] })
|
50
47
|
end
|
51
48
|
|
52
49
|
def test_enumerable_drop
|
53
50
|
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",
|
54
|
-
|
55
|
-
|
51
|
+
'{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
|
52
|
+
'numbers' => ArrayDrop.new([1, 2, 3, 4, 5, 6]))
|
56
53
|
end
|
57
54
|
|
58
55
|
def test_offset_and_limit
|
59
56
|
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",
|
60
|
-
|
61
|
-
|
57
|
+
'{% tablerow n in numbers cols:3 offset:1 limit:6%} {{n}} {% endtablerow %}',
|
58
|
+
'numbers' => [0, 1, 2, 3, 4, 5, 6, 7])
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_blank_string_not_iterable
|
62
|
+
assert_template_result("<tr class=\"row1\">\n</tr>\n", "{% tablerow char in characters cols:3 %}I WILL NOT BE OUTPUT{% endtablerow %}", 'characters' => '')
|
62
63
|
end
|
63
64
|
end
|
@@ -4,16 +4,16 @@ class UnlessElseTagTest < Minitest::Test
|
|
4
4
|
include Liquid
|
5
5
|
|
6
6
|
def test_unless
|
7
|
-
assert_template_result(' ',' {% unless true %} this text should not go into the output {% endunless %} ')
|
7
|
+
assert_template_result(' ', ' {% unless true %} this text should not go into the output {% endunless %} ')
|
8
8
|
assert_template_result(' this text should go into the output ',
|
9
|
-
|
10
|
-
assert_template_result(' you rock ?','{% unless true %} you suck {% endunless %} {% unless false %} you rock {% endunless %}?')
|
9
|
+
' {% unless false %} this text should go into the output {% endunless %} ')
|
10
|
+
assert_template_result(' you rock ?', '{% unless true %} you suck {% endunless %} {% unless false %} you rock {% endunless %}?')
|
11
11
|
end
|
12
12
|
|
13
13
|
def test_unless_else
|
14
|
-
assert_template_result(' YES ','{% unless true %} NO {% else %} YES {% endunless %}')
|
15
|
-
assert_template_result(' YES ','{% unless false %} YES {% else %} NO {% endunless %}')
|
16
|
-
assert_template_result(' YES ','{% unless "foo" %} NO {% else %} YES {% endunless %}')
|
14
|
+
assert_template_result(' YES ', '{% unless true %} NO {% else %} YES {% endunless %}')
|
15
|
+
assert_template_result(' YES ', '{% unless false %} YES {% else %} NO {% endunless %}')
|
16
|
+
assert_template_result(' YES ', '{% unless "foo" %} NO {% else %} YES {% endunless %}')
|
17
17
|
end
|
18
18
|
|
19
19
|
def test_unless_in_loop
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'test_helper'
|
2
|
+
require 'timeout'
|
2
3
|
|
3
4
|
class TemplateContextDrop < Liquid::Drop
|
4
|
-
def
|
5
|
+
def liquid_method_missing(method)
|
5
6
|
method
|
6
7
|
end
|
7
8
|
|
@@ -14,12 +15,10 @@ class TemplateContextDrop < Liquid::Drop
|
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
17
|
-
class SomethingWithLength
|
18
|
+
class SomethingWithLength < Liquid::Drop
|
18
19
|
def length
|
19
20
|
nil
|
20
21
|
end
|
21
|
-
|
22
|
-
liquid_methods :length
|
23
22
|
end
|
24
23
|
|
25
24
|
class ErroneousDrop < Liquid::Drop
|
@@ -37,6 +36,16 @@ class TemplateTest < Minitest::Test
|
|
37
36
|
assert_equal 'from instance assigns', t.parse("{{ foo }}").render!
|
38
37
|
end
|
39
38
|
|
39
|
+
def test_warnings_is_not_exponential_time
|
40
|
+
str = "false"
|
41
|
+
100.times do
|
42
|
+
str = "{% if true %}true{% else %}#{str}{% endif %}"
|
43
|
+
end
|
44
|
+
|
45
|
+
t = Template.parse(str)
|
46
|
+
assert_equal [], Timeout.timeout(1) { t.warnings }
|
47
|
+
end
|
48
|
+
|
40
49
|
def test_instance_assigns_persist_on_same_template_parsing_between_renders
|
41
50
|
t = Template.new.parse("{{ foo }}{% assign foo = 'foo' %}{{ foo }}")
|
42
51
|
assert_equal 'foo', t.render!
|
@@ -64,7 +73,7 @@ class TemplateTest < Minitest::Test
|
|
64
73
|
|
65
74
|
def test_lambda_is_called_once_from_persistent_assigns_over_multiple_parses_and_renders
|
66
75
|
t = Template.new
|
67
|
-
t.assigns['number'] =
|
76
|
+
t.assigns['number'] = -> { @global ||= 0; @global += 1 }
|
68
77
|
assert_equal '1', t.parse("{{number}}").render!
|
69
78
|
assert_equal '1', t.parse("{{number}}").render!
|
70
79
|
assert_equal '1', t.render!
|
@@ -73,7 +82,7 @@ class TemplateTest < Minitest::Test
|
|
73
82
|
|
74
83
|
def test_lambda_is_called_once_from_custom_assigns_over_multiple_parses_and_renders
|
75
84
|
t = Template.new
|
76
|
-
assigns = {'number' =>
|
85
|
+
assigns = { 'number' => -> { @global ||= 0; @global += 1 } }
|
77
86
|
assert_equal '1', t.parse("{{number}}").render!(assigns)
|
78
87
|
assert_equal '1', t.parse("{{number}}").render!(assigns)
|
79
88
|
assert_equal '1', t.render!(assigns)
|
@@ -82,69 +91,92 @@ class TemplateTest < Minitest::Test
|
|
82
91
|
|
83
92
|
def test_resource_limits_works_with_custom_length_method
|
84
93
|
t = Template.parse("{% assign foo = bar %}")
|
85
|
-
t.resource_limits =
|
94
|
+
t.resource_limits.render_length_limit = 42
|
86
95
|
assert_equal "", t.render!("bar" => SomethingWithLength.new)
|
87
96
|
end
|
88
97
|
|
89
98
|
def test_resource_limits_render_length
|
90
99
|
t = Template.parse("0123456789")
|
91
|
-
t.resource_limits =
|
92
|
-
assert_equal "Liquid error: Memory limits exceeded", t.render
|
93
|
-
assert t.resource_limits
|
94
|
-
|
95
|
-
|
96
|
-
|
100
|
+
t.resource_limits.render_length_limit = 5
|
101
|
+
assert_equal "Liquid error: Memory limits exceeded", t.render
|
102
|
+
assert t.resource_limits.reached?
|
103
|
+
|
104
|
+
t.resource_limits.render_length_limit = 10
|
105
|
+
assert_equal "0123456789", t.render!
|
106
|
+
refute_nil t.resource_limits.render_length
|
97
107
|
end
|
98
108
|
|
99
109
|
def test_resource_limits_render_score
|
100
110
|
t = Template.parse("{% for a in (1..10) %} {% for a in (1..10) %} foo {% endfor %} {% endfor %}")
|
101
|
-
t.resource_limits =
|
102
|
-
assert_equal "Liquid error: Memory limits exceeded", t.render
|
103
|
-
assert t.resource_limits
|
111
|
+
t.resource_limits.render_score_limit = 50
|
112
|
+
assert_equal "Liquid error: Memory limits exceeded", t.render
|
113
|
+
assert t.resource_limits.reached?
|
114
|
+
|
104
115
|
t = Template.parse("{% for a in (1..100) %} foo {% endfor %}")
|
105
|
-
t.resource_limits =
|
106
|
-
assert_equal "Liquid error: Memory limits exceeded", t.render
|
107
|
-
assert t.resource_limits
|
108
|
-
|
109
|
-
|
110
|
-
|
116
|
+
t.resource_limits.render_score_limit = 50
|
117
|
+
assert_equal "Liquid error: Memory limits exceeded", t.render
|
118
|
+
assert t.resource_limits.reached?
|
119
|
+
|
120
|
+
t.resource_limits.render_score_limit = 200
|
121
|
+
assert_equal (" foo " * 100), t.render!
|
122
|
+
refute_nil t.resource_limits.render_score
|
111
123
|
end
|
112
124
|
|
113
125
|
def test_resource_limits_assign_score
|
114
126
|
t = Template.parse("{% assign foo = 42 %}{% assign bar = 23 %}")
|
115
|
-
t.resource_limits =
|
116
|
-
assert_equal "Liquid error: Memory limits exceeded", t.render
|
117
|
-
assert t.resource_limits
|
118
|
-
|
119
|
-
|
120
|
-
|
127
|
+
t.resource_limits.assign_score_limit = 1
|
128
|
+
assert_equal "Liquid error: Memory limits exceeded", t.render
|
129
|
+
assert t.resource_limits.reached?
|
130
|
+
|
131
|
+
t.resource_limits.assign_score_limit = 2
|
132
|
+
assert_equal "", t.render!
|
133
|
+
refute_nil t.resource_limits.assign_score
|
121
134
|
end
|
122
135
|
|
123
136
|
def test_resource_limits_aborts_rendering_after_first_error
|
124
137
|
t = Template.parse("{% for a in (1..100) %} foo1 {% endfor %} bar {% for a in (1..100) %} foo2 {% endfor %}")
|
125
|
-
t.resource_limits =
|
126
|
-
assert_equal "Liquid error: Memory limits exceeded", t.render
|
127
|
-
assert t.resource_limits
|
138
|
+
t.resource_limits.render_score_limit = 50
|
139
|
+
assert_equal "Liquid error: Memory limits exceeded", t.render
|
140
|
+
assert t.resource_limits.reached?
|
128
141
|
end
|
129
142
|
|
130
143
|
def test_resource_limits_hash_in_template_gets_updated_even_if_no_limits_are_set
|
131
144
|
t = Template.parse("{% for a in (1..100) %} {% assign foo = 1 %} {% endfor %}")
|
132
|
-
t.render!
|
133
|
-
assert t.resource_limits
|
134
|
-
assert t.resource_limits
|
135
|
-
assert t.resource_limits
|
145
|
+
t.render!
|
146
|
+
assert t.resource_limits.assign_score > 0
|
147
|
+
assert t.resource_limits.render_score > 0
|
148
|
+
assert t.resource_limits.render_length > 0
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_render_length_persists_between_blocks
|
152
|
+
t = Template.parse("{% if true %}aaaa{% endif %}")
|
153
|
+
t.resource_limits.render_length_limit = 7
|
154
|
+
assert_equal "Liquid error: Memory limits exceeded", t.render
|
155
|
+
t.resource_limits.render_length_limit = 8
|
156
|
+
assert_equal "aaaa", t.render
|
157
|
+
|
158
|
+
t = Template.parse("{% if true %}aaaa{% endif %}{% if true %}bbb{% endif %}")
|
159
|
+
t.resource_limits.render_length_limit = 13
|
160
|
+
assert_equal "Liquid error: Memory limits exceeded", t.render
|
161
|
+
t.resource_limits.render_length_limit = 14
|
162
|
+
assert_equal "aaaabbb", t.render
|
163
|
+
|
164
|
+
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 %}")
|
165
|
+
t.resource_limits.render_length_limit = 5
|
166
|
+
assert_equal "Liquid error: Memory limits exceeded", t.render
|
167
|
+
t.resource_limits.render_length_limit = 11
|
168
|
+
assert_equal "Liquid error: Memory limits exceeded", t.render
|
169
|
+
t.resource_limits.render_length_limit = 12
|
170
|
+
assert_equal "ababab", t.render
|
136
171
|
end
|
137
172
|
|
138
173
|
def test_default_resource_limits_unaffected_by_render_with_context
|
139
174
|
context = Context.new
|
140
175
|
t = Template.parse("{% for a in (1..100) %} {% assign foo = 1 %} {% endfor %}")
|
141
176
|
t.render!(context)
|
142
|
-
assert context.resource_limits
|
143
|
-
assert context.resource_limits
|
144
|
-
assert context.resource_limits
|
145
|
-
refute Template.default_resource_limits.key?(:assign_score_current)
|
146
|
-
refute Template.default_resource_limits.key?(:render_score_current)
|
147
|
-
refute Template.default_resource_limits.key?(:render_length_current)
|
177
|
+
assert context.resource_limits.assign_score > 0
|
178
|
+
assert context.resource_limits.render_score > 0
|
179
|
+
assert context.resource_limits.render_length > 0
|
148
180
|
end
|
149
181
|
|
150
182
|
def test_can_use_drop_as_context
|
@@ -157,7 +189,7 @@ class TemplateTest < Minitest::Test
|
|
157
189
|
end
|
158
190
|
|
159
191
|
def test_render_bang_force_rethrow_errors_on_passed_context
|
160
|
-
context = Context.new({'drop' => ErroneousDrop.new})
|
192
|
+
context = Context.new({ 'drop' => ErroneousDrop.new })
|
161
193
|
t = Template.new.parse('{{ drop.bad_method }}')
|
162
194
|
|
163
195
|
e = assert_raises RuntimeError do
|
@@ -169,14 +201,28 @@ class TemplateTest < Minitest::Test
|
|
169
201
|
def test_exception_handler_doesnt_reraise_if_it_returns_false
|
170
202
|
exception = nil
|
171
203
|
Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_handler: ->(e) { exception = e; false })
|
172
|
-
assert exception.is_a?(ZeroDivisionError)
|
204
|
+
assert exception.is_a?(Liquid::ZeroDivisionError)
|
173
205
|
end
|
174
206
|
|
175
207
|
def test_exception_handler_does_reraise_if_it_returns_true
|
176
208
|
exception = nil
|
177
|
-
assert_raises(ZeroDivisionError) do
|
209
|
+
assert_raises(Liquid::ZeroDivisionError) do
|
178
210
|
Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_handler: ->(e) { exception = e; true })
|
179
211
|
end
|
180
|
-
assert exception.is_a?(ZeroDivisionError)
|
212
|
+
assert exception.is_a?(Liquid::ZeroDivisionError)
|
213
|
+
end
|
214
|
+
|
215
|
+
def test_global_filter_option_on_render
|
216
|
+
global_filter_proc = ->(output) { "#{output} filtered" }
|
217
|
+
rendered_template = Template.parse("{{name}}").render({ "name" => "bob" }, global_filter: global_filter_proc)
|
218
|
+
|
219
|
+
assert_equal 'bob filtered', rendered_template
|
220
|
+
end
|
221
|
+
|
222
|
+
def test_global_filter_option_when_native_filters_exist
|
223
|
+
global_filter_proc = ->(output) { "#{output} filtered" }
|
224
|
+
rendered_template = Template.parse("{{name | upcase}}").render({ "name" => "bob" }, global_filter: global_filter_proc)
|
225
|
+
|
226
|
+
assert_equal 'BOB filtered', rendered_template
|
181
227
|
end
|
182
228
|
end
|
@@ -4,7 +4,7 @@ class VariableTest < Minitest::Test
|
|
4
4
|
include Liquid
|
5
5
|
|
6
6
|
def test_simple_variable
|
7
|
-
template = Template.parse(
|
7
|
+
template = Template.parse(%({{test}}))
|
8
8
|
assert_equal 'worked', template.render!('test' => 'worked')
|
9
9
|
assert_equal 'worked wonderfully', template.render!('test' => 'worked wonderfully')
|
10
10
|
end
|
@@ -14,19 +14,29 @@ class VariableTest < Minitest::Test
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def test_simple_with_whitespaces
|
17
|
-
template = Template.parse(
|
17
|
+
template = Template.parse(%( {{ test }} ))
|
18
18
|
assert_equal ' worked ', template.render!('test' => 'worked')
|
19
19
|
assert_equal ' worked wonderfully ', template.render!('test' => 'worked wonderfully')
|
20
20
|
end
|
21
21
|
|
22
22
|
def test_ignore_unknown
|
23
|
-
template = Template.parse(
|
23
|
+
template = Template.parse(%({{ test }}))
|
24
|
+
assert_equal '', template.render!
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_using_blank_as_variable_name
|
28
|
+
template = Template.parse("{% assign foo = blank %}{{ foo }}")
|
29
|
+
assert_equal '', template.render!
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_using_empty_as_variable_name
|
33
|
+
template = Template.parse("{% assign foo = empty %}{{ foo }}")
|
24
34
|
assert_equal '', template.render!
|
25
35
|
end
|
26
36
|
|
27
37
|
def test_hash_scoping
|
28
|
-
template = Template.parse(
|
29
|
-
assert_equal 'worked', template.render!('test' => {'test' => 'worked'})
|
38
|
+
template = Template.parse(%({{ test.test }}))
|
39
|
+
assert_equal 'worked', template.render!('test' => { 'test' => 'worked' })
|
30
40
|
end
|
31
41
|
|
32
42
|
def test_false_renders_as_false
|
@@ -40,23 +50,23 @@ class VariableTest < Minitest::Test
|
|
40
50
|
end
|
41
51
|
|
42
52
|
def test_preset_assigns
|
43
|
-
template = Template.parse(
|
53
|
+
template = Template.parse(%({{ test }}))
|
44
54
|
template.assigns['test'] = 'worked'
|
45
55
|
assert_equal 'worked', template.render!
|
46
56
|
end
|
47
57
|
|
48
58
|
def test_reuse_parsed_template
|
49
|
-
template = Template.parse(
|
59
|
+
template = Template.parse(%({{ greeting }} {{ name }}))
|
50
60
|
template.assigns['greeting'] = 'Goodbye'
|
51
61
|
assert_equal 'Hello Tobi', template.render!('greeting' => 'Hello', 'name' => 'Tobi')
|
52
62
|
assert_equal 'Hello ', template.render!('greeting' => 'Hello', 'unknown' => 'Tobi')
|
53
63
|
assert_equal 'Hello Brian', template.render!('greeting' => 'Hello', 'name' => 'Brian')
|
54
64
|
assert_equal 'Goodbye Brian', template.render!('name' => 'Brian')
|
55
|
-
assert_equal({'greeting'=>'Goodbye'}, template.assigns)
|
65
|
+
assert_equal({ 'greeting' => 'Goodbye' }, template.assigns)
|
56
66
|
end
|
57
67
|
|
58
68
|
def test_assigns_not_polluted_from_template
|
59
|
-
template = Template.parse(
|
69
|
+
template = Template.parse(%({{ test }}{% assign test = 'bar' %}{{ test }}))
|
60
70
|
template.assigns['test'] = 'baz'
|
61
71
|
assert_equal 'bazbar', template.render!
|
62
72
|
assert_equal 'bazbar', template.render!
|
@@ -65,14 +75,14 @@ class VariableTest < Minitest::Test
|
|
65
75
|
end
|
66
76
|
|
67
77
|
def test_hash_with_default_proc
|
68
|
-
template = Template.parse(
|
69
|
-
assigns = Hash.new { |h,k| raise "Unknown variable '#{k}'" }
|
78
|
+
template = Template.parse(%(Hello {{ test }}))
|
79
|
+
assigns = Hash.new { |h, k| raise "Unknown variable '#{k}'" }
|
70
80
|
assigns['test'] = 'Tobi'
|
71
81
|
assert_equal 'Hello Tobi', template.render!(assigns)
|
72
82
|
assigns.delete('test')
|
73
|
-
e = assert_raises(RuntimeError)
|
83
|
+
e = assert_raises(RuntimeError) do
|
74
84
|
template.render!(assigns)
|
75
|
-
|
85
|
+
end
|
76
86
|
assert_equal "Unknown variable 'test'", e.message
|
77
87
|
end
|
78
88
|
|
data/test/test_helper.rb
CHANGED
@@ -4,8 +4,9 @@ ENV["MT_NO_EXPECTATIONS"] = "1"
|
|
4
4
|
require 'minitest/autorun'
|
5
5
|
require 'spy/integration'
|
6
6
|
|
7
|
-
|
7
|
+
$LOAD_PATH.unshift(File.join(File.expand_path(__dir__), '..', 'lib'))
|
8
8
|
require 'liquid.rb'
|
9
|
+
require 'liquid/profiler'
|
9
10
|
|
10
11
|
mode = :strict
|
11
12
|
if env_mode = ENV['LIQUID_PARSER_MODE']
|
@@ -14,6 +15,11 @@ if env_mode = ENV['LIQUID_PARSER_MODE']
|
|
14
15
|
end
|
15
16
|
Liquid::Template.error_mode = mode
|
16
17
|
|
18
|
+
if ENV['LIQUID-C'] == '1'
|
19
|
+
puts "-- LIQUID C"
|
20
|
+
require 'liquid/c'
|
21
|
+
end
|
22
|
+
|
17
23
|
if Minitest.const_defined?('Test')
|
18
24
|
# We're on Minitest 5+. Nothing to do here.
|
19
25
|
else
|
@@ -24,7 +30,7 @@ end
|
|
24
30
|
module Minitest
|
25
31
|
class Test
|
26
32
|
def fixture(name)
|
27
|
-
File.join(File.expand_path(
|
33
|
+
File.join(File.expand_path(__dir__), "fixtures", name)
|
28
34
|
end
|
29
35
|
end
|
30
36
|
|
@@ -41,10 +47,10 @@ module Minitest
|
|
41
47
|
assert_match expected, Template.parse(template).render!(assigns), message
|
42
48
|
end
|
43
49
|
|
44
|
-
def assert_match_syntax_error(match, template,
|
45
|
-
exception = assert_raises(Liquid::SyntaxError)
|
50
|
+
def assert_match_syntax_error(match, template, assigns = {})
|
51
|
+
exception = assert_raises(Liquid::SyntaxError) do
|
46
52
|
Template.parse(template).render(assigns)
|
47
|
-
|
53
|
+
end
|
48
54
|
assert_match match, exception.message
|
49
55
|
end
|
50
56
|
|
@@ -87,3 +93,25 @@ class ThingWithToLiquid
|
|
87
93
|
'foobar'
|
88
94
|
end
|
89
95
|
end
|
96
|
+
|
97
|
+
class ErrorDrop < Liquid::Drop
|
98
|
+
def standard_error
|
99
|
+
raise Liquid::StandardError, 'standard error'
|
100
|
+
end
|
101
|
+
|
102
|
+
def argument_error
|
103
|
+
raise Liquid::ArgumentError, 'argument error'
|
104
|
+
end
|
105
|
+
|
106
|
+
def syntax_error
|
107
|
+
raise Liquid::SyntaxError, 'syntax error'
|
108
|
+
end
|
109
|
+
|
110
|
+
def runtime_error
|
111
|
+
raise 'runtime error'
|
112
|
+
end
|
113
|
+
|
114
|
+
def exception
|
115
|
+
raise Exception, 'exception'
|
116
|
+
end
|
117
|
+
end
|