liquor 0.1.1 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +3 -9
  5. data/Gemfile +7 -0
  6. data/Guardfile +11 -0
  7. data/MIT-LICENSE +6 -2
  8. data/README.md +4 -122
  9. data/Rakefile +20 -23
  10. data/doc/language-spec.html +768 -0
  11. data/doc/language-spec.md +698 -0
  12. data/lib/liquor.rb +39 -68
  13. data/lib/liquor/ast_tools.rb +28 -0
  14. data/lib/liquor/compiler.rb +110 -0
  15. data/lib/liquor/context.rb +76 -254
  16. data/lib/liquor/diagnostics.rb +151 -0
  17. data/lib/liquor/drop/drop.rb +168 -0
  18. data/lib/liquor/drop/drop_delegation.rb +24 -0
  19. data/lib/liquor/drop/drop_scope.rb +118 -0
  20. data/lib/liquor/drop/dropable.rb +17 -0
  21. data/lib/liquor/emitter.rb +313 -0
  22. data/lib/liquor/extensions/kaminari.rb +14 -0
  23. data/lib/liquor/extensions/pagination.rb +235 -0
  24. data/lib/liquor/extensions/rails.rb +97 -0
  25. data/lib/liquor/extensions/thinking_sphinx.rb +14 -0
  26. data/lib/liquor/extensions/tire.rb +30 -0
  27. data/lib/liquor/external.rb +79 -0
  28. data/lib/liquor/function.rb +94 -0
  29. data/lib/liquor/grammar/lexer.rb +1223 -0
  30. data/lib/liquor/grammar/lexer.rl +297 -0
  31. data/lib/liquor/grammar/parser.racc +288 -0
  32. data/lib/liquor/grammar/parser.rb +885 -0
  33. data/lib/liquor/library.rb +41 -0
  34. data/lib/liquor/manager.rb +146 -0
  35. data/lib/liquor/runtime.rb +167 -0
  36. data/lib/liquor/stdlib/builtin_functions.rb +315 -0
  37. data/lib/liquor/stdlib/builtin_tags.rb +228 -0
  38. data/lib/liquor/stdlib/html_truncater.rb +162 -0
  39. data/lib/liquor/stdlib/partial_tags.rb +76 -0
  40. data/lib/liquor/tag.rb +83 -14
  41. data/lib/liquor/version.rb +1 -1
  42. data/liquor.gemspec +29 -6
  43. data/spec/builtins_spec.rb +264 -0
  44. data/spec/compiler_spec.rb +136 -0
  45. data/spec/context_spec.rb +49 -0
  46. data/spec/drop_delegation_spec.rb +21 -0
  47. data/spec/drop_spec.rb +222 -0
  48. data/spec/errors_spec.rb +40 -0
  49. data/spec/external_spec.rb +207 -0
  50. data/spec/function_spec.rb +80 -0
  51. data/spec/lexer_spec.rb +173 -0
  52. data/spec/library_spec.rb +18 -0
  53. data/spec/manager_spec.rb +84 -0
  54. data/spec/parser_spec.rb +381 -0
  55. data/spec/partials_spec.rb +74 -0
  56. data/spec/runtime_spec.rb +97 -0
  57. data/spec/spec_helper.rb +94 -0
  58. data/spec/tag_spec.rb +7 -0
  59. metadata +216 -173
  60. data/AUTHORS +0 -2
  61. data/CHANGELOG +0 -48
  62. data/Gemfile.lock +0 -91
  63. data/History.txt +0 -44
  64. data/LICENSE +0 -23
  65. data/example/server/example_servlet.rb +0 -37
  66. data/example/server/liquid_servlet.rb +0 -28
  67. data/example/server/liquor_servlet.rb +0 -28
  68. data/example/server/server.rb +0 -12
  69. data/example/server/templates/index.liquid +0 -6
  70. data/example/server/templates/index.liquor +0 -6
  71. data/example/server/templates/products.liquid +0 -45
  72. data/example/server/templates/products.liquor +0 -45
  73. data/init.rb +0 -8
  74. data/lib/extras/liquid_view.rb +0 -51
  75. data/lib/extras/liquor_view.rb +0 -51
  76. data/lib/liquor/block.rb +0 -101
  77. data/lib/liquor/condition.rb +0 -120
  78. data/lib/liquor/document.rb +0 -17
  79. data/lib/liquor/drop.rb +0 -256
  80. data/lib/liquor/errors.rb +0 -11
  81. data/lib/liquor/extensions.rb +0 -72
  82. data/lib/liquor/file_system.rb +0 -62
  83. data/lib/liquor/htmltags.rb +0 -74
  84. data/lib/liquor/module_ex.rb +0 -60
  85. data/lib/liquor/standardfilters.rb +0 -315
  86. data/lib/liquor/strainer.rb +0 -58
  87. data/lib/liquor/tags/assign.rb +0 -33
  88. data/lib/liquor/tags/capture.rb +0 -35
  89. data/lib/liquor/tags/case.rb +0 -83
  90. data/lib/liquor/tags/comment.rb +0 -9
  91. data/lib/liquor/tags/content_for.rb +0 -54
  92. data/lib/liquor/tags/cycle.rb +0 -59
  93. data/lib/liquor/tags/for.rb +0 -136
  94. data/lib/liquor/tags/if.rb +0 -80
  95. data/lib/liquor/tags/ifchanged.rb +0 -20
  96. data/lib/liquor/tags/include.rb +0 -56
  97. data/lib/liquor/tags/unless.rb +0 -33
  98. data/lib/liquor/tags/yield.rb +0 -49
  99. data/lib/liquor/template.rb +0 -181
  100. data/lib/liquor/variable.rb +0 -52
  101. data/performance/shopify.rb +0 -92
  102. data/performance/shopify/comment_form.rb +0 -33
  103. data/performance/shopify/database.rb +0 -45
  104. data/performance/shopify/json_filter.rb +0 -7
  105. data/performance/shopify/liquid.rb +0 -18
  106. data/performance/shopify/liquor.rb +0 -18
  107. data/performance/shopify/money_filter.rb +0 -18
  108. data/performance/shopify/paginate.rb +0 -93
  109. data/performance/shopify/shop_filter.rb +0 -98
  110. data/performance/shopify/tag_filter.rb +0 -25
  111. data/performance/shopify/vision.database.yml +0 -945
  112. data/performance/shopify/weight_filter.rb +0 -11
  113. data/performance/tests/dropify/article.liquid +0 -74
  114. data/performance/tests/dropify/blog.liquid +0 -33
  115. data/performance/tests/dropify/cart.liquid +0 -66
  116. data/performance/tests/dropify/collection.liquid +0 -22
  117. data/performance/tests/dropify/index.liquid +0 -47
  118. data/performance/tests/dropify/page.liquid +0 -8
  119. data/performance/tests/dropify/product.liquid +0 -68
  120. data/performance/tests/dropify/theme.liquid +0 -105
  121. data/performance/tests/ripen/article.liquid +0 -74
  122. data/performance/tests/ripen/blog.liquid +0 -13
  123. data/performance/tests/ripen/cart.liquid +0 -54
  124. data/performance/tests/ripen/collection.liquid +0 -29
  125. data/performance/tests/ripen/index.liquid +0 -32
  126. data/performance/tests/ripen/page.liquid +0 -4
  127. data/performance/tests/ripen/product.liquid +0 -75
  128. data/performance/tests/ripen/theme.liquid +0 -85
  129. data/performance/tests/tribble/404.liquid +0 -56
  130. data/performance/tests/tribble/article.liquid +0 -98
  131. data/performance/tests/tribble/blog.liquid +0 -41
  132. data/performance/tests/tribble/cart.liquid +0 -134
  133. data/performance/tests/tribble/collection.liquid +0 -70
  134. data/performance/tests/tribble/index.liquid +0 -94
  135. data/performance/tests/tribble/page.liquid +0 -56
  136. data/performance/tests/tribble/product.liquid +0 -116
  137. data/performance/tests/tribble/search.liquid +0 -51
  138. data/performance/tests/tribble/theme.liquid +0 -90
  139. data/performance/tests/vogue/article.liquid +0 -66
  140. data/performance/tests/vogue/blog.liquid +0 -32
  141. data/performance/tests/vogue/cart.liquid +0 -58
  142. data/performance/tests/vogue/collection.liquid +0 -19
  143. data/performance/tests/vogue/index.liquid +0 -22
  144. data/performance/tests/vogue/page.liquid +0 -3
  145. data/performance/tests/vogue/product.liquid +0 -62
  146. data/performance/tests/vogue/theme.liquid +0 -122
  147. data/test/assign_test.rb +0 -11
  148. data/test/block_test.rb +0 -58
  149. data/test/capture_test.rb +0 -41
  150. data/test/condition_test.rb +0 -115
  151. data/test/content_for_test.rb +0 -15
  152. data/test/context_test.rb +0 -479
  153. data/test/drop_test.rb +0 -162
  154. data/test/error_handling_test.rb +0 -89
  155. data/test/extra/breakpoint.rb +0 -547
  156. data/test/extra/caller.rb +0 -80
  157. data/test/file_system_test.rb +0 -30
  158. data/test/filter_test.rb +0 -147
  159. data/test/helper.rb +0 -24
  160. data/test/html_tag_test.rb +0 -31
  161. data/test/if_else_test.rb +0 -139
  162. data/test/include_tag_test.rb +0 -129
  163. data/test/module_ex_test.rb +0 -89
  164. data/test/output_test.rb +0 -121
  165. data/test/parsing_quirks_test.rb +0 -54
  166. data/test/regexp_test.rb +0 -45
  167. data/test/security_test.rb +0 -41
  168. data/test/standard_filter_test.rb +0 -170
  169. data/test/standard_tag_test.rb +0 -405
  170. data/test/statements_test.rb +0 -137
  171. data/test/strainer_test.rb +0 -27
  172. data/test/template_test.rb +0 -82
  173. data/test/test_helper.rb +0 -28
  174. data/test/unless_else_test.rb +0 -27
  175. data/test/variable_test.rb +0 -173
  176. data/test/yield_test.rb +0 -24
