liquid 3.0.6 → 4.0.3

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 (103) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +154 -58
  3. data/{MIT-LICENSE → LICENSE} +0 -0
  4. data/README.md +33 -0
  5. data/lib/liquid/block.rb +42 -125
  6. data/lib/liquid/block_body.rb +99 -79
  7. data/lib/liquid/condition.rb +52 -32
  8. data/lib/liquid/context.rb +57 -51
  9. data/lib/liquid/document.rb +19 -9
  10. data/lib/liquid/drop.rb +17 -16
  11. data/lib/liquid/errors.rb +20 -24
  12. data/lib/liquid/expression.rb +26 -10
  13. data/lib/liquid/extensions.rb +19 -7
  14. data/lib/liquid/file_system.rb +11 -11
  15. data/lib/liquid/forloop_drop.rb +42 -0
  16. data/lib/liquid/i18n.rb +6 -6
  17. data/lib/liquid/interrupts.rb +1 -2
  18. data/lib/liquid/lexer.rb +12 -8
  19. data/lib/liquid/locales/en.yml +6 -2
  20. data/lib/liquid/parse_context.rb +38 -0
  21. data/lib/liquid/parse_tree_visitor.rb +42 -0
  22. data/lib/liquid/parser_switching.rb +4 -4
  23. data/lib/liquid/profiler/hooks.rb +7 -7
  24. data/lib/liquid/profiler.rb +18 -19
  25. data/lib/liquid/range_lookup.rb +16 -1
  26. data/lib/liquid/resource_limits.rb +23 -0
  27. data/lib/liquid/standardfilters.rb +207 -61
  28. data/lib/liquid/strainer.rb +15 -8
  29. data/lib/liquid/tablerowloop_drop.rb +62 -0
  30. data/lib/liquid/tag.rb +9 -8
  31. data/lib/liquid/tags/assign.rb +25 -4
  32. data/lib/liquid/tags/break.rb +0 -3
  33. data/lib/liquid/tags/capture.rb +1 -1
  34. data/lib/liquid/tags/case.rb +27 -12
  35. data/lib/liquid/tags/comment.rb +2 -2
  36. data/lib/liquid/tags/cycle.rb +16 -8
  37. data/lib/liquid/tags/decrement.rb +1 -4
  38. data/lib/liquid/tags/for.rb +103 -75
  39. data/lib/liquid/tags/if.rb +60 -44
  40. data/lib/liquid/tags/ifchanged.rb +0 -2
  41. data/lib/liquid/tags/include.rb +71 -51
  42. data/lib/liquid/tags/raw.rb +32 -4
  43. data/lib/liquid/tags/table_row.rb +21 -31
  44. data/lib/liquid/tags/unless.rb +3 -4
  45. data/lib/liquid/template.rb +42 -54
  46. data/lib/liquid/tokenizer.rb +31 -0
  47. data/lib/liquid/truffle.rb +5 -0
  48. data/lib/liquid/utils.rb +52 -8
  49. data/lib/liquid/variable.rb +59 -46
  50. data/lib/liquid/variable_lookup.rb +14 -6
  51. data/lib/liquid/version.rb +2 -1
  52. data/lib/liquid.rb +10 -7
  53. data/test/integration/assign_test.rb +8 -8
  54. data/test/integration/blank_test.rb +14 -14
  55. data/test/integration/block_test.rb +12 -0
  56. data/test/integration/context_test.rb +2 -2
  57. data/test/integration/document_test.rb +19 -0
  58. data/test/integration/drop_test.rb +42 -40
  59. data/test/integration/error_handling_test.rb +96 -43
  60. data/test/integration/filter_test.rb +60 -20
  61. data/test/integration/hash_ordering_test.rb +9 -9
  62. data/test/integration/output_test.rb +26 -27
  63. data/test/integration/parse_tree_visitor_test.rb +247 -0
  64. data/test/integration/parsing_quirks_test.rb +19 -13
  65. data/test/integration/render_profiling_test.rb +20 -20
  66. data/test/integration/security_test.rb +23 -7
  67. data/test/integration/standard_filter_test.rb +426 -46
  68. data/test/integration/tags/break_tag_test.rb +1 -2
  69. data/test/integration/tags/continue_tag_test.rb +0 -1
  70. data/test/integration/tags/for_tag_test.rb +135 -100
  71. data/test/integration/tags/if_else_tag_test.rb +75 -77
  72. data/test/integration/tags/include_tag_test.rb +50 -31
  73. data/test/integration/tags/increment_tag_test.rb +10 -11
  74. data/test/integration/tags/raw_tag_test.rb +7 -1
  75. data/test/integration/tags/standard_tag_test.rb +121 -122
  76. data/test/integration/tags/statements_test.rb +3 -5
  77. data/test/integration/tags/table_row_test.rb +20 -19
  78. data/test/integration/tags/unless_else_tag_test.rb +6 -6
  79. data/test/integration/template_test.rb +199 -49
  80. data/test/integration/trim_mode_test.rb +529 -0
  81. data/test/integration/variable_test.rb +27 -13
  82. data/test/test_helper.rb +33 -6
  83. data/test/truffle/truffle_test.rb +9 -0
  84. data/test/unit/block_unit_test.rb +8 -5
  85. data/test/unit/condition_unit_test.rb +94 -77
  86. data/test/unit/context_unit_test.rb +69 -72
  87. data/test/unit/file_system_unit_test.rb +3 -3
  88. data/test/unit/i18n_unit_test.rb +2 -2
  89. data/test/unit/lexer_unit_test.rb +12 -9
  90. data/test/unit/parser_unit_test.rb +2 -2
  91. data/test/unit/regexp_unit_test.rb +1 -1
  92. data/test/unit/strainer_unit_test.rb +96 -1
  93. data/test/unit/tag_unit_test.rb +7 -2
  94. data/test/unit/tags/case_tag_unit_test.rb +1 -1
  95. data/test/unit/tags/for_tag_unit_test.rb +2 -2
  96. data/test/unit/tags/if_tag_unit_test.rb +1 -1
  97. data/test/unit/template_unit_test.rb +14 -5
  98. data/test/unit/tokenizer_unit_test.rb +24 -7
  99. data/test/unit/variable_unit_test.rb +60 -43
  100. metadata +62 -50
  101. data/lib/liquid/module_ex.rb +0 -62
  102. data/lib/liquid/token.rb +0 -18
  103. data/test/unit/module_ex_unit_test.rb +0 -87
