locomotivecms-liquid 2.6.0 → 4.0.0.alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +62 -5
  3. data/README.md +4 -4
  4. data/lib/liquid.rb +16 -12
  5. data/lib/liquid/block.rb +37 -118
  6. data/lib/liquid/block_body.rb +131 -0
  7. data/lib/liquid/condition.rb +28 -17
  8. data/lib/liquid/context.rb +94 -146
  9. data/lib/liquid/document.rb +16 -10
  10. data/lib/liquid/drop.rb +8 -5
  11. data/lib/liquid/drops/inherited_block_drop.rb +24 -0
  12. data/lib/liquid/errors.rb +44 -5
  13. data/lib/liquid/expression.rb +33 -0
  14. data/lib/liquid/file_system.rb +17 -6
  15. data/lib/liquid/i18n.rb +2 -2
  16. data/lib/liquid/interrupts.rb +1 -1
  17. data/lib/liquid/lexer.rb +11 -9
  18. data/lib/liquid/locales/en.yml +2 -4
  19. data/lib/liquid/parser.rb +2 -1
  20. data/lib/liquid/parser_switching.rb +31 -0
  21. data/lib/liquid/profiler.rb +162 -0
  22. data/lib/liquid/profiler/hooks.rb +23 -0
  23. data/lib/liquid/range_lookup.rb +22 -0
  24. data/lib/liquid/resource_limits.rb +23 -0
  25. data/lib/liquid/standardfilters.rb +142 -67
  26. data/lib/liquid/strainer.rb +14 -4
  27. data/lib/liquid/tag.rb +22 -41
  28. data/lib/liquid/tags/assign.rb +15 -10
  29. data/lib/liquid/tags/break.rb +1 -1
  30. data/lib/liquid/tags/capture.rb +7 -9
  31. data/lib/liquid/tags/case.rb +28 -19
  32. data/lib/liquid/tags/comment.rb +2 -2
  33. data/lib/liquid/tags/continue.rb +1 -4
  34. data/lib/liquid/tags/cycle.rb +10 -14
  35. data/lib/liquid/tags/decrement.rb +3 -4
  36. data/lib/liquid/tags/extends.rb +28 -44
  37. data/lib/liquid/tags/for.rb +64 -42
  38. data/lib/liquid/tags/if.rb +30 -19
  39. data/lib/liquid/tags/ifchanged.rb +4 -4
  40. data/lib/liquid/tags/include.rb +30 -20
  41. data/lib/liquid/tags/increment.rb +3 -8
  42. data/lib/liquid/tags/inherited_block.rb +54 -56
  43. data/lib/liquid/tags/raw.rb +18 -10
  44. data/lib/liquid/tags/table_row.rb +72 -0
  45. data/lib/liquid/tags/unless.rb +5 -7
  46. data/lib/liquid/template.rb +113 -53
  47. data/lib/liquid/token.rb +18 -0
  48. data/lib/liquid/utils.rb +13 -4
  49. data/lib/liquid/variable.rb +68 -50
  50. data/lib/liquid/variable_lookup.rb +78 -0
  51. data/lib/liquid/version.rb +1 -1
  52. data/test/fixtures/en_locale.yml +9 -0
  53. data/test/integration/assign_test.rb +48 -0
  54. data/test/integration/blank_test.rb +106 -0
  55. data/test/integration/capture_test.rb +50 -0
  56. data/test/integration/context_test.rb +32 -0
  57. data/test/integration/document_test.rb +19 -0
  58. data/test/integration/drop_test.rb +271 -0
  59. data/test/integration/error_handling_test.rb +207 -0
  60. data/test/integration/filter_test.rb +125 -0
  61. data/test/integration/hash_ordering_test.rb +23 -0
  62. data/test/integration/output_test.rb +116 -0
  63. data/test/integration/parsing_quirks_test.rb +119 -0
  64. data/test/integration/render_profiling_test.rb +154 -0
  65. data/test/integration/security_test.rb +64 -0
  66. data/test/integration/standard_filter_test.rb +379 -0
  67. data/test/integration/tags/break_tag_test.rb +16 -0
  68. data/test/integration/tags/continue_tag_test.rb +16 -0
  69. data/test/integration/tags/extends_tag_test.rb +104 -0
  70. data/test/integration/tags/for_tag_test.rb +375 -0
  71. data/test/integration/tags/if_else_tag_test.rb +169 -0
  72. data/test/integration/tags/include_tag_test.rb +234 -0
  73. data/test/integration/tags/increment_tag_test.rb +24 -0
  74. data/test/integration/tags/raw_tag_test.rb +25 -0
  75. data/test/integration/tags/standard_tag_test.rb +297 -0
  76. data/test/integration/tags/statements_test.rb +113 -0
  77. data/test/integration/tags/table_row_test.rb +63 -0
  78. data/test/integration/tags/unless_else_tag_test.rb +26 -0
  79. data/test/integration/template_test.rb +216 -0
  80. data/test/integration/variable_test.rb +82 -0
  81. data/test/test_helper.rb +83 -0
  82. data/test/unit/block_unit_test.rb +55 -0
  83. data/test/unit/condition_unit_test.rb +149 -0
  84. data/test/unit/context_unit_test.rb +482 -0
  85. data/test/unit/file_system_unit_test.rb +35 -0
  86. data/test/unit/i18n_unit_test.rb +37 -0
  87. data/test/unit/lexer_unit_test.rb +51 -0
  88. data/test/unit/module_ex_unit_test.rb +87 -0
  89. data/test/unit/parser_unit_test.rb +82 -0
  90. data/test/unit/regexp_unit_test.rb +44 -0
  91. data/test/unit/strainer_unit_test.rb +71 -0
  92. data/test/unit/tag_unit_test.rb +16 -0
  93. data/test/unit/tags/case_tag_unit_test.rb +10 -0
  94. data/test/unit/tags/for_tag_unit_test.rb +13 -0
  95. data/test/unit/tags/if_tag_unit_test.rb +8 -0
  96. data/test/unit/template_unit_test.rb +70 -0
  97. data/test/unit/tokenizer_unit_test.rb +38 -0
  98. data/test/unit/variable_unit_test.rb +150 -0
  99. metadata +144 -15
  100. data/lib/extras/liquid_view.rb +0 -51
  101. data/lib/liquid/htmltags.rb +0 -74
  102. data/lib/liquid/tags/default_content.rb +0 -21
  103. data/lib/locomotivecms-liquid.rb +0 -1
