liquid 2.6.3 → 3.0.0.rc1

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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +42 -13
  3. data/README.md +27 -2
  4. data/lib/liquid.rb +11 -11
  5. data/lib/liquid/block.rb +75 -45
  6. data/lib/liquid/condition.rb +15 -11
  7. data/lib/liquid/context.rb +68 -29
  8. data/lib/liquid/document.rb +3 -3
  9. data/lib/liquid/drop.rb +17 -1
  10. data/lib/liquid/file_system.rb +17 -6
  11. data/lib/liquid/i18n.rb +39 -0
  12. data/lib/liquid/interrupts.rb +1 -1
  13. data/lib/liquid/lexer.rb +51 -0
  14. data/lib/liquid/locales/en.yml +22 -0
  15. data/lib/liquid/parser.rb +90 -0
  16. data/lib/liquid/standardfilters.rb +115 -52
  17. data/lib/liquid/strainer.rb +14 -4
  18. data/lib/liquid/tag.rb +42 -7
  19. data/lib/liquid/tags/assign.rb +10 -8
  20. data/lib/liquid/tags/break.rb +1 -1
  21. data/lib/liquid/tags/capture.rb +10 -8
  22. data/lib/liquid/tags/case.rb +13 -13
  23. data/lib/liquid/tags/comment.rb +9 -2
  24. data/lib/liquid/tags/continue.rb +1 -4
  25. data/lib/liquid/tags/cycle.rb +5 -7
  26. data/lib/liquid/tags/decrement.rb +3 -4
  27. data/lib/liquid/tags/for.rb +69 -36
  28. data/lib/liquid/tags/if.rb +52 -25
  29. data/lib/liquid/tags/ifchanged.rb +2 -2
  30. data/lib/liquid/tags/include.rb +8 -7
  31. data/lib/liquid/tags/increment.rb +4 -8
  32. data/lib/liquid/tags/raw.rb +3 -3
  33. data/lib/liquid/tags/table_row.rb +73 -0
  34. data/lib/liquid/tags/unless.rb +2 -4
  35. data/lib/liquid/template.rb +69 -10
  36. data/lib/liquid/utils.rb +13 -4
  37. data/lib/liquid/variable.rb +59 -8
  38. data/lib/liquid/version.rb +1 -1
  39. data/test/fixtures/en_locale.yml +9 -0
  40. data/test/{liquid → integration}/assign_test.rb +6 -0
  41. data/test/integration/blank_test.rb +106 -0
  42. data/test/{liquid → integration}/capture_test.rb +2 -2
  43. data/test/integration/context_test.rb +33 -0
  44. data/test/integration/drop_test.rb +245 -0
  45. data/test/{liquid → integration}/error_handling_test.rb +31 -2
  46. data/test/{liquid → integration}/filter_test.rb +7 -7
  47. data/test/{liquid → integration}/hash_ordering_test.rb +0 -0
  48. data/test/{liquid → integration}/output_test.rb +12 -12
  49. data/test/integration/parsing_quirks_test.rb +94 -0
  50. data/test/{liquid → integration}/security_test.rb +9 -9
  51. data/test/{liquid → integration}/standard_filter_test.rb +103 -33
  52. data/test/{liquid → integration}/tags/break_tag_test.rb +0 -0
  53. data/test/{liquid → integration}/tags/continue_tag_test.rb +0 -0
  54. data/test/{liquid → integration}/tags/for_tag_test.rb +78 -0
  55. data/test/{liquid → integration}/tags/if_else_tag_test.rb +1 -1
  56. data/test/integration/tags/include_tag_test.rb +212 -0
  57. data/test/{liquid → integration}/tags/increment_tag_test.rb +0 -0
  58. data/test/{liquid → integration}/tags/raw_tag_test.rb +1 -0
  59. data/test/{liquid → integration}/tags/standard_tag_test.rb +24 -22
  60. data/test/integration/tags/statements_test.rb +113 -0
  61. data/test/{liquid/tags/html_tag_test.rb → integration/tags/table_row_test.rb} +5 -5
  62. data/test/{liquid → integration}/tags/unless_else_tag_test.rb +0 -0
  63. data/test/{liquid → integration}/template_test.rb +66 -42
  64. data/test/integration/variable_test.rb +72 -0
  65. data/test/test_helper.rb +32 -7
  66. data/test/{liquid/block_test.rb → unit/block_unit_test.rb} +1 -1
  67. data/test/{liquid/condition_test.rb → unit/condition_unit_test.rb} +19 -1
  68. data/test/{liquid/context_test.rb → unit/context_unit_test.rb} +27 -19
  69. data/test/{liquid/file_system_test.rb → unit/file_system_unit_test.rb} +7 -1
  70. data/test/unit/i18n_unit_test.rb +37 -0
  71. data/test/unit/lexer_unit_test.rb +48 -0
  72. data/test/{liquid/module_ex_test.rb → unit/module_ex_unit_test.rb} +7 -7
  73. data/test/unit/parser_unit_test.rb +82 -0
  74. data/test/{liquid/regexp_test.rb → unit/regexp_unit_test.rb} +3 -3
  75. data/test/{liquid/strainer_test.rb → unit/strainer_unit_test.rb} +19 -1
  76. data/test/unit/tag_unit_test.rb +11 -0
  77. data/test/unit/tags/case_tag_unit_test.rb +10 -0
  78. data/test/unit/tags/for_tag_unit_test.rb +13 -0
  79. data/test/unit/tags/if_tag_unit_test.rb +8 -0
  80. data/test/unit/template_unit_test.rb +69 -0
  81. data/test/unit/tokenizer_unit_test.rb +29 -0
  82. data/test/{liquid/variable_test.rb → unit/variable_unit_test.rb} +17 -67
  83. metadata +117 -73
  84. data/lib/extras/liquid_view.rb +0 -51
  85. data/lib/liquid/htmltags.rb +0 -73
  86. data/test/liquid/drop_test.rb +0 -180
  87. data/test/liquid/parsing_quirks_test.rb +0 -52
  88. data/test/liquid/tags/include_tag_test.rb +0 -166
  89. data/test/liquid/tags/statements_test.rb +0 -134
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class HtmlTagTest < Test::Unit::TestCase
3
+ class TableRowTest < Test::Unit::TestCase
4
4
  include Liquid
