liquid 5.0.1 → 5.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +31 -0
- data/README.md +2 -2
- data/lib/liquid/block_body.rb +2 -2
- data/lib/liquid/condition.rb +10 -4
- data/lib/liquid/context.rb +1 -1
- data/lib/liquid/expression.rb +11 -10
- data/lib/liquid/range_lookup.rb +8 -0
- data/lib/liquid/standardfilters.rb +87 -20
- data/lib/liquid/static_registers.rb +5 -1
- data/lib/liquid/strainer_factory.rb +11 -10
- data/lib/liquid/strainer_template.rb +5 -0
- data/lib/liquid/tags/case.rb +8 -1
- data/lib/liquid/tags/if.rb +5 -1
- data/lib/liquid/tags/unless.rb +10 -2
- data/lib/liquid/tokenizer.rb +2 -2
- data/lib/liquid/utils.rb +8 -0
- data/lib/liquid/variable_lookup.rb +3 -0
- data/lib/liquid/version.rb +1 -1
- data/lib/liquid.rb +2 -2
- data/test/integration/context_test.rb +12 -14
- data/test/integration/filter_kwarg_test.rb +24 -0
- data/test/integration/profiler_test.rb +33 -6
- data/test/integration/standard_filter_test.rb +119 -32
- data/test/integration/template_test.rb +14 -0
- data/test/integration/variable_test.rb +31 -0
- data/test/test_helper.rb +48 -10
- data/test/unit/condition_unit_test.rb +27 -14
- data/test/unit/parse_tree_visitor_test.rb +7 -0
- data/test/unit/strainer_factory_unit_test.rb +2 -1
- data/test/unit/strainer_template_unit_test.rb +1 -1
- metadata +48 -46
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class FilterKwargTest < Minitest::Test
|
6
|
+
module KwargFilter
|
7
|
+
def html_tag(_tag, attributes)
|
8
|
+
attributes
|
9
|
+
.map { |key, value| "#{key}='#{value}'" }
|
10
|
+
.join(' ')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
include Liquid
|
15
|
+
|
16
|
+
def test_can_parse_data_kwargs
|
17
|
+
with_global_filter(KwargFilter) do
|
18
|
+
assert_equal(
|
19
|
+
"data-src='src' data-widths='100, 200'",
|
20
|
+
Template.parse("{{ 'img' | html_tag: data-src: 'src', data-widths: '100, 200' }}").render(nil, nil)
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -3,6 +3,27 @@
|
|
3
3
|
require 'test_helper'
|
4
4
|
|
5
5
|
class ProfilerTest < Minitest::Test
|
6
|
+
class TestDrop < Liquid::Drop
|
7
|
+
def initialize(value)
|
8
|
+
super()
|
9
|
+
@value = value
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
artificial_execution_time
|
14
|
+
|
15
|
+
@value
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# Monotonic clock precision fluctuate based on the operating system
|
21
|
+
# By introducing a small sleep we ensure ourselves to register a non zero unit of time
|
22
|
+
def artificial_execution_time
|
23
|
+
sleep(Process.clock_getres(Process::CLOCK_MONOTONIC))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
6
27
|
include Liquid
|
7
28
|
|
8
29
|
class ProfilingFileSystem
|
@@ -198,16 +219,22 @@ class ProfilerTest < Minitest::Test
|
|
198
219
|
|
199
220
|
def test_profiling_supports_self_time
|
200
221
|
t = Template.parse("{% for item in collection %} {{ item }} {% endfor %}", profile: true)
|
201
|
-
|
202
|
-
|
222
|
+
collection = [
|
223
|
+
TestDrop.new("one"),
|
224
|
+
TestDrop.new("two"),
|
225
|
+
]
|
226
|
+
output = t.render!("collection" => collection)
|
227
|
+
assert_equal(" one two ", output)
|
203
228
|
|
204
|
-
|
229
|
+
leaf = t.profiler[0].children[0]
|
230
|
+
assert_operator(leaf.self_time, :>, 0.0)
|
205
231
|
end
|
206
232
|
|
207
233
|
def test_profiling_supports_total_time
|
208
|
-
t = Template.parse("{% if true %} {
|
209
|
-
t.render!
|
234
|
+
t = Template.parse("{% if true %} {{ test }} {% endif %}", profile: true)
|
235
|
+
output = t.render!("test" => TestDrop.new("one"))
|
236
|
+
assert_equal(" one ", output)
|
210
237
|
|
211
|
-
assert_operator(t.profiler[0].total_time, :>, 0)
|
238
|
+
assert_operator(t.profiler[0].total_time, :>, 0.0)
|
212
239
|
end
|
213
240
|
end
|
@@ -3,10 +3,6 @@
|
|
3
3
|
|
4
4
|
require 'test_helper'
|
5
5
|
|
6
|
-
class Filters
|
7
|
-
include Liquid::StandardFilters
|
8
|
-
end
|
9
|
-
|
10
6
|
class TestThing
|
11
7
|
attr_reader :foo
|
12
8
|
|
@@ -29,8 +25,24 @@ class TestThing
|
|
29
25
|
end
|
30
26
|
|
31
27
|
class TestDrop < Liquid::Drop
|
32
|
-
def
|
33
|
-
|
28
|
+
def initialize(value:)
|
29
|
+
@value = value
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :value
|
33
|
+
|
34
|
+
def registers
|
35
|
+
@context.registers
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class TestModel
|
40
|
+
def initialize(value:)
|
41
|
+
@value = value
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_liquid
|
45
|
+
TestDrop.new(value: @value)
|
34
46
|
end
|
35
47
|
end
|
36
48
|
|
@@ -53,10 +65,13 @@ class NumberLikeThing < Liquid::Drop
|
|
53
65
|
end
|
54
66
|
|
55
67
|
class StandardFiltersTest < Minitest::Test
|
68
|
+
Filters = Class.new(Liquid::StrainerTemplate)
|
69
|
+
Filters.add_filter(Liquid::StandardFilters)
|
70
|
+
|
56
71
|
include Liquid
|
57
72
|
|
58
73
|
def setup
|
59
|
-
@filters = Filters.new
|
74
|
+
@filters = Filters.new(Context.new)
|
60
75
|
end
|
61
76
|
|
62
77
|
def test_size
|
@@ -145,6 +160,40 @@ class StandardFiltersTest < Minitest::Test
|
|
145
160
|
assert_equal('<strong>Hulk</strong>', @filters.escape_once('<strong>Hulk</strong>'))
|
146
161
|
end
|
147
162
|
|
163
|
+
def test_base64_encode
|
164
|
+
assert_equal('b25lIHR3byB0aHJlZQ==', @filters.base64_encode('one two three'))
|
165
|
+
assert_equal('', @filters.base64_encode(nil))
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_base64_decode
|
169
|
+
assert_equal('one two three', @filters.base64_decode('b25lIHR3byB0aHJlZQ=='))
|
170
|
+
|
171
|
+
exception = assert_raises(Liquid::ArgumentError) do
|
172
|
+
@filters.base64_decode("invalidbase64")
|
173
|
+
end
|
174
|
+
|
175
|
+
assert_equal('Liquid error: invalid base64 provided to base64_decode', exception.message)
|
176
|
+
end
|
177
|
+
|
178
|
+
def test_base64_url_safe_encode
|
179
|
+
assert_equal(
|
180
|
+
'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVogMTIzNDU2Nzg5MCAhQCMkJV4mKigpLT1fKy8_Ljo7W117fVx8',
|
181
|
+
@filters.base64_url_safe_encode('abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 !@#$%^&*()-=_+/?.:;[]{}\|')
|
182
|
+
)
|
183
|
+
assert_equal('', @filters.base64_url_safe_encode(nil))
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_base64_url_safe_decode
|
187
|
+
assert_equal(
|
188
|
+
'abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 !@#$%^&*()-=_+/?.:;[]{}\|',
|
189
|
+
@filters.base64_url_safe_decode('YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVogMTIzNDU2Nzg5MCAhQCMkJV4mKigpLT1fKy8_Ljo7W117fVx8')
|
190
|
+
)
|
191
|
+
exception = assert_raises(Liquid::ArgumentError) do
|
192
|
+
@filters.base64_url_safe_decode("invalidbase64")
|
193
|
+
end
|
194
|
+
assert_equal('Liquid error: invalid base64 provided to base64_url_safe_decode', exception.message)
|
195
|
+
end
|
196
|
+
|
148
197
|
def test_url_encode
|
149
198
|
assert_equal('foo%2B1%40example.com', @filters.url_encode('foo+1@example.com'))
|
150
199
|
assert_equal('1', @filters.url_encode(1))
|
@@ -178,6 +227,10 @@ class StandardFiltersTest < Minitest::Test
|
|
178
227
|
assert_equal('one two three...', @filters.truncatewords("one two\tthree\nfour", 3))
|
179
228
|
assert_equal('one two...', @filters.truncatewords("one two three four", 2))
|
180
229
|
assert_equal('one...', @filters.truncatewords("one two three four", 0))
|
230
|
+
exception = assert_raises(Liquid::ArgumentError) do
|
231
|
+
@filters.truncatewords("one two three four", 1 << 31)
|
232
|
+
end
|
233
|
+
assert_equal("Liquid error: integer #{1 << 31} too big for truncatewords", exception.message)
|
181
234
|
end
|
182
235
|
|
183
236
|
def test_strip_html
|
@@ -221,8 +274,8 @@ class StandardFiltersTest < Minitest::Test
|
|
221
274
|
{ "price" => 1, "handle" => "gamma" },
|
222
275
|
{ "price" => 2, "handle" => "epsilon" },
|
223
276
|
{ "price" => 4, "handle" => "alpha" },
|
224
|
-
{ "handle" => "delta" },
|
225
277
|
{ "handle" => "beta" },
|
278
|
+
{ "handle" => "delta" },
|
226
279
|
]
|
227
280
|
assert_equal(expectation, @filters.sort(input, "price"))
|
228
281
|
end
|
@@ -325,8 +378,9 @@ class StandardFiltersTest < Minitest::Test
|
|
325
378
|
assert_equal(["foo"], @filters.uniq("foo"))
|
326
379
|
assert_equal([1, 3, 2, 4], @filters.uniq([1, 1, 3, 2, 3, 1, 4, 3, 2, 1]))
|
327
380
|
assert_equal([{ "a" => 1 }, { "a" => 3 }, { "a" => 2 }], @filters.uniq([{ "a" => 1 }, { "a" => 3 }, { "a" => 1 }, { "a" => 2 }], "a"))
|
328
|
-
|
329
|
-
|
381
|
+
test_drop = TestDrop.new(value: "test")
|
382
|
+
test_drop_alternate = TestDrop.new(value: "test")
|
383
|
+
assert_equal([test_drop], @filters.uniq([test_drop, test_drop_alternate], 'value'))
|
330
384
|
end
|
331
385
|
|
332
386
|
def test_uniq_empty_array
|
@@ -385,6 +439,16 @@ class StandardFiltersTest < Minitest::Test
|
|
385
439
|
assert_template_result("woot: 1", '{{ foo | map: "whatever" }}', "foo" => [t])
|
386
440
|
end
|
387
441
|
|
442
|
+
def test_map_calls_context=
|
443
|
+
model = TestModel.new(value: "test")
|
444
|
+
|
445
|
+
template = Template.parse('{{ foo | map: "registers" }}')
|
446
|
+
template.registers[:test] = 1234
|
447
|
+
template.assigns['foo'] = [model]
|
448
|
+
|
449
|
+
assert_template_result("{:test=>1234}", template.render!)
|
450
|
+
end
|
451
|
+
|
388
452
|
def test_map_on_hashes
|
389
453
|
assert_template_result("4217", '{{ thing | map: "foo" | map: "bar" }}',
|
390
454
|
"thing" => { "foo" => [{ "bar" => 42 }, { "bar" => 17 }] })
|
@@ -403,9 +467,9 @@ class StandardFiltersTest < Minitest::Test
|
|
403
467
|
end
|
404
468
|
|
405
469
|
def test_map_over_proc
|
406
|
-
drop = TestDrop.new
|
470
|
+
drop = TestDrop.new(value: "testfoo")
|
407
471
|
p = proc { drop }
|
408
|
-
templ = '{{ procs | map: "
|
472
|
+
templ = '{{ procs | map: "value" }}'
|
409
473
|
assert_template_result("testfoo", templ, "procs" => [p])
|
410
474
|
end
|
411
475
|
|
@@ -501,19 +565,31 @@ class StandardFiltersTest < Minitest::Test
|
|
501
565
|
end
|
502
566
|
|
503
567
|
def test_replace
|
504
|
-
assert_equal('
|
568
|
+
assert_equal('b b b b', @filters.replace('a a a a', 'a', 'b'))
|
505
569
|
assert_equal('2 2 2 2', @filters.replace('1 1 1 1', 1, 2))
|
506
|
-
assert_equal('
|
570
|
+
assert_equal('1 1 1 1', @filters.replace('1 1 1 1', 2, 3))
|
571
|
+
assert_template_result('2 2 2 2', "{{ '1 1 1 1' | replace: '1', 2 }}")
|
572
|
+
|
573
|
+
assert_equal('b a a a', @filters.replace_first('a a a a', 'a', 'b'))
|
507
574
|
assert_equal('2 1 1 1', @filters.replace_first('1 1 1 1', 1, 2))
|
575
|
+
assert_equal('1 1 1 1', @filters.replace_first('1 1 1 1', 2, 3))
|
508
576
|
assert_template_result('2 1 1 1', "{{ '1 1 1 1' | replace_first: '1', 2 }}")
|
577
|
+
|
578
|
+
assert_equal('a a a b', @filters.replace_last('a a a a', 'a', 'b'))
|
579
|
+
assert_equal('1 1 1 2', @filters.replace_last('1 1 1 1', 1, 2))
|
580
|
+
assert_equal('1 1 1 1', @filters.replace_last('1 1 1 1', 2, 3))
|
581
|
+
assert_template_result('1 1 1 2', "{{ '1 1 1 1' | replace_last: '1', 2 }}")
|
509
582
|
end
|
510
583
|
|
511
584
|
def test_remove
|
512
585
|
assert_equal(' ', @filters.remove("a a a a", 'a'))
|
513
|
-
|
514
|
-
|
515
|
-
assert_equal('
|
516
|
-
assert_template_result('
|
586
|
+
assert_template_result(' ', "{{ '1 1 1 1' | remove: 1 }}")
|
587
|
+
|
588
|
+
assert_equal('b a a', @filters.remove_first("a b a a", 'a '))
|
589
|
+
assert_template_result(' 1 1 1', "{{ '1 1 1 1' | remove_first: 1 }}")
|
590
|
+
|
591
|
+
assert_equal('a a b', @filters.remove_last("a a b a", ' a'))
|
592
|
+
assert_template_result('1 1 1 ', "{{ '1 1 1 1' | remove_last: 1 }}")
|
517
593
|
end
|
518
594
|
|
519
595
|
def test_pipes_in_string_arguments
|
@@ -690,6 +766,8 @@ class StandardFiltersTest < Minitest::Test
|
|
690
766
|
assert_equal("bar", @filters.default([], "bar"))
|
691
767
|
assert_equal("bar", @filters.default({}, "bar"))
|
692
768
|
assert_template_result('bar', "{{ false | default: 'bar' }}")
|
769
|
+
assert_template_result('bar', "{{ drop | default: 'bar' }}", 'drop' => BooleanDrop.new(false))
|
770
|
+
assert_template_result('Yay', "{{ drop | default: 'bar' }}", 'drop' => BooleanDrop.new(true))
|
693
771
|
end
|
694
772
|
|
695
773
|
def test_default_handle_false
|
@@ -700,6 +778,8 @@ class StandardFiltersTest < Minitest::Test
|
|
700
778
|
assert_equal("bar", @filters.default([], "bar", "allow_false" => true))
|
701
779
|
assert_equal("bar", @filters.default({}, "bar", "allow_false" => true))
|
702
780
|
assert_template_result('false', "{{ false | default: 'bar', allow_false: true }}")
|
781
|
+
assert_template_result('Nay', "{{ drop | default: 'bar', allow_false: true }}", 'drop' => BooleanDrop.new(false))
|
782
|
+
assert_template_result('Yay', "{{ drop | default: 'bar', allow_false: true }}", 'drop' => BooleanDrop.new(true))
|
703
783
|
end
|
704
784
|
|
705
785
|
def test_cannot_access_private_methods
|
@@ -728,6 +808,18 @@ class StandardFiltersTest < Minitest::Test
|
|
728
808
|
assert_equal(expectation, @filters.where(input, "ok"))
|
729
809
|
end
|
730
810
|
|
811
|
+
def test_where_string_keys
|
812
|
+
input = [
|
813
|
+
"alpha", "beta", "gamma", "delta"
|
814
|
+
]
|
815
|
+
|
816
|
+
expectation = [
|
817
|
+
"beta",
|
818
|
+
]
|
819
|
+
|
820
|
+
assert_equal(expectation, @filters.where(input, "be"))
|
821
|
+
end
|
822
|
+
|
731
823
|
def test_where_no_key_set
|
732
824
|
input = [
|
733
825
|
{ "handle" => "alpha", "ok" => true },
|
@@ -773,7 +865,7 @@ class StandardFiltersTest < Minitest::Test
|
|
773
865
|
end
|
774
866
|
|
775
867
|
def test_all_filters_never_raise_non_liquid_exception
|
776
|
-
test_drop = TestDrop.new
|
868
|
+
test_drop = TestDrop.new(value: "test")
|
777
869
|
test_drop.context = Context.new
|
778
870
|
test_enum = TestEnumerable.new
|
779
871
|
test_enum.context = Context.new
|
@@ -798,19 +890,14 @@ class StandardFiltersTest < Minitest::Test
|
|
798
890
|
{ 1 => "bar" },
|
799
891
|
["foo", 123, nil, true, false, Drop, ["foo"], { foo: "bar" }],
|
800
892
|
]
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
@filters.send(method, *inputs)
|
810
|
-
rescue Liquid::ArgumentError, Liquid::ZeroDivisionError
|
811
|
-
nil
|
812
|
-
end
|
813
|
-
end
|
893
|
+
StandardFilters.public_instance_methods(false).each do |method|
|
894
|
+
arg_count = @filters.method(method).arity
|
895
|
+
arg_count *= -1 if arg_count < 0
|
896
|
+
|
897
|
+
test_types.repeated_permutation(arg_count) do |args|
|
898
|
+
@filters.send(method, *args)
|
899
|
+
rescue Liquid::Error
|
900
|
+
nil
|
814
901
|
end
|
815
902
|
end
|
816
903
|
end
|
@@ -323,4 +323,18 @@ class TemplateTest < Minitest::Test
|
|
323
323
|
result = t.render('x' => 1, 'y' => 5)
|
324
324
|
assert_equal('12345', result)
|
325
325
|
end
|
326
|
+
|
327
|
+
def test_source_string_subclass
|
328
|
+
string_subclass = Class.new(String) do
|
329
|
+
# E.g. ActiveSupport::SafeBuffer does this, so don't just rely on to_s to return a String
|
330
|
+
def to_s
|
331
|
+
self
|
332
|
+
end
|
333
|
+
end
|
334
|
+
source = string_subclass.new("{% assign x = 2 -%} x= {{- x }}")
|
335
|
+
assert_instance_of(string_subclass, source)
|
336
|
+
output = Template.parse(source).render!
|
337
|
+
assert_equal("x=2", output)
|
338
|
+
assert_instance_of(String, output)
|
339
|
+
end
|
326
340
|
end
|
@@ -15,6 +15,33 @@ class VariableTest < Minitest::Test
|
|
15
15
|
assert_template_result('foobar', '{{ foo }}', 'foo' => ThingWithToLiquid.new)
|
16
16
|
end
|
17
17
|
|
18
|
+
def test_variable_lookup_calls_to_liquid_value
|
19
|
+
assert_template_result('1', '{{ foo }}', 'foo' => IntegerDrop.new('1'))
|
20
|
+
assert_template_result('2', '{{ list[foo] }}', 'foo' => IntegerDrop.new('1'), 'list' => [1, 2, 3])
|
21
|
+
assert_template_result('one', '{{ list[foo] }}', 'foo' => IntegerDrop.new('1'), 'list' => { 1 => 'one' })
|
22
|
+
assert_template_result('Yay', '{{ foo }}', 'foo' => BooleanDrop.new(true))
|
23
|
+
assert_template_result('YAY', '{{ foo | upcase }}', 'foo' => BooleanDrop.new(true))
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_if_tag_calls_to_liquid_value
|
27
|
+
assert_template_result('one', '{% if foo == 1 %}one{% endif %}', 'foo' => IntegerDrop.new('1'))
|
28
|
+
assert_template_result('one', '{% if 0 < foo %}one{% endif %}', 'foo' => IntegerDrop.new('1'))
|
29
|
+
assert_template_result('one', '{% if foo > 0 %}one{% endif %}', 'foo' => IntegerDrop.new('1'))
|
30
|
+
assert_template_result('true', '{% if foo == true %}true{% endif %}', 'foo' => BooleanDrop.new(true))
|
31
|
+
assert_template_result('true', '{% if foo %}true{% endif %}', 'foo' => BooleanDrop.new(true))
|
32
|
+
|
33
|
+
assert_template_result('', '{% if foo %}true{% endif %}', 'foo' => BooleanDrop.new(false))
|
34
|
+
assert_template_result('', '{% if foo == true %}True{% endif %}', 'foo' => BooleanDrop.new(false))
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_unless_tag_calls_to_liquid_value
|
38
|
+
assert_template_result('', '{% unless foo %}true{% endunless %}', 'foo' => BooleanDrop.new(true))
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_case_tag_calls_to_liquid_value
|
42
|
+
assert_template_result('One', '{% case foo %}{% when 1 %}One{% endcase %}', 'foo' => IntegerDrop.new('1'))
|
43
|
+
end
|
44
|
+
|
18
45
|
def test_simple_with_whitespaces
|
19
46
|
template = Template.parse(%( {{ test }} ))
|
20
47
|
assert_equal(' worked ', template.render!('test' => 'worked'))
|
@@ -104,4 +131,8 @@ class VariableTest < Minitest::Test
|
|
104
131
|
def test_dynamic_find_var
|
105
132
|
assert_template_result('bar', '{{ [key] }}', 'key' => 'foo', 'foo' => 'bar')
|
106
133
|
end
|
134
|
+
|
135
|
+
def test_raw_value_variable
|
136
|
+
assert_template_result('bar', '{{ [key] }}', 'key' => 'foo', 'foo' => 'bar')
|
137
|
+
end
|
107
138
|
end
|
data/test/test_helper.rb
CHANGED
@@ -72,21 +72,21 @@ module Minitest
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def with_global_filter(*globals)
|
75
|
-
|
76
|
-
Liquid::StrainerFactory.
|
77
|
-
|
78
|
-
Liquid::StrainerFactory.add_global_filter(global)
|
79
|
-
end
|
80
|
-
|
81
|
-
Liquid::StrainerFactory.send(:strainer_class_cache).clear
|
75
|
+
original_global_cache = Liquid::StrainerFactory::GlobalCache
|
76
|
+
Liquid::StrainerFactory.send(:remove_const, :GlobalCache)
|
77
|
+
Liquid::StrainerFactory.const_set(:GlobalCache, Class.new(Liquid::StrainerTemplate))
|
82
78
|
|
83
79
|
globals.each do |global|
|
84
80
|
Liquid::Template.register_filter(global)
|
85
81
|
end
|
86
|
-
yield
|
87
|
-
ensure
|
88
82
|
Liquid::StrainerFactory.send(:strainer_class_cache).clear
|
89
|
-
|
83
|
+
begin
|
84
|
+
yield
|
85
|
+
ensure
|
86
|
+
Liquid::StrainerFactory.send(:remove_const, :GlobalCache)
|
87
|
+
Liquid::StrainerFactory.const_set(:GlobalCache, original_global_cache)
|
88
|
+
Liquid::StrainerFactory.send(:strainer_class_cache).clear
|
89
|
+
end
|
90
90
|
end
|
91
91
|
|
92
92
|
def with_error_mode(mode)
|
@@ -119,6 +119,44 @@ class ThingWithToLiquid
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
+
class IntegerDrop < Liquid::Drop
|
123
|
+
def initialize(value)
|
124
|
+
super()
|
125
|
+
@value = value.to_i
|
126
|
+
end
|
127
|
+
|
128
|
+
def ==(other)
|
129
|
+
@value == other
|
130
|
+
end
|
131
|
+
|
132
|
+
def to_s
|
133
|
+
@value.to_s
|
134
|
+
end
|
135
|
+
|
136
|
+
def to_liquid_value
|
137
|
+
@value
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class BooleanDrop < Liquid::Drop
|
142
|
+
def initialize(value)
|
143
|
+
super()
|
144
|
+
@value = value
|
145
|
+
end
|
146
|
+
|
147
|
+
def ==(other)
|
148
|
+
@value == other
|
149
|
+
end
|
150
|
+
|
151
|
+
def to_liquid_value
|
152
|
+
@value
|
153
|
+
end
|
154
|
+
|
155
|
+
def to_s
|
156
|
+
@value ? "Yay" : "Nay"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
122
160
|
class ErrorDrop < Liquid::Drop
|
123
161
|
def standard_error
|
124
162
|
raise Liquid::StandardError, 'standard error'
|
@@ -10,8 +10,8 @@ class ConditionUnitTest < Minitest::Test
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def test_basic_condition
|
13
|
-
assert_equal(false, Condition.new(1, '==', 2).evaluate)
|
14
|
-
assert_equal(true, Condition.new(1, '==', 1).evaluate)
|
13
|
+
assert_equal(false, Condition.new(1, '==', 2).evaluate(Context.new))
|
14
|
+
assert_equal(true, Condition.new(1, '==', 1).evaluate(Context.new))
|
15
15
|
end
|
16
16
|
|
17
17
|
def test_default_operators_evalute_true
|
@@ -67,11 +67,11 @@ class ConditionUnitTest < Minitest::Test
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def test_hash_compare_backwards_compatibility
|
70
|
-
assert_nil(Condition.new({}, '>', 2).evaluate)
|
71
|
-
assert_nil(Condition.new(2, '>', {}).evaluate)
|
72
|
-
assert_equal(false, Condition.new({}, '==', 2).evaluate)
|
73
|
-
assert_equal(true, Condition.new({ 'a' => 1 }, '==', 'a' => 1).evaluate)
|
74
|
-
assert_equal(true, Condition.new({ 'a' => 2 }, 'contains', 'a').evaluate)
|
70
|
+
assert_nil(Condition.new({}, '>', 2).evaluate(Context.new))
|
71
|
+
assert_nil(Condition.new(2, '>', {}).evaluate(Context.new))
|
72
|
+
assert_equal(false, Condition.new({}, '==', 2).evaluate(Context.new))
|
73
|
+
assert_equal(true, Condition.new({ 'a' => 1 }, '==', 'a' => 1).evaluate(Context.new))
|
74
|
+
assert_equal(true, Condition.new({ 'a' => 2 }, 'contains', 'a').evaluate(Context.new))
|
75
75
|
end
|
76
76
|
|
77
77
|
def test_contains_works_on_arrays
|
@@ -106,30 +106,29 @@ class ConditionUnitTest < Minitest::Test
|
|
106
106
|
|
107
107
|
def test_or_condition
|
108
108
|
condition = Condition.new(1, '==', 2)
|
109
|
-
|
110
|
-
assert_equal(false, condition.evaluate)
|
109
|
+
assert_equal(false, condition.evaluate(Context.new))
|
111
110
|
|
112
111
|
condition.or(Condition.new(2, '==', 1))
|
113
112
|
|
114
|
-
assert_equal(false, condition.evaluate)
|
113
|
+
assert_equal(false, condition.evaluate(Context.new))
|
115
114
|
|
116
115
|
condition.or(Condition.new(1, '==', 1))
|
117
116
|
|
118
|
-
assert_equal(true, condition.evaluate)
|
117
|
+
assert_equal(true, condition.evaluate(Context.new))
|
119
118
|
end
|
120
119
|
|
121
120
|
def test_and_condition
|
122
121
|
condition = Condition.new(1, '==', 1)
|
123
122
|
|
124
|
-
assert_equal(true, condition.evaluate)
|
123
|
+
assert_equal(true, condition.evaluate(Context.new))
|
125
124
|
|
126
125
|
condition.and(Condition.new(2, '==', 2))
|
127
126
|
|
128
|
-
assert_equal(true, condition.evaluate)
|
127
|
+
assert_equal(true, condition.evaluate(Context.new))
|
129
128
|
|
130
129
|
condition.and(Condition.new(2, '==', 1))
|
131
130
|
|
132
|
-
assert_equal(false, condition.evaluate)
|
131
|
+
assert_equal(false, condition.evaluate(Context.new))
|
133
132
|
end
|
134
133
|
|
135
134
|
def test_should_allow_custom_proc_operator
|
@@ -148,6 +147,20 @@ class ConditionUnitTest < Minitest::Test
|
|
148
147
|
assert_evaluates_true(VariableLookup.new("one"), '==', VariableLookup.new("another"))
|
149
148
|
end
|
150
149
|
|
150
|
+
def test_default_context_is_deprecated
|
151
|
+
if Gem::Version.new(Liquid::VERSION) >= Gem::Version.new('6.0.0')
|
152
|
+
flunk("Condition#evaluate without a context argument is to be removed")
|
153
|
+
end
|
154
|
+
|
155
|
+
_out, err = capture_io do
|
156
|
+
assert_equal(true, Condition.new(1, '==', 1).evaluate)
|
157
|
+
end
|
158
|
+
|
159
|
+
expected = "DEPRECATION WARNING: Condition#evaluate without a context argument is deprecated" \
|
160
|
+
" and will be removed from Liquid 6.0.0."
|
161
|
+
assert_includes(err.lines.map(&:strip), expected)
|
162
|
+
end
|
163
|
+
|
151
164
|
private
|
152
165
|
|
153
166
|
def assert_evaluates_true(left, op, right)
|
@@ -159,6 +159,13 @@ class ParseTreeVisitorTest < Minitest::Test
|
|
159
159
|
)
|
160
160
|
end
|
161
161
|
|
162
|
+
def test_for_range
|
163
|
+
assert_equal(
|
164
|
+
["test"],
|
165
|
+
visit(%({% for x in (1..test) %}{% endfor %}))
|
166
|
+
)
|
167
|
+
end
|
168
|
+
|
162
169
|
def test_tablerow_in
|
163
170
|
assert_equal(
|
164
171
|
["test"],
|
@@ -52,7 +52,8 @@ class StrainerFactoryUnitTest < Minitest::Test
|
|
52
52
|
/\ALiquid error: wrong number of arguments \((1 for 0|given 1, expected 0)\)\z/,
|
53
53
|
exception.message
|
54
54
|
)
|
55
|
-
|
55
|
+
source = AccessScopeFilters.instance_method(:public_filter).source_location
|
56
|
+
assert_equal(source.map(&:to_s), exception.backtrace[0].split(':')[0..1])
|
56
57
|
end
|
57
58
|
|
58
59
|
def test_strainer_only_invokes_public_filter_methods
|
@@ -57,8 +57,8 @@ class StrainerTemplateUnitTest < Minitest::Test
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def test_add_filter_does_not_raise_when_module_overrides_previously_registered_method
|
60
|
-
strainer = Context.new.strainer
|
61
60
|
with_global_filter do
|
61
|
+
strainer = Context.new.strainer
|
62
62
|
strainer.class.add_filter(PublicMethodOverrideFilter)
|
63
63
|
assert(strainer.class.send(:filter_methods).include?('public_filter'))
|
64
64
|
end
|