@@ -0,0 +1,64 @@
1
+ require 'test_helper'
2
+
3
+ module SecurityFilter
4
+ def add_one(input)
5
+ "#{input} + 1"
6
+ end
7
+ end
8
+
9
+ class SecurityTest < Minitest::Test
10
+ include Liquid
11
+
12
+ def test_no_instance_eval
13
+ text = %( {{ '1+1' | instance_eval }} )
14
+ expected = %| 1+1 |
15
+
16
+ assert_equal expected, Template.parse(text).render!(@assigns)
17
+ end
18
+
19
+ def test_no_existing_instance_eval
20
+ text = %( {{ '1+1' | __instance_eval__ }} )
21
+ expected = %| 1+1 |
22
+
23
+ assert_equal expected, Template.parse(text).render!(@assigns)
24
+ end
25
+
26
+
27
+ def test_no_instance_eval_after_mixing_in_new_filter
28
+ text = %( {{ '1+1' | instance_eval }} )
29
+ expected = %| 1+1 |
30
+
31
+ assert_equal expected, Template.parse(text).render!(@assigns)
32
+ end
33
+
34
+
35
+ def test_no_instance_eval_later_in_chain
36
+ text = %( {{ '1+1' | add_one | instance_eval }} )
37
+ expected = %| 1+1 + 1 |
38
+
39
+ assert_equal expected, Template.parse(text).render!(@assigns, :filters => SecurityFilter)
40
+ end
41
+
42
+ def test_does_not_add_filters_to_symbol_table
43
+ current_symbols = Symbol.all_symbols
44
+
45
+ test = %( {{ "some_string" | a_bad_filter }} )
46
+
47
+ template = Template.parse(test)
48
+ assert_equal [], (Symbol.all_symbols - current_symbols)
49
+
50
+ template.render!
51
+ assert_equal [], (Symbol.all_symbols - current_symbols)
52
+ end
53
+
54
+ def test_does_not_add_drop_methods_to_symbol_table
55
+ current_symbols = Symbol.all_symbols
56
+
57
+ assigns = { 'drop' => Drop.new }
58
+ assert_equal "", Template.parse("{{ drop.custom_method_1 }}", assigns).render!
59
+ assert_equal "", Template.parse("{{ drop.custom_method_2 }}", assigns).render!
60
+ assert_equal "", Template.parse("{{ drop.custom_method_3 }}", assigns).render!
61
+
62
+ assert_equal [], (Symbol.all_symbols - current_symbols)
63
+ end
64
+ end # SecurityTest
@@ -0,0 +1,379 @@
1
+ # encoding: utf-8
2
+
3
+ require 'test_helper'
4
+
5
+ class Filters
6
+ include Liquid::StandardFilters
7
+ end
8
+
9
+ class TestThing
10
+ attr_reader :foo
11
+
12
+ def initialize
13
+ @foo = 0
14
+ end
15
+
16
+ def to_s
17
+ "woot: #{@foo}"
18
+ end
19
+
20
+ def [](whatever)
21
+ to_s
22
+ end
23
+
24
+ def to_liquid
25
+ @foo += 1
26
+ self
27
+ end
28
+ end
29
+
30
+ class TestDrop < Liquid::Drop
31
+ def test
32
+ "testfoo"
33
+ end
34
+ end
35
+
36
+ class TestEnumerable < Liquid::Drop
37
+ include Enumerable
38
+
39
+ def each(&block)
40
+ [ { "foo" => 1, "bar" => 2 }, { "foo" => 2, "bar" => 1 }, { "foo" => 3, "bar" => 3 } ].each(&block)
41
+ end
42
+ end
43
+
44
+ class StandardFiltersTest < Minitest::Test
45
+ include Liquid
46
+
47
+ def setup
48
+ @filters = Filters.new
49
+ end
50
+
51
+ def test_size
52
+ assert_equal 3, @filters.size([1,2,3])
53
+ assert_equal 0, @filters.size([])
54
+ assert_equal 0, @filters.size(nil)
55
+ end
56
+
57
+ def test_downcase
58
+ assert_equal 'testing', @filters.downcase("Testing")
59
+ assert_equal '', @filters.downcase(nil)
60
+ end
61
+
62
+ def test_upcase
63
+ assert_equal 'TESTING', @filters.upcase("Testing")
64
+ assert_equal '', @filters.upcase(nil)
65
+ end
66
+
67
+ def test_slice
68
+ assert_equal 'oob', @filters.slice('foobar', 1, 3)
69
+ assert_equal 'oobar', @filters.slice('foobar', 1, 1000)
70
+ assert_equal '', @filters.slice('foobar', 1, 0)
71
+ assert_equal 'o', @filters.slice('foobar', 1, 1)
72
+ assert_equal 'bar', @filters.slice('foobar', 3, 3)
73
+ assert_equal 'ar', @filters.slice('foobar', -2, 2)
74
+ assert_equal 'ar', @filters.slice('foobar', -2, 1000)
75
+ assert_equal 'r', @filters.slice('foobar', -1)
76
+ assert_equal '', @filters.slice(nil, 0)
77
+ assert_equal '', @filters.slice('foobar', 100, 10)
78
+ assert_equal '', @filters.slice('foobar', -100, 10)
79
+ end
80
+
81
+ def test_slice_on_arrays
82
+ input = 'foobar'.split(//)
83
+ assert_equal %w{o o b}, @filters.slice(input, 1, 3)
84
+ assert_equal %w{o o b a r}, @filters.slice(input, 1, 1000)
85
+ assert_equal %w{}, @filters.slice(input, 1, 0)
86
+ assert_equal %w{o}, @filters.slice(input, 1, 1)
87
+ assert_equal %w{b a r}, @filters.slice(input, 3, 3)
88
+ assert_equal %w{a r}, @filters.slice(input, -2, 2)
89
+ assert_equal %w{a r}, @filters.slice(input, -2, 1000)
90
+ assert_equal %w{r}, @filters.slice(input, -1)
91
+ assert_equal %w{}, @filters.slice(input, 100, 10)
92
+ assert_equal %w{}, @filters.slice(input, -100, 10)
93
+ end
94
+
95
+ def test_truncate
96
+ assert_equal '1234...', @filters.truncate('1234567890', 7)
97
+ assert_equal '1234567890', @filters.truncate('1234567890', 20)
98
+ assert_equal '...', @filters.truncate('1234567890', 0)
99
+ assert_equal '1234567890', @filters.truncate('1234567890')
100
+ assert_equal "测试...", @filters.truncate("测试测试测试测试", 5)
101
+ end
102
+
103
+ def test_split
104
+ assert_equal ['12','34'], @filters.split('12~34', '~')
105
+ assert_equal ['A? ',' ,Z'], @filters.split('A? ~ ~ ~ ,Z', '~ ~ ~')
106
+ assert_equal ['A?Z'], @filters.split('A?Z', '~')
107
+ # Regexp works although Liquid does not support.
108
+ assert_equal ['A','Z'], @filters.split('AxZ', /x/)
109
+ assert_equal [], @filters.split(nil, ' ')
110
+ end
111
+
112
+ def test_escape
113
+ assert_equal '&lt;strong&gt;', @filters.escape('<strong>')
114
+ assert_equal '&lt;strong&gt;', @filters.h('<strong>')
115
+ end
116
+
117
+ def test_escape_once
118
+ assert_equal '&lt;strong&gt;Hulk&lt;/strong&gt;', @filters.escape_once('&lt;strong&gt;Hulk</strong>')
119
+ end
120
+
121
+ def test_url_encode
122
+ assert_equal 'foo%2B1%40example.com', @filters.url_encode('foo+1@example.com')
123
+ assert_equal nil, @filters.url_encode(nil)
124
+ end
125
+
126
+ def test_truncatewords
127
+ assert_equal 'one two three', @filters.truncatewords('one two three', 4)
128
+ assert_equal 'one two...', @filters.truncatewords('one two three', 2)
129
+ assert_equal 'one two three', @filters.truncatewords('one two three')
130
+ assert_equal 'Two small (13&#8221; x 5.5&#8221; x 10&#8221; high) baskets fit inside one large basket (13&#8221;...', @filters.truncatewords('Two small (13&#8221; x 5.5&#8221; x 10&#8221; high) baskets fit inside one large basket (13&#8221; x 16&#8221; x 10.5&#8221; high) with cover.', 15)
131
+ assert_equal "测试测试测试测试", @filters.truncatewords('测试测试测试测试', 5)
132
+ end
133
+
134
+ def test_strip_html
135
+ assert_equal 'test', @filters.strip_html("<div>test</div>")
136
+ assert_equal 'test', @filters.strip_html("<div id='test'>test</div>")
137
+ assert_equal '', @filters.strip_html("<script type='text/javascript'>document.write('some stuff');</script>")
138
+ assert_equal '', @filters.strip_html("<style type='text/css'>foo bar</style>")
139
+ assert_equal 'test', @filters.strip_html("<div\nclass='multiline'>test</div>")
140
+ assert_equal 'test', @filters.strip_html("<!-- foo bar \n test -->test")
141
+ assert_equal '', @filters.strip_html(nil)
142
+ end
143
+
144
+ def test_join
145
+ assert_equal '1 2 3 4', @filters.join([1,2,3,4])
146
+ assert_equal '1 - 2 - 3 - 4', @filters.join([1,2,3,4], ' - ')
147
+ end
148
+
149
+ def test_sort
150
+ assert_equal [1,2,3,4], @filters.sort([4,3,2,1])
151
+ assert_equal [{"a" => 1}, {"a" => 2}, {"a" => 3}, {"a" => 4}], @filters.sort([{"a" => 4}, {"a" => 3}, {"a" => 1}, {"a" => 2}], "a")
152
+ end
153
+
154
+ def test_legacy_sort_hash
155
+ assert_equal [{a:1, b:2}], @filters.sort({a:1, b:2})
156
+ end
157
+
158
+ def test_numerical_vs_lexicographical_sort
159
+ assert_equal [2, 10], @filters.sort([10, 2])
160
+ assert_equal [{"a" => 2}, {"a" => 10}], @filters.sort([{"a" => 10}, {"a" => 2}], "a")
161
+ assert_equal ["10", "2"], @filters.sort(["10", "2"])
162
+ assert_equal [{"a" => "10"}, {"a" => "2"}], @filters.sort([{"a" => "10"}, {"a" => "2"}], "a")
163
+ end
164
+
165
+ def test_uniq
166
+ assert_equal [1,3,2,4], @filters.uniq([1,1,3,2,3,1,4,3,2,1])
167
+ assert_equal [{"a" => 1}, {"a" => 3}, {"a" => 2}], @filters.uniq([{"a" => 1}, {"a" => 3}, {"a" => 1}, {"a" => 2}], "a")
168
+ testdrop = TestDrop.new
169
+ assert_equal [testdrop], @filters.uniq([testdrop, TestDrop.new], 'test')
170
+ end
171
+
172
+ def test_reverse
173
+ assert_equal [4,3,2,1], @filters.reverse([1,2,3,4])
174
+ end
175
+
176
+ def test_legacy_reverse_hash
177
+ assert_equal [{a:1, b:2}], @filters.reverse(a:1, b:2)
178
+ end
179
+
180
+ def test_map
181
+ assert_equal [1,2,3,4], @filters.map([{"a" => 1}, {"a" => 2}, {"a" => 3}, {"a" => 4}], 'a')
182
+ assert_template_result 'abc', "{{ ary | map:'foo' | map:'bar' }}",
183
+ 'ary' => [{'foo' => {'bar' => 'a'}}, {'foo' => {'bar' => 'b'}}, {'foo' => {'bar' => 'c'}}]
184
+ end
185
+
186
+ def test_map_doesnt_call_arbitrary_stuff
187
+ assert_template_result "", '{{ "foo" | map: "__id__" }}'
188
+ assert_template_result "", '{{ "foo" | map: "inspect" }}'
189
+ end
190
+
191
+ def test_map_calls_to_liquid
192
+ t = TestThing.new
193
+ assert_template_result "woot: 1", '{{ foo | map: "whatever" }}', "foo" => [t]
194
+ end
195
+
196
+ def test_map_on_hashes
197
+ assert_template_result "4217", '{{ thing | map: "foo" | map: "bar" }}',
198
+ "thing" => { "foo" => [ { "bar" => 42 }, { "bar" => 17 } ] }
199
+ end
200
+
201
+ def test_legacy_map_on_hashes_with_dynamic_key
202
+ template = "{% assign key = 'foo' %}{{ thing | map: key | map: 'bar' }}"
203
+ hash = { "foo" => { "bar" => 42 } }
204
+ assert_template_result "42", template, "thing" => hash
205
+ end
206
+
207
+ def test_sort_calls_to_liquid
208
+ t = TestThing.new
209
+ Liquid::Template.parse('{{ foo | sort: "whatever" }}').render("foo" => [t])
210
+ assert t.foo > 0
211
+ end
212
+
213
+ def test_map_over_proc
214
+ drop = TestDrop.new
215
+ p = Proc.new{ drop }
216
+ templ = '{{ procs | map: "test" }}'
217
+ assert_template_result "testfoo", templ, "procs" => [p]
218
+ end
219
+
220
+ def test_map_works_on_enumerables
221
+ assert_template_result "123", '{{ foo | map: "foo" }}', "foo" => TestEnumerable.new
222
+ end
223
+
224
+ def test_sort_works_on_enumerables
225
+ assert_template_result "213", '{{ foo | sort: "bar" | map: "foo" }}', "foo" => TestEnumerable.new
226
+ end
227
+
228
+ def test_first_and_last_call_to_liquid
229
+ assert_template_result 'foobar', '{{ foo | first }}', 'foo' => [ThingWithToLiquid.new]
230
+ assert_template_result 'foobar', '{{ foo | last }}', 'foo' => [ThingWithToLiquid.new]
231
+ end
232
+
233
+ def test_date
234
+ assert_equal 'May', @filters.date(Time.parse("2006-05-05 10:00:00"), "%B")
235
+ assert_equal 'June', @filters.date(Time.parse("2006-06-05 10:00:00"), "%B")
236
+ assert_equal 'July', @filters.date(Time.parse("2006-07-05 10:00:00"), "%B")
237
+
238
+ assert_equal 'May', @filters.date("2006-05-05 10:00:00", "%B")
239
+ assert_equal 'June', @filters.date("2006-06-05 10:00:00", "%B")
240
+ assert_equal 'July', @filters.date("2006-07-05 10:00:00", "%B")
241
+
242
+ assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
243
+ assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
244
+ assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", "")
245
+ assert_equal '2006-07-05 10:00:00', @filters.date("2006-07-05 10:00:00", nil)
246
+
247
+ assert_equal '07/05/2006', @filters.date("2006-07-05 10:00:00", "%m/%d/%Y")
248
+
249
+ assert_equal "07/16/2004", @filters.date("Fri Jul 16 01:00:00 2004", "%m/%d/%Y")
250
+ assert_equal "#{Date.today.year}", @filters.date('now', '%Y')
251
+ assert_equal "#{Date.today.year}", @filters.date('today', '%Y')
252
+
253
+ assert_equal nil, @filters.date(nil, "%B")
254
+
255
+ assert_equal "07/05/2006", @filters.date(1152098955, "%m/%d/%Y")
256
+ assert_equal "07/05/2006", @filters.date("1152098955", "%m/%d/%Y")
257
+ end
258
+
259
+ def test_first_last
260
+ assert_equal 1, @filters.first([1,2,3])
261
+ assert_equal 3, @filters.last([1,2,3])
262
+ assert_equal nil, @filters.first([])
263
+ assert_equal nil, @filters.last([])
264
+ end
265
+
266
+ def test_replace
267
+ assert_equal '2 2 2 2', @filters.replace('1 1 1 1', '1', 2)
268
+ assert_equal '2 1 1 1', @filters.replace_first('1 1 1 1', '1', 2)
269
+ assert_template_result '2 1 1 1', "{{ '1 1 1 1' | replace_first: '1', 2 }}"
270
+ end
271
+
272
+ def test_remove
273
+ assert_equal ' ', @filters.remove("a a a a", 'a')
274
+ assert_equal 'a a a', @filters.remove_first("a a a a", 'a ')
275
+ assert_template_result 'a a a', "{{ 'a a a a' | remove_first: 'a ' }}"
276
+ end
277
+
278
+ def test_pipes_in_string_arguments
279
+ assert_template_result 'foobar', "{{ 'foo|bar' | remove: '|' }}"
280
+ end
281
+
282
+ def test_strip
283
+ assert_template_result 'ab c', "{{ source | strip }}", 'source' => " ab c "
284
+ assert_template_result 'ab c', "{{ source | strip }}", 'source' => " \tab c \n \t"
285
+ end
286
+
287
+ def test_lstrip
288
+ assert_template_result 'ab c ', "{{ source | lstrip }}", 'source' => " ab c "
289
+ assert_template_result "ab c \n \t", "{{ source | lstrip }}", 'source' => " \tab c \n \t"
290
+ end
291
+
292
+ def test_rstrip
293
+ assert_template_result " ab c", "{{ source | rstrip }}", 'source' => " ab c "
294
+ assert_template_result " \tab c", "{{ source | rstrip }}", 'source' => " \tab c \n \t"
295
+ end
296
+
297
+ def test_strip_newlines
298
+ assert_template_result 'abc', "{{ source | strip_newlines }}", 'source' => "a\nb\nc"
299
+ assert_template_result 'abc', "{{ source | strip_newlines }}", 'source' => "a\r\nb\nc"
300
+ end
301
+
302
+ def test_newlines_to_br
303
+ assert_template_result "a<br />\nb<br />\nc", "{{ source | newline_to_br }}", 'source' => "a\nb\nc"
304
+ end
305
+
306
+ def test_plus
307
+ assert_template_result "2", "{{ 1 | plus:1 }}"
308
+ assert_template_result "2.0", "{{ '1' | plus:'1.0' }}"
309
+ end
310
+
311
+ def test_minus
312
+ assert_template_result "4", "{{ input | minus:operand }}", 'input' => 5, 'operand' => 1
313
+ assert_template_result "2.3", "{{ '4.3' | minus:'2' }}"
314
+ end
315
+
316
+ def test_times
317
+ assert_template_result "12", "{{ 3 | times:4 }}"
318
+ assert_template_result "0", "{{ 'foo' | times:4 }}"
319
+
320
+ assert_template_result "6", "{{ '2.1' | times:3 | replace: '.','-' | plus:0}}"
321
+
322
+ assert_template_result "7.25", "{{ 0.0725 | times:100 }}"
323
+ end
324
+
325
+ def test_divided_by
326
+ assert_template_result "4", "{{ 12 | divided_by:3 }}"
327
+ assert_template_result "4", "{{ 14 | divided_by:3 }}"
328
+
329
+ assert_template_result "5", "{{ 15 | divided_by:3 }}"
330
+ assert_equal "Liquid error: divided by 0", Template.parse("{{ 5 | divided_by:0 }}").render
331
+
332
+ assert_template_result "0.5", "{{ 2.0 | divided_by:4 }}"
333
+ end
334
+
335
+ def test_modulo
336
+ assert_template_result "1", "{{ 3 | modulo:2 }}"
337
+ end
338
+
339
+ def test_round
340
+ assert_template_result "5", "{{ input | round }}", 'input' => 4.6
341
+ assert_template_result "4", "{{ '4.3' | round }}"
342
+ assert_template_result "4.56", "{{ input | round: 2 }}", 'input' => 4.5612
343
+ end
344
+
345
+ def test_ceil
346
+ assert_template_result "5", "{{ input | ceil }}", 'input' => 4.6
347
+ assert_template_result "5", "{{ '4.3' | ceil }}"
348
+ end
349
+
350
+ def test_floor
351
+ assert_template_result "4", "{{ input | floor }}", 'input' => 4.6
352
+ assert_template_result "4", "{{ '4.3' | floor }}"
353
+ end
354
+
355
+ def test_append
356
+ assigns = {'a' => 'bc', 'b' => 'd' }
357
+ assert_template_result('bcd',"{{ a | append: 'd'}}",assigns)
358
+ assert_template_result('bcd',"{{ a | append: b}}",assigns)
359
+ end
360
+
361
+ def test_prepend
362
+ assigns = {'a' => 'bc', 'b' => 'a' }
363
+ assert_template_result('abc',"{{ a | prepend: 'a'}}",assigns)
364
+ assert_template_result('abc',"{{ a | prepend: b}}",assigns)
365
+ end
366
+
367
+ def test_default
368
+ assert_equal "foo", @filters.default("foo", "bar")
369
+ assert_equal "bar", @filters.default(nil, "bar")
370
+ assert_equal "bar", @filters.default("", "bar")
371
+ assert_equal "bar", @filters.default(false, "bar")
372
+ assert_equal "bar", @filters.default([], "bar")
373
+ assert_equal "bar", @filters.default({}, "bar")
374
+ end
375
+
376
+ def test_cannot_access_private_methods
377
+ assert_template_result('a',"{{ 'a' | to_number }}")
378
+ end
379
+ end # StandardFiltersTest
@@ -0,0 +1,16 @@
1
+ require 'test_helper'
2
+
3
+ class BreakTagTest < Minitest::Test
4
+ include Liquid
5
+
6
+ # tests that no weird errors are raised if break is called outside of a
7
+ # block
8
+ def test_break_with_no_block
9
+ assigns = {'i' => 1}
10
+ markup = '{% break %}'
11
+ expected = ''
12
+
13
+ assert_template_result(expected, markup, assigns)
14
+ end
15
+
16
+ end