liquid 4.0.2 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +59 -0
  3. data/README.md +6 -0
  4. data/lib/liquid/block.rb +31 -14
  5. data/lib/liquid/block_body.rb +166 -53
  6. data/lib/liquid/condition.rb +41 -20
  7. data/lib/liquid/context.rb +107 -52
  8. data/lib/liquid/document.rb +47 -9
  9. data/lib/liquid/drop.rb +4 -2
  10. data/lib/liquid/errors.rb +20 -18
  11. data/lib/liquid/expression.rb +29 -34
  12. data/lib/liquid/extensions.rb +2 -0
  13. data/lib/liquid/file_system.rb +6 -4
  14. data/lib/liquid/forloop_drop.rb +11 -4
  15. data/lib/liquid/i18n.rb +5 -3
  16. data/lib/liquid/interrupts.rb +3 -1
  17. data/lib/liquid/lexer.rb +30 -23
  18. data/lib/liquid/locales/en.yml +3 -1
  19. data/lib/liquid/parse_context.rb +20 -4
  20. data/lib/liquid/parse_tree_visitor.rb +2 -2
  21. data/lib/liquid/parser.rb +30 -18
  22. data/lib/liquid/parser_switching.rb +17 -3
  23. data/lib/liquid/partial_cache.rb +24 -0
  24. data/lib/liquid/profiler/hooks.rb +26 -14
  25. data/lib/liquid/profiler.rb +67 -86
  26. data/lib/liquid/range_lookup.rb +13 -3
  27. data/lib/liquid/register.rb +6 -0
  28. data/lib/liquid/resource_limits.rb +47 -8
  29. data/lib/liquid/standardfilters.rb +95 -46
  30. data/lib/liquid/static_registers.rb +44 -0
  31. data/lib/liquid/strainer_factory.rb +36 -0
  32. data/lib/liquid/strainer_template.rb +53 -0
  33. data/lib/liquid/tablerowloop_drop.rb +6 -4
  34. data/lib/liquid/tag/disableable.rb +22 -0
  35. data/lib/liquid/tag/disabler.rb +21 -0
  36. data/lib/liquid/tag.rb +28 -6
  37. data/lib/liquid/tags/assign.rb +24 -10
  38. data/lib/liquid/tags/break.rb +8 -3
  39. data/lib/liquid/tags/capture.rb +11 -8
  40. data/lib/liquid/tags/case.rb +40 -27
  41. data/lib/liquid/tags/comment.rb +5 -3
  42. data/lib/liquid/tags/continue.rb +8 -3
  43. data/lib/liquid/tags/cycle.rb +25 -14
  44. data/lib/liquid/tags/decrement.rb +6 -3
  45. data/lib/liquid/tags/echo.rb +34 -0
  46. data/lib/liquid/tags/for.rb +68 -44
  47. data/lib/liquid/tags/if.rb +39 -23
  48. data/lib/liquid/tags/ifchanged.rb +11 -10
  49. data/lib/liquid/tags/include.rb +34 -47
  50. data/lib/liquid/tags/increment.rb +7 -3
  51. data/lib/liquid/tags/raw.rb +14 -11
  52. data/lib/liquid/tags/render.rb +84 -0
  53. data/lib/liquid/tags/table_row.rb +23 -19
  54. data/lib/liquid/tags/unless.rb +23 -15
  55. data/lib/liquid/template.rb +53 -72
  56. data/lib/liquid/template_factory.rb +9 -0
  57. data/lib/liquid/tokenizer.rb +18 -10
  58. data/lib/liquid/usage.rb +8 -0
  59. data/lib/liquid/utils.rb +13 -3
  60. data/lib/liquid/variable.rb +46 -41
  61. data/lib/liquid/variable_lookup.rb +11 -6
  62. data/lib/liquid/version.rb +2 -1
  63. data/lib/liquid.rb +17 -5
  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 +47 -1
  67. data/test/integration/capture_test.rb +18 -10
  68. data/test/integration/context_test.rb +609 -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 +73 -61
  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 +19 -7
  77. data/test/integration/{render_profiling_test.rb → profiler_test.rb} +84 -25
  78. data/test/integration/security_test.rb +30 -21
  79. data/test/integration/standard_filter_test.rb +385 -281
  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 +107 -51
  86. data/test/integration/tags/if_else_tag_test.rb +5 -3
  87. data/test/integration/tags/include_tag_test.rb +76 -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 +132 -124
  97. data/test/integration/trim_mode_test.rb +78 -44
  98. data/test/integration/variable_test.rb +74 -32
  99. data/test/test_helper.rb +113 -22
  100. data/test/unit/block_unit_test.rb +19 -24
  101. data/test/unit/condition_unit_test.rb +79 -77
  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 +11 -9
  105. data/test/{integration → unit}/parse_tree_visitor_test.rb +16 -2
  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 +26 -19
  119. data/test/unit/variable_unit_test.rb +51 -49
  120. metadata +76 -50
  121. data/lib/liquid/strainer.rb +0 -66
  122. data/lib/liquid/truffle.rb +0 -5
  123. data/test/truffle/truffle_test.rb +0 -9
  124. data/test/unit/context_unit_test.rb +0 -489
  125. data/test/unit/strainer_unit_test.rb +0 -164
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class TrimModeTest < Minitest::Test
@@ -67,7 +69,7 @@ class TrimModeTest < Minitest::Test
67
69
  # Make sure the trim isn't applied to standard tags
