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.
Files changed (123) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +93 -2
  3. data/README.md +8 -0
  4. data/lib/liquid.rb +18 -5
  5. data/lib/liquid/block.rb +47 -20
  6. data/lib/liquid/block_body.rb +190 -76
  7. data/lib/liquid/condition.rb +69 -29
  8. data/lib/liquid/context.rb +122 -76
  9. data/lib/liquid/document.rb +47 -9
  10. data/lib/liquid/drop.rb +4 -2
  11. data/lib/liquid/errors.rb +20 -25
  12. data/lib/liquid/expression.rb +30 -31
  13. data/lib/liquid/extensions.rb +8 -0
  14. data/lib/liquid/file_system.rb +6 -4
  15. data/lib/liquid/forloop_drop.rb +11 -4
  16. data/lib/liquid/i18n.rb +5 -3
  17. data/lib/liquid/interrupts.rb +3 -1
  18. data/lib/liquid/lexer.rb +35 -26
  19. data/lib/liquid/locales/en.yml +4 -2
  20. data/lib/liquid/parse_context.rb +17 -4
  21. data/lib/liquid/parse_tree_visitor.rb +42 -0
  22. data/lib/liquid/parser.rb +30 -18
  23. data/lib/liquid/parser_switching.rb +17 -3
  24. data/lib/liquid/partial_cache.rb +24 -0
  25. data/lib/liquid/profiler.rb +67 -86
  26. data/lib/liquid/profiler/hooks.rb +26 -14
  27. data/lib/liquid/range_lookup.rb +5 -3
  28. data/lib/liquid/register.rb +6 -0
  29. data/lib/liquid/resource_limits.rb +47 -8
  30. data/lib/liquid/standardfilters.rb +171 -57
  31. data/lib/liquid/static_registers.rb +44 -0
  32. data/lib/liquid/strainer_factory.rb +36 -0
  33. data/lib/liquid/strainer_template.rb +53 -0
  34. data/lib/liquid/tablerowloop_drop.rb +6 -4
  35. data/lib/liquid/tag.rb +28 -6
  36. data/lib/liquid/tag/disableable.rb +22 -0
  37. data/lib/liquid/tag/disabler.rb +21 -0
  38. data/lib/liquid/tags/assign.rb +32 -10
  39. data/lib/liquid/tags/break.rb +8 -3
  40. data/lib/liquid/tags/capture.rb +11 -8
  41. data/lib/liquid/tags/case.rb +41 -27
  42. data/lib/liquid/tags/comment.rb +5 -3
  43. data/lib/liquid/tags/continue.rb +8 -3
  44. data/lib/liquid/tags/cycle.rb +35 -16
  45. data/lib/liquid/tags/decrement.rb +6 -3
  46. data/lib/liquid/tags/echo.rb +26 -0
  47. data/lib/liquid/tags/for.rb +79 -47
  48. data/lib/liquid/tags/if.rb +53 -30
  49. data/lib/liquid/tags/ifchanged.rb +11 -10
  50. data/lib/liquid/tags/include.rb +42 -44
  51. data/lib/liquid/tags/increment.rb +7 -3
  52. data/lib/liquid/tags/raw.rb +14 -11
  53. data/lib/liquid/tags/render.rb +84 -0
  54. data/lib/liquid/tags/table_row.rb +32 -20
  55. data/lib/liquid/tags/unless.rb +15 -15
  56. data/lib/liquid/template.rb +60 -71
  57. data/lib/liquid/template_factory.rb +9 -0
  58. data/lib/liquid/tokenizer.rb +17 -9
  59. data/lib/liquid/usage.rb +8 -0
  60. data/lib/liquid/utils.rb +6 -4
  61. data/lib/liquid/variable.rb +55 -38
  62. data/lib/liquid/variable_lookup.rb +14 -6
  63. data/lib/liquid/version.rb +3 -1
  64. data/test/integration/assign_test.rb +74 -5
  65. data/test/integration/blank_test.rb +11 -8
  66. data/test/integration/block_test.rb +58 -0
  67. data/test/integration/capture_test.rb +18 -10
  68. data/test/integration/context_test.rb +608 -5
  69. data/test/integration/document_test.rb +4 -2
  70. data/test/integration/drop_test.rb +67 -83
  71. data/test/integration/error_handling_test.rb +90 -60
  72. data/test/integration/expression_test.rb +46 -0
  73. data/test/integration/filter_test.rb +53 -42
  74. data/test/integration/hash_ordering_test.rb +5 -3
  75. data/test/integration/output_test.rb +26 -24
  76. data/test/integration/parsing_quirks_test.rb +24 -8
  77. data/test/integration/{render_profiling_test.rb → profiler_test.rb} +84 -25
  78. data/test/integration/security_test.rb +41 -18
  79. data/test/integration/standard_filter_test.rb +523 -205
  80. data/test/integration/tag/disableable_test.rb +59 -0
  81. data/test/integration/tag_test.rb +45 -0
  82. data/test/integration/tags/break_tag_test.rb +4 -2
  83. data/test/integration/tags/continue_tag_test.rb +4 -2
  84. data/test/integration/tags/echo_test.rb +13 -0
  85. data/test/integration/tags/for_tag_test.rb +109 -53
  86. data/test/integration/tags/if_else_tag_test.rb +5 -3
  87. data/test/integration/tags/include_tag_test.rb +83 -52
  88. data/test/integration/tags/increment_tag_test.rb +4 -2
  89. data/test/integration/tags/liquid_tag_test.rb +116 -0
  90. data/test/integration/tags/raw_tag_test.rb +14 -11
  91. data/test/integration/tags/render_tag_test.rb +213 -0
  92. data/test/integration/tags/standard_tag_test.rb +38 -31
  93. data/test/integration/tags/statements_test.rb +23 -21
  94. data/test/integration/tags/table_row_test.rb +2 -0
  95. data/test/integration/tags/unless_else_tag_test.rb +4 -2
  96. data/test/integration/template_test.rb +128 -121
  97. data/test/integration/trim_mode_test.rb +82 -44
  98. data/test/integration/variable_test.rb +46 -31
  99. data/test/test_helper.rb +75 -23
  100. data/test/unit/block_unit_test.rb +19 -24
  101. data/test/unit/condition_unit_test.rb +82 -72
  102. data/test/unit/file_system_unit_test.rb +6 -4
  103. data/test/unit/i18n_unit_test.rb +7 -5
  104. data/test/unit/lexer_unit_test.rb +12 -10
  105. data/test/unit/parse_tree_visitor_test.rb +247 -0
  106. data/test/unit/parser_unit_test.rb +37 -35
  107. data/test/unit/partial_cache_unit_test.rb +128 -0
  108. data/test/unit/regexp_unit_test.rb +17 -15
  109. data/test/unit/static_registers_unit_test.rb +156 -0
  110. data/test/unit/strainer_factory_unit_test.rb +100 -0
  111. data/test/unit/strainer_template_unit_test.rb +82 -0
  112. data/test/unit/tag_unit_test.rb +5 -3
  113. data/test/unit/tags/case_tag_unit_test.rb +3 -1
  114. data/test/unit/tags/for_tag_unit_test.rb +4 -2
  115. data/test/unit/tags/if_tag_unit_test.rb +3 -1
  116. data/test/unit/template_factory_unit_test.rb +12 -0
  117. data/test/unit/template_unit_test.rb +19 -10
  118. data/test/unit/tokenizer_unit_test.rb +19 -17
  119. data/test/unit/variable_unit_test.rb +51 -49
  120. metadata +83 -50
  121. data/lib/liquid/strainer.rb +0 -65
  122. data/test/unit/context_unit_test.rb +0 -483
  123. 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 VariableTest < Minitest::Test