5
5
 
6
6
  class ArrayDrop < Liquid::Drop
@@ -15,7 +15,7 @@ class HtmlTagTest < Test::Unit::TestCase
15
15
  end
16
16
  end
17
17
 
18
- def test_html_table
18
+ def test_table_row
19
19
 
20
20
  assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 4 </td><td class=\"col2\"> 5 </td><td class=\"col3\"> 6 </td></tr>\n",
21
21
  '{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
@@ -26,14 +26,14 @@ class HtmlTagTest < Test::Unit::TestCase
26
26
  'numbers' => [])
27
27
  end
28
28
 
29
- def test_html_table_with_different_cols
29
+ def test_table_row_with_different_cols
30
30
  assert_template_result("<tr class=\"row1\">\n<td class=\"col1\"> 1 </td><td class=\"col2\"> 2 </td><td class=\"col3\"> 3 </td><td class=\"col4\"> 4 </td><td class=\"col5\"> 5 </td></tr>\n<tr class=\"row2\"><td class=\"col1\"> 6 </td></tr>\n",
31
31
  '{% tablerow n in numbers cols:5%} {{n}} {% endtablerow %}',
32
32
  'numbers' => [1,2,3,4,5,6])
33
33
 
34
34
  end
35
35
 
36
- def test_html_col_counter
36
+ def test_table_col_counter
37
37
  assert_template_result("<tr class=\"row1\">\n<td class=\"col1\">1</td><td class=\"col2\">2</td></tr>\n<tr class=\"row2\"><td class=\"col1\">1</td><td class=\"col2\">2</td></tr>\n<tr class=\"row3\"><td class=\"col1\">1</td><td class=\"col2\">2</td></tr>\n",
38
38
  '{% tablerow n in numbers cols:2%}{{tablerowloop.col}}{% endtablerow %}',
39
39
  'numbers' => [1,2,3,4,5,6])