68
70
  def test_standard_tags
69
71
  whitespace = ' '
70
- text = <<-END_TEMPLATE
72
+ text = <<-END_TEMPLATE
71
73
  <div>
72
74
  <p>
73
75
  {% if true %}
@@ -76,14 +78,14 @@ class TrimModeTest < Minitest::Test
76
78
  </p>
77
79
  </div>
78
80
  END_TEMPLATE
79
- expected = <<-END_EXPECTED
80
- <div>
81
- <p>
82
- #{whitespace}
83
- yes
84
- #{whitespace}
85
- </p>
86
- </div>
81
+ expected = <<~END_EXPECTED
82
+ <div>
83
+ <p>
84
+ #{whitespace}
85
+ yes
86
+ #{whitespace}
87
+ </p>
88
+ </div>
87
89
  END_EXPECTED
88
90
  assert_template_result(expected, text)
89
91
 
@@ -96,70 +98,70 @@ class TrimModeTest < Minitest::Test
96
98
  </p>
97
99
  </div>
98
100
  END_TEMPLATE
99
- expected = <<-END_EXPECTED
100
- <div>
101
- <p>
102
- #{whitespace}
103
- </p>
104
- </div>
101
+ expected = <<~END_EXPECTED
102
+ <div>
103
+ <p>
104
+ #{whitespace}
105
+ </p>
106
+ </div>
105
107
  END_EXPECTED
106
108
  assert_template_result(expected, text)
107
109
  end
108
110
 
109
111
  # Make sure the trim isn't too agressive
110
112
  def test_no_trim_output
111
- text = '<p>{{- \'John\' -}}</p>'
113
+ text = '<p>{{- \'John\' -}}</p>'
112
114
  expected = '<p>John</p>'
113
115
  assert_template_result(expected, text)
114
116
  end
115
117
 
116
118
  # Make sure the trim isn't too agressive
117
119
  def test_no_trim_tags
118
- text = '<p>{%- if true -%}yes{%- endif -%}</p>'
120
+ text = '<p>{%- if true -%}yes{%- endif -%}</p>'
119
121
  expected = '<p>yes</p>'
120
122
  assert_template_result(expected, text)
121
123
 
122
- text = '<p>{%- if false -%}no{%- endif -%}</p>'
124
+ text = '<p>{%- if false -%}no{%- endif -%}</p>'
123
125
  expected = '<p></p>'
124
126
  assert_template_result(expected, text)
125
127
  end
126
128
 
127
129
  def test_single_line_outer_tag
128
- text = '<p> {%- if true %} yes {% endif -%} </p>'
130
+ text = '<p> {%- if true %} yes {% endif -%} </p>'
129
131
  expected = '<p> yes </p>'