@@ -5,88 +7,101 @@ class VariableTest < Minitest::Test
5
7
 
6
8
  def test_simple_variable
7
9
  template = Template.parse(%({{test}}))
8
- assert_equal 'worked', template.render!('test' => 'worked')
9
- assert_equal 'worked wonderfully', template.render!('test' => 'worked wonderfully')
10
+ assert_equal('worked', template.render!('test' => 'worked'))
11
+ assert_equal('worked wonderfully', template.render!('test' => 'worked wonderfully'))
10
12
  end
11
13
 
12
14
  def test_variable_render_calls_to_liquid
13
- assert_template_result 'foobar', '{{ foo }}', 'foo' => ThingWithToLiquid.new
15
+ assert_template_result('foobar', '{{ foo }}', 'foo' => ThingWithToLiquid.new)
14
16
  end
15
17
 
16
18
  def test_simple_with_whitespaces
17
19
  template = Template.parse(%( {{ test }} ))
18
- assert_equal ' worked ', template.render!('test' => 'worked')
19
- assert_equal ' worked wonderfully ', template.render!('test' => 'worked wonderfully')
20
+ assert_equal(' worked ', template.render!('test' => 'worked'))
21
+ assert_equal(' worked wonderfully ', template.render!('test' => 'worked wonderfully'))
22
+ end
23
+
24
+ def test_expression_with_whitespace_in_square_brackets
25
+ assert_template_result('result', "{{ a[ 'b' ] }}", 'a' => { 'b' => 'result' })
26
+ assert_template_result('result', "{{ a[ [ 'b' ] ] }}", 'b' => 'c', 'a' => { 'c' => 'result' })
20
27
  end