@@ -60,4 +60,4 @@ class HtmlTagTest < Test::Unit::TestCase
60
60
  '{% tablerow n in numbers cols:3 offset:1 limit:6%} {{n}} {% endtablerow %}',
61
61
  'numbers' => [0,1,2,3,4,5,6,7])
62
62
  end
63
- end # HtmlTagTest
63
+ end
@@ -14,85 +14,85 @@ class TemplateContextDrop < Liquid::Drop
14
14
  end
15
15
  end
16
16
 
17
- class TemplateTest < Test::Unit::TestCase
18
- include Liquid
19
-
20
- def test_tokenize_strings
21
- assert_equal [' '], Template.new.send(:tokenize, ' ')
22
- assert_equal ['hello world'], Template.new.send(:tokenize, 'hello world')
23
- end
24
-
25
- def test_tokenize_variables
26
- assert_equal ['{{funk}}'], Template.new.send(:tokenize, '{{funk}}')
27
- assert_equal [' ', '{{funk}}', ' '], Template.new.send(:tokenize, ' {{funk}} ')
28
- assert_equal [' ', '{{funk}}', ' ', '{{so}}', ' ', '{{brother}}', ' '], Template.new.send(:tokenize, ' {{funk}} {{so}} {{brother}} ')
29
- assert_equal [' ', '{{ funk }}', ' '], Template.new.send(:tokenize, ' {{ funk }} ')
17
+ class SomethingWithLength
18
+ def length
19
+ nil
30
20
  end
31
21
 
32
- def test_tokenize_blocks
33
- assert_equal ['{%comment%}'], Template.new.send(:tokenize, '{%comment%}')
34
- assert_equal [' ', '{%comment%}', ' '], Template.new.send(:tokenize, ' {%comment%} ')
22
+ liquid_methods :length
23
+ end
35
24
 
36
- assert_equal [' ', '{%comment%}', ' ', '{%endcomment%}', ' '], Template.new.send(:tokenize, ' {%comment%} {%endcomment%} ')
37
- assert_equal [' ', '{% comment %}', ' ', '{% endcomment %}', ' '], Template.new.send(:tokenize, " {% comment %} {% endcomment %} ")
25
+ class ErroneousDrop < Liquid::Drop
26
+ def bad_method
27
+ raise 'ruby error in drop'
38
28
  end
29
+ end
30
+
31
+ class TemplateTest < Test::Unit::TestCase
32
+ include Liquid
39
33
 
40
34
  def test_instance_assigns_persist_on_same_template_object_between_parses
41
35
  t = Template.new
42
- assert_equal 'from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render
43
- assert_equal 'from instance assigns', t.parse("{{ foo }}").render
36
+ assert_equal 'from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render!
37
+ assert_equal 'from instance assigns', t.parse("{{ foo }}").render!
44
38
  end
45
39
 
46
40
  def test_instance_assigns_persist_on_same_template_parsing_between_renders
47
41
  t = Template.new.parse("{{ foo }}{% assign foo = 'foo' %}{{ foo }}")
48
- assert_equal 'foo', t.render
49
- assert_equal 'foofoo', t.render
42
+ assert_equal 'foo', t.render!
43
+ assert_equal 'foofoo', t.render!
50
44
  end
51
45
 
52
46
  def test_custom_assigns_do_not_persist_on_same_template
53
47
  t = Template.new
54
- assert_equal 'from custom assigns', t.parse("{{ foo }}").render('foo' => 'from custom assigns')
55
- assert_equal '', t.parse("{{ foo }}").render
48
+ assert_equal 'from custom assigns', t.parse("{{ foo }}").render!('foo' => 'from custom assigns')
49
+ assert_equal '', t.parse("{{ foo }}").render!
56
50
  end
57
51
 
58
52
  def test_custom_assigns_squash_instance_assigns
59
53
  t = Template.new