@@ -34,7 +34,7 @@ class BlockUnitTest < Minitest::Test
34
34
  template = Liquid::Template.parse(" {{funk}} {{so}} {{brother}} ")
35
35
  assert_equal 7, template.root.nodelist.size
36
36
  assert_equal [String, Variable, String, Variable, String, Variable, String],
37
- block_types(template.root.nodelist)
37
+ block_types(template.root.nodelist)
38
38
  end
39
39
 
40
40
  def test_with_block
@@ -45,11 +45,14 @@ class BlockUnitTest < Minitest::Test
45
45
 
46
46
  def test_with_custom_tag
47
47
  Liquid::Template.register_tag("testtag", Block)
48
- assert Liquid::Template.parse( "{% testtag %} {% endtesttag %}")
48
+ assert Liquid::Template.parse("{% testtag %} {% endtesttag %}")
49
+ ensure
50
+ Liquid::Template.tags.delete('testtag')
49
51
  end
50
52
 
51
53
  private
52
- def block_types(nodelist)
53
- nodelist.collect { |node| node.class }
54
- end
54
+
55
+ def block_types(nodelist)
56
+ nodelist.collect(&:class)
57
+ end
55
58
  end # VariableTest
@@ -3,147 +3,164 @@ require 'test_helper'
3
3
  class ConditionUnitTest < Minitest::Test
4
4
  include Liquid
5
5
 
6
+ def setup
7
+ @context = Liquid::Context.new
8
+ end
9
+
6
10
  def test_basic_condition
7
- assert_equal false, Condition.new('1', '==', '2').evaluate
8
- assert_equal true, Condition.new('1', '==', '1').evaluate
11
+ assert_equal false, Condition.new(1, '==', 2).evaluate
12
+ assert_equal true, Condition.new(1, '==', 1).evaluate
9
13
  end
10
14
 
11
15
  def test_default_operators_evalute_true
12
- assert_evalutes_true '1', '==', '1'
13
- assert_evalutes_true '1', '!=', '2'
14
- assert_evalutes_true '1', '<>', '2'
15
- assert_evalutes_true '1', '<', '2'
16
- assert_evalutes_true '2', '>', '1'
17
- assert_evalutes_true '1', '>=', '1'
18
- assert_evalutes_true '2', '>=', '1'
19
- assert_evalutes_true '1', '<=', '2'
20
- assert_evalutes_true '1', '<=', '1'
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
21
25
  # negative numbers