21
28
 
22
29
  def test_ignore_unknown
23
30
  template = Template.parse(%({{ test }}))
24
- assert_equal '', template.render!
31
+ assert_equal('', template.render!)
25
32
  end
26
33
 
27
34
  def test_using_blank_as_variable_name
28
35
  template = Template.parse("{% assign foo = blank %}{{ foo }}")
29
- assert_equal '', template.render!
36
+ assert_equal('', template.render!)
30
37
  end
31
38
 
32
39
  def test_using_empty_as_variable_name
33
40
  template = Template.parse("{% assign foo = empty %}{{ foo }}")
34
- assert_equal '', template.render!
41
+ assert_equal('', template.render!)
35
42
  end
36
43
 
37
44
  def test_hash_scoping
38
- template = Template.parse(%({{ test.test }}))
39
- assert_equal 'worked', template.render!('test' => { 'test' => 'worked' })
45
+ assert_template_result('worked', "{{ test.test }}", 'test' => { 'test' => 'worked' })
46
+ assert_template_result('worked', "{{ test . test }}", 'test' => { 'test' => 'worked' })
40
47
  end
41
48
 
42
49
  def test_false_renders_as_false
43
- assert_equal 'false', Template.parse("{{ foo }}").render!('foo' => false)
44
- assert_equal 'false', Template.parse("{{ false }}").render!
50
+ assert_equal('false', Template.parse("{{ foo }}").render!('foo' => false))
51
+ assert_equal('false', Template.parse("{{ false }}").render!)
45
52
  end
46
53
 
47
54
  def test_nil_renders_as_empty_string
48
- assert_equal '', Template.parse("{{ nil }}").render!
49
- assert_equal 'cat', Template.parse("{{ nil | append: 'cat' }}").render!
55
+ assert_equal('', Template.parse("{{ nil }}").render!)
56
+ assert_equal('cat', Template.parse("{{ nil | append: 'cat' }}").render!)
50
57
  end
51
58
 
52
59
  def test_preset_assigns
53
- template = Template.parse(%({{ test }}))
60
+ template = Template.parse(%({{ test }}))
54
61
  template.assigns['test'] = 'worked'
55
- assert_equal 'worked', template.render!
62
+ assert_equal('worked', template.render!)
56
63
  end
57
64
 
58
65
  def test_reuse_parsed_template
59
- template = Template.parse(%({{ greeting }} {{ name }}))
66
+ template = Template.parse(%({{ greeting }} {{ name }}))
60
67
  template.assigns['greeting'] = 'Goodbye'
61
- assert_equal 'Hello Tobi', template.render!('greeting' => 'Hello', 'name' => 'Tobi')
62
- assert_equal 'Hello ', template.render!('greeting' => 'Hello', 'unknown' => 'Tobi')
63
- assert_equal 'Hello Brian', template.render!('greeting' => 'Hello', 'name' => 'Brian')
64
- assert_equal 'Goodbye Brian', template.render!('name' => 'Brian')
68
+ assert_equal('Hello Tobi', template.render!('greeting' => 'Hello', 'name' => 'Tobi'))
69
+ assert_equal('Hello ', template.render!('greeting' => 'Hello', 'unknown' => 'Tobi'))
70
+ assert_equal('Hello Brian', template.render!('greeting' => 'Hello', 'name' => 'Brian'))
71
+ assert_equal('Goodbye Brian', template.render!('name' => 'Brian'))
65
72
  assert_equal({ 'greeting' => 'Goodbye' }, template.assigns)
66
73
  end
67
74
 
68
75
  def test_assigns_not_polluted_from_template
69
- template = Template.parse(%({{ test }}{% assign test = 'bar' %}{{ test }}))
76
+ template = Template.parse(%({{ test }}{% assign test = 'bar' %}{{ test }}))
70
77
  template.assigns['test'] = 'baz'
71
- assert_equal 'bazbar', template.render!
72
- assert_equal 'bazbar', template.render!
73
- assert_equal 'foobar', template.render!('test' => 'foo')
74
- assert_equal 'bazbar', template.render!
78
+ assert_equal('bazbar', template.render!)
79
+ assert_equal('bazbar', template.render!)
80
+ assert_equal('foobar', template.render!('test' => 'foo'))
81
+ assert_equal('bazbar', template.render!)
75
82
  end