60
- assert_equal 'from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render
61
- assert_equal 'from custom assigns', t.parse("{{ foo }}").render('foo' => 'from custom assigns')
54
+ assert_equal 'from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render!
55
+ assert_equal 'from custom assigns', t.parse("{{ foo }}").render!('foo' => 'from custom assigns')
62
56
  end
63
57
 
64
58
  def test_persistent_assigns_squash_instance_assigns
65
59
  t = Template.new
66
- assert_equal 'from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render
60
+ assert_equal 'from instance assigns', t.parse("{% assign foo = 'from instance assigns' %}{{ foo }}").render!
67
61
  t.assigns['foo'] = 'from persistent assigns'
68
- assert_equal 'from persistent assigns', t.parse("{{ foo }}").render
62
+ assert_equal 'from persistent assigns', t.parse("{{ foo }}").render!
69
63
  end
70
64
 
71
65
  def test_lambda_is_called_once_from_persistent_assigns_over_multiple_parses_and_renders
72
66
  t = Template.new
73
67
  t.assigns['number'] = lambda { @global ||= 0; @global += 1 }
74
- assert_equal '1', t.parse("{{number}}").render
75
- assert_equal '1', t.parse("{{number}}").render
76
- assert_equal '1', t.render
68
+ assert_equal '1', t.parse("{{number}}").render!
69
+ assert_equal '1', t.parse("{{number}}").render!
70
+ assert_equal '1', t.render!
77
71
  @global = nil
78
72
  end
79
73
 
80
74
  def test_lambda_is_called_once_from_custom_assigns_over_multiple_parses_and_renders
81
75
  t = Template.new
82
76
  assigns = {'number' => lambda { @global ||= 0; @global += 1 }}
83
- assert_equal '1', t.parse("{{number}}").render(assigns)
84
- assert_equal '1', t.parse("{{number}}").render(assigns)
85
- assert_equal '1', t.render(assigns)
77
+ assert_equal '1', t.parse("{{number}}").render!(assigns)
78
+ assert_equal '1', t.parse("{{number}}").render!(assigns)
79
+ assert_equal '1', t.render!(assigns)
86
80
  @global = nil
87
81
  end
88
82
 
83
+ def test_resource_limits_works_with_custom_length_method
84
+ t = Template.parse("{% assign foo = bar %}")
85
+ t.resource_limits = { :render_length_limit => 42 }
86
+ assert_equal "", t.render!("bar" => SomethingWithLength.new)
87
+ end
88
+
89
89
  def test_resource_limits_render_length
90
90
  t = Template.parse("0123456789")
91
91
  t.resource_limits = { :render_length_limit => 5 }
92
92
  assert_equal "Liquid error: Memory limits exceeded", t.render()
93
93
  assert t.resource_limits[:reached]
94
94
  t.resource_limits = { :render_length_limit => 10 }
95
- assert_equal "0123456789", t.render()
95
+ assert_equal "0123456789", t.render!()
96
96
  assert_not_nil t.resource_limits[:render_length_current]
97
97
  end
98
98
 
@@ -106,7 +106,7 @@ class TemplateTest < Test::Unit::TestCase
106
106
  assert_equal "Liquid error: Memory limits exceeded", t.render()
107
107
  assert t.resource_limits[:reached]
108
108
  t.resource_limits = { :render_score_limit => 200 }
109
- assert_equal (" foo " * 100), t.render()
109
+ assert_equal (" foo " * 100), t.render!()
110
110
  assert_not_nil t.resource_limits[:render_score_current]
111
111
  end
112
112
 
@@ -116,7 +116,7 @@ class TemplateTest < Test::Unit::TestCase
116
116
  assert_equal "Liquid error: Memory limits exceeded", t.render()
117
117
  assert t.resource_limits[:reached]
118
118
  t.resource_limits = { :assign_score_limit => 2 }
119
- assert_equal "", t.render()
119
+ assert_equal "", t.render!()
120
120
  assert_not_nil t.resource_limits[:assign_score_current]
121
121
  end
122
122
 
