liquid 2.2.2 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/{History.txt → History.md} +26 -23
  2. data/README.md +18 -16
  3. data/lib/liquid.rb +1 -4
  4. data/lib/liquid/block.rb +2 -2
  5. data/lib/liquid/context.rb +29 -33
  6. data/lib/liquid/drop.rb +11 -13
  7. data/lib/liquid/extensions.rb +13 -7
  8. data/lib/liquid/file_system.rb +2 -2
  9. data/lib/liquid/htmltags.rb +5 -4
  10. data/lib/liquid/standardfilters.rb +12 -1
  11. data/lib/liquid/strainer.rb +1 -1
  12. data/lib/liquid/tags/capture.rb +1 -1
  13. data/lib/liquid/tags/case.rb +4 -8
  14. data/lib/liquid/tags/decrement.rb +39 -0
  15. data/lib/liquid/tags/for.rb +20 -5
  16. data/lib/liquid/tags/include.rb +21 -12
  17. data/lib/liquid/tags/increment.rb +35 -0
  18. data/lib/liquid/tags/raw.rb +21 -0
  19. data/lib/liquid/tags/unless.rb +5 -5
  20. data/lib/liquid/template.rb +3 -2
  21. data/lib/liquid/variable.rb +1 -1
  22. data/test/liquid/assign_test.rb +15 -0
  23. data/test/liquid/block_test.rb +58 -0
  24. data/test/liquid/capture_test.rb +40 -0
  25. data/test/liquid/condition_test.rb +122 -0
  26. data/test/liquid/context_test.rb +478 -0
  27. data/test/liquid/drop_test.rb +162 -0
  28. data/test/liquid/error_handling_test.rb +81 -0
  29. data/test/liquid/file_system_test.rb +29 -0
  30. data/test/liquid/filter_test.rb +106 -0
  31. data/test/liquid/module_ex_test.rb +87 -0
  32. data/test/liquid/output_test.rb +116 -0
  33. data/test/liquid/parsing_quirks_test.rb +52 -0
  34. data/test/liquid/regexp_test.rb +44 -0
  35. data/test/liquid/security_test.rb +41 -0
  36. data/test/liquid/standard_filter_test.rb +191 -0
  37. data/test/liquid/strainer_test.rb +25 -0
  38. data/test/liquid/tags/html_tag_test.rb +29 -0
  39. data/test/liquid/tags/if_else_tag_test.rb +160 -0
  40. data/test/liquid/tags/include_tag_test.rb +139 -0
  41. data/test/liquid/tags/increment_tag_test.rb +24 -0
  42. data/test/liquid/tags/raw_tag_test.rb +15 -0
  43. data/test/liquid/tags/standard_tag_test.rb +461 -0
  44. data/test/liquid/tags/statements_test.rb +134 -0
  45. data/test/liquid/tags/unless_else_tag_test.rb +26 -0
  46. data/test/liquid/template_test.rb +74 -0
  47. data/test/liquid/variable_test.rb +170 -0
  48. data/test/test_helper.rb +29 -0
  49. metadata +67 -16
  50. data/Manifest.txt +0 -34
  51. data/lib/liquid/tags/literal.rb +0 -42