22
- assert_evalutes_true '1', '>', '-1'
23
- assert_evalutes_true '-1', '<', '1'
24
- assert_evalutes_true '1.0', '>', '-1.0'
25
- assert_evalutes_true '-1.0', '<', '1.0'
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
26
30
  end
27
31
 
28
32
  def test_default_operators_evalute_false
29
- assert_evalutes_false '1', '==', '2'
30
- assert_evalutes_false '1', '!=', '1'
31
- assert_evalutes_false '1', '<>', '1'
32
- assert_evalutes_false '1', '<', '0'
33
- assert_evalutes_false '2', '>', '4'
34
- assert_evalutes_false '1', '>=', '3'
35
- assert_evalutes_false '2', '>=', '4'
36
- assert_evalutes_false '1', '<=', '0'
37
- assert_evalutes_false '1', '<=', '0'
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
38
42
  end
39
43
 
40
44
  def test_contains_works_on_strings
41
- assert_evalutes_true "'bob'", 'contains', "'o'"
42
- assert_evalutes_true "'bob'", 'contains', "'b'"
43
- assert_evalutes_true "'bob'", 'contains', "'bo'"
44
- assert_evalutes_true "'bob'", 'contains', "'ob'"
45
- assert_evalutes_true "'bob'", 'contains', "'bob'"
46
-
47
- assert_evalutes_false "'bob'", 'contains', "'bob2'"
48
- assert_evalutes_false "'bob'", 'contains', "'a'"
49
- assert_evalutes_false "'bob'", 'contains', "'---'"
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'
50
+
51
+ assert_evaluates_false 'bob', 'contains', 'bob2'
52
+ assert_evaluates_false 'bob', 'contains', 'a'
53
+ assert_evaluates_false 'bob', 'contains', '---'
50
54
  end
51
55
 
52
56
  def test_invalid_comparation_operator
53
- assert_evaluates_argument_error "1", '~~', '0'
57
+ assert_evaluates_argument_error 1, '~~', 0
54
58
  end
55
59
 
56
60
  def test_comparation_of_int_and_str
57
- assert_evaluates_argument_error "'1'", '>', '0'
58
- assert_evaluates_argument_error "'1'", '<', '0'
59
- assert_evaluates_argument_error "'1'", '>=', '0'
60
- assert_evaluates_argument_error "'1'", '<=', '0'
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
65
+ end
66
+
67
+ def test_hash_compare_backwards_compatibility
68
+ assert_nil Condition.new({}, '>', 2).evaluate
69
+ assert_nil Condition.new(2, '>', {}).evaluate
70
+ assert_equal false, Condition.new({}, '==', 2).evaluate
71
+ assert_equal true, Condition.new({ 'a' => 1 }, '==', { 'a' => 1 }).evaluate
72
+ assert_equal true, Condition.new({ 'a' => 2 }, 'contains', 'a').evaluate
61
73
  end
62
74
 
63
75
  def test_contains_works_on_arrays
64
76
  @context = Liquid::Context.new
65
- @context['array'] = [1,2,3,4,5]
66
-
67
- assert_evalutes_false "array", 'contains', '0'
68
- assert_evalutes_true "array", 'contains', '1'
69
- assert_evalutes_true "array", 'contains', '2'
70
- assert_evalutes_true "array", 'contains', '3'
71
- assert_evalutes_true "array", 'contains', '4'
72
- assert_evalutes_true "array", 'contains', '5'
73
- assert_evalutes_false "array", 'contains', '6'
74
- assert_evalutes_false "array", 'contains', '"1"'
77
+ @context['array'] = [1, 2, 3, 4, 5]
78
+ array_expr = VariableLookup.new("array")
79
+
80
+ assert_evaluates_false array_expr, 'contains', 0
81
+ assert_evaluates_true array_expr, 'contains', 1
82
+ assert_evaluates_true array_expr, 'contains', 2
83
+ assert_evaluates_true array_expr, 'contains', 3
84
+ assert_evaluates_true array_expr, 'contains', 4
85
+ assert_evaluates_true array_expr, 'contains', 5
86
+ assert_evaluates_false array_expr, 'contains', 6
87
+ assert_evaluates_false array_expr, 'contains', "1"
75
88
  end
76
89
 
77
90
  def test_contains_returns_false_for_nil_operands
78
91
  @context = Liquid::Context.new
79
- assert_evalutes_false "not_assigned", 'contains', '0'
80
- assert_evalutes_false "0", 'contains', 'not_assigned'
92
+ assert_evaluates_false VariableLookup.new('not_assigned'), 'contains', '0'
93
+ assert_evaluates_false 0, 'contains', VariableLookup.new('not_assigned')
81
94
  end