@@ -129,7 +129,7 @@ class TemplateTest < Test::Unit::TestCase
129
129
 
130
130
  def test_resource_limits_hash_in_template_gets_updated_even_if_no_limits_are_set
131
131
  t = Template.parse("{% for a in (1..100) %} {% assign foo = 1 %} {% endfor %}")
132
- t.render()
132
+ t.render!()
133
133
  assert t.resource_limits[:assign_score_current] > 0
134
134
  assert t.resource_limits[:render_score_current] > 0
135
135
  assert t.resource_limits[:render_length_current] > 0
@@ -139,8 +139,32 @@ class TemplateTest < Test::Unit::TestCase
139
139
  t = Template.new
140
140
  t.registers['lulz'] = 'haha'
141
141
  drop = TemplateContextDrop.new
142
- assert_equal 'fizzbuzz', t.parse('{{foo}}').render(drop)
143
- assert_equal 'bar', t.parse('{{bar}}').render(drop)
144
- assert_equal 'haha', t.parse("{{baz}}").render(drop)
142
+ assert_equal 'fizzbuzz', t.parse('{{foo}}').render!(drop)
143
+ assert_equal 'bar', t.parse('{{bar}}').render!(drop)
144
+ assert_equal 'haha', t.parse("{{baz}}").render!(drop)
145
+ end
146
+
147
+ def test_render_bang_force_rethrow_errors_on_passed_context
148
+ context = Context.new({'drop' => ErroneousDrop.new})
149
+ t = Template.new.parse('{{ drop.bad_method }}')
150
+
151
+ e = assert_raises RuntimeError do
152
+ t.render!(context)
153
+ end
154
+ assert_equal 'ruby error in drop', e.message
145
155
  end
146
- end # TemplateTest
156
+
157
+ def test_exception_handler_doesnt_reraise_if_it_returns_false
158
+ exception = nil
159
+ Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_handler: ->(e) { exception = e; false })
160
+ assert exception.is_a?(ZeroDivisionError)
161
+ end
162
+
163
+ def test_exception_handler_does_reraise_if_it_returns_true
164
+ exception = nil
165
+ assert_raises(ZeroDivisionError) do
166
+ Template.parse("{{ 1 | divided_by: 0 }}").render({}, exception_handler: ->(e) { exception = e; true })
167
+ end
168
+ assert exception.is_a?(ZeroDivisionError)
169
+ end
170
+ end
@@ -0,0 +1,72 @@
1
+ require 'test_helper'
2
+
3
+ class VariableTest < Test::Unit::TestCase
4
+ include Liquid
5
+
6
+ def test_simple_variable
7
+ template = Template.parse(%|{{test}}|)
8
+ assert_equal 'worked', template.render!('test' => 'worked')
9
+ assert_equal 'worked wonderfully', template.render!('test' => 'worked wonderfully')
10
+ end
11
+
12
+ def test_simple_with_whitespaces
13
+ template = Template.parse(%| {{ test }} |)
14
+ assert_equal ' worked ', template.render!('test' => 'worked')
15
+ assert_equal ' worked wonderfully ', template.render!('test' => 'worked wonderfully')
16
+ end
17
+
18
+ def test_ignore_unknown
19
+ template = Template.parse(%|{{ test }}|)
20
+ assert_equal '', template.render!
21
+ end
22
+
23
+ def test_hash_scoping
24
+ template = Template.parse(%|{{ test.test }}|)
25
+ assert_equal 'worked', template.render!('test' => {'test' => 'worked'})
26
+ end
27
+
28
+ def test_false_renders_as_false
29
+ assert_equal 'false', Template.parse("{{ foo }}").render!('foo' => false)
30
+ end
31
+
32
+ def test_preset_assigns
33
+ template = Template.parse(%|{{ test }}|)
34
+ template.assigns['test'] = 'worked'
35
+ assert_equal 'worked', template.render!
36
+ end
37
+
38
+ def test_reuse_parsed_template
39
+ template = Template.parse(%|{{ greeting }} {{ name }}|)
40
+ template.assigns['greeting'] = 'Goodbye'
41
+ assert_equal 'Hello Tobi', template.render!('greeting' => 'Hello', 'name' => 'Tobi')
42
+ assert_equal 'Hello ', template.render!('greeting' => 'Hello', 'unknown' => 'Tobi')
43
+ assert_equal 'Hello Brian', template.render!('greeting' => 'Hello', 'name' => 'Brian')
44
+ assert_equal 'Goodbye Brian', template.render!('name' => 'Brian')
45
+ assert_equal({'greeting'=>'Goodbye'}, template.assigns)
46
+ end
47
+
48
+ def test_assigns_not_polluted_from_template
49
+ template = Template.parse(%|{{ test }}{% assign test = 'bar' %}{{ test }}|)
50
+ template.assigns['test'] = 'baz'
51
+ assert_equal 'bazbar', template.render!
52
+ assert_equal 'bazbar', template.render!
53
+ assert_equal 'foobar', template.render!('test' => 'foo')
54
+ assert_equal 'bazbar', template.render!
55
+ end
56
+
57
+ def test_hash_with_default_proc
58
+ template = Template.parse(%|Hello {{ test }}|)
59
+ assigns = Hash.new { |h,k| raise "Unknown variable '#{k}'" }
60
+ assigns['test'] = 'Tobi'
61
+ assert_equal 'Hello Tobi', template.render!(assigns)
62
+ assigns.delete('test')
63
+ e = assert_raises(RuntimeError) {
64
+ template.render!(assigns)
65
+ }
66
+ assert_equal "Unknown variable 'test'", e.message
67
+ end
68
+
69
+ def test_multiline_variable
70
+ assert_equal 'worked', Template.parse("{{\ntest\n}}").render!('test' => 'worked')
71
+ end
72
+ end
data/test/test_helper.rb CHANGED
@@ -2,27 +2,52 @@
2
2
 