@@ -0,0 +1,29 @@
1
+ require 'test_helper'
2
+
3
+ class HtmlTagTest < Test::Unit::TestCase
4
+ include Liquid
5
+
6
+ def test_html_table
7
+
8
+ 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",
9
+ '{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
10
+ 'numbers' => [1,2,3,4,5,6])
11
+
12
+ assert_template_result("<tr class=\"row1\">\n</tr>\n",
13
+ '{% tablerow n in numbers cols:3%} {{n}} {% endtablerow %}',
14
+ 'numbers' => [])
15
+ end
16
+
17
+ def test_html_table_with_different_cols
18
+ 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",
19
+ '{% tablerow n in numbers cols:5%} {{n}} {% endtablerow %}',
20
+ 'numbers' => [1,2,3,4,5,6])
21
+
22
+ end
23
+
24
+ def test_html_col_counter
25
+ 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",
26
+ '{% tablerow n in numbers cols:2%}{{tablerowloop.col}}{% endtablerow %}',
27
+ 'numbers' => [1,2,3,4,5,6])
28
+ end
29
+ end # HtmlTagTest
@@ -0,0 +1,160 @@
1
+ require 'test_helper'
2
+
3
+ class IfElseTagTest < Test::Unit::TestCase
4
+ include Liquid
5
+
6
+ def test_if
7
+ assert_template_result(' ',' {% if false %} this text should not go into the output {% endif %} ')
8
+ assert_template_result(' this text should go into the output ',
9
+ ' {% if true %} this text should go into the output {% endif %} ')
10
+ assert_template_result(' you rock ?','{% if false %} you suck {% endif %} {% if true %} you rock {% endif %}?')
11
+ end
12
+
13
+ def test_if_else
14
+ assert_template_result(' YES ','{% if false %} NO {% else %} YES {% endif %}')
15
+ assert_template_result(' YES ','{% if true %} YES {% else %} NO {% endif %}')
16
+ assert_template_result(' YES ','{% if "foo" %} YES {% else %} NO {% endif %}')
17
+ end
18
+
19
+ def test_if_boolean
20
+ assert_template_result(' YES ','{% if var %} YES {% endif %}', 'var' => true)
21
+ end
22
+
23
+ def test_if_or
24
+ assert_template_result(' YES ','{% if a or b %} YES {% endif %}', 'a' => true, 'b' => true)
25
+ assert_template_result(' YES ','{% if a or b %} YES {% endif %}', 'a' => true, 'b' => false)
26
+ assert_template_result(' YES ','{% if a or b %} YES {% endif %}', 'a' => false, 'b' => true)
27
+ assert_template_result('', '{% if a or b %} YES {% endif %}', 'a' => false, 'b' => false)
28
+
29
+ assert_template_result(' YES ','{% if a or b or c %} YES {% endif %}', 'a' => false, 'b' => false, 'c' => true)
30
+ assert_template_result('', '{% if a or b or c %} YES {% endif %}', 'a' => false, 'b' => false, 'c' => false)
31
+ end
32
+
33
+ def test_if_or_with_operators
34
+ assert_template_result(' YES ','{% if a == true or b == true %} YES {% endif %}', 'a' => true, 'b' => true)
35
+ assert_template_result(' YES ','{% if a == true or b == false %} YES {% endif %}', 'a' => true, 'b' => true)
36
+ assert_template_result('','{% if a == false or b == false %} YES {% endif %}', 'a' => true, 'b' => true)
37
+ end
38
+
39
+ def test_comparison_of_strings_containing_and_or_or
40
+ assert_nothing_raised do
41
+ awful_markup = "a == 'and' and b == 'or' and c == 'foo and bar' and d == 'bar or baz' and e == 'foo' and foo and bar"
42
+ assigns = {'a' => 'and', 'b' => 'or', 'c' => 'foo and bar', 'd' => 'bar or baz', 'e' => 'foo', 'foo' => true, 'bar' => true}
43
+ assert_template_result(' YES ',"{% if #{awful_markup} %} YES {% endif %}", assigns)
44
+ end
45
+ end
46
+
47
+ def test_comparison_of_expressions_starting_with_and_or_or
48
+ assigns = {'order' => {'items_count' => 0}, 'android' => {'name' => 'Roy'}}
49
+ assert_nothing_raised do
50
+ assert_template_result( "YES",
51
+ "{% if android.name == 'Roy' %}YES{% endif %}",
52
+ assigns)
53
+ end
54
+ assert_nothing_raised do
55
+ assert_template_result( "YES",
56
+ "{% if order.items_count == 0 %}YES{% endif %}",
57
+ assigns)
58
+ end
59
+ end
60
+
61
+ def test_if_and
62
+ assert_template_result(' YES ','{% if true and true %} YES {% endif %}')
63
+ assert_template_result('','{% if false and true %} YES {% endif %}')
64
+ assert_template_result('','{% if false and true %} YES {% endif %}')
65
+ end
66
+
67
+
68
+ def test_hash_miss_generates_false
69
+ assert_template_result('','{% if foo.bar %} NO {% endif %}', 'foo' => {})
70
+ end
71
+
72
+ def test_if_from_variable
73
+ assert_template_result('','{% if var %} NO {% endif %}', 'var' => false)
74
+ assert_template_result('','{% if var %} NO {% endif %}', 'var' => nil)
75
+ assert_template_result('','{% if foo.bar %} NO {% endif %}', 'foo' => {'bar' => false})
76
+ assert_template_result('','{% if foo.bar %} NO {% endif %}', 'foo' => {})
77
+ assert_template_result('','{% if foo.bar %} NO {% endif %}', 'foo' => nil)
78
+ assert_template_result('','{% if foo.bar %} NO {% endif %}', 'foo' => true)
79
+
80
+ assert_template_result(' YES ','{% if var %} YES {% endif %}', 'var' => "text")
81
+ assert_template_result(' YES ','{% if var %} YES {% endif %}', 'var' => true)
82
+ assert_template_result(' YES ','{% if var %} YES {% endif %}', 'var' => 1)
83
+ assert_template_result(' YES ','{% if var %} YES {% endif %}', 'var' => {})
84
+ assert_template_result(' YES ','{% if var %} YES {% endif %}', 'var' => [])
85
+ assert_template_result(' YES ','{% if "foo" %} YES {% endif %}')
86
+ assert_template_result(' YES ','{% if foo.bar %} YES {% endif %}', 'foo' => {'bar' => true})
87
+ assert_template_result(' YES ','{% if foo.bar %} YES {% endif %}', 'foo' => {'bar' => "text"})
88
+ assert_template_result(' YES ','{% if foo.bar %} YES {% endif %}', 'foo' => {'bar' => 1 })
89
+ assert_template_result(' YES ','{% if foo.bar %} YES {% endif %}', 'foo' => {'bar' => {} })
90
+ assert_template_result(' YES ','{% if foo.bar %} YES {% endif %}', 'foo' => {'bar' => [] })
91
+
92
+ assert_template_result(' YES ','{% if var %} NO {% else %} YES {% endif %}', 'var' => false)
93
+ assert_template_result(' YES ','{% if var %} NO {% else %} YES {% endif %}', 'var' => nil)
94
+ assert_template_result(' YES ','{% if var %} YES {% else %} NO {% endif %}', 'var' => true)
95
+ assert_template_result(' YES ','{% if "foo" %} YES {% else %} NO {% endif %}', 'var' => "text")
96
+
97
+ assert_template_result(' YES ','{% if foo.bar %} NO {% else %} YES {% endif %}', 'foo' => {'bar' => false})
98
+ assert_template_result(' YES ','{% if foo.bar %} YES {% else %} NO {% endif %}', 'foo' => {'bar' => true})
99
+ assert_template_result(' YES ','{% if foo.bar %} YES {% else %} NO {% endif %}', 'foo' => {'bar' => "text"})
100
+ assert_template_result(' YES ','{% if foo.bar %} NO {% else %} YES {% endif %}', 'foo' => {'notbar' => true})
101
+ assert_template_result(' YES ','{% if foo.bar %} NO {% else %} YES {% endif %}', 'foo' => {})
102
+ assert_template_result(' YES ','{% if foo.bar %} NO {% else %} YES {% endif %}', 'notfoo' => {'bar' => true})
103
+ end
104
+
105
+ def test_nested_if
106
+ assert_template_result('', '{% if false %}{% if false %} NO {% endif %}{% endif %}')
107
+ assert_template_result('', '{% if false %}{% if true %} NO {% endif %}{% endif %}')
108
+ assert_template_result('', '{% if true %}{% if false %} NO {% endif %}{% endif %}')
109
+ assert_template_result(' YES ', '{% if true %}{% if true %} YES {% endif %}{% endif %}')
110
+
111
+ assert_template_result(' YES ', '{% if true %}{% if true %} YES {% else %} NO {% endif %}{% else %} NO {% endif %}')
112
+ assert_template_result(' YES ', '{% if true %}{% if false %} NO {% else %} YES {% endif %}{% else %} NO {% endif %}')
113
+ assert_template_result(' YES ', '{% if false %}{% if true %} NO {% else %} NONO {% endif %}{% else %} YES {% endif %}')
114
+
115
+ end
116
+
117
+ def test_comparisons_on_null
118
+ assert_template_result('','{% if null < 10 %} NO {% endif %}')
119
+ assert_template_result('','{% if null <= 10 %} NO {% endif %}')
120
+ assert_template_result('','{% if null >= 10 %} NO {% endif %}')
121
+ assert_template_result('','{% if null > 10 %} NO {% endif %}')
122
+
123
+ assert_template_result('','{% if 10 < null %} NO {% endif %}')
124
+ assert_template_result('','{% if 10 <= null %} NO {% endif %}')
125
+ assert_template_result('','{% if 10 >= null %} NO {% endif %}')
126
+ assert_template_result('','{% if 10 > null %} NO {% endif %}')
127
+ end
128
+
129
+ def test_else_if
130
+ assert_template_result('0','{% if 0 == 0 %}0{% elsif 1 == 1%}1{% else %}2{% endif %}')
131
+ assert_template_result('1','{% if 0 != 0 %}0{% elsif 1 == 1%}1{% else %}2{% endif %}')
132
+ assert_template_result('2','{% if 0 != 0 %}0{% elsif 1 != 1%}1{% else %}2{% endif %}')
133
+
134
+ assert_template_result('elsif','{% if false %}if{% elsif true %}elsif{% endif %}')
135
+ end
136
+
137
+ def test_syntax_error_no_variable
138
+ assert_raise(SyntaxError){ assert_template_result('', '{% if jerry == 1 %}')}
139
+ end
140
+
141
+ def test_syntax_error_no_expression
142
+ assert_raise(SyntaxError) { assert_template_result('', '{% if %}') }
143
+ end
144
+
145
+ def test_if_with_custom_condition
146
+ Condition.operators['contains'] = :[]
147
+
148
+ assert_template_result('yes', %({% if 'bob' contains 'o' %}yes{% endif %}))
149
+ assert_template_result('no', %({% if 'bob' contains 'f' %}yes{% else %}no{% endif %}))
150
+ ensure
151
+ Condition.operators.delete 'contains'
152
+ end
153
+
154
+ def test_operators_are_ignored_unless_isolated
155
+ Condition.operators['contains'] = :[]
156
+
157
+ assert_template_result('yes',
158
+ %({% if 'gnomeslab-and-or-liquid' contains 'gnomeslab-and-or-liquid' %}yes{% endif %}))
159
+ end
160
+ end # IfElseTest
@@ -0,0 +1,139 @@
1
+ require 'test_helper'
2
+
3
+ class TestFileSystem
4
+ def read_template_file(template_path, context)
5
+ case template_path
6
+ when "product"
7
+ "Product: {{ product.title }} "
8
+
9
+ when "locale_variables"
10
+ "Locale: {{echo1}} {{echo2}}"
11
+
12
+ when "variant"
13
+ "Variant: {{ variant.title }}"
14
+
15
+ when "nested_template"
16
+ "{% include 'header' %} {% include 'body' %} {% include 'footer' %}"
17
+
18
+ when "body"
19
+ "body {% include 'body_detail' %}"
20
+
21
+ when "nested_product_template"
22
+ "Product: {{ nested_product_template.title }} {%include 'details'%} "
23
+
24
+ when "recursively_nested_template"
25
+ "-{% include 'recursively_nested_template' %}"
26
+
27
+ when "pick_a_source"
28
+ "from TestFileSystem"
29
+
30
+ else
31
+ template_path
32
+ end
33
+ end
34
+ end
35
+
36
+ class OtherFileSystem
37
+ def read_template_file(template_path, context)
38
+ 'from OtherFileSystem'
39
+ end
40
+ end
41
+
42
+ class IncludeTagTest < Test::Unit::TestCase
43
+ include Liquid
44
+
45
+ def setup
46
+ Liquid::Template.file_system = TestFileSystem.new
47
+ end
48
+
49
+ def test_include_tag_looks_for_file_system_in_registers_first
50
+ assert_equal 'from OtherFileSystem',
51
+ Template.parse("{% include 'pick_a_source' %}").render({}, :registers => {:file_system => OtherFileSystem.new})
52
+ end
53
+
54
+
55
+ def test_include_tag_with
56
+ assert_equal "Product: Draft 151cm ",
57
+ Template.parse("{% include 'product' with products[0] %}").render( "products" => [ {'title' => 'Draft 151cm'}, {'title' => 'Element 155cm'} ] )
58
+ end
59
+
60
+ def test_include_tag_with_default_name
61
+ assert_equal "Product: Draft 151cm ",
62
+ Template.parse("{% include 'product' %}").render( "product" => {'title' => 'Draft 151cm'} )
63
+ end
64
+
65
+ def test_include_tag_for
66
+
67
+ assert_equal "Product: Draft 151cm Product: Element 155cm ",
68
+ Template.parse("{% include 'product' for products %}").render( "products" => [ {'title' => 'Draft 151cm'}, {'title' => 'Element 155cm'} ] )
69
+ end
70
+
71
+ def test_include_tag_with_local_variables
72
+ assert_equal "Locale: test123 ",
73
+ Template.parse("{% include 'locale_variables' echo1: 'test123' %}").render
74
+ end
75
+
76
+ def test_include_tag_with_multiple_local_variables
77
+ assert_equal "Locale: test123 test321",
78
+ Template.parse("{% include 'locale_variables' echo1: 'test123', echo2: 'test321' %}").render
79
+ end
80
+
81
+ def test_include_tag_with_multiple_local_variables_from_context
82
+ assert_equal "Locale: test123 test321",
83
+ Template.parse("{% include 'locale_variables' echo1: echo1, echo2: more_echos.echo2 %}").render('echo1' => 'test123', 'more_echos' => { "echo2" => 'test321'})
84
+ end
85
+
86
+ def test_nested_include_tag
87
+ assert_equal "body body_detail",
88
+ Template.parse("{% include 'body' %}").render
89
+
90
+ assert_equal "header body body_detail footer",
91
+ Template.parse("{% include 'nested_template' %}").render
92
+ end
93
+
94
+ def test_nested_include_with_variable
95
+
96
+ assert_equal "Product: Draft 151cm details ",
97
+ Template.parse("{% include 'nested_product_template' with product %}").render("product" => {"title" => 'Draft 151cm'})
98
+
99
+ assert_equal "Product: Draft 151cm details Product: Element 155cm details ",
100
+ Template.parse("{% include 'nested_product_template' for products %}").render("products" => [{"title" => 'Draft 151cm'}, {"title" => 'Element 155cm'}])
101
+
102
+ end
103
+
104
+ def test_recursively_included_template_does_not_produce_endless_loop
105
+
106
+ infinite_file_system = Class.new do
107
+ def read_template_file(template_path, context)
108
+ "-{% include 'loop' %}"
109
+ end
110
+ end
111
+
112
+ Liquid::Template.file_system = infinite_file_system.new
113
+
114
+ assert_raise(Liquid::StackLevelError) do
115
+ Template.parse("{% include 'loop' %}").render!
116
+ end
117
+
118
+ end
119
+
120
+ def test_backwards_compatability_support_for_overridden_read_template_file
121
+ infinite_file_system = Class.new do
122
+ def read_template_file(template_path) # testing only one argument here.
123
+ "- hi mom"
124
+ end
125
+ end
126
+
127
+ Liquid::Template.file_system = infinite_file_system.new
128
+
129
+ Template.parse("{% include 'hi_mom' %}").render!
130
+ end
131
+
132
+ def test_dynamically_choosen_template
133
+
134
+ assert_equal "Test123", Template.parse("{% include template %}").render("template" => 'Test123')
135
+ assert_equal "Test321", Template.parse("{% include template %}").render("template" => 'Test321')
136
+
137
+ assert_equal "Product: Draft 151cm ", Template.parse("{% include template for product %}").render("template" => 'product', 'product' => { 'title' => 'Draft 151cm'})
138
+ end
139
+ end # IncludeTagTest
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+
3
+ class IncrementTagTest < Test::Unit::TestCase
4
+ include Liquid
5
+
6
+ def test_inc
7
+ assert_template_result('0','{%increment port %}', {})
8
+ assert_template_result('0 1','{%increment port %} {%increment port%}', {})
9
+ assert_template_result('0 0 1 2 1',
10
+ '{%increment port %} {%increment starboard%} ' +
11
+ '{%increment port %} {%increment port%} ' +
12
+ '{%increment starboard %}', {})
13
+ end
14
+
15
+ def test_dec
16
+ assert_template_result('9','{%decrement port %}', { 'port' => 10})
17
+ assert_template_result('-1 -2','{%decrement port %} {%decrement port%}', {})
18
+ assert_template_result('1 5 2 2 5',
19
+ '{%increment port %} {%increment starboard%} ' +
20
+ '{%increment port %} {%decrement port%} ' +
21
+ '{%decrement starboard %}', { 'port' => 1, 'starboard' => 5 })
22
+ end
23
+
24
+ end
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+
3
+ class RawTagTest < Test::Unit::TestCase
4
+ include Liquid
5
+
6
+ def test_tag_in_raw
7
+ assert_template_result '{% comment %} test {% endcomment %}',
8
+ '{% raw %}{% comment %} test {% endcomment %}{% endraw %}'
9
+ end
10
+
11
+ def test_output_in_raw
12
+ assert_template_result '{{ test }}',
13
+ '{% raw %}{{ test }}{% endraw %}'
14
+ end
15
+ end
@@ -0,0 +1,461 @@
1
+ require 'test_helper'
2
+
3
+ class StandardTagTest < Test::Unit::TestCase
4
+ include Liquid
5
+
6
+ def test_tag
7
+ tag = Tag.new('tag', [], [])
8
+ assert_equal 'liquid::tag', tag.name
9
+ assert_equal '', tag.render(Context.new)
10
+ end
11
+
12
+ def test_no_transform
13
+ assert_template_result('this text should come out of the template without change...',
14
+ 'this text should come out of the template without change...')
15
+
16
+ assert_template_result('blah','blah')
17
+ assert_template_result('<blah>','<blah>')
18
+ assert_template_result('|,.:','|,.:')
19
+ assert_template_result('','')
20
+
21
+ text = %|this shouldnt see any transformation either but has multiple lines
22
+ as you can clearly see here ...|
23
+ assert_template_result(text,text)
24
+ end
25
+
26
+ def test_has_a_block_which_does_nothing
27
+ assert_template_result(%|the comment block should be removed .. right?|,
28
+ %|the comment block should be removed {%comment%} be gone.. {%endcomment%} .. right?|)
29
+
30
+ assert_template_result('','{%comment%}{%endcomment%}')
31
+ assert_template_result('','{%comment%}{% endcomment %}')
32
+ assert_template_result('','{% comment %}{%endcomment%}')
33
+ assert_template_result('','{% comment %}{% endcomment %}')
34
+ assert_template_result('','{%comment%}comment{%endcomment%}')
35
+ assert_template_result('','{% comment %}comment{% endcomment %}')
36
+
37
+ assert_template_result('foobar','foo{%comment%}comment{%endcomment%}bar')
38
+ assert_template_result('foobar','foo{% comment %}comment{% endcomment %}bar')
39
+ assert_template_result('foobar','foo{%comment%} comment {%endcomment%}bar')
40
+ assert_template_result('foobar','foo{% comment %} comment {% endcomment %}bar')
41
+
42
+ assert_template_result('foo bar','foo {%comment%} {%endcomment%} bar')
43
+ assert_template_result('foo bar','foo {%comment%}comment{%endcomment%} bar')
44
+ assert_template_result('foo bar','foo {%comment%} comment {%endcomment%} bar')
45
+
46
+ assert_template_result('foobar','foo{%comment%}
47
+ {%endcomment%}bar')
48
+ end
49
+
50
+ def test_for
51
+ assert_template_result(' yo yo yo yo ','{%for item in array%} yo {%endfor%}','array' => [1,2,3,4])
52
+ assert_template_result('yoyo','{%for item in array%}yo{%endfor%}','array' => [1,2])
53
+ assert_template_result(' yo ','{%for item in array%} yo {%endfor%}','array' => [1])
54
+ assert_template_result('','{%for item in array%}{%endfor%}','array' => [1,2])
55
+ expected = <<HERE
56
+
57
+ yo
58
+
59
+ yo
60
+
61
+ yo
62
+
63
+ HERE
64
+ template = <<HERE
65
+ {%for item in array%}
66
+ yo
67
+ {%endfor%}
68
+ HERE
69
+ assert_template_result(expected,template,'array' => [1,2,3])
70
+ end
71
+
72
+ def test_for_with_range
73
+ assert_template_result(' 1 2 3 ','{%for item in (1..3) %} {{item}} {%endfor%}')
74
+ end
75
+
76
+ def test_for_with_variable
77
+ assert_template_result(' 1 2 3 ','{%for item in array%} {{item}} {%endfor%}','array' => [1,2,3])
78
+ assert_template_result('123','{%for item in array%}{{item}}{%endfor%}','array' => [1,2,3])
79
+ assert_template_result('123','{% for item in array %}{{item}}{% endfor %}','array' => [1,2,3])
80
+ assert_template_result('abcd','{%for item in array%}{{item}}{%endfor%}','array' => ['a','b','c','d'])
81
+ assert_template_result('a b c','{%for item in array%}{{item}}{%endfor%}','array' => ['a',' ','b',' ','c'])
82
+ assert_template_result('abc','{%for item in array%}{{item}}{%endfor%}','array' => ['a','','b','','c'])
83
+ end
84
+
85
+ def test_for_helpers
86
+ assigns = {'array' => [1,2,3] }
87
+ assert_template_result(' 1/3 2/3 3/3 ',
88
+ '{%for item in array%} {{forloop.index}}/{{forloop.length}} {%endfor%}',
89
+ assigns)
90
+ assert_template_result(' 1 2 3 ', '{%for item in array%} {{forloop.index}} {%endfor%}', assigns)
91
+ assert_template_result(' 0 1 2 ', '{%for item in array%} {{forloop.index0}} {%endfor%}', assigns)
92
+ assert_template_result(' 2 1 0 ', '{%for item in array%} {{forloop.rindex0}} {%endfor%}', assigns)
93
+ assert_template_result(' 3 2 1 ', '{%for item in array%} {{forloop.rindex}} {%endfor%}', assigns)
94
+ assert_template_result(' true false false ', '{%for item in array%} {{forloop.first}} {%endfor%}', assigns)
95
+ assert_template_result(' false false true ', '{%for item in array%} {{forloop.last}} {%endfor%}', assigns)
96
+ end
97
+
98
+ def test_for_and_if
99
+ assigns = {'array' => [1,2,3] }
100
+ assert_template_result('+--',
101
+ '{%for item in array%}{% if forloop.first %}+{% else %}-{% endif %}{%endfor%}',
102
+ assigns)
103
+ end
104
+
105
+ def test_for_else
106
+ assert_template_result('+++', '{%for item in array%}+{%else%}-{%endfor%}', 'array'=>[1,2,3])
107
+ assert_template_result('-', '{%for item in array%}+{%else%}-{%endfor%}', 'array'=>[])
108
+ assert_template_result('-', '{%for item in array%}+{%else%}-{%endfor%}', 'array'=>nil)
109
+ end
110
+
111
+ def test_limiting
112
+ assigns = {'array' => [1,2,3,4,5,6,7,8,9,0]}
113
+ assert_template_result('12', '{%for i in array limit:2 %}{{ i }}{%endfor%}', assigns)
114
+ assert_template_result('1234', '{%for i in array limit:4 %}{{ i }}{%endfor%}', assigns)
115
+ assert_template_result('3456', '{%for i in array limit:4 offset:2 %}{{ i }}{%endfor%}', assigns)
116
+ assert_template_result('3456', '{%for i in array limit: 4 offset: 2 %}{{ i }}{%endfor%}', assigns)
117
+ end
118
+
119
+ def test_dynamic_variable_limiting
120
+ assigns = {'array' => [1,2,3,4,5,6,7,8,9,0]}
121
+ assigns['limit'] = 2
122
+ assigns['offset'] = 2
123
+
124
+ assert_template_result('34', '{%for i in array limit: limit offset: offset %}{{ i }}{%endfor%}', assigns)
125
+ end
126
+
127
+ def test_nested_for
128
+ assigns = {'array' => [[1,2],[3,4],[5,6]] }
129
+ assert_template_result('123456', '{%for item in array%}{%for i in item%}{{ i }}{%endfor%}{%endfor%}', assigns)
130
+ end
131
+
132
+ def test_offset_only
133
+ assigns = {'array' => [1,2,3,4,5,6,7,8,9,0]}
134
+ assert_template_result('890', '{%for i in array offset:7 %}{{ i }}{%endfor%}', assigns)
135
+ end
136
+
137
+ def test_pause_resume
138
+ assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
139
+ markup = <<-MKUP
140
+ {%for i in array.items limit: 3 %}{{i}}{%endfor%}
141
+ next
142
+ {%for i in array.items offset:continue limit: 3 %}{{i}}{%endfor%}
143
+ next
144
+ {%for i in array.items offset:continue limit: 3 %}{{i}}{%endfor%}
145
+ MKUP
146
+ expected = <<-XPCTD
147
+ 123
148
+ next
149
+ 456
150
+ next
151
+ 789
152
+ XPCTD
153
+ assert_template_result(expected,markup,assigns)
154
+ end
155
+
156
+ def test_pause_resume_limit
157
+ assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
158
+ markup = <<-MKUP
159
+ {%for i in array.items limit:3 %}{{i}}{%endfor%}
160
+ next
161
+ {%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
162
+ next
163
+ {%for i in array.items offset:continue limit:1 %}{{i}}{%endfor%}
164
+ MKUP
165
+ expected = <<-XPCTD
166
+ 123
167
+ next
168
+ 456
169
+ next
170
+ 7
171
+ XPCTD
172
+ assert_template_result(expected,markup,assigns)
173
+ end
174
+
175
+ def test_pause_resume_BIG_limit
176
+ assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
177
+ markup = <<-MKUP
178
+ {%for i in array.items limit:3 %}{{i}}{%endfor%}
179
+ next
180
+ {%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
181
+ next
182
+ {%for i in array.items offset:continue limit:1000 %}{{i}}{%endfor%}
183
+ MKUP
184
+ expected = <<-XPCTD
185
+ 123
186
+ next
187
+ 456
188
+ next
189
+ 7890
190
+ XPCTD
191
+ assert_template_result(expected,markup,assigns)
192
+ end
193
+
194
+
195
+ def test_pause_resume_BIG_offset
196
+ assigns = {'array' => {'items' => [1,2,3,4,5,6,7,8,9,0]}}
197
+ markup = %q({%for i in array.items limit:3 %}{{i}}{%endfor%}
198
+ next
199
+ {%for i in array.items offset:continue limit:3 %}{{i}}{%endfor%}
200
+ next
201
+ {%for i in array.items offset:continue limit:3 offset:1000 %}{{i}}{%endfor%})
202
+ expected = %q(123
203
+ next
204
+ 456
205
+ next
206
+ )
207
+ assert_template_result(expected,markup,assigns)
208
+ end
209
+
210
+ def test_assign
211
+ assigns = {'var' => 'content' }
212
+ assert_template_result('var2: var2:content', 'var2:{{var2}} {%assign var2 = var%} var2:{{var2}}', assigns)
213
+
214
+ end
215
+
216
+ def test_hyphenated_assign
217
+ assigns = {'a-b' => '1' }
218
+ assert_template_result('a-b:1 a-b:2', 'a-b:{{a-b}} {%assign a-b = 2 %}a-b:{{a-b}}', assigns)
219
+
220
+ end
221
+
222
+ def test_assign_with_colon_and_spaces
223
+ assigns = {'var' => {'a:b c' => {'paged' => '1' }}}
224
+ assert_template_result('var2: 1', '{%assign var2 = var["a:b c"].paged %}var2: {{var2}}', assigns)
225
+ end
226
+
227
+ def test_capture
228
+ assigns = {'var' => 'content' }
229
+ assert_template_result('content foo content foo ',
230
+ '{{ var2 }}{% capture var2 %}{{ var }} foo {% endcapture %}{{ var2 }}{{ var2 }}',
231
+ assigns)
232
+ end
233
+
234
+ def test_capture_detects_bad_syntax
235
+ assert_raise(SyntaxError) do
236
+ assert_template_result('content foo content foo ',
237
+ '{{ var2 }}{% capture %}{{ var }} foo {% endcapture %}{{ var2 }}{{ var2 }}',
238
+ {'var' => 'content' })
239
+ end
240
+ end
241
+
242
+ def test_case
243
+ assigns = {'condition' => 2 }
244
+ assert_template_result(' its 2 ',
245
+ '{% case condition %}{% when 1 %} its 1 {% when 2 %} its 2 {% endcase %}',
246
+ assigns)
247
+
248
+ assigns = {'condition' => 1 }
249
+ assert_template_result(' its 1 ',
250
+ '{% case condition %}{% when 1 %} its 1 {% when 2 %} its 2 {% endcase %}',
251
+ assigns)
252
+
253
+ assigns = {'condition' => 3 }
254
+ assert_template_result('',
255
+ '{% case condition %}{% when 1 %} its 1 {% when 2 %} its 2 {% endcase %}',
256
+ assigns)
257
+
258
+ assigns = {'condition' => "string here" }
259
+ assert_template_result(' hit ',
260
+ '{% case condition %}{% when "string here" %} hit {% endcase %}',
261
+ assigns)
262
+
263
+ assigns = {'condition' => "bad string here" }
264
+ assert_template_result('',
265
+ '{% case condition %}{% when "string here" %} hit {% endcase %}',\
266
+ assigns)
267
+ end
268
+
269
+ def test_case_with_else
270
+ assigns = {'condition' => 5 }
271
+ assert_template_result(' hit ',
272
+ '{% case condition %}{% when 5 %} hit {% else %} else {% endcase %}',
273
+ assigns)
274
+
275
+ assigns = {'condition' => 6 }
276
+ assert_template_result(' else ',
277
+ '{% case condition %}{% when 5 %} hit {% else %} else {% endcase %}',
278
+ assigns)
279
+
280
+ assigns = {'condition' => 6 }
281
+ assert_template_result(' else ',
282
+ '{% case condition %} {% when 5 %} hit {% else %} else {% endcase %}',
283
+ assigns)
284
+ end
285
+
286
+ def test_case_on_size
287
+ assert_template_result('', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [])
288
+ assert_template_result('1', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1])
289
+ assert_template_result('2', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1, 1])
290
+ assert_template_result('', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1, 1, 1])
291
+ assert_template_result('', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1, 1, 1, 1])
292
+ assert_template_result('', '{% case a.size %}{% when 1 %}1{% when 2 %}2{% endcase %}', 'a' => [1, 1, 1, 1, 1])
293
+ end
294
+
295
+ def test_case_on_size_with_else
296
+ assert_template_result('else',
297
+ '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}',
298
+ 'a' => [])
299
+
300
+ assert_template_result('1',
301
+ '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}',
302
+ 'a' => [1])
303
+
304
+ assert_template_result('2',
305
+ '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}',
306
+ 'a' => [1, 1])
307
+
308
+ assert_template_result('else',
309
+ '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}',
310
+ 'a' => [1, 1, 1])
311
+
312
+ assert_template_result('else',
313
+ '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}',
314
+ 'a' => [1, 1, 1, 1])
315
+
316
+ assert_template_result('else',
317
+ '{% case a.size %}{% when 1 %}1{% when 2 %}2{% else %}else{% endcase %}',
318
+ 'a' => [1, 1, 1, 1, 1])
319
+ end
320
+
321
+ def test_case_on_length_with_else
322
+ assert_template_result('else',
323
+ '{% case a.empty? %}{% when true %}true{% when false %}false{% else %}else{% endcase %}',
324
+ {})
325
+
326
+ assert_template_result('false',
327
+ '{% case false %}{% when true %}true{% when false %}false{% else %}else{% endcase %}',
328
+ {})
329
+
330
+ assert_template_result('true',
331
+ '{% case true %}{% when true %}true{% when false %}false{% else %}else{% endcase %}',
332
+ {})
333
+
334
+ assert_template_result('else',
335
+ '{% case NULL %}{% when true %}true{% when false %}false{% else %}else{% endcase %}',
336
+ {})
337
+ end
338
+
339
+ def test_assign_from_case
340
+ # Example from the shopify forums
341
+ code = %q({% case collection.handle %}{% when 'menswear-jackets' %}{% assign ptitle = 'menswear' %}{% when 'menswear-t-shirts' %}{% assign ptitle = 'menswear' %}{% else %}{% assign ptitle = 'womenswear' %}{% endcase %}{{ ptitle }})
342
+ template = Liquid::Template.parse(code)
343
+ assert_equal "menswear", template.render("collection" => {'handle' => 'menswear-jackets'})
344
+ assert_equal "menswear", template.render("collection" => {'handle' => 'menswear-t-shirts'})
345
+ assert_equal "womenswear", template.render("collection" => {'handle' => 'x'})
346
+ assert_equal "womenswear", template.render("collection" => {'handle' => 'y'})
347
+ assert_equal "womenswear", template.render("collection" => {'handle' => 'z'})
348
+ end
349
+
350
+ def test_case_when_or
351
+ code = '{% case condition %}{% when 1 or 2 or 3 %} its 1 or 2 or 3 {% when 4 %} its 4 {% endcase %}'
352
+ assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 1 })
353
+ assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 2 })
354
+ assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 3 })
355
+ assert_template_result(' its 4 ', code, {'condition' => 4 })
356
+ assert_template_result('', code, {'condition' => 5 })
357
+
358
+ code = '{% case condition %}{% when 1 or "string" or null %} its 1 or 2 or 3 {% when 4 %} its 4 {% endcase %}'
359
+ assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 1 })
360
+ assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 'string' })
361
+ assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => nil })
362
+ assert_template_result('', code, {'condition' => 'something else' })
363
+ end
364
+
365
+ def test_case_when_comma
366
+ code = '{% case condition %}{% when 1, 2, 3 %} its 1 or 2 or 3 {% when 4 %} its 4 {% endcase %}'
367
+ assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 1 })
368
+ assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 2 })
369
+ assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 3 })
370
+ assert_template_result(' its 4 ', code, {'condition' => 4 })
371
+ assert_template_result('', code, {'condition' => 5 })
372
+
373
+ code = '{% case condition %}{% when 1, "string", null %} its 1 or 2 or 3 {% when 4 %} its 4 {% endcase %}'
374
+ assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 1 })
375
+ assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => 'string' })
376
+ assert_template_result(' its 1 or 2 or 3 ', code, {'condition' => nil })
377
+ assert_template_result('', code, {'condition' => 'something else' })
378
+ end
379
+
380
+ def test_assign
381
+ assert_equal 'variable', Liquid::Template.parse( '{% assign a = "variable"%}{{a}}' ).render
382
+ end
383
+
384
+ def test_assign_an_empty_string
385
+ assert_equal '', Liquid::Template.parse( '{% assign a = ""%}{{a}}' ).render
386
+ end
387
+
388
+ def test_assign_is_global
389
+ assert_equal 'variable',
390
+ Liquid::Template.parse( '{%for i in (1..2) %}{% assign a = "variable"%}{% endfor %}{{a}}' ).render
391
+ end
392
+
393
+ def test_case_detects_bad_syntax
394
+ assert_raise(SyntaxError) do
395
+ assert_template_result('', '{% case false %}{% when %}true{% endcase %}', {})
396
+ end
397
+
398
+ assert_raise(SyntaxError) do
399
+ assert_template_result('', '{% case false %}{% huh %}true{% endcase %}', {})
400
+ end
401
+
402
+ end
403
+
404
+ def test_cycle
405
+ assert_template_result('one','{%cycle "one", "two"%}')
406
+ assert_template_result('one two','{%cycle "one", "two"%} {%cycle "one", "two"%}')
407
+ assert_template_result(' two','{%cycle "", "two"%} {%cycle "", "two"%}')
408
+
409
+ assert_template_result('one two one','{%cycle "one", "two"%} {%cycle "one", "two"%} {%cycle "one", "two"%}')
410
+
411
+ assert_template_result('text-align: left text-align: right',
412
+ '{%cycle "text-align: left", "text-align: right" %} {%cycle "text-align: left", "text-align: right"%}')
413
+ end
414
+
415
+ def test_multiple_cycles
416
+ assert_template_result('1 2 1 1 2 3 1',
417
+ '{%cycle 1,2%} {%cycle 1,2%} {%cycle 1,2%} {%cycle 1,2,3%} {%cycle 1,2,3%} {%cycle 1,2,3%} {%cycle 1,2,3%}')
418
+ end
419
+
420
+ def test_multiple_named_cycles
421
+ assert_template_result('one one two two one one',
422
+ '{%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %} {%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %} {%cycle 1: "one", "two" %} {%cycle 2: "one", "two" %}')
423
+ end
424
+
425
+ def test_multiple_named_cycles_with_names_from_context
426
+ assigns = {"var1" => 1, "var2" => 2 }
427
+ assert_template_result('one one two two one one',
428
+ '{%cycle var1: "one", "two" %} {%cycle var2: "one", "two" %} {%cycle var1: "one", "two" %} {%cycle var2: "one", "two" %} {%cycle var1: "one", "two" %} {%cycle var2: "one", "two" %}', assigns)
429
+ end
430
+
431
+ def test_size_of_array
432
+ assigns = {"array" => [1,2,3,4]}
433
+ assert_template_result('array has 4 elements', "array has {{ array.size }} elements", assigns)
434
+ end
435
+
436
+ def test_size_of_hash
437
+ assigns = {"hash" => {:a => 1, :b => 2, :c=> 3, :d => 4}}
438
+ assert_template_result('hash has 4 elements', "hash has {{ hash.size }} elements", assigns)
439
+ end
440
+
441
+ def test_illegal_symbols
442
+ assert_template_result('', '{% if true == empty %}?{% endif %}', {})
443
+ assert_template_result('', '{% if true == null %}?{% endif %}', {})
444
+ assert_template_result('', '{% if empty == true %}?{% endif %}', {})
445
+ assert_template_result('', '{% if null == true %}?{% endif %}', {})
446
+ end
447
+
448
+ def test_for_reversed
449
+ assigns = {'array' => [ 1, 2, 3] }
450
+ assert_template_result('321','{%for item in array reversed %}{{item}}{%endfor%}',assigns)
451
+ end
452
+
453
+
454
+ def test_ifchanged
455
+ assigns = {'array' => [ 1, 1, 2, 2, 3, 3] }
456
+ assert_template_result('123','{%for item in array%}{%ifchanged%}{{item}}{% endifchanged %}{%endfor%}',assigns)
457
+
458
+ assigns = {'array' => [ 1, 1, 1, 1] }
459
+ assert_template_result('1','{%for item in array%}{%ifchanged%}{{item}}{% endifchanged %}{%endfor%}',assigns)
460
+ end
461
+ end # StandardTagTest