130
132
  assert_template_result(expected, text)
131
133
 
132
- text = '<p> {%- if false %} no {% endif -%} </p>'
134
+ text = '<p> {%- if false %} no {% endif -%} </p>'
133
135
  expected = '<p></p>'
134
136
  assert_template_result(expected, text)
135
137
  end
136
138
 
137
139
  def test_single_line_inner_tag
138
- text = '<p> {% if true -%} yes {%- endif %} </p>'
140
+ text = '<p> {% if true -%} yes {%- endif %} </p>'
139
141
  expected = '<p> yes </p>'
140
142
  assert_template_result(expected, text)
141
143
 
142
- text = '<p> {% if false -%} no {%- endif %} </p>'
144
+ text = '<p> {% if false -%} no {%- endif %} </p>'
143
145
  expected = '<p> </p>'
144
146
  assert_template_result(expected, text)
145
147
  end
146
148
 
147
149
  def test_single_line_post_tag
148
- text = '<p> {% if true -%} yes {% endif -%} </p>'
150
+ text = '<p> {% if true -%} yes {% endif -%} </p>'
149
151
  expected = '<p> yes </p>'
150
152
  assert_template_result(expected, text)
151
153
 
152
- text = '<p> {% if false -%} no {% endif -%} </p>'
154
+ text = '<p> {% if false -%} no {% endif -%} </p>'
153
155
  expected = '<p> </p>'
154
156
  assert_template_result(expected, text)
155
157
  end
156
158
 
157
159
  def test_single_line_pre_tag
158
- text = '<p> {%- if true %} yes {%- endif %} </p>'
160
+ text = '<p> {%- if true %} yes {%- endif %} </p>'
159
161
  expected = '<p> yes </p>'
160
162
  assert_template_result(expected, text)
161
163
 
162
- text = '<p> {%- if false %} no {%- endif %} </p>'
164
+ text = '<p> {%- if false %} no {%- endif %} </p>'
163
165
  expected = '<p> </p>'
164
166
  assert_template_result(expected, text)
165
167
  end
@@ -328,7 +330,7 @@ class TrimModeTest < Minitest::Test
328
330
  assert_template_result(expected, text)
329
331
 
330
332
  whitespace = ' '
331
- text = <<-END_TEMPLATE
333
+ text = <<-END_TEMPLATE
332
334
  <div>
333
335
  <p>
334
336
  {% if false -%}
@@ -337,12 +339,12 @@ class TrimModeTest < Minitest::Test
337
339
  </p>
338
340
  </div>
339
341
  END_TEMPLATE
340
- expected = <<-END_EXPECTED
341
- <div>
342
- <p>
343
- #{whitespace}
344
- </p>
345
- </div>
342
+ expected = <<~END_EXPECTED
343
+ <div>
344
+ <p>
345
+ #{whitespace}
346
+ </p>
347
+ </div>
346
348
  END_EXPECTED
347
349
  assert_template_result(expected, text)
348
350
  end
@@ -502,7 +504,7 @@ class TrimModeTest < Minitest::Test
502
504
 
503
505
  def test_raw_output
504
506
  whitespace = ' '
505
- text = <<-END_TEMPLATE
507
+ text = <<-END_TEMPLATE
506
508
  <div>
507
509
  {% raw %}
508
510
  {%- if true -%}
@@ -513,17 +515,49 @@ class TrimModeTest < Minitest::Test
513
515
  {% endraw %}
514
516
  </div>
515
517
  END_TEMPLATE
516
- expected = <<-END_EXPECTED
517
- <div>
518
- #{whitespace}
519
- {%- if true -%}
520
- <p>
521
- {{- 'John' -}}
522
- </p>
523
- {%- endif -%}
524
- #{whitespace}
525
- </div>
518
+ expected = <<~END_EXPECTED
519
+ <div>
520
+ #{whitespace}
521
+ {%- if true -%}
522
+ <p>
523
+ {{- 'John' -}}
524
+ </p>
525
+ {%- endif -%}
526
+ #{whitespace}
527
+ </div>
526
528
  END_EXPECTED