3
3
  require 'test/unit'
4
4
  require 'test/unit/assertions'
5
- begin
6
- require 'ruby-debug'
7
- rescue LoadError
8
- puts "Couldn't load ruby-debug. gem install ruby-debug if you need it."
5
+ require 'spy/integration'
6
+
7
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
8
+ require 'liquid.rb'
9
+
10
+ mode = :strict
11
+ if env_mode = ENV['LIQUID_PARSER_MODE']
12
+ puts "-- #{env_mode.upcase} ERROR MODE"
13
+ mode = env_mode.to_sym
9
14
  end
10
- require File.join(File.dirname(__FILE__), '..', 'lib', 'liquid')
15
+ Liquid::Template.error_mode = mode
11
16
 
12
17
 
13
18
  module Test
14
19
  module Unit
20
+ class TestCase
21
+ def fixture(name)
22
+ File.join(File.expand_path(File.dirname(__FILE__)), "fixtures", name)
23
+ end
24
+ end
25
+
15
26
  module Assertions
16
27
  include Liquid
17
28
 
18
29
  def assert_template_result(expected, template, assigns = {}, message = nil)
19
- assert_equal expected, Template.parse(template).render(assigns)
30
+ assert_equal expected, Template.parse(template).render!(assigns)
20
31
  end
21
32
 
22
33
  def assert_template_result_matches(expected, template, assigns = {}, message = nil)
23
34
  return assert_template_result(expected, template, assigns, message) unless expected.is_a? Regexp
24
35
 
25
- assert_match expected, Template.parse(template).render(assigns)
36
+ assert_match expected, Template.parse(template).render!(assigns)
37
+ end
38
+
39
+ def assert_match_syntax_error(match, template, registers = {})
40
+ exception = assert_raise(Liquid::SyntaxError) {
41
+ Template.parse(template).render(assigns)
42
+ }
43
+ assert_match match, exception.message
44
+ end
45
+
46
+ def with_error_mode(mode)
47
+ old_mode = Liquid::Template.error_mode
48
+ Liquid::Template.error_mode = mode
49
+ yield
50
+ Liquid::Template.error_mode = old_mode
26
51
  end