76
83
 
77
84
  def test_hash_with_default_proc
78
- template = Template.parse(%(Hello {{ test }}))
79
- assigns = Hash.new { |h, k| raise "Unknown variable '#{k}'" }
85
+ template = Template.parse(%(Hello {{ test }}))
86
+ assigns = Hash.new { |_h, k| raise "Unknown variable '#{k}'" }
80
87
  assigns['test'] = 'Tobi'
81
- assert_equal 'Hello Tobi', template.render!(assigns)
88
+ assert_equal('Hello Tobi', template.render!(assigns))
82
89
  assigns.delete('test')
83
90
  e = assert_raises(RuntimeError) do
84
91
  template.render!(assigns)
85
92
  end
86
- assert_equal "Unknown variable 'test'", e.message
93
+ assert_equal("Unknown variable 'test'", e.message)
87
94
  end
88
95
 
89
96
  def test_multiline_variable
90
- assert_equal 'worked', Template.parse("{{\ntest\n}}").render!('test' => 'worked')
97
+ assert_equal('worked', Template.parse("{{\ntest\n}}").render!('test' => 'worked'))
98
+ end
99
+
100
+ def test_render_symbol
101
+ assert_template_result('bar', '{{ foo }}', 'foo' => :bar)
102
+ end
103
+
104
+ def test_dynamic_find_var
105
+ assert_template_result('bar', '{{ [key] }}', 'key' => 'foo', 'foo' => 'bar')
91
106
  end
92
107
  end
@@ -1,21 +1,21 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  ENV["MT_NO_EXPECTATIONS"] = "1"
4
5
  require 'minitest/autorun'
5
- require 'spy/integration'
6
6
 
7
7
  $LOAD_PATH.unshift(File.join(File.expand_path(__dir__), '..', 'lib'))
8
8
  require 'liquid.rb'
9
9
  require 'liquid/profiler'
10
10
 
11
11
  mode = :strict
12
- if env_mode = ENV['LIQUID_PARSER_MODE']
12
+ if (env_mode = ENV['LIQUID_PARSER_MODE'])
13
13
  puts "-- #{env_mode.upcase} ERROR MODE"
14
14
  mode = env_mode.to_sym
15
15
  end
16
16
  Liquid::Template.error_mode = mode
17
17
 
18
- if ENV['LIQUID-C'] == '1'
18
+ if ENV['LIQUID_C'] == '1'
19
19
  puts "-- LIQUID C"
20
20
  require 'liquid/c'
21
21
  end
@@ -38,44 +38,55 @@ module Minitest
38
38
  include Liquid
39
39
 
40
40
  def assert_template_result(expected, template, assigns = {}, message = nil)
41
- assert_equal expected, Template.parse(template).render!(assigns), message
41
+ assert_equal(expected, Template.parse(template, line_numbers: true).render!(assigns), message)
42
42
  end
43
43
 
44
44
  def assert_template_result_matches(expected, template, assigns = {}, message = nil)
45
- return assert_template_result(expected, template, assigns, message) unless expected.is_a? Regexp
45
+ return assert_template_result(expected, template, assigns, message) unless expected.is_a?(Regexp)
46
46
 
47
- assert_match expected, Template.parse(template).render!(assigns), message
47
+ assert_match(expected, Template.parse(template, line_numbers: true).render!(assigns), message)
48
48
  end
49
49
 
50
50
  def assert_match_syntax_error(match, template, assigns = {})
51
51
  exception = assert_raises(Liquid::SyntaxError) do
52
- Template.parse(template).render(assigns)
52
+ Template.parse(template, line_numbers: true).render(assigns)
53
53
  end
54
- assert_match match, exception.message
54
+ assert_match(match, exception.message)
55
+ end
56
+
57
+ def assert_usage_increment(name, times: 1)
58
+ old_method = Liquid::Usage.method(:increment)
59
+ calls = 0
60
+ begin
61
+ Liquid::Usage.singleton_class.send(:remove_method, :increment)
62
+ Liquid::Usage.define_singleton_method(:increment) do |got_name|
63
+ calls += 1 if got_name == name
64
+ old_method.call(got_name)
65
+ end
66
+ yield
67
+ ensure
68
+ Liquid::Usage.singleton_class.send(:remove_method, :increment)
69
+ Liquid::Usage.define_singleton_method(:increment, old_method)
70
+ end
71
+ assert_equal(times, calls, "Number of calls to Usage.increment with #{name.inspect}")
55
72
  end