527
529
  assert_template_result(expected, text)
528
530
  end
531
+
532
+ def test_pre_trim_blank_preceding_text
533
+ template = Liquid::Template.parse("\n{%- raw %}{% endraw %}")
534
+ assert_equal("", template.render)
535
+
536
+ template = Liquid::Template.parse("\n{%- if true %}{% endif %}")
537
+ assert_equal("", template.render)
538
+
539
+ template = Liquid::Template.parse("{{ 'B' }} \n{%- if true %}C{% endif %}")
540
+ assert_equal("BC", template.render)
541
+ end
542
+
543
+ def test_bug_compatible_pre_trim
544
+ template = Liquid::Template.parse("\n {%- raw %}{% endraw %}", bug_compatible_whitespace_trimming: true)
545
+ assert_equal("\n", template.render)
546
+
547
+ template = Liquid::Template.parse("\n {%- if true %}{% endif %}", bug_compatible_whitespace_trimming: true)
548
+ assert_equal("\n", template.render)
549
+
550
+ template = Liquid::Template.parse("{{ 'B' }} \n{%- if true %}C{% endif %}", bug_compatible_whitespace_trimming: true)
551
+ assert_equal("B C", template.render)
552
+
553
+ template = Liquid::Template.parse("B\n {%- raw %}{% endraw %}", bug_compatible_whitespace_trimming: true)
554
+ assert_equal("B", template.render)
555
+
556
+ template = Liquid::Template.parse("B\n {%- if true %}{% endif %}", bug_compatible_whitespace_trimming: true)
557
+ assert_equal("B", template.render)
558
+ end
559
+
560
+ def test_trim_blank
561
+ assert_template_result('foobar', 'foo {{-}} bar')
562
+ end
529
563
  end # TrimModeTest
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  class VariableTest < Minitest::Test
@@ -5,92 +7,132 @@ 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)
16
+ end
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'))
14
43
  end
15
44
 
16
45
  def test_simple_with_whitespaces
17
46
  template = Template.parse(%( {{ test }} ))
18
- assert_equal ' worked ', template.render!('test' => 'worked')
19
- assert_equal ' worked wonderfully ', template.render!('test' => 'worked wonderfully')
47
+ assert_equal(' worked ', template.render!('test' => 'worked'))
48
+ assert_equal(' worked wonderfully ', template.render!('test' => 'worked wonderfully'))
49
+ end
50
+
51
+ def test_expression_with_whitespace_in_square_brackets
52
+ assert_template_result('result', "{{ a[ 'b' ] }}", 'a' => { 'b' => 'result' })
53
+ assert_template_result('result', "{{ a[ [ 'b' ] ] }}", 'b' => 'c', 'a' => { 'c' => 'result' })
20
54
  end
21
55
 
22
56
  def test_ignore_unknown
23
57
  template = Template.parse(%({{ test }}))
24
- assert_equal '', template.render!
58
+ assert_equal('', template.render!)
25
59
  end
26
60
 
27
61
  def test_using_blank_as_variable_name
28
62
  template = Template.parse("{% assign foo = blank %}{{ foo }}")
29
- assert_equal '', template.render!
63
+ assert_equal('', template.render!)
30
64
  end
31
65
 
32
66
  def test_using_empty_as_variable_name
33
67
  template = Template.parse("{% assign foo = empty %}{{ foo }}")
34
- assert_equal '', template.render!
68
+ assert_equal('', template.render!)
35
69
  end
36
70
 
37
71
  def test_hash_scoping
38
- template = Template.parse(%({{ test.test }}))
39
- assert_equal 'worked', template.render!('test' => { 'test' => 'worked' })
72
+ assert_template_result('worked', "{{ test.test }}", 'test' => { 'test' => 'worked' })
73
+ assert_template_result('worked', "{{ test . test }}", 'test' => { 'test' => 'worked' })
40
74
  end
41
75
 
42
76
  def test_false_renders_as_false