@@ -1,11 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- class AssignTest < Test::Unit::TestCase
4
- include Liquor
5
-
6
- def test_assigned_variable
7
- assert_template_result('.foo.','{% assign foo = values %}.{{ foo[0] }}.', 'values' => %w{foo bar baz})
8
- assert_template_result('.bar.','{% assign foo = values %}.{{ foo[1] }}.', 'values' => %w{foo bar baz})
9
- end
10
-
11
- end
@@ -1,58 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- class VariableTest < Test::Unit::TestCase
4
- include Liquor
5
-
6
- def test_blankspace
7
- template = Liquor::Template.parse(" ")
8
- assert_equal [" "], template.root.nodelist
9
- end
10
-
11
- def test_variable_beginning
12
- template = Liquor::Template.parse("{{funk}} ")
13
- assert_equal 2, template.root.nodelist.size
14
- assert_equal Variable, template.root.nodelist[0].class
15
- assert_equal String, template.root.nodelist[1].class
16
- end
17
-
18
- def test_variable_end
19
- template = Liquor::Template.parse(" {{funk}}")
20
- assert_equal 2, template.root.nodelist.size
21
- assert_equal String, template.root.nodelist[0].class
22
- assert_equal Variable, template.root.nodelist[1].class
23
- end
24
-
25
- def test_variable_middle
26
- template = Liquor::Template.parse(" {{funk}} ")
27
- assert_equal 3, template.root.nodelist.size
28
- assert_equal String, template.root.nodelist[0].class
29
- assert_equal Variable, template.root.nodelist[1].class
30
- assert_equal String, template.root.nodelist[2].class
31
- end
32
-
33
- def test_variable_many_embedded_fragments
34
- template = Liquor::Template.parse(" {{funk}} {{so}} {{brother}} ")
35
- assert_equal 7, template.root.nodelist.size
36
- assert_equal [String, Variable, String, Variable, String, Variable, String], block_types(template.root.nodelist)
37
- end
38
-
39
- def test_with_block
40
- template = Liquor::Template.parse(" {% comment %} {% endcomment %} ")
41
- assert_equal [String, Comment, String], block_types(template.root.nodelist)
42
- assert_equal 3, template.root.nodelist.size
43
- end
44
-
45
- def test_with_custom_tag
46
- Liquor::Template.register_tag("testtag", Block)
47
-
48
- assert_nothing_thrown do
49
- template = Liquor::Template.parse( "{% testtag %} {% endtesttag %}")
50
- end
51
- end
52
-
53
- private
54
-
55
- def block_types(nodelist)
56
- nodelist.collect { |node| node.class }
57
- end
58
- end
@@ -1,41 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- class CaptureTest < Test::Unit::TestCase
4
- include Liquor
5
-
6
- def test_captures_block_content_in_variable
7
- assert_template_result("test string", "{% capture 'var' %}test string{% endcapture %}{{var}}", {})
8
- end
9
-
10
- def test_capture_to_variable_from_outer_scope_if_existing
11
- template_source = <<-END_TEMPLATE
12
- {% assign var = '' %}
13
- {% if true %}
14
- {% capture var %}first-block-string{% endcapture %}
15
- {% endif %}
16
- {% if true %}
17
- {% capture var %}test-string{% endcapture %}
18
- {% endif %}
19
- {{var}}
20
- END_TEMPLATE
21
- template = Template.parse(template_source)
22
- rendered = template.render
23
- assert_equal "test-string", rendered.gsub(/\s/, '')
24
- end
25
-
26
- def test_assigning_from_capture
27
- template_source = <<-END_TEMPLATE
28
- {% assign first = '' %}
29
- {% assign second = '' %}
30
- {% for number in (1..3) %}
31
- {% capture first %}{{number}}{% endcapture %}
32
- {% assign second = first %}
33
- {% endfor %}
34
- {{ first }}-{{ second }}
35
- END_TEMPLATE
36
- template = Template.parse(template_source)
37
- rendered = template.render
38
- assert_equal "3-3", rendered.gsub(/\s/, '')
39
- end
40
-
41
- end
@@ -1,115 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- class ConditionTest < Test::Unit::TestCase
4
- include Liquor
5
-
6
- def test_basic_condition
7
- assert_equal false, Condition.new('1', '==', '2').evaluate
8
- assert_equal true, Condition.new('1', '==', '1').evaluate
9
- end
10
-
11
- def test_default_operators_evalute_true
12
- assert_evalutes_true '1', '==', '1'
13
- assert_evalutes_true '1', '!=', '2'
14
- assert_evalutes_true '1', '<>', '2'
15
- assert_evalutes_true '1', '<', '2'
16
- assert_evalutes_true '2', '>', '1'
17
- assert_evalutes_true '1', '>=', '1'
18
- assert_evalutes_true '2', '>=', '1'
19
- assert_evalutes_true '1', '<=', '2'
20
- assert_evalutes_true '1', '<=', '1'
21
- end
22
-
23
- def test_default_operators_evalute_false
24
- assert_evalutes_false '1', '==', '2'
25
- assert_evalutes_false '1', '!=', '1'
26
- assert_evalutes_false '1', '<>', '1'
27
- assert_evalutes_false '1', '<', '0'
28
- assert_evalutes_false '2', '>', '4'
29
- assert_evalutes_false '1', '>=', '3'
30
- assert_evalutes_false '2', '>=', '4'
31
- assert_evalutes_false '1', '<=', '0'
32
- assert_evalutes_false '1', '<=', '0'
33
- end
34
-
35
- def test_contains_works_on_strings
36
- assert_evalutes_true "'bob'", 'contains', "'o'"
37
- assert_evalutes_true "'bob'", 'contains', "'b'"
38
- assert_evalutes_true "'bob'", 'contains', "'bo'"
39
- assert_evalutes_true "'bob'", 'contains', "'ob'"
40
- assert_evalutes_true "'bob'", 'contains', "'bob'"
41
-
42
- assert_evalutes_false "'bob'", 'contains', "'bob2'"
43
- assert_evalutes_false "'bob'", 'contains', "'a'"
44
- assert_evalutes_false "'bob'", 'contains', "'---'"
45
- end
46
-
47
- def test_contains_works_on_arrays
48
- @context = Liquor::Context.new
49
- @context['array'] = [1,2,3,4,5]
50
-
51
- assert_evalutes_false "array", 'contains', '0'
52
- assert_evalutes_true "array", 'contains', '1'
53
- assert_evalutes_true "array", 'contains', '2'
54
- assert_evalutes_true "array", 'contains', '3'
55
- assert_evalutes_true "array", 'contains', '4'
56
- assert_evalutes_true "array", 'contains', '5'
57
- assert_evalutes_false "array", 'contains', '6'
58
-
59
- assert_evalutes_false "array", 'contains', '"1"'
60
-
61
- end
62
-
63
- def test_contains_returns_false_for_nil_operands
64
- @context = Liquor::Context.new
65
- assert_evalutes_false "not_assigned", 'contains', '0'
66
- assert_evalutes_false "0", 'contains', 'not_assigned'
67
- end
68
-
69
- def test_or_condition
70
- condition = Condition.new('1', '==', '2')
71
-
72
- assert_equal false, condition.evaluate
73
-
74
- condition.or Condition.new('2', '==', '1')
75
-
76
- assert_equal false, condition.evaluate
77
-
78
- condition.or Condition.new('1', '==', '1')
79
-
80
- assert_equal true, condition.evaluate
81
- end
82
-
83
- def test_and_condition
84
- condition = Condition.new('1', '==', '1')
85
-
86
- assert_equal true, condition.evaluate
87
-
88
- condition.and Condition.new('2', '==', '2')
89
-
90
- assert_equal true, condition.evaluate
91
-
92
- condition.and Condition.new('2', '==', '1')
93
-
94
- assert_equal false, condition.evaluate
95
- end
96
-
97
-
98
- def test_should_allow_custom_proc_operator
99
- Condition.operators['starts_with'] = Proc.new { |cond, left, right| left =~ %r{^#{right}}}
100
-
101
- assert_evalutes_true "'bob'", 'starts_with', "'b'"
102
- assert_evalutes_false "'bob'", 'starts_with', "'o'"
103
- ensure
104
- Condition.operators.delete 'starts_with'
105
- end
106
-
107
- private
108
- def assert_evalutes_true(left, op, right)
109
- assert Condition.new(left, op, right).evaluate(@context || Liquor::Context.new), "Evaluated false: #{left} #{op} #{right}"
110
- end
111
-
112
- def assert_evalutes_false(left, op, right)
113
- assert !Condition.new(left, op, right).evaluate(@context || Liquor::Context.new), "Evaluated true: #{left} #{op} #{right}"
114
- end
115
- end
@@ -1,15 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- class ContentForTest < Test::Unit::TestCase
4
- include Liquor
5
-
6
- def test_content_for
7
- layout_template = '<title>{% yield title %}</title> <body>{% yield %}</body>'
8
- view_template = '{% content_for title %}{% assign text="aaa" %}{{ text }}{% end_content_for %}{% assign text="body" %}{{ text }}'
9
-
10
- rendered_template = Template.parse(view_template).render({ :layout => Template.parse(layout_template) })
11
-
12
- assert_equal '<title>aaa</title> <body>body</body>', rendered_template
13
- end
14
-
15
- end
@@ -1,479 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
- class HundredCentes
3
- def to_liquor
4
- 100
5
- end
6
- end
7
-
8
- class CentsDrop < Liquor::Drop
9
- def amount
10
- HundredCentes.new
11
- end
12
-
13
- def non_zero?
14
- true
15
- end
16
- end
17
-
18
- class ContextSensitiveDrop < Liquor::Drop
19
- def test
20
- @context['test']
21
- end
22
- end
23
-
24
- class Category < Liquor::Drop
25
- attr_accessor :name
26
-
27
- def initialize(name)
28
- @name = name
29
- end
30
-
31
- def to_liquor
32
- CategoryDrop.new(self)
33
- end
34
- end
35
-
36
- class CategoryDrop
37
- attr_accessor :category, :context
38
- def initialize(category)
39
- @category = category
40
- end
41
- end
42
-
43
- class CounterDrop < Liquor::Drop
44
- def count
45
- @count ||= 0
46
- @count += 1
47
- end
48
- end
49
-
50
- class ArrayLike
51
- def fetch(index)
52
- end
53
-
54
- def [](index)
55
- @counts ||= []
56
- @counts[index] ||= 0
57
- @counts[index] += 1
58
- end
59
-
60
- def to_liquor
61
- self
62
- end
63
- end
64
-
65
-
66
- class ContextTest < Test::Unit::TestCase
67
- include Liquor
68
-
69
- def setup
70
- @context = Liquor::Context.new
71
- end
72
-
73
- def test_variables
74
- @context['string'] = 'string'
75
- assert_equal 'string', @context['string']
76
-
77
- @context['num'] = 5
78
- assert_equal 5, @context['num']
79
-
80
- @context['time'] = Time.parse('2006-06-06 12:00:00')
81
- assert_equal Time.parse('2006-06-06 12:00:00'), @context['time']
82
-
83
- @context['date'] = Date.today
84
- assert_equal Date.today, @context['date']
85
-
86
- now = DateTime.now
87
- @context['datetime'] = now
88
- assert_equal now, @context['datetime']
89
-
90
- @context['bool'] = true
91
- assert_equal true, @context['bool']
92
-
93
- @context['bool'] = false
94
- assert_equal false, @context['bool']
95
-
96
- @context['nil'] = nil
97
- assert_equal nil, @context['nil']
98
- assert_equal nil, @context['nil']
99
- end
100
-
101
- def test_variables_not_existing
102
- assert_equal nil, @context['does_not_exist']
103
- end
104
-
105
- def test_scoping
106
- assert_nothing_raised do
107
- @context.push
108
- @context.pop
109
- end
110
-
111
- assert_raise(Liquor::ContextError) do
112
- @context.pop
113
- end
114
-
115
- assert_raise(Liquor::ContextError) do
116
- @context.push
117
- @context.pop
118
- @context.pop
119
- end
120
- end
121
-
122
- def test_length_query
123
-
124
- @context['numbers'] = [1,2,3,4]
125
-
126
- assert_equal 4, @context['numbers.size']
127
-
128
- @context['numbers'] = {1 => 1,2 => 2,3 => 3,4 => 4}
129
-
130
- assert_equal 4, @context['numbers.size']
131
-
132
- @context['numbers'] = {1 => 1,2 => 2,3 => 3,4 => 4, 'size' => 1000}
133
-
134
- assert_equal 1000, @context['numbers.size']
135
-
136
- end
137
-
138
- def test_hyphenated_variable
139
-
140
- @context['oh-my'] = 'godz'
141
- assert_equal 'godz', @context['oh-my']
142
-
143
- end
144
-
145
- def test_add_filter
146
-
147
- filter = Module.new do
148
- def hi(output)
149
- output + ' hi!'
150
- end
151
- end
152
-
153
- context = Context.new
154
- context.add_filters(filter)
155
- assert_equal 'hi? hi!', context.invoke(:hi, 'hi?')
156
-
157
- context = Context.new
158
- assert_equal 'hi?', context.invoke(:hi, 'hi?')
159
-
160
- context.add_filters(filter)
161
- assert_equal 'hi? hi!', context.invoke(:hi, 'hi?')
162
-
163
- end
164
-
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
- def test_only_intended_filters_make_it_there
184
-
185
- filter = Module.new do
186
- def hi(output)
187
- output + ' hi!'
188
- end
189
- end
190
-
191
- context = Context.new
192
- methods_before = context.strainer.methods.map { |method| method.to_s }
193
- context.add_filters(filter)
194
- methods_after = context.strainer.methods.map { |method| method.to_s }
195
- assert_equal (methods_before + ["hi"]).sort, methods_after.sort
196
- end
197
-
198
- def test_add_item_in_outer_scope
199
- @context['test'] = 'test'
200
- @context.push
201
- assert_equal 'test', @context['test']
202
- @context.pop
203
- assert_equal 'test', @context['test']
204
- end
205
-
206
- def test_add_item_in_inner_scope
207
- @context.push
208
- @context['test'] = 'test'
209
- assert_equal 'test', @context['test']
210
- @context.pop
211
- assert_equal nil, @context['test']
212
- end
213
-
214
- def test_hierachical_data
215
- @context['hash'] = {"name" => 'tobi'}
216
- assert_equal 'tobi', @context['hash.name']
217
- assert_equal 'tobi', @context['hash["name"]']
218
- end
219
-
220
- def test_keywords
221
- assert_equal true, @context['true']
222
- assert_equal false, @context['false']
223
- end
224
-
225
- def test_digits
226
- assert_equal 100, @context['100']
227
- assert_equal 100.00, @context['100.00']
228
- end
229
-
230
- def test_strings
231
- assert_equal "hello!", @context['"hello!"']
232
- assert_equal "hello!", @context["'hello!'"]
233
- end
234
-
235
- def test_merge
236
- @context.merge({ "test" => "test" })
237
- assert_equal 'test', @context['test']
238
- @context.merge({ "test" => "newvalue", "foo" => "bar" })
239
- assert_equal 'newvalue', @context['test']
240
- assert_equal 'bar', @context['foo']
241
- end
242
-
243
- def test_array_notation
244
- @context['test'] = [1,2,3,4,5]
245
-
246
- assert_equal 1, @context['test[0]']
247
- assert_equal 2, @context['test[1]']
248
- assert_equal 3, @context['test[2]']
249
- assert_equal 4, @context['test[3]']
250
- assert_equal 5, @context['test[4]']
251
- end
252
-
253
- def test_recoursive_array_notation
254
- @context['test'] = {'test' => [1,2,3,4,5]}
255
-
256
- assert_equal 1, @context['test.test[0]']
257
-
258
- @context['test'] = [{'test' => 'worked'}]
259
-
260
- assert_equal 'worked', @context['test[0].test']
261
- end
262
-
263
- def test_hash_to_array_transition
264
- @context['colors'] = {
265
- 'Blue' => ['003366','336699', '6699CC', '99CCFF'],
266
- 'Green' => ['003300','336633', '669966', '99CC99'],
267
- 'Yellow' => ['CC9900','FFCC00', 'FFFF99', 'FFFFCC'],
268
- 'Red' => ['660000','993333', 'CC6666', 'FF9999']
269
- }
270
-
271
- assert_equal '003366', @context['colors.Blue[0]']
272
- assert_equal 'FF9999', @context['colors.Red[3]']
273
- end
274
-
275
- def test_try_first
276
- @context['test'] = [1,2,3,4,5]
277
-
278
- assert_equal 1, @context['test.first']
279
- assert_equal 5, @context['test.last']
280
-
281
- @context['test'] = {'test' => [1,2,3,4,5]}
282
-
283
- assert_equal 1, @context['test.test.first']
284
- assert_equal 5, @context['test.test.last']
285
-
286
- @context['test'] = [1]
287
- assert_equal 1, @context['test.first']
288
- assert_equal 1, @context['test.last']
289
- end
290
-
291
- def test_access_hashes_with_hash_notation
292
- @context['products'] = {'count' => 5, 'tags' => ['deepsnow', 'freestyle'] }
293
- @context['product'] = {'variants' => [ {'title' => 'draft151cm'}, {'title' => 'element151cm'} ]}
294
-
295
- assert_equal 5, @context['products["count"]']
296
- assert_equal 'deepsnow', @context['products["tags"][0]']
297
- assert_equal 'deepsnow', @context['products["tags"].first']
298
- assert_equal 'draft151cm', @context['product["variants"][0]["title"]']
299
- assert_equal 'element151cm', @context['product["variants"][1]["title"]']
300
- assert_equal 'draft151cm', @context['product["variants"][0]["title"]']
301
- assert_equal 'element151cm', @context['product["variants"].last["title"]']
302
- end
303
-
304
- def test_access_variable_with_hash_notation
305
- @context['foo'] = 'baz'
306
- @context['bar'] = 'foo'
307
-
308
- assert_equal 'baz', @context['["foo"]']
309
- assert_equal 'baz', @context['[bar]']
310
- end
311
-
312
- def test_access_hashes_with_hash_access_variables
313
-
314
- @context['var'] = 'tags'
315
- @context['nested'] = {'var' => 'tags'}
316
- @context['products'] = {'count' => 5, 'tags' => ['deepsnow', 'freestyle'] }
317
-
318
- assert_equal 'deepsnow', @context['products[var].first']
319
- assert_equal 'freestyle', @context['products[nested.var].last']
320
- end
321
-
322
- def test_hash_notation_only_for_hash_access
323
- @context['array'] = [1,2,3,4,5]
324
- @context['hash'] = {'first' => 'Hello'}
325
-
326
- assert_equal 1, @context['array.first']
327
- assert_equal nil, @context['array["first"]']
328
- assert_equal 'Hello', @context['hash["first"]']
329
- end
330
-
331
- def test_first_can_appear_in_middle_of_callchain
332
-
333
- @context['product'] = {'variants' => [ {'title' => 'draft151cm'}, {'title' => 'element151cm'} ]}
334
-
335
- assert_equal 'draft151cm', @context['product.variants[0].title']
336
- assert_equal 'element151cm', @context['product.variants[1].title']
337
- assert_equal 'draft151cm', @context['product.variants.first.title']
338
- assert_equal 'element151cm', @context['product.variants.last.title']
339
-
340
- end
341
-
342
- def test_cents
343
- @context.merge( "cents" => HundredCentes.new )
344
- assert_equal 100, @context['cents']
345
- end
346
-
347
- def test_nested_cents
348
- @context.merge( "cents" => { 'amount' => HundredCentes.new} )
349
- assert_equal 100, @context['cents.amount']
350
-
351
- @context.merge( "cents" => { 'cents' => { 'amount' => HundredCentes.new} } )
352
- assert_equal 100, @context['cents.cents.amount']
353
- end
354
-
355
- def test_cents_through_drop
356
- @context.merge( "cents" => CentsDrop.new )
357
- assert_equal 100, @context['cents.amount']
358
- end
359
-
360
- def test_nested_cents_through_drop
361
- @context.merge( "vars" => {"cents" => CentsDrop.new} )
362
- assert_equal 100, @context['vars.cents.amount']
363
- end
364
-
365
- def test_drop_methods_with_question_marks
366
- @context.merge( "cents" => CentsDrop.new )
367
- assert @context['cents.non_zero?']
368
- end
369
-
370
- def test_context_from_within_drop
371
- @context.merge( "test" => '123', "vars" => ContextSensitiveDrop.new )
372
- assert_equal '123', @context['vars.test']
373
- end
374
-
375
- def test_nested_context_from_within_drop
376
- @context.merge( "test" => '123', "vars" => {"local" => ContextSensitiveDrop.new } )
377
- assert_equal '123', @context['vars.local.test']
378
- end
379
-
380
- def test_ranges
381
- @context.merge( "test" => '5' )
382
- assert_equal (1..5), @context['(1..5)']
383
- assert_equal (1..5), @context['(1..test)']
384
- assert_equal (5..5), @context['(test..test)']
385
- end
386
-
387
- def test_cents_through_drop_nestedly
388
- @context.merge( "cents" => {"cents" => CentsDrop.new} )
389
- assert_equal 100, @context['cents.cents.amount']
390
-
391
- @context.merge( "cents" => { "cents" => {"cents" => CentsDrop.new}} )
392
- assert_equal 100, @context['cents.cents.cents.amount']
393
- end
394
-
395
- def test_drop_with_variable_called_only_once
396
- @context['counter'] = CounterDrop.new
397
-
398
- assert_equal 1, @context['counter.count']
399
- assert_equal 2, @context['counter.count']
400
- assert_equal 3, @context['counter.count']
401
- end
402
-
403
- def test_drop_with_key_called_only_once
404
- @context['counter'] = CounterDrop.new
405
-
406
- assert_equal 1, @context['counter["count"]']
407
- assert_equal 2, @context['counter["count"]']
408
- assert_equal 3, @context['counter["count"]']
409
- end
410
-
411
- def test_proc_as_variable
412
- @context['dynamic'] = Proc.new { 'Hello' }
413
-
414
- assert_equal 'Hello', @context['dynamic']
415
- end
416
-
417
- def test_lambda_as_variable
418
- @context['dynamic'] = proc { 'Hello' }
419
-
420
- assert_equal 'Hello', @context['dynamic']
421
- end
422
-
423
- def test_nested_lambda_as_variable
424
- @context['dynamic'] = { "lambda" => proc { 'Hello' } }
425
-
426
- assert_equal 'Hello', @context['dynamic.lambda']
427
- end
428
-
429
- def test_array_containing_lambda_as_variable
430
- @context['dynamic'] = [1,2, proc { 'Hello' } ,4,5]
431
-
432
- assert_equal 'Hello', @context['dynamic[2]']
433
- end
434
-
435
- def test_lambda_is_called_once
436
- @context['callcount'] = proc { @global ||= 0; @global += 1; @global.to_s }
437
-
438
- assert_equal '1', @context['callcount']
439
- assert_equal '1', @context['callcount']
440
- assert_equal '1', @context['callcount']
441
-
442
- @global = nil
443
- end
444
-
445
- def test_nested_lambda_is_called_once
446
- @context['callcount'] = { "lambda" => proc { @global ||= 0; @global += 1; @global.to_s } }
447
-
448
- assert_equal '1', @context['callcount.lambda']
449
- assert_equal '1', @context['callcount.lambda']
450
- assert_equal '1', @context['callcount.lambda']
451
-
452
- @global = nil
453
- end
454
-
455
- def test_lambda_in_array_is_called_once
456
- @context['callcount'] = [1,2, proc { @global ||= 0; @global += 1; @global.to_s } ,4,5]
457
-
458
- assert_equal '1', @context['callcount[2]']
459
- assert_equal '1', @context['callcount[2]']
460
- assert_equal '1', @context['callcount[2]']
461
-
462
- @global = nil
463
- end
464
-
465
- def test_access_to_context_from_proc
466
- @context.registers[:magic] = 345392
467
-
468
- @context['magic'] = proc { @context.registers[:magic] }
469
-
470
- assert_equal 345392, @context['magic']
471
- end
472
-
473
- def test_to_liquor_and_context_at_first_level
474
- @context['category'] = Category.new("foobar")
475
- assert_kind_of CategoryDrop, @context['category']
476
- assert_equal @context, @context['category'].context
477
- end
478
-
479
- end