56
73
 
57
74
  def with_global_filter(*globals)
58
- original_global_strainer = Liquid::Strainer.class_variable_get(:@@global_strainer)
59
- Liquid::Strainer.class_variable_set(:@@global_strainer, Class.new(Liquid::Strainer) do
60
- @filter_methods = Set.new
61
- end)
62
- Liquid::Strainer.class_variable_get(:@@strainer_class_cache).clear
75
+ original_global_filters = Liquid::StrainerFactory.instance_variable_get(:@global_filters)
76
+ Liquid::StrainerFactory.instance_variable_set(:@global_filters, [])
77
+ globals.each do |global|
78
+ Liquid::StrainerFactory.add_global_filter(global)
79
+ end
80
+
81
+ Liquid::StrainerFactory.send(:strainer_class_cache).clear
63
82
 
64
83
  globals.each do |global|
65
84
  Liquid::Template.register_filter(global)
66
85
  end
67
86
  yield
68
87
  ensure
69
- Liquid::Strainer.class_variable_get(:@@strainer_class_cache).clear
70
- Liquid::Strainer.class_variable_set(:@@global_strainer, original_global_strainer)
71
- end
72
-
73
- def with_taint_mode(mode)
74
- old_mode = Liquid::Template.taint_mode
75
- Liquid::Template.taint_mode = mode
76
- yield
77
- ensure
78
- Liquid::Template.taint_mode = old_mode
88
+ Liquid::StrainerFactory.send(:strainer_class_cache).clear
89
+ Liquid::StrainerFactory.instance_variable_set(:@global_filters, original_global_filters)
79
90
  end
80
91
 
81
92
  def with_error_mode(mode)
@@ -85,6 +96,20 @@ module Minitest
85
96
  ensure
86
97
  Liquid::Template.error_mode = old_mode
87
98
  end
99
+
100
+ def with_custom_tag(tag_name, tag_class)
101
+ old_tag = Liquid::Template.tags[tag_name]
102
+ begin
103
+ Liquid::Template.register_tag(tag_name, tag_class)
104
+ yield
105
+ ensure
106
+ if old_tag
107
+ Liquid::Template.tags[tag_name] = old_tag
108
+ else
109
+ Liquid::Template.tags.delete(tag_name)
110
+ end
111
+ end
112
+ end
88
113
  end
89
114
  end
90
115
 
@@ -115,3 +140,30 @@ class ErrorDrop < Liquid::Drop
115
140
  raise Exception, 'exception'
116
141
  end
117
142
  end
143
+
144
+ class StubFileSystem
145
+ attr_reader :file_read_count
146
+
147
+ def initialize(values)
148
+ @file_read_count = 0
149
+ @values = values
150
+ end
151
+
152
+ def read_template_file(template_path)
153
+ @file_read_count += 1
154
+ @values.fetch(template_path)
155
+ end
156
+ end
157
+
158
+ class StubTemplateFactory
159
+ attr_reader :count
160
+
161
+ def initialize
162
+ @count = 0
163
+ end
164
+
165
+ def for(_template_name)
166
+ @count += 1
167
+ Liquid::Template.new
168
+ end
169
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class BlockUnitTest < Minitest::Test
@@ -5,49 +7,42 @@ class BlockUnitTest < Minitest::Test
5
7
 
6
8
  def test_blankspace
7
9
  template = Liquid::Template.parse(" ")
8
- assert_equal [" "], template.root.nodelist
10
+ assert_equal([" "], template.root.nodelist)
9
11
  end
10
12
 
11
13
  def test_variable_beginning
12
14
  template = Liquid::Template.parse("{{funk}} ")
13
- assert_equal 2, template.root.nodelist.size
14
- assert_equal Variable, template.root.nodelist[0].class
15
- assert_equal String, template.root.nodelist[1].class
15
+ assert_equal(2, template.root.nodelist.size)
16
+ assert_equal(Variable, template.root.nodelist[0].class)
17
+ assert_equal(String, template.root.nodelist[1].class)
16
18
  end
17
19
 
18
20
  def test_variable_end
19
21
  template = Liquid::Template.parse(" {{funk}}")
20
- assert_equal 2, template.root.nodelist.size
21
- assert_equal String, template.root.nodelist[0].class
22
- assert_equal Variable, template.root.nodelist[1].class
22
+ assert_equal(2, template.root.nodelist.size)
23
+ assert_equal(String, template.root.nodelist[0].class)
24
+ assert_equal(Variable, template.root.nodelist[1].class)
23
25
  end