82
95
 
83
96
  def test_contains_return_false_on_wrong_data_type
84
- assert_evalutes_false "1", 'contains', '0'
97
+ assert_evaluates_false 1, 'contains', 0
98
+ end
99
+
100
+ def test_contains_with_string_left_operand_coerces_right_operand_to_string
101
+ assert_evaluates_true ' 1 ', 'contains', 1
102
+ assert_evaluates_false ' 1 ', 'contains', 2
85
103
  end
86
104
 
87
105
  def test_or_condition
88
- condition = Condition.new('1', '==', '2')
106
+ condition = Condition.new(1, '==', 2)
89
107
 
90
108
  assert_equal false, condition.evaluate
91
109
 
92
- condition.or Condition.new('2', '==', '1')
110
+ condition.or Condition.new(2, '==', 1)
93
111
 
94
112
  assert_equal false, condition.evaluate
95
113
 
96
- condition.or Condition.new('1', '==', '1')
114
+ condition.or Condition.new(1, '==', 1)
97
115
 
98
116
  assert_equal true, condition.evaluate
99
117
  end
100
118
 
101
119
  def test_and_condition
102
- condition = Condition.new('1', '==', '1')
120
+ condition = Condition.new(1, '==', 1)
103
121
 
104
122
  assert_equal true, condition.evaluate
105
123
 
106
- condition.and Condition.new('2', '==', '2')
124
+ condition.and Condition.new(2, '==', 2)
107
125
 
108
126
  assert_equal true, condition.evaluate
109
127
 
110
- condition.and Condition.new('2', '==', '1')
128
+ condition.and Condition.new(2, '==', 1)
111
129
 
112
130
  assert_equal false, condition.evaluate
113
131
  end
114
132
 
115
133
  def test_should_allow_custom_proc_operator