43
- assert_equal 'false', Template.parse("{{ foo }}").render!('foo' => false)
44
- assert_equal 'false', Template.parse("{{ false }}").render!
77
+ assert_equal('false', Template.parse("{{ foo }}").render!('foo' => false))
78
+ assert_equal('false', Template.parse("{{ false }}").render!)
45
79
  end
46
80
 
47
81
  def test_nil_renders_as_empty_string
48
- assert_equal '', Template.parse("{{ nil }}").render!
49
- assert_equal 'cat', Template.parse("{{ nil | append: 'cat' }}").render!
82
+ assert_equal('', Template.parse("{{ nil }}").render!)
83
+ assert_equal('cat', Template.parse("{{ nil | append: 'cat' }}").render!)
50
84
  end
51
85
 
52
86
  def test_preset_assigns
53
- template = Template.parse(%({{ test }}))
87
+ template = Template.parse(%({{ test }}))
54
88
  template.assigns['test'] = 'worked'
55
- assert_equal 'worked', template.render!
89
+ assert_equal('worked', template.render!)
56
90
  end
57
91
 
58
92
  def test_reuse_parsed_template
59
- template = Template.parse(%({{ greeting }} {{ name }}))
93
+ template = Template.parse(%({{ greeting }} {{ name }}))
60
94
  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')
95
+ assert_equal('Hello Tobi', template.render!('greeting' => 'Hello', 'name' => 'Tobi'))
96
+ assert_equal('Hello ', template.render!('greeting' => 'Hello', 'unknown' => 'Tobi'))
97
+ assert_equal('Hello Brian', template.render!('greeting' => 'Hello', 'name' => 'Brian'))
98
+ assert_equal('Goodbye Brian', template.render!('name' => 'Brian'))
65
99
  assert_equal({ 'greeting' => 'Goodbye' }, template.assigns)
66
100
  end
67
101
 
68
102
  def test_assigns_not_polluted_from_template
69
- template = Template.parse(%({{ test }}{% assign test = 'bar' %}{{ test }}))
103
+ template = Template.parse(%({{ test }}{% assign test = 'bar' %}{{ test }}))
70
104
  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!
105
+ assert_equal('bazbar', template.render!)
106
+ assert_equal('bazbar', template.render!)
107
+ assert_equal('foobar', template.render!('test' => 'foo'))
108
+ assert_equal('bazbar', template.render!)
75
109
  end
76
110
 
77
111
  def test_hash_with_default_proc
78
- template = Template.parse(%(Hello {{ test }}))
79
- assigns = Hash.new { |h, k| raise "Unknown variable '#{k}'" }
112
+ template = Template.parse(%(Hello {{ test }}))
113
+ assigns = Hash.new { |_h, k| raise "Unknown variable '#{k}'" }
80
114
  assigns['test'] = 'Tobi'
81
- assert_equal 'Hello Tobi', template.render!(assigns)
115
+ assert_equal('Hello Tobi', template.render!(assigns))
82
116
  assigns.delete('test')
83
117
  e = assert_raises(RuntimeError) do
84
118
  template.render!(assigns)
85
119
  end
86
- assert_equal "Unknown variable 'test'", e.message
120
+ assert_equal("Unknown variable 'test'", e.message)
87
121
  end
88
122
 
89
123
  def test_multiline_variable
90
- assert_equal 'worked', Template.parse("{{\ntest\n}}").render!('test' => 'worked')
124
+ assert_equal('worked', Template.parse("{{\ntest\n}}").render!('test' => 'worked'))
91
125
  end
92
126
 
93
127
  def test_render_symbol
94
- assert_template_result 'bar', '{{ foo }}', 'foo' => :bar
128
+ assert_template_result('bar', '{{ foo }}', 'foo' => :bar)
129
+ end
130
+
131
+ def test_dynamic_find_var
132
+ assert_template_result('bar', '{{ [key] }}', 'key' => 'foo', 'foo' => 'bar')
133
+ end
134
+
135
+ def test_raw_value_variable
136
+ assert_template_result('bar', '{{ [key] }}', 'key' => 'foo', 'foo' => 'bar')
95
137
  end
96
138
  end