24
26
 
25
27
  def test_variable_middle
26
28
  template = Liquid::Template.parse(" {{funk}} ")
27
- assert_equal 3, template.root.nodelist.size
28
- assert_equal String, template.root.nodelist[0].class
29
- assert_equal Variable, template.root.nodelist[1].class
30
- assert_equal String, template.root.nodelist[2].class
29
+ assert_equal(3, template.root.nodelist.size)
30
+ assert_equal(String, template.root.nodelist[0].class)
31
+ assert_equal(Variable, template.root.nodelist[1].class)
32
+ assert_equal(String, template.root.nodelist[2].class)
31
33
  end
32
34
 
33
35
  def test_variable_many_embedded_fragments
34
36
  template = Liquid::Template.parse(" {{funk}} {{so}} {{brother}} ")
35
- assert_equal 7, template.root.nodelist.size
36
- assert_equal [String, Variable, String, Variable, String, Variable, String],
37
- block_types(template.root.nodelist)
37
+ assert_equal(7, template.root.nodelist.size)
38
+ assert_equal([String, Variable, String, Variable, String, Variable, String],
39
+ block_types(template.root.nodelist))
38
40
  end
39
41
 
40
42
  def test_with_block
41
43
  template = Liquid::Template.parse(" {% comment %} {% endcomment %} ")
42
- assert_equal [String, Comment, String], block_types(template.root.nodelist)
43
- assert_equal 3, template.root.nodelist.size
44
- end
45
-
46
- def test_with_custom_tag
47
- Liquid::Template.register_tag("testtag", Block)
48
- assert Liquid::Template.parse("{% testtag %} {% endtesttag %}")
49
- ensure
50
- Liquid::Template.tags.delete('testtag')
44
+ assert_equal([String, Comment, String], block_types(template.root.nodelist))
45
+ assert_equal(3, template.root.nodelist.size)
51
46
  end
52
47
 
53
48
  private
@@ -55,4 +50,4 @@ class BlockUnitTest < Minitest::Test
55
50
  def block_types(nodelist)
56
51
  nodelist.collect(&:class)
57
52
  end
58
- end # VariableTest
53
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class ConditionUnitTest < Minitest::Test
@@ -8,146 +10,154 @@ class ConditionUnitTest < Minitest::Test
8
10
  end
9
11
 
10
12
  def test_basic_condition
11
- assert_equal false, Condition.new(1, '==', 2).evaluate
12
- assert_equal true, Condition.new(1, '==', 1).evaluate
13
+ assert_equal(false, Condition.new(1, '==', 2).evaluate)
14
+ assert_equal(true, Condition.new(1, '==', 1).evaluate)
13
15
  end
14
16
 
15
17
  def test_default_operators_evalute_true
16
- assert_evaluates_true 1, '==', 1
17
- assert_evaluates_true 1, '!=', 2
18
- assert_evaluates_true 1, '<>', 2
19
- assert_evaluates_true 1, '<', 2
20
- assert_evaluates_true 2, '>', 1
21
- assert_evaluates_true 1, '>=', 1
22
- assert_evaluates_true 2, '>=', 1
23
- assert_evaluates_true 1, '<=', 2
24
- assert_evaluates_true 1, '<=', 1
18
+ assert_evaluates_true(1, '==', 1)
19
+ assert_evaluates_true(1, '!=', 2)
20
+ assert_evaluates_true(1, '<>', 2)
21
+ assert_evaluates_true(1, '<', 2)
22
+ assert_evaluates_true(2, '>', 1)
23
+ assert_evaluates_true(1, '>=', 1)
24
+ assert_evaluates_true(2, '>=', 1)
25
+ assert_evaluates_true(1, '<=', 2)
26
+ assert_evaluates_true(1, '<=', 1)
25
27
  # negative numbers
26
- assert_evaluates_true 1, '>', -1
27
- assert_evaluates_true (-1), '<', 1
28
- assert_evaluates_true 1.0, '>', -1.0
29
- assert_evaluates_true (-1.0), '<', 1.0
28
+ assert_evaluates_true(1, '>', -1)
29
+ assert_evaluates_true(-1, '<', 1)
30
+ assert_evaluates_true(1.0, '>', -1.0)
31
+ assert_evaluates_true(-1.0, '<', 1.0)
30
32
  end
31
33
 
32
34
  def test_default_operators_evalute_false