27
52
  end # Assertions
28
53
  end # Unit
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class BlockTest < Test::Unit::TestCase
3
+ class BlockUnitTest < Test::Unit::TestCase
4
4
  include Liquid
5
5
 
6
6
  def test_blankspace
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class ConditionTest < Test::Unit::TestCase
3
+ class ConditionUnitTest < Test::Unit::TestCase
4
4
  include Liquid
5
5
 
6
6
  def test_basic_condition
@@ -49,6 +49,17 @@ class ConditionTest < Test::Unit::TestCase
49
49
  assert_evalutes_false "'bob'", 'contains', "'---'"
50
50
  end
51
51
 
52
+ def test_invalid_comparation_operator
53
+ assert_evaluates_argument_error "1", '~~', '0'
54
+ end
55
+
56
+ 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
+ end
62
+
52
63
  def test_contains_works_on_arrays
53
64
  @context = Liquid::Context.new
54
65
  @context['array'] = [1,2,3,4,5]
@@ -124,4 +135,11 @@ class ConditionTest < Test::Unit::TestCase
124
135
  assert !Condition.new(left, op, right).evaluate(@context || Liquid::Context.new),
125
136
  "Evaluated true: #{left} #{op} #{right}"
126
137
  end
138
+
139
+ def assert_evaluates_argument_error(left, op, right)
140
+ assert_raises(Liquid::ArgumentError) do
141
+ Condition.new(left, op, right).evaluate(@context || Liquid::Context.new)
142
+ end
143
+ end
144
+
127
145
  end # ConditionTest
@@ -63,13 +63,17 @@ class ArrayLike
63
63
  end
64
64
  end
65
65
 
66
- class ContextTest < Test::Unit::TestCase
66
+ class ContextUnitTest < Test::Unit::TestCase
67
67
  include Liquid
68
68
 
69
69
  def setup
70
70
  @context = Liquid::Context.new
71
71
  end
72
72
 
73
+ def teardown
74
+ Spy.teardown
75
+ end
76
+
73
77
  def test_variables
74
78
  @context['string'] = 'string'
75
79
  assert_equal 'string', @context['string']
@@ -162,24 +166,6 @@ class ContextTest < Test::Unit::TestCase
162
166
 
163
167
  end
164
168
 
165
- def test_override_global_filter
166
- global = Module.new do
167
- def notice(output)
168
- "Global #{output}"
169
- end
170
- end
171
-
172
- local = Module.new do
173
- def notice(output)
174
- "Local #{output}"
175
- end
176
- end
177
-
178
- Template.register_filter(global)
179
- assert_equal 'Global test', Template.parse("{{'test' | notice }}").render
180
- assert_equal 'Local test', Template.parse("{{'test' | notice }}").render({}, :filters => [local])
181
- end
182
-
183
169
  def test_only_intended_filters_make_it_there
184
170
 
185
171
  filter = Module.new do
@@ -475,4 +461,26 @@ class ContextTest < Test::Unit::TestCase
475
461
  assert_kind_of CategoryDrop, @context['category']
476
462
  assert_equal @context, @context['category'].context
477
463
  end
464
+
465
+ def test_use_empty_instead_of_any_in_interrupt_handling_to_avoid_lots_of_unnecessary_object_allocations
466
+ mock_any = Spy.on_instance_method(Array, :any?)
467
+ mock_empty = Spy.on_instance_method(Array, :empty?)
468
+ mock_has_interrupt = Spy.on(@context, :has_interrupt?).and_call_through
469
+
470
+ @context.has_interrupt?
471
+
472
+ refute mock_any.has_been_called?
473
+ assert mock_empty.has_been_called?
474
+ end
475
+
476
+ def test_variable_lookup_caches_markup
477
+ mock_scan = Spy.on_instance_method(String, :scan).and_return(["string"])
478
+
479
+ @context['string'] = 'string'
480
+ @context['string']
481
+ @context['string']
482
+
483
+ assert_equal 1, mock_scan.calls.size
484
+ end
485
+
478
486
  end # ContextTest