116
- Condition.operators['starts_with'] = Proc.new { |cond, left, right| left =~ %r{^#{right}} }
134
+ Condition.operators['starts_with'] = proc { |cond, left, right| left =~ %r{^#{right}} }
117
135
 
118
- assert_evalutes_true "'bob'", 'starts_with', "'b'"
119
- assert_evalutes_false "'bob'", 'starts_with', "'o'"
120
-
121
- ensure
122
- Condition.operators.delete 'starts_with'
136
+ assert_evaluates_true 'bob', 'starts_with', 'b'
137
+ assert_evaluates_false 'bob', 'starts_with', 'o'
138
+ ensure
139
+ Condition.operators.delete 'starts_with'
123
140
  end
124
141
 
125
142
  def test_left_or_right_may_contain_operators
126
143
  @context = Liquid::Context.new
127
144
  @context['one'] = @context['another'] = "gnomeslab-and-or-liquid"
128
145
 
129
- assert_evalutes_true "one", '==', "another"
146
+ assert_evaluates_true VariableLookup.new("one"), '==', VariableLookup.new("another")
130
147
  end
131
148
 
132
149
  private
133
- def assert_evalutes_true(left, op, right)
134
- assert Condition.new(left, op, right).evaluate(@context || Liquid::Context.new),
135
- "Evaluated false: #{left} #{op} #{right}"
136
- end
137
150
 
138
- def assert_evalutes_false(left, op, right)
139
- assert !Condition.new(left, op, right).evaluate(@context || Liquid::Context.new),
140
- "Evaluated true: #{left} #{op} #{right}"
141
- end
151
+ def assert_evaluates_true(left, op, right)
152
+ assert Condition.new(left, op, right).evaluate(@context),
153
+ "Evaluated false: #{left} #{op} #{right}"
154
+ end
142
155
 
143
- def assert_evaluates_argument_error(left, op, right)
144
- assert_raises(Liquid::ArgumentError) do
145
- Condition.new(left, op, right).evaluate(@context || Liquid::Context.new)
146
- end
147
- end
156
+ def assert_evaluates_false(left, op, right)
157
+ assert !Condition.new(left, op, right).evaluate(@context),
158
+ "Evaluated true: #{left} #{op} #{right}"
159
+ end
148
160
 
161
+ def assert_evaluates_argument_error(left, op, right)
162
+ assert_raises(Liquid::ArgumentError) do
163
+ Condition.new(left, op, right).evaluate(@context)
164
+ end
165
+ end
149
166
  end # ConditionTest
@@ -70,10 +70,6 @@ class ContextUnitTest < Minitest::Test
70
70
  @context = Liquid::Context.new
71
71
  end
72
72
 
73
- def teardown
74
- Spy.teardown
75
- end
76
-
77
73
  def test_variables
78
74
  @context['string'] = 'string'
79
75
  assert_equal 'string', @context['string']
@@ -98,12 +94,12 @@ class ContextUnitTest < Minitest::Test
98
94
  assert_equal false, @context['bool']
99
95
 
100
96
  @context['nil'] = nil
101
- assert_equal nil, @context['nil']
102
- assert_equal nil, @context['nil']
97
+ assert_nil @context['nil']
98
+ assert_nil @context['nil']
103
99
  end
104
100
 
105
101
  def test_variables_not_existing
106
- assert_equal nil, @context['does_not_exist']
102
+ assert_nil @context['does_not_exist']
107
103
  end
108
104
 
109
105
  def test_scoping
@@ -122,30 +118,25 @@ class ContextUnitTest < Minitest::Test
122
118
  end
123
119
 
124
120
  def test_length_query
125
-
126
- @context['numbers'] = [1,2,3,4]
121
+ @context['numbers'] = [1, 2, 3, 4]
127
122
 
128
123
  assert_equal 4, @context['numbers.size']
129
124
 
130
- @context['numbers'] = {1 => 1,2 => 2,3 => 3,4 => 4}
125
+ @context['numbers'] = { 1 => 1, 2 => 2, 3 => 3, 4 => 4 }
131
126
 
132
127
  assert_equal 4, @context['numbers.size']
133
128
 
134
- @context['numbers'] = {1 => 1,2 => 2,3 => 3,4 => 4, 'size' => 1000}
129
+ @context['numbers'] = { 1 => 1, 2 => 2, 3 => 3, 4 => 4, 'size' => 1000 }
135
130
 
136
131
  assert_equal 1000, @context['numbers.size']
137
-
138
132
  end
139
133
 
140
134
  def test_hyphenated_variable
141
-
142
135
  @context['oh-my'] = 'godz'
143
136
  assert_equal 'godz', @context['oh-my']
144
-
145
137
  end
146
138
 
147
139
  def test_add_filter
148
-
149
140
  filter = Module.new do
150
141
  def hi(output)
151
142
  output + ' hi!'
@@ -161,11 +152,9 @@ class ContextUnitTest < Minitest::Test
161
152
 
162
153
  context.add_filters(filter)
163
154
  assert_equal 'hi? hi!', context.invoke(:hi, 'hi?')
164
-
165
155
  end
166
156
 
167
157
  def test_only_intended_filters_make_it_there
168
-
169
158
  filter = Module.new do
170
159
  def hi(output)
171
160
  output + ' hi!'
@@ -192,11 +181,11 @@ class ContextUnitTest < Minitest::Test
192
181
  @context['test'] = 'test'
193
182
  assert_equal 'test', @context['test']
194
183
  @context.pop
195
- assert_equal nil, @context['test']
184
+ assert_nil @context['test']
196
185
  end
197
186
 
198
187
  def test_hierachical_data
199
- @context['hash'] = {"name" => 'tobi'}
188
+ @context['hash'] = { "name" => 'tobi' }
200
189
  assert_equal 'tobi', @context['hash.name']
201
190
  assert_equal 'tobi', @context['hash["name"]']
202
191
  end
@@ -225,7 +214,7 @@ class ContextUnitTest < Minitest::Test
225
214
  end
226
215
 
227
216
  def test_array_notation
228
- @context['test'] = [1,2,3,4,5]
217
+ @context['test'] = [1, 2, 3, 4, 5]
229
218
 
230
219
  assert_equal 1, @context['test[0]']
231
220
  assert_equal 2, @context['test[1]']
@@ -235,21 +224,21 @@ class ContextUnitTest < Minitest::Test
235
224
  end
236
225
 
237
226
  def test_recoursive_array_notation
238
- @context['test'] = {'test' => [1,2,3,4,5]}
227
+ @context['test'] = { 'test' => [1, 2, 3, 4, 5] }
239
228
 
240
229
  assert_equal 1, @context['test.test[0]']
241
230
 
242
- @context['test'] = [{'test' => 'worked'}]
231
+ @context['test'] = [{ 'test' => 'worked' }]
243
232
 
244
233
  assert_equal 'worked', @context['test[0].test']
245
234
  end
246
235
 
247
236
  def test_hash_to_array_transition
248
237
  @context['colors'] = {
249
- 'Blue' => ['003366','336699', '6699CC', '99CCFF'],
250
- 'Green' => ['003300','336633', '669966', '99CC99'],
251
- 'Yellow' => ['CC9900','FFCC00', 'FFFF99', 'FFFFCC'],
252
- 'Red' => ['660000','993333', 'CC6666', 'FF9999']
238
+ 'Blue' => ['003366', '336699', '6699CC', '99CCFF'],
239
+ 'Green' => ['003300', '336633', '669966', '99CC99'],
240
+ 'Yellow' => ['CC9900', 'FFCC00', 'FFFF99', 'FFFFCC'],
241
+ 'Red' => ['660000', '993333', 'CC6666', 'FF9999']
253
242
  }
254
243
 
255
244
  assert_equal '003366', @context['colors.Blue[0]']
@@ -257,12 +246,12 @@ class ContextUnitTest < Minitest::Test
257
246
  end
258
247
 
259
248
  def test_try_first
260
- @context['test'] = [1,2,3,4,5]
249
+ @context['test'] = [1, 2, 3, 4, 5]
261
250
 
262
251
  assert_equal 1, @context['test.first']
263
252
  assert_equal 5, @context['test.last']
264
253
 
265
- @context['test'] = {'test' => [1,2,3,4,5]}
254
+ @context['test'] = { 'test' => [1, 2, 3, 4, 5] }
266
255
 
267
256
  assert_equal 1, @context['test.test.first']
268
257
  assert_equal 5, @context['test.test.last']
@@ -273,8 +262,8 @@ class ContextUnitTest < Minitest::Test
273
262
  end
274
263
 
275
264
  def test_access_hashes_with_hash_notation
276
- @context['products'] = {'count' => 5, 'tags' => ['deepsnow', 'freestyle'] }
277
- @context['product'] = {'variants' => [ {'title' => 'draft151cm'}, {'title' => 'element151cm'} ]}
265
+ @context['products'] = { 'count' => 5, 'tags' => ['deepsnow', 'freestyle'] }
266
+ @context['product'] = { 'variants' => [ { 'title' => 'draft151cm' }, { 'title' => 'element151cm' } ] }
278
267
 
279
268
  assert_equal 5, @context['products["count"]']
280
269
  assert_equal 'deepsnow', @context['products["tags"][0]']
@@ -294,85 +283,82 @@ class ContextUnitTest < Minitest::Test
294
283
  end
295
284
 
296
285
  def test_access_hashes_with_hash_access_variables
297
-
298
286
  @context['var'] = 'tags'
299
- @context['nested'] = {'var' => 'tags'}
300
- @context['products'] = {'count' => 5, 'tags' => ['deepsnow', 'freestyle'] }
287
+ @context['nested'] = { 'var' => 'tags' }
288
+ @context['products'] = { 'count' => 5, 'tags' => ['deepsnow', 'freestyle'] }
301
289
 
302
290
  assert_equal 'deepsnow', @context['products[var].first']
303
291
  assert_equal 'freestyle', @context['products[nested.var].last']
304
292
  end
305
293
 
306
294
  def test_hash_notation_only_for_hash_access
307
- @context['array'] = [1,2,3,4,5]
308
- @context['hash'] = {'first' => 'Hello'}
295
+ @context['array'] = [1, 2, 3, 4, 5]
296
+ @context['hash'] = { 'first' => 'Hello' }
309
297
 
310
298
  assert_equal 1, @context['array.first']
311
- assert_equal nil, @context['array["first"]']
299
+ assert_nil @context['array["first"]']
312
300
  assert_equal 'Hello', @context['hash["first"]']
313
301
  end
314
302
 
315
303
  def test_first_can_appear_in_middle_of_callchain
316
-
317
- @context['product'] = {'variants' => [ {'title' => 'draft151cm'}, {'title' => 'element151cm'} ]}
304
+ @context['product'] = { 'variants' => [ { 'title' => 'draft151cm' }, { 'title' => 'element151cm' } ] }
318
305
 
319
306
  assert_equal 'draft151cm', @context['product.variants[0].title']
320
307
  assert_equal 'element151cm', @context['product.variants[1].title']
321
308
  assert_equal 'draft151cm', @context['product.variants.first.title']
322
309
  assert_equal 'element151cm', @context['product.variants.last.title']
323
-
324
310
  end
325
311
 
326
312
  def test_cents
327
- @context.merge( "cents" => HundredCentes.new )
313
+ @context.merge("cents" => HundredCentes.new)
328
314
  assert_equal 100, @context['cents']
329
315
  end
330
316
 
331
317
  def test_nested_cents
332
- @context.merge( "cents" => { 'amount' => HundredCentes.new} )
318
+ @context.merge("cents" => { 'amount' => HundredCentes.new })
333
319
  assert_equal 100, @context['cents.amount']
334
320
 
335
- @context.merge( "cents" => { 'cents' => { 'amount' => HundredCentes.new} } )
321
+ @context.merge("cents" => { 'cents' => { 'amount' => HundredCentes.new } })
336
322
  assert_equal 100, @context['cents.cents.amount']
337
323
  end
338
324
 
339
325
  def test_cents_through_drop
340
- @context.merge( "cents" => CentsDrop.new )
326
+ @context.merge("cents" => CentsDrop.new)
341
327
  assert_equal 100, @context['cents.amount']
342
328
  end
343
329
 
344
330
  def test_nested_cents_through_drop
345
- @context.merge( "vars" => {"cents" => CentsDrop.new} )
331
+ @context.merge("vars" => { "cents" => CentsDrop.new })
346
332
  assert_equal 100, @context['vars.cents.amount']
347
333
  end
348
334
 
349
335
  def test_drop_methods_with_question_marks
350
- @context.merge( "cents" => CentsDrop.new )
336
+ @context.merge("cents" => CentsDrop.new)
351
337
  assert @context['cents.non_zero?']
352
338
  end
353
339
 
354
340
  def test_context_from_within_drop
355
- @context.merge( "test" => '123', "vars" => ContextSensitiveDrop.new )
341
+ @context.merge("test" => '123', "vars" => ContextSensitiveDrop.new)
356
342
  assert_equal '123', @context['vars.test']
357
343
  end
358
344
 
359
345
  def test_nested_context_from_within_drop
360
- @context.merge( "test" => '123', "vars" => {"local" => ContextSensitiveDrop.new } )
346
+ @context.merge("test" => '123', "vars" => { "local" => ContextSensitiveDrop.new })
361
347
  assert_equal '123', @context['vars.local.test']
362
348
  end
363
349
 
364
350
  def test_ranges
365
- @context.merge( "test" => '5' )
351
+ @context.merge("test" => '5')
366
352
  assert_equal (1..5), @context['(1..5)']
367
353
  assert_equal (1..5), @context['(1..test)']
368
354
  assert_equal (5..5), @context['(test..test)']
369
355
  end
370
356
 
371
357
  def test_cents_through_drop_nestedly
372
- @context.merge( "cents" => {"cents" => CentsDrop.new} )
358
+ @context.merge("cents" => { "cents" => CentsDrop.new })
373
359
  assert_equal 100, @context['cents.cents.amount']
374
360
 
375
- @context.merge( "cents" => { "cents" => {"cents" => CentsDrop.new}} )
361
+ @context.merge("cents" => { "cents" => { "cents" => CentsDrop.new } })
376
362
  assert_equal 100, @context['cents.cents.cents.amount']
377
363
  end
378
364
 
@@ -393,7 +379,7 @@ class ContextUnitTest < Minitest::Test
393
379
  end
394
380
 
395
381
  def test_proc_as_variable
396
- @context['dynamic'] = Proc.new { 'Hello' }
382
+ @context['dynamic'] = proc { 'Hello' }
397
383
 
398
384
  assert_equal 'Hello', @context['dynamic']
399
385
  end
@@ -411,7 +397,7 @@ class ContextUnitTest < Minitest::Test
411
397
  end
412
398
 
413
399
  def test_array_containing_lambda_as_variable
414
- @context['dynamic'] = [1,2, proc { 'Hello' } ,4,5]
400
+ @context['dynamic'] = [1, 2, proc { 'Hello' }, 4, 5]
415
401
 
416
402
  assert_equal 'Hello', @context['dynamic[2]']
417
403
  end
@@ -437,7 +423,7 @@ class ContextUnitTest < Minitest::Test
437
423
  end
438
424
 
439
425
  def test_lambda_in_array_is_called_once
440
- @context['callcount'] = [1,2, proc { @global ||= 0; @global += 1; @global.to_s } ,4,5]
426
+ @context['callcount'] = [1, 2, proc { @global ||= 0; @global += 1; @global.to_s }, 4, 5]
441
427
 
442
428
  assert_equal '1', @context['callcount[2]']
443
429
  assert_equal '1', @context['callcount[2]']
@@ -460,33 +446,44 @@ class ContextUnitTest < Minitest::Test
460
446
  assert_equal @context, @context['category'].context
461
447
  end
462
448
 
463
- def test_use_empty_instead_of_any_in_interrupt_handling_to_avoid_lots_of_unnecessary_object_allocations
464
- mock_any = Spy.on_instance_method(Array, :any?)
465
- mock_empty = Spy.on_instance_method(Array, :empty?)
466
- mock_has_interrupt = Spy.on(@context, :has_interrupt?).and_call_through
449
+ def test_interrupt_avoids_object_allocations
450
+ assert_no_object_allocations do
451
+ @context.interrupt?
452
+ end
453
+ end
467
454
 
468
- @context.has_interrupt?
455
+ def test_context_initialization_with_a_proc_in_environment
456
+ contx = Context.new([test: ->(c) { c['poutine'] }], { test: :foo })
469
457
 
470
- refute mock_any.has_been_called?
471
- assert mock_empty.has_been_called?
472
- end
458
+ assert contx
459
+ assert_nil contx['poutine']
460
+ end
473
461
 
474
- def test_variable_lookup_caches_markup
475
- mock_scan = Spy.on_instance_method(String, :scan).and_return(["string"])
462
+ def test_apply_global_filter
463
+ global_filter_proc = ->(output) { "#{output} filtered" }
476
464
 
477
- @context['string'] = 'string'
478
- @context['string']
479
- @context['string']
465
+ context = Context.new
466
+ context.global_filter = global_filter_proc
480
467
 
481
- assert_equal 1, mock_scan.calls.size
468
+ assert_equal 'hi filtered', context.apply_global_filter('hi')
482
469
  end
483
470
 
484
- def test_context_initialization_with_a_proc_in_environment
485
- contx = Context.new([:test => lambda { |c| c['poutine']}], {:test => :foo})
486
-
487
- assert contx
488
- assert_nil contx['poutine']
471
+ def test_apply_global_filter_when_no_global_filter_exist
472
+ context = Context.new
473
+ assert_equal 'hi', context.apply_global_filter('hi')
489
474
  end
490
475
 
476
+ private
491
477
 
478
+ def assert_no_object_allocations
479
+ unless RUBY_ENGINE == 'ruby'
480
+ skip "stackprof needed to count object allocations"
481
+ end
482
+ require 'stackprof'
483
+
484
+ profile = StackProf.run(mode: :object) do
485
+ yield
486
+ end
487
+ assert_equal 0, profile[:samples]
488
+ end
492
489
  end # ContextTest
@@ -5,13 +5,13 @@ class FileSystemUnitTest < Minitest::Test
5
5
 
6
6
  def test_default
7
7
  assert_raises(FileSystemError) do
8
- BlankFileSystem.new.read_template_file("dummy", {'dummy'=>'smarty'})
8
+ BlankFileSystem.new.read_template_file("dummy")
9
9
  end
10
10
  end
11
11
 
12
12
  def test_local
13
13
  file_system = Liquid::LocalFileSystem.new("/some/path")
14
- assert_equal "/some/path/_mypartial.liquid" , file_system.full_path("mypartial")
14
+ assert_equal "/some/path/_mypartial.liquid", file_system.full_path("mypartial")
15
15
  assert_equal "/some/path/dir/_mypartial.liquid", file_system.full_path("dir/mypartial")
16
16
 
17
17
  assert_raises(FileSystemError) do
@@ -29,7 +29,7 @@ class FileSystemUnitTest < Minitest::Test
29
29
 
30
30
  def test_custom_template_filename_patterns
31
31
  file_system = Liquid::LocalFileSystem.new("/some/path", "%s.html")
32
- assert_equal "/some/path/mypartial.html" , file_system.full_path("mypartial")
32
+ assert_equal "/some/path/mypartial.html", file_system.full_path("mypartial")
33
33
  assert_equal "/some/path/dir/mypartial.html", file_system.full_path("dir/mypartial")
34
34
  end
35
35
  end # FileSystemTest
@@ -16,7 +16,7 @@ class I18nUnitTest < Minitest::Test
16
16
  end
17
17
 
18
18
  def test_single_string_interpolation
19
- assert_equal "something different", @i18n.translate("whatever", :something => "different")
19
+ assert_equal "something different", @i18n.translate("whatever", something: "different")
20
20
  end
21
21
 
22
22
  # def test_raises_translation_error_on_undefined_interpolation_key
@@ -24,7 +24,7 @@ class I18nUnitTest < Minitest::Test
24
24
  # @i18n.translate("whatever", :oopstypos => "yes")
25
25
  # end
26
26
  # end
27
-
27
+
28
28
  def test_raises_unknown_translation
29
29
  assert_raises I18n::TranslationError do
30
30
  @i18n.translate("doesnt_exist")