33
- assert_evaluates_false 1, '==', 2
34
- assert_evaluates_false 1, '!=', 1
35
- assert_evaluates_false 1, '<>', 1
36
- assert_evaluates_false 1, '<', 0
37
- assert_evaluates_false 2, '>', 4
38
- assert_evaluates_false 1, '>=', 3
39
- assert_evaluates_false 2, '>=', 4
40
- assert_evaluates_false 1, '<=', 0
41
- assert_evaluates_false 1, '<=', 0
35
+ assert_evaluates_false(1, '==', 2)
36
+ assert_evaluates_false(1, '!=', 1)
37
+ assert_evaluates_false(1, '<>', 1)
38
+ assert_evaluates_false(1, '<', 0)
39
+ assert_evaluates_false(2, '>', 4)
40
+ assert_evaluates_false(1, '>=', 3)
41
+ assert_evaluates_false(2, '>=', 4)
42
+ assert_evaluates_false(1, '<=', 0)
43
+ assert_evaluates_false(1, '<=', 0)
42
44
  end
43
45
 
44
46
  def test_contains_works_on_strings
45
- assert_evaluates_true 'bob', 'contains', 'o'
46
- assert_evaluates_true 'bob', 'contains', 'b'
47
- assert_evaluates_true 'bob', 'contains', 'bo'
48
- assert_evaluates_true 'bob', 'contains', 'ob'
49
- assert_evaluates_true 'bob', 'contains', 'bob'
47
+ assert_evaluates_true('bob', 'contains', 'o')
48
+ assert_evaluates_true('bob', 'contains', 'b')
49
+ assert_evaluates_true('bob', 'contains', 'bo')
50
+ assert_evaluates_true('bob', 'contains', 'ob')
51
+ assert_evaluates_true('bob', 'contains', 'bob')
50
52
 
51
- assert_evaluates_false 'bob', 'contains', 'bob2'
52
- assert_evaluates_false 'bob', 'contains', 'a'
53
- assert_evaluates_false 'bob', 'contains', '---'
53
+ assert_evaluates_false('bob', 'contains', 'bob2')
54
+ assert_evaluates_false('bob', 'contains', 'a')
55
+ assert_evaluates_false('bob', 'contains', '---')
54
56
  end
55
57
 
56
58
  def test_invalid_comparation_operator
57
- assert_evaluates_argument_error 1, '~~', 0
59
+ assert_evaluates_argument_error(1, '~~', 0)
58
60
  end
59
61
 
60
62
  def test_comparation_of_int_and_str
61
- assert_evaluates_argument_error '1', '>', 0
62
- assert_evaluates_argument_error '1', '<', 0
63
- assert_evaluates_argument_error '1', '>=', 0
64
- assert_evaluates_argument_error '1', '<=', 0
63
+ assert_evaluates_argument_error('1', '>', 0)
64
+ assert_evaluates_argument_error('1', '<', 0)
65
+ assert_evaluates_argument_error('1', '>=', 0)
66
+ assert_evaluates_argument_error('1', '<=', 0)
67
+ end
68
+
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)
65
75
  end
66
76
 
67
77
  def test_contains_works_on_arrays
68
- @context = Liquid::Context.new
78
+ @context = Liquid::Context.new
69
79
  @context['array'] = [1, 2, 3, 4, 5]
70
- array_expr = VariableLookup.new("array")
80
+ array_expr = VariableLookup.new("array")
71
81
 
72
- assert_evaluates_false array_expr, 'contains', 0
73
- assert_evaluates_true array_expr, 'contains', 1
74
- assert_evaluates_true array_expr, 'contains', 2
75
- assert_evaluates_true array_expr, 'contains', 3
76
- assert_evaluates_true array_expr, 'contains', 4
77
- assert_evaluates_true array_expr, 'contains', 5
78
- assert_evaluates_false array_expr, 'contains', 6
79
- assert_evaluates_false array_expr, 'contains', "1"
82
+ assert_evaluates_false(array_expr, 'contains', 0)
83
+ assert_evaluates_true(array_expr, 'contains', 1)
84
+ assert_evaluates_true(array_expr, 'contains', 2)
85
+ assert_evaluates_true(array_expr, 'contains', 3)
86
+ assert_evaluates_true(array_expr, 'contains', 4)
87
+ assert_evaluates_true(array_expr, 'contains', 5)
88
+ assert_evaluates_false(array_expr, 'contains', 6)
89
+ assert_evaluates_false(array_expr, 'contains', "1")
80
90
  end
81
91
 
82
92
  def test_contains_returns_false_for_nil_operands