data/test/test_helper.rb CHANGED
@@ -1,4 +1,5 @@
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'
@@ -8,13 +9,13 @@ require 'liquid.rb'
8
9
  require 'liquid/profiler'
9
10
 
10
11
  mode = :strict
11
- if env_mode = ENV['LIQUID_PARSER_MODE']
12
+ if (env_mode = ENV['LIQUID_PARSER_MODE'])
12
13
  puts "-- #{env_mode.upcase} ERROR MODE"
13
14
  mode = env_mode.to_sym
14
15
  end
15
16
  Liquid::Template.error_mode = mode
16
17
 
17
- if ENV['LIQUID-C'] == '1'
18
+ if ENV['LIQUID_C'] == '1'
18
19
  puts "-- LIQUID C"
19
20
  require 'liquid/c'
20
21
  end
@@ -37,44 +38,55 @@ module Minitest
37
38
  include Liquid
38
39
 
39
40
  def assert_template_result(expected, template, assigns = {}, message = nil)
40
- assert_equal expected, Template.parse(template).render!(assigns), message
41
+ assert_equal(expected, Template.parse(template, line_numbers: true).render!(assigns), message)
41
42
  end
42
43
 
43
44
  def assert_template_result_matches(expected, template, assigns = {}, message = nil)
44
- 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)
45
46
 
46
- assert_match expected, Template.parse(template).render!(assigns), message
47
+ assert_match(expected, Template.parse(template, line_numbers: true).render!(assigns), message)
47
48
  end
48
49
 
49
50
  def assert_match_syntax_error(match, template, assigns = {})
50
51
  exception = assert_raises(Liquid::SyntaxError) do
51
- Template.parse(template).render(assigns)
52
+ Template.parse(template, line_numbers: true).render(assigns)
52
53
  end
53
- 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}")
54
72
  end
55
73
 
56
74
  def with_global_filter(*globals)
57
- original_global_strainer = Liquid::Strainer.class_variable_get(:@@global_strainer)
58
- Liquid::Strainer.class_variable_set(:@@global_strainer, Class.new(Liquid::Strainer) do
59
- @filter_methods = Set.new
60
- end)
61
- 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
62
82
 
63
83
  globals.each do |global|
64
84
  Liquid::Template.register_filter(global)
65
85
  end
66
86
  yield
67
87
  ensure
68
- Liquid::Strainer.class_variable_get(:@@strainer_class_cache).clear
69
- Liquid::Strainer.class_variable_set(:@@global_strainer, original_global_strainer)
70
- end
71
-
72
- def with_taint_mode(mode)
73
- old_mode = Liquid::Template.taint_mode
74
- Liquid::Template.taint_mode = mode
75
- yield
76
- ensure
77
- 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)
78
90
  end
79
91
 
80
92
  def with_error_mode(mode)
@@ -84,6 +96,20 @@ module Minitest
84
96
  ensure
85
97
  Liquid::Template.error_mode = old_mode
86
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
87
113
  end
88
114
  end
89
115
 
@@ -93,6 +119,44 @@ class ThingWithToLiquid
93
119
  end
94
120
  end
95
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
+
96
160
  class ErrorDrop < Liquid::Drop
97
161
  def standard_error
98
162
  raise Liquid::StandardError, 'standard error'
@@ -114,3 +178,30 @@ class ErrorDrop < Liquid::Drop
114
178
  raise Exception, 'exception'
115
179
  end
116
180
  end
181
+
182
+ class StubFileSystem
183
+ attr_reader :file_read_count
184
+
185
+ def initialize(values)
186
+ @file_read_count = 0
187
+ @values = values
188
+ end
189
+
190
+ def read_template_file(template_path)
191
+ @file_read_count += 1
192
+ @values.fetch(template_path)
193
+ end
194
+ end
195
+
196
+ class StubTemplateFactory
197
+ attr_reader :count
198
+
199
+ def initialize
200
+ @count = 0
201
+ end
202
+
203
+ def for(_template_name)
204
+ @count += 1
205
+ Liquid::Template.new
206
+ end
207
+ end