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.
- checksums.yaml +4 -4
- data/History.md +42 -13
- data/README.md +27 -2
- data/lib/liquid.rb +11 -11
- data/lib/liquid/block.rb +75 -45
- data/lib/liquid/condition.rb +15 -11
- data/lib/liquid/context.rb +68 -29
- data/lib/liquid/document.rb +3 -3
- data/lib/liquid/drop.rb +17 -1
- data/lib/liquid/file_system.rb +17 -6
- data/lib/liquid/i18n.rb +39 -0
- data/lib/liquid/interrupts.rb +1 -1
- data/lib/liquid/lexer.rb +51 -0
- data/lib/liquid/locales/en.yml +22 -0
- data/lib/liquid/parser.rb +90 -0
- data/lib/liquid/standardfilters.rb +115 -52
- data/lib/liquid/strainer.rb +14 -4
- data/lib/liquid/tag.rb +42 -7
- data/lib/liquid/tags/assign.rb +10 -8
- data/lib/liquid/tags/break.rb +1 -1
- data/lib/liquid/tags/capture.rb +10 -8
- data/lib/liquid/tags/case.rb +13 -13
- data/lib/liquid/tags/comment.rb +9 -2
- data/lib/liquid/tags/continue.rb +1 -4
- data/lib/liquid/tags/cycle.rb +5 -7
- data/lib/liquid/tags/decrement.rb +3 -4
- data/lib/liquid/tags/for.rb +69 -36
- data/lib/liquid/tags/if.rb +52 -25
- data/lib/liquid/tags/ifchanged.rb +2 -2
- data/lib/liquid/tags/include.rb +8 -7
- data/lib/liquid/tags/increment.rb +4 -8
- data/lib/liquid/tags/raw.rb +3 -3
- data/lib/liquid/tags/table_row.rb +73 -0
- data/lib/liquid/tags/unless.rb +2 -4
- data/lib/liquid/template.rb +69 -10
- data/lib/liquid/utils.rb +13 -4
- data/lib/liquid/variable.rb +59 -8
- data/lib/liquid/version.rb +1 -1
- data/test/fixtures/en_locale.yml +9 -0
- data/test/{liquid → integration}/assign_test.rb +6 -0
- data/test/integration/blank_test.rb +106 -0
- data/test/{liquid → integration}/capture_test.rb +2 -2
- data/test/integration/context_test.rb +33 -0
- data/test/integration/drop_test.rb +245 -0
- data/test/{liquid → integration}/error_handling_test.rb +31 -2
- data/test/{liquid → integration}/filter_test.rb +7 -7
- data/test/{liquid → integration}/hash_ordering_test.rb +0 -0
- data/test/{liquid → integration}/output_test.rb +12 -12
- data/test/integration/parsing_quirks_test.rb +94 -0
- data/test/{liquid → integration}/security_test.rb +9 -9
- data/test/{liquid → integration}/standard_filter_test.rb +103 -33
- data/test/{liquid → integration}/tags/break_tag_test.rb +0 -0
- data/test/{liquid → integration}/tags/continue_tag_test.rb +0 -0
- data/test/{liquid → integration}/tags/for_tag_test.rb +78 -0
- data/test/{liquid → integration}/tags/if_else_tag_test.rb +1 -1
- data/test/integration/tags/include_tag_test.rb +212 -0
- data/test/{liquid → integration}/tags/increment_tag_test.rb +0 -0
- data/test/{liquid → integration}/tags/raw_tag_test.rb +1 -0
- data/test/{liquid → integration}/tags/standard_tag_test.rb +24 -22
- data/test/integration/tags/statements_test.rb +113 -0
- data/test/{liquid/tags/html_tag_test.rb → integration/tags/table_row_test.rb} +5 -5
- data/test/{liquid → integration}/tags/unless_else_tag_test.rb +0 -0
- data/test/{liquid → integration}/template_test.rb +66 -42
- data/test/integration/variable_test.rb +72 -0
- data/test/test_helper.rb +32 -7
- data/test/{liquid/block_test.rb → unit/block_unit_test.rb} +1 -1
- data/test/{liquid/condition_test.rb → unit/condition_unit_test.rb} +19 -1
- data/test/{liquid/context_test.rb → unit/context_unit_test.rb} +27 -19
- data/test/{liquid/file_system_test.rb → unit/file_system_unit_test.rb} +7 -1
- data/test/unit/i18n_unit_test.rb +37 -0
- data/test/unit/lexer_unit_test.rb +48 -0
- data/test/{liquid/module_ex_test.rb → unit/module_ex_unit_test.rb} +7 -7
- data/test/unit/parser_unit_test.rb +82 -0
- data/test/{liquid/regexp_test.rb → unit/regexp_unit_test.rb} +3 -3
- data/test/{liquid/strainer_test.rb → unit/strainer_unit_test.rb} +19 -1
- data/test/unit/tag_unit_test.rb +11 -0
- data/test/unit/tags/case_tag_unit_test.rb +10 -0
- data/test/unit/tags/for_tag_unit_test.rb +13 -0
- data/test/unit/tags/if_tag_unit_test.rb +8 -0
- data/test/unit/template_unit_test.rb +69 -0
- data/test/unit/tokenizer_unit_test.rb +29 -0
- data/test/{liquid/variable_test.rb → unit/variable_unit_test.rb} +17 -67
- metadata +117 -73
- data/lib/extras/liquid_view.rb +0 -51
- data/lib/liquid/htmltags.rb +0 -73
- data/test/liquid/drop_test.rb +0 -180
- data/test/liquid/parsing_quirks_test.rb +0 -52
- data/test/liquid/tags/include_tag_test.rb +0 -166
- data/test/liquid/tags/statements_test.rb +0 -134
@@ -58,19 +58,48 @@ class ErrorHandlingTest < Test::Unit::TestCase
|
|
58
58
|
|
59
59
|
def test_missing_endtag_parse_time_error
|
60
60
|
assert_raise(Liquid::SyntaxError) do
|
61
|
-
|
61
|
+
Liquid::Template.parse(' {% for a in b %} ... ')
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
65
|
def test_unrecognized_operator
|
66
|
+
with_error_mode(:strict) do
|
67
|
+
assert_raise(SyntaxError) do
|
68
|
+
Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_lax_unrecognized_operator
|
66
74
|
assert_nothing_raised do
|
67
|
-
template = Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ')
|
75
|
+
template = Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ', :error_mode => :lax)
|
68
76
|
assert_equal ' Liquid error: Unknown operator =! ', template.render
|
69
77
|
assert_equal 1, template.errors.size
|
70
78
|
assert_equal Liquid::ArgumentError, template.errors.first.class
|
71
79
|
end
|
72
80
|
end
|
73
81
|
|
82
|
+
def test_strict_error_messages
|
83
|
+
err = assert_raise(SyntaxError) do
|
84
|
+
Liquid::Template.parse(' {% if 1 =! 2 %}ok{% endif %} ', :error_mode => :strict)
|
85
|
+
end
|
86
|
+
assert_equal 'Unexpected character = in "1 =! 2"', err.message
|
87
|
+
|
88
|
+
err = assert_raise(SyntaxError) do
|
89
|
+
Liquid::Template.parse('{{%%%}}', :error_mode => :strict)
|
90
|
+
end
|
91
|
+
assert_equal 'Unexpected character % in "{{%%%}}"', err.message
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_warnings
|
95
|
+
template = Liquid::Template.parse('{% if ~~~ %}{{%%%}}{% else %}{{ hello. }}{% endif %}', :error_mode => :warn)
|
96
|
+
assert_equal 3, template.warnings.size
|
97
|
+
assert_equal 'Unexpected character ~ in "~~~"', template.warnings[0].message
|
98
|
+
assert_equal 'Unexpected character % in "{{%%%}}"', template.warnings[1].message
|
99
|
+
assert_equal 'Expected id but found end_of_string in "{{ hello. }}"', template.warnings[2].message
|
100
|
+
assert_equal '', template.render
|
101
|
+
end
|
102
|
+
|
74
103
|
# Liquid should not catch Exceptions that are not subclasses of StandardError, like Interrupt and NoMemoryError
|
75
104
|
def test_exceptions_propagate
|
76
105
|
assert_raise Exception do
|
@@ -67,12 +67,12 @@ class FiltersTest < Test::Unit::TestCase
|
|
67
67
|
@context['value'] = 3
|
68
68
|
@context['numbers'] = [2,1,4,3]
|
69
69
|
@context['words'] = ['expected', 'as', 'alphabetic']
|
70
|
-
@context['arrays'] = [
|
70
|
+
@context['arrays'] = ['flower', 'are']
|
71
71
|
|
72
72
|
assert_equal [1,2,3,4], Variable.new("numbers | sort").render(@context)
|
73
73
|
assert_equal ['alphabetic', 'as', 'expected'], Variable.new("words | sort").render(@context)
|
74
74
|
assert_equal [3], Variable.new("value | sort").render(@context)
|
75
|
-
assert_equal ['are', '
|
75
|
+
assert_equal ['are', 'flower'], Variable.new("arrays | sort").render(@context)
|
76
76
|
end
|
77
77
|
|
78
78
|
def test_strip_html
|
@@ -113,13 +113,13 @@ class FiltersInTemplate < Test::Unit::TestCase
|
|
113
113
|
def test_local_global
|
114
114
|
Template.register_filter(MoneyFilter)
|
115
115
|
|
116
|
-
assert_equal " 1000$ ", Template.parse("{{1000 | money}}").render(nil, nil)
|
117
|
-
assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render(nil, :filters => CanadianMoneyFilter)
|
118
|
-
assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render(nil, :filters => [CanadianMoneyFilter])
|
116
|
+
assert_equal " 1000$ ", Template.parse("{{1000 | money}}").render!(nil, nil)
|
117
|
+
assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render!(nil, :filters => CanadianMoneyFilter)
|
118
|
+
assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render!(nil, :filters => [CanadianMoneyFilter])
|
119
119
|
end
|
120
120
|
|
121
121
|
def test_local_filter_with_deprecated_syntax
|
122
|
-
assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render(nil, CanadianMoneyFilter)
|
123
|
-
assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render(nil, [CanadianMoneyFilter])
|
122
|
+
assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render!(nil, CanadianMoneyFilter)
|
123
|
+
assert_equal " 1000$ CAD ", Template.parse("{{1000 | money}}").render!(nil, [CanadianMoneyFilter])
|
124
124
|
end
|
125
125
|
end # FiltersTest
|
File without changes
|
@@ -41,76 +41,76 @@ class OutputTest < Test::Unit::TestCase
|
|
41
41
|
text = %| {{best_cars}} |
|
42
42
|
|
43
43
|
expected = %| bmw |
|
44
|
-
assert_equal expected, Template.parse(text).render(@assigns)
|
44
|
+
assert_equal expected, Template.parse(text).render!(@assigns)
|
45
45
|
end
|
46
46
|
|
47
47
|
def test_variable_traversing
|
48
48
|
text = %| {{car.bmw}} {{car.gm}} {{car.bmw}} |
|
49
49
|
|
50
50
|
expected = %| good bad good |
|
51
|
-
assert_equal expected, Template.parse(text).render(@assigns)
|
51
|
+
assert_equal expected, Template.parse(text).render!(@assigns)
|
52
52
|
end
|
53
53
|
|
54
54
|
def test_variable_piping
|
55
55
|
text = %( {{ car.gm | make_funny }} )
|
56
56
|
expected = %| LOL |
|
57
57
|
|
58
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
58
|
+
assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
|
59
59
|
end
|
60
60
|
|
61
61
|
def test_variable_piping_with_input
|
62
62
|
text = %( {{ car.gm | cite_funny }} )
|
63
63
|
expected = %| LOL: bad |
|
64
64
|
|
65
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
65
|
+
assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
|
66
66
|
end
|
67
67
|
|
68
68
|
def test_variable_piping_with_args
|
69
69
|
text = %! {{ car.gm | add_smiley : ':-(' }} !
|
70
70
|
expected = %| bad :-( |
|
71
71
|
|
72
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
72
|
+
assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
|
73
73
|
end
|
74
74
|
|
75
75
|
def test_variable_piping_with_no_args
|
76
76
|
text = %! {{ car.gm | add_smiley }} !
|
77
77
|
expected = %| bad :-) |
|
78
78
|
|
79
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
79
|
+
assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
|
80
80
|
end
|
81
81
|
|
82
82
|
def test_multiple_variable_piping_with_args
|
83
83
|
text = %! {{ car.gm | add_smiley : ':-(' | add_smiley : ':-('}} !
|
84
84
|
expected = %| bad :-( :-( |
|
85
85
|
|
86
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
86
|
+
assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
|
87
87
|
end
|
88
88
|
|
89
|
-
def
|
89
|
+
def test_variable_piping_with_multiple_args
|
90
90
|
text = %! {{ car.gm | add_tag : 'span', 'bar'}} !
|
91
91
|
expected = %| <span id="bar">bad</span> |
|
92
92
|
|
93
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
93
|
+
assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
|
94
94
|
end
|
95
95
|
|
96
96
|
def test_variable_piping_with_variable_args
|
97
97
|
text = %! {{ car.gm | add_tag : 'span', car.bmw}} !
|
98
98
|
expected = %| <span id="good">bad</span> |
|
99
99
|
|
100
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
100
|
+
assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
|
101
101
|
end
|
102
102
|
|
103
103
|
def test_multiple_pipings
|
104
104
|
text = %( {{ best_cars | cite_funny | paragraph }} )
|
105
105
|
expected = %| <p>LOL: bmw</p> |
|
106
106
|
|
107
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
107
|
+
assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
|
108
108
|
end
|
109
109
|
|
110
110
|
def test_link_to
|
111
111
|
text = %( {{ 'Typo' | link_to: 'http://typo.leetsoft.com' }} )
|
112
112
|
expected = %| <a href="http://typo.leetsoft.com">Typo</a> |
|
113
113
|
|
114
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => [FunnyFilter])
|
114
|
+
assert_equal expected, Template.parse(text).render!(@assigns, :filters => [FunnyFilter])
|
115
115
|
end
|
116
116
|
end # OutputTest
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ParsingQuirksTest < Test::Unit::TestCase
|
4
|
+
include Liquid
|
5
|
+
|
6
|
+
def test_parsing_css
|
7
|
+
text = " div { font-weight: bold; } "
|
8
|
+
assert_equal text, Template.parse(text).render!
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_raise_on_single_close_bracet
|
12
|
+
assert_raise(SyntaxError) do
|
13
|
+
Template.parse("text {{method} oh nos!")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_raise_on_label_and_no_close_bracets
|
18
|
+
assert_raise(SyntaxError) do
|
19
|
+
Template.parse("TEST {{ ")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_raise_on_label_and_no_close_bracets_percent
|
24
|
+
assert_raise(SyntaxError) do
|
25
|
+
Template.parse("TEST {% ")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_error_on_empty_filter
|
30
|
+
assert_nothing_raised do
|
31
|
+
Template.parse("{{test}}")
|
32
|
+
Template.parse("{{|test}}")
|
33
|
+
end
|
34
|
+
with_error_mode(:strict) do
|
35
|
+
assert_raise(SyntaxError) do
|
36
|
+
Template.parse("{{test |a|b|}}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_meaningless_parens_error
|
42
|
+
with_error_mode(:strict) do
|
43
|
+
assert_raise(SyntaxError) do
|
44
|
+
markup = "a == 'foo' or (b == 'bar' and c == 'baz') or false"
|
45
|
+
Template.parse("{% if #{markup} %} YES {% endif %}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_unexpected_characters_syntax_error
|
51
|
+
with_error_mode(:strict) do
|
52
|
+
assert_raise(SyntaxError) do
|
53
|
+
markup = "true && false"
|
54
|
+
Template.parse("{% if #{markup} %} YES {% endif %}")
|
55
|
+
end
|
56
|
+
assert_raise(SyntaxError) do
|
57
|
+
markup = "false || true"
|
58
|
+
Template.parse("{% if #{markup} %} YES {% endif %}")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_no_error_on_lax_empty_filter
|
64
|
+
assert_nothing_raised do
|
65
|
+
Template.parse("{{test |a|b|}}", :error_mode => :lax)
|
66
|
+
Template.parse("{{test}}", :error_mode => :lax)
|
67
|
+
Template.parse("{{|test|}}", :error_mode => :lax)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_meaningless_parens_lax
|
72
|
+
with_error_mode(:lax) do
|
73
|
+
assigns = {'b' => 'bar', 'c' => 'baz'}
|
74
|
+
markup = "a == 'foo' or (b == 'bar' and c == 'baz') or false"
|
75
|
+
assert_template_result(' YES ',"{% if #{markup} %} YES {% endif %}", assigns)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_unexpected_characters_silently_eat_logic_lax
|
80
|
+
with_error_mode(:lax) do
|
81
|
+
markup = "true && false"
|
82
|
+
assert_template_result(' YES ',"{% if #{markup} %} YES {% endif %}")
|
83
|
+
markup = "false || true"
|
84
|
+
assert_template_result('',"{% if #{markup} %} YES {% endif %}")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_raise_on_invalid_tag_delimiter
|
89
|
+
assert_raise(Liquid::SyntaxError) do
|
90
|
+
Template.new.parse('{% end %}')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end # ParsingQuirksTest
|
@@ -13,14 +13,14 @@ class SecurityTest < Test::Unit::TestCase
|
|
13
13
|
text = %( {{ '1+1' | instance_eval }} )
|
14
14
|
expected = %| 1+1 |
|
15
15
|
|
16
|
-
assert_equal expected, Template.parse(text).render(@assigns)
|
16
|
+
assert_equal expected, Template.parse(text).render!(@assigns)
|
17
17
|
end
|
18
18
|
|
19
19
|
def test_no_existing_instance_eval
|
20
20
|
text = %( {{ '1+1' | __instance_eval__ }} )
|
21
21
|
expected = %| 1+1 |
|
22
22
|
|
23
|
-
assert_equal expected, Template.parse(text).render(@assigns)
|
23
|
+
assert_equal expected, Template.parse(text).render!(@assigns)
|
24
24
|
end
|
25
25
|
|
26
26
|
|
@@ -28,7 +28,7 @@ class SecurityTest < Test::Unit::TestCase
|
|
28
28
|
text = %( {{ '1+1' | instance_eval }} )
|
29
29
|
expected = %| 1+1 |
|
30
30
|
|
31
|
-
assert_equal expected, Template.parse(text).render(@assigns)
|
31
|
+
assert_equal expected, Template.parse(text).render!(@assigns)
|
32
32
|
end
|
33
33
|
|
34
34
|
|
@@ -36,7 +36,7 @@ class SecurityTest < Test::Unit::TestCase
|
|
36
36
|
text = %( {{ '1+1' | add_one | instance_eval }} )
|
37
37
|
expected = %| 1+1 + 1 |
|
38
38
|
|
39
|
-
assert_equal expected, Template.parse(text).render(@assigns, :filters => SecurityFilter)
|
39
|
+
assert_equal expected, Template.parse(text).render!(@assigns, :filters => SecurityFilter)
|
40
40
|
end
|
41
41
|
|
42
42
|
def test_does_not_add_filters_to_symbol_table
|
@@ -47,17 +47,17 @@ class SecurityTest < Test::Unit::TestCase
|
|
47
47
|
template = Template.parse(test)
|
48
48
|
assert_equal [], (Symbol.all_symbols - current_symbols)
|
49
49
|
|
50
|
-
template.render
|
50
|
+
template.render!
|
51
51
|
assert_equal [], (Symbol.all_symbols - current_symbols)
|
52
52
|
end
|
53
53
|
|
54
54
|
def test_does_not_add_drop_methods_to_symbol_table
|
55
55
|
current_symbols = Symbol.all_symbols
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
57
|
+
assigns = { 'drop' => Drop.new }
|
58
|
+
assert_equal "", Template.parse("{{ drop.custom_method_1 }}", assigns).render!
|
59
|
+
assert_equal "", Template.parse("{{ drop.custom_method_2 }}", assigns).render!
|
60
|
+
assert_equal "", Template.parse("{{ drop.custom_method_3 }}", assigns).render!
|
61
61
|
|
62
62
|
assert_equal [], (Symbol.all_symbols - current_symbols)
|
63
63
|
end
|
@@ -7,6 +7,8 @@ class Filters
|
|
7
7
|
end
|
8
8
|
|
9
9
|
class TestThing
|
10
|
+
attr_reader :foo
|
11
|
+
|
10
12
|
def initialize
|
11
13
|
@foo = 0
|
12
14
|
end
|
@@ -15,6 +17,10 @@ class TestThing
|
|
15
17
|
"woot: #{@foo}"
|
16
18
|
end
|
17
19
|
|
20
|
+
def [](whatever)
|
21
|
+
to_s
|
22
|
+
end
|
23
|
+
|
18
24
|
def to_liquid
|
19
25
|
@foo += 1
|
20
26
|
self
|
@@ -27,6 +33,14 @@ class TestDrop < Liquid::Drop
|
|
27
33
|
end
|
28
34
|
end
|
29
35
|
|
36
|
+
class TestEnumerable < Liquid::Drop
|
37
|
+
include Enumerable
|
38
|
+
|
39
|
+
def each(&block)
|
40
|
+
[ { "foo" => 1, "bar" => 2 }, { "foo" => 2, "bar" => 1 }, { "foo" => 3, "bar" => 3 } ].each(&block)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
30
44
|
class StandardFiltersTest < Test::Unit::TestCase
|
31
45
|
include Liquid
|
32
46
|
|
@@ -50,11 +64,6 @@ class StandardFiltersTest < Test::Unit::TestCase
|
|
50
64
|
assert_equal '', @filters.upcase(nil)
|
51
65
|
end
|
52
66
|
|
53
|
-
def test_upcase
|
54
|
-
assert_equal 'TESTING', @filters.upcase("Testing")
|
55
|
-
assert_equal '', @filters.upcase(nil)
|
56
|
-
end
|
57
|
-
|
58
67
|
def test_truncate
|
59
68
|
assert_equal '1234...', @filters.truncate('1234567890', 7)
|
60
69
|
assert_equal '1234567890', @filters.truncate('1234567890', 20)
|
@@ -63,7 +72,7 @@ class StandardFiltersTest < Test::Unit::TestCase
|
|
63
72
|
assert_equal "测试...", @filters.truncate("测试测试测试测试", 5)
|
64
73
|
end
|
65
74
|
|
66
|
-
def
|
75
|
+
def test_split
|
67
76
|
assert_equal ['12','34'], @filters.split('12~34', '~')
|
68
77
|
assert_equal ['A? ',' ,Z'], @filters.split('A? ~ ~ ~ ,Z', '~ ~ ~')
|
69
78
|
assert_equal ['A?Z'], @filters.split('A?Z', '~')
|
@@ -77,7 +86,7 @@ class StandardFiltersTest < Test::Unit::TestCase
|
|
77
86
|
end
|
78
87
|
|
79
88
|
def test_escape_once
|
80
|
-
assert_equal '<strong>', @filters.escape_once(
|
89
|
+
assert_equal '<strong>Hulk</strong>', @filters.escape_once('<strong>Hulk</strong>')
|
81
90
|
end
|
82
91
|
|
83
92
|
def test_truncatewords
|
@@ -108,10 +117,25 @@ class StandardFiltersTest < Test::Unit::TestCase
|
|
108
117
|
assert_equal [{"a" => 1}, {"a" => 2}, {"a" => 3}, {"a" => 4}], @filters.sort([{"a" => 4}, {"a" => 3}, {"a" => 1}, {"a" => 2}], "a")
|
109
118
|
end
|
110
119
|
|
120
|
+
def test_legacy_sort_hash
|
121
|
+
assert_equal [{a:1, b:2}], @filters.sort({a:1, b:2})
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_numerical_vs_lexicographical_sort
|
125
|
+
assert_equal [2, 10], @filters.sort([10, 2])
|
126
|
+
assert_equal [{"a" => 2}, {"a" => 10}], @filters.sort([{"a" => 10}, {"a" => 2}], "a")
|
127
|
+
assert_equal ["10", "2"], @filters.sort(["10", "2"])
|
128
|
+
assert_equal [{"a" => "10"}, {"a" => "2"}], @filters.sort([{"a" => "10"}, {"a" => "2"}], "a")
|
129
|
+
end
|
130
|
+
|
111
131
|
def test_reverse
|
112
132
|
assert_equal [4,3,2,1], @filters.reverse([1,2,3,4])
|
113
133
|
end
|
114
134
|
|
135
|
+
def test_legacy_reverse_hash
|
136
|
+
assert_equal [{a:1, b:2}], @filters.reverse(a:1, b:2)
|
137
|
+
end
|
138
|
+
|
115
139
|
def test_map
|
116
140
|
assert_equal [1,2,3,4], @filters.map([{"a" => 1}, {"a" => 2}, {"a" => 3}, {"a" => 4}], 'a')
|
117
141
|
assert_template_result 'abc', "{{ ary | map:'foo' | map:'bar' }}",
|
@@ -119,20 +143,45 @@ class StandardFiltersTest < Test::Unit::TestCase
|
|
119
143
|
end
|
120
144
|
|
121
145
|
def test_map_doesnt_call_arbitrary_stuff
|
122
|
-
|
123
|
-
|
146
|
+
assert_template_result "", '{{ "foo" | map: "__id__" }}'
|
147
|
+
assert_template_result "", '{{ "foo" | map: "inspect" }}'
|
124
148
|
end
|
125
149
|
|
126
150
|
def test_map_calls_to_liquid
|
127
151
|
t = TestThing.new
|
128
|
-
|
152
|
+
assert_template_result "woot: 1", '{{ foo | map: "whatever" }}', "foo" => [t]
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_map_on_hashes
|
156
|
+
assert_template_result "4217", '{{ thing | map: "foo" | map: "bar" }}',
|
157
|
+
"thing" => { "foo" => [ { "bar" => 42 }, { "bar" => 17 } ] }
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_legacy_map_on_hashes_with_dynamic_key
|
161
|
+
template = "{% assign key = 'foo' %}{{ thing | map: key | map: 'bar' }}"
|
162
|
+
hash = { "foo" => { "bar" => 42 } }
|
163
|
+
assert_template_result "42", template, "thing" => hash
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_sort_calls_to_liquid
|
167
|
+
t = TestThing.new
|
168
|
+
Liquid::Template.parse('{{ foo | sort: "whatever" }}').render("foo" => [t])
|
169
|
+
assert t.foo > 0
|
129
170
|
end
|
130
171
|
|
131
172
|
def test_map_over_proc
|
132
173
|
drop = TestDrop.new
|
133
174
|
p = Proc.new{ drop }
|
134
175
|
templ = '{{ procs | map: "test" }}'
|
135
|
-
|
176
|
+
assert_template_result "testfoo", templ, "procs" => [p]
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_map_works_on_enumerables
|
180
|
+
assert_template_result "123", '{{ foo | map: "foo" }}', "foo" => TestEnumerable.new
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_sort_works_on_enumerables
|
184
|
+
assert_template_result "213", '{{ foo | sort: "bar" | map: "foo" }}', "foo" => TestEnumerable.new
|
136
185
|
end
|
137
186
|
|
138
187
|
def test_date
|
@@ -157,13 +206,10 @@ class StandardFiltersTest < Test::Unit::TestCase
|
|
157
206
|
|
158
207
|
assert_equal nil, @filters.date(nil, "%B")
|
159
208
|
|
160
|
-
|
161
|
-
|
162
|
-
assert_equal "07/05/2006", @filters.date("1152098955", "%m/%d/%Y")
|
163
|
-
end
|
209
|
+
assert_equal "07/05/2006", @filters.date(1152098955, "%m/%d/%Y")
|
210
|
+
assert_equal "07/05/2006", @filters.date("1152098955", "%m/%d/%Y")
|
164
211
|
end
|
165
212
|
|
166
|
-
|
167
213
|
def test_first_last
|
168
214
|
assert_equal 1, @filters.first([1,2,3])
|
169
215
|
assert_equal 3, @filters.last([1,2,3])
|
@@ -187,6 +233,21 @@ class StandardFiltersTest < Test::Unit::TestCase
|
|
187
233
|
assert_template_result 'foobar', "{{ 'foo|bar' | remove: '|' }}"
|
188
234
|
end
|
189
235
|
|
236
|
+
def test_strip
|
237
|
+
assert_template_result 'ab c', "{{ source | strip }}", 'source' => " ab c "
|
238
|
+
assert_template_result 'ab c', "{{ source | strip }}", 'source' => " \tab c \n \t"
|
239
|
+
end
|
240
|
+
|
241
|
+
def test_lstrip
|
242
|
+
assert_template_result 'ab c ', "{{ source | lstrip }}", 'source' => " ab c "
|
243
|
+
assert_template_result "ab c \n \t", "{{ source | lstrip }}", 'source' => " \tab c \n \t"
|
244
|
+
end
|
245
|
+
|
246
|
+
def test_rstrip
|
247
|
+
assert_template_result " ab c", "{{ source | rstrip }}", 'source' => " ab c "
|
248
|
+
assert_template_result " \tab c", "{{ source | rstrip }}", 'source' => " \tab c \n \t"
|
249
|
+
end
|
250
|
+
|
190
251
|
def test_strip_newlines
|
191
252
|
assert_template_result 'abc', "{{ source | strip_newlines }}", 'source' => "a\nb\nc"
|
192
253
|
assert_template_result 'abc', "{{ source | strip_newlines }}", 'source' => "a\r\nb\nc"
|
@@ -210,9 +271,6 @@ class StandardFiltersTest < Test::Unit::TestCase
|
|
210
271
|
assert_template_result "12", "{{ 3 | times:4 }}"
|
211
272
|
assert_template_result "0", "{{ 'foo' | times:4 }}"
|
212
273
|
|
213
|
-
# Ruby v1.9.2-rc1, or higher, backwards compatible Float test
|
214
|
-
assert_match(/(6\.3)|(6\.(0{13})1)/, Template.parse("{{ '2.1' | times:3 }}").render)
|
215
|
-
|
216
274
|
assert_template_result "6", "{{ '2.1' | times:3 | replace: '.','-' | plus:0}}"
|
217
275
|
|
218
276
|
assert_template_result "7.25", "{{ 0.0725 | times:100 }}"
|
@@ -222,11 +280,8 @@ class StandardFiltersTest < Test::Unit::TestCase
|
|
222
280
|
assert_template_result "4", "{{ 12 | divided_by:3 }}"
|
223
281
|
assert_template_result "4", "{{ 14 | divided_by:3 }}"
|
224
282
|
|
225
|
-
# Ruby v1.9.2-rc1, or higher, backwards compatible Float test
|
226
|
-
assert_match(/4\.(6{13,14})7/, Template.parse("{{ 14 | divided_by:'3.0' }}").render)
|
227
|
-
|
228
283
|
assert_template_result "5", "{{ 15 | divided_by:3 }}"
|
229
|
-
|
284
|
+
assert_equal "Liquid error: divided by 0", Template.parse("{{ 5 | divided_by:0 }}").render
|
230
285
|
|
231
286
|
assert_template_result "0.5", "{{ 2.0 | divided_by:4 }}"
|
232
287
|
end
|
@@ -235,6 +290,22 @@ class StandardFiltersTest < Test::Unit::TestCase
|
|
235
290
|
assert_template_result "1", "{{ 3 | modulo:2 }}"
|
236
291
|
end
|
237
292
|
|
293
|
+
def test_round
|
294
|
+
assert_template_result "5", "{{ input | round }}", 'input' => 4.6
|
295
|
+
assert_template_result "4", "{{ '4.3' | round }}"
|
296
|
+
assert_template_result "4.56", "{{ input | round: 2 }}", 'input' => 4.5612
|
297
|
+
end
|
298
|
+
|
299
|
+
def test_ceil
|
300
|
+
assert_template_result "5", "{{ input | ceil }}", 'input' => 4.6
|
301
|
+
assert_template_result "5", "{{ '4.3' | ceil }}"
|
302
|
+
end
|
303
|
+
|
304
|
+
def test_floor
|
305
|
+
assert_template_result "4", "{{ input | floor }}", 'input' => 4.6
|
306
|
+
assert_template_result "4", "{{ '4.3' | floor }}"
|
307
|
+
end
|
308
|
+
|
238
309
|
def test_append
|
239
310
|
assigns = {'a' => 'bc', 'b' => 'd' }
|
240
311
|
assert_template_result('bcd',"{{ a | append: 'd'}}",assigns)
|
@@ -247,17 +318,16 @@ class StandardFiltersTest < Test::Unit::TestCase
|
|
247
318
|
assert_template_result('abc',"{{ a | prepend: b}}",assigns)
|
248
319
|
end
|
249
320
|
|
250
|
-
def
|
251
|
-
|
321
|
+
def test_default
|
322
|
+
assert_equal "foo", @filters.default("foo", "bar")
|
323
|
+
assert_equal "bar", @filters.default(nil, "bar")
|
324
|
+
assert_equal "bar", @filters.default("", "bar")
|
325
|
+
assert_equal "bar", @filters.default(false, "bar")
|
326
|
+
assert_equal "bar", @filters.default([], "bar")
|
327
|
+
assert_equal "bar", @filters.default({}, "bar")
|
252
328
|
end
|
253
329
|
|
254
|
-
|
255
|
-
|
256
|
-
def with_timezone(tz)
|
257
|
-
old_tz = ENV['TZ']
|
258
|
-
ENV['TZ'] = tz
|
259
|
-
yield
|
260
|
-
ensure
|
261
|
-
ENV['TZ'] = old_tz
|
330
|
+
def test_cannot_access_private_methods
|
331
|
+
assert_template_result('a',"{{ 'a' | to_number }}")
|
262
332
|
end
|
263
333
|
end # StandardFiltersTest
|