83
93
  @context = Liquid::Context.new
84
- assert_evaluates_false VariableLookup.new('not_assigned'), 'contains', '0'
85
- assert_evaluates_false 0, 'contains', VariableLookup.new('not_assigned')
94
+ assert_evaluates_false(VariableLookup.new('not_assigned'), 'contains', '0')
95
+ assert_evaluates_false(0, 'contains', VariableLookup.new('not_assigned'))
86
96
  end
87
97
 
88
98
  def test_contains_return_false_on_wrong_data_type
89
- assert_evaluates_false 1, 'contains', 0
99
+ assert_evaluates_false(1, 'contains', 0)
90
100
  end
91
101
 
92
102
  def test_contains_with_string_left_operand_coerces_right_operand_to_string
93
- assert_evaluates_true ' 1 ', 'contains', 1
94
- assert_evaluates_false ' 1 ', 'contains', 2
103
+ assert_evaluates_true(' 1 ', 'contains', 1)
104
+ assert_evaluates_false(' 1 ', 'contains', 2)
95
105
  end
96
106
 
97
107
  def test_or_condition
98
108
  condition = Condition.new(1, '==', 2)
99
109
 
100
- assert_equal false, condition.evaluate
110
+ assert_equal(false, condition.evaluate)
101
111
 
102
- condition.or Condition.new(2, '==', 1)
112
+ condition.or(Condition.new(2, '==', 1))
103
113
 
104
- assert_equal false, condition.evaluate
114
+ assert_equal(false, condition.evaluate)
105
115
 
106
- condition.or Condition.new(1, '==', 1)
116
+ condition.or(Condition.new(1, '==', 1))
107
117
 
108
- assert_equal true, condition.evaluate
118
+ assert_equal(true, condition.evaluate)
109
119
  end
110
120
 
111
121
  def test_and_condition
112
122
  condition = Condition.new(1, '==', 1)
113
123
 
114
- assert_equal true, condition.evaluate
124
+ assert_equal(true, condition.evaluate)
115
125
 
116
- condition.and Condition.new(2, '==', 2)
126
+ condition.and(Condition.new(2, '==', 2))
117
127
 
118
- assert_equal true, condition.evaluate
128
+ assert_equal(true, condition.evaluate)
119
129
 
120
- condition.and Condition.new(2, '==', 1)
130
+ condition.and(Condition.new(2, '==', 1))
121
131
 
122
- assert_equal false, condition.evaluate
132
+ assert_equal(false, condition.evaluate)
123
133
  end
124
134
 
125
135
  def test_should_allow_custom_proc_operator
126
- Condition.operators['starts_with'] = proc { |cond, left, right| left =~ %r{^#{right}} }
136
+ Condition.operators['starts_with'] = proc { |_cond, left, right| left =~ /^#{right}/ }
127
137
 
128
- assert_evaluates_true 'bob', 'starts_with', 'b'
129
- assert_evaluates_false 'bob', 'starts_with', 'o'
138
+ assert_evaluates_true('bob', 'starts_with', 'b')
139
+ assert_evaluates_false('bob', 'starts_with', 'o')
130
140
  ensure
131
- Condition.operators.delete 'starts_with'
141
+ Condition.operators.delete('starts_with')
132
142
  end
133
143
 
134
144
  def test_left_or_right_may_contain_operators
135
- @context = Liquid::Context.new
145
+ @context = Liquid::Context.new
136
146
  @context['one'] = @context['another'] = "gnomeslab-and-or-liquid"
137
147
 
138
- assert_evaluates_true VariableLookup.new("one"), '==', VariableLookup.new("another")
148
+ assert_evaluates_true(VariableLookup.new("one"), '==', VariableLookup.new("another"))
139
149
  end
140
150
 
141
151
  private
142
152
 
143
153
  def assert_evaluates_true(left, op, right)
144
- assert Condition.new(left, op, right).evaluate(@context),
145
- "Evaluated false: #{left} #{op} #{right}"
154
+ assert(Condition.new(left, op, right).evaluate(@context),
155
+ "Evaluated false: #{left} #{op} #{right}")
146
156
  end
147
157
 
148
158
  def assert_evaluates_false(left, op, right)
149
- assert !Condition.new(left, op, right).evaluate(@context),
150
- "Evaluated true: #{left} #{op} #{right}"
159
+ assert(!Condition.new(left, op, right).evaluate(@context),
160
+ "Evaluated true: #{left} #{op} #{right}")
151
161
  end
152
162
 
153
163
  def assert_evaluates_argument_error(left, op, right)