sass 3.2.7 → 3.3.0.rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. data/MIT-LICENSE +2 -2
  2. data/README.md +14 -2
  3. data/Rakefile +25 -1
  4. data/VERSION +1 -1
  5. data/VERSION_DATE +1 -1
  6. data/VERSION_NAME +1 -1
  7. data/lib/sass/cache_stores/base.rb +4 -2
  8. data/lib/sass/cache_stores/chain.rb +2 -1
  9. data/lib/sass/cache_stores/filesystem.rb +2 -6
  10. data/lib/sass/cache_stores/memory.rb +1 -1
  11. data/lib/sass/cache_stores/null.rb +2 -2
  12. data/lib/sass/callbacks.rb +1 -0
  13. data/lib/sass/css.rb +10 -10
  14. data/lib/sass/engine.rb +403 -150
  15. data/lib/sass/environment.rb +136 -57
  16. data/lib/sass/error.rb +7 -7
  17. data/lib/sass/exec.rb +123 -39
  18. data/lib/sass/features.rb +41 -0
  19. data/lib/sass/importers/base.rb +33 -2
  20. data/lib/sass/importers/deprecated_path.rb +45 -0
  21. data/lib/sass/importers/filesystem.rb +25 -14
  22. data/lib/sass/importers.rb +1 -0
  23. data/lib/sass/logger/base.rb +3 -3
  24. data/lib/sass/logger/log_level.rb +4 -6
  25. data/lib/sass/media.rb +19 -19
  26. data/lib/sass/plugin/compiler.rb +141 -101
  27. data/lib/sass/plugin/configuration.rb +18 -22
  28. data/lib/sass/plugin/merb.rb +1 -1
  29. data/lib/sass/plugin/staleness_checker.rb +24 -8
  30. data/lib/sass/plugin.rb +4 -2
  31. data/lib/sass/repl.rb +3 -3
  32. data/lib/sass/script/css_lexer.rb +9 -4
  33. data/lib/sass/script/css_parser.rb +6 -2
  34. data/lib/sass/script/functions.rb +1343 -590
  35. data/lib/sass/script/lexer.rb +84 -52
  36. data/lib/sass/script/parser.rb +217 -97
  37. data/lib/sass/script/tree/funcall.rb +290 -0
  38. data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +34 -13
  39. data/lib/sass/script/tree/list_literal.rb +80 -0
  40. data/lib/sass/script/tree/literal.rb +47 -0
  41. data/lib/sass/script/tree/map_literal.rb +64 -0
  42. data/lib/sass/script/{node.rb → tree/node.rb} +22 -12
  43. data/lib/sass/script/{operation.rb → tree/operation.rb} +17 -25
  44. data/lib/sass/script/tree/selector.rb +30 -0
  45. data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +5 -4
  46. data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +14 -9
  47. data/lib/sass/script/tree/variable.rb +57 -0
  48. data/lib/sass/script/tree.rb +16 -0
  49. data/lib/sass/script/{arg_list.rb → value/arg_list.rb} +4 -24
  50. data/lib/sass/script/value/base.rb +248 -0
  51. data/lib/sass/script/value/bool.rb +36 -0
  52. data/lib/sass/script/{color.rb → value/color.rb} +239 -195
  53. data/lib/sass/script/value/helpers.rb +155 -0
  54. data/lib/sass/script/value/list.rb +119 -0
  55. data/lib/sass/script/value/map.rb +70 -0
  56. data/lib/sass/script/value/null.rb +45 -0
  57. data/lib/sass/script/{number.rb → value/number.rb} +91 -65
  58. data/lib/sass/script/{string.rb → value/string.rb} +9 -11
  59. data/lib/sass/script/value.rb +11 -0
  60. data/lib/sass/script.rb +35 -8
  61. data/lib/sass/scss/css_parser.rb +2 -1
  62. data/lib/sass/scss/parser.rb +338 -170
  63. data/lib/sass/scss/rx.rb +5 -6
  64. data/lib/sass/scss/script_lexer.rb +1 -0
  65. data/lib/sass/scss/script_parser.rb +1 -0
  66. data/lib/sass/scss/static_parser.rb +23 -6
  67. data/lib/sass/selector/abstract_sequence.rb +2 -2
  68. data/lib/sass/selector/comma_sequence.rb +21 -16
  69. data/lib/sass/selector/sequence.rb +60 -34
  70. data/lib/sass/selector/simple.rb +11 -12
  71. data/lib/sass/selector/simple_sequence.rb +55 -33
  72. data/lib/sass/selector.rb +52 -48
  73. data/lib/sass/source/map.rb +211 -0
  74. data/lib/sass/source/position.rb +39 -0
  75. data/lib/sass/source/range.rb +41 -0
  76. data/lib/sass/stack.rb +120 -0
  77. data/lib/sass/supports.rb +12 -13
  78. data/lib/sass/tree/at_root_node.rb +82 -0
  79. data/lib/sass/tree/comment_node.rb +3 -3
  80. data/lib/sass/tree/css_import_node.rb +11 -11
  81. data/lib/sass/tree/debug_node.rb +2 -2
  82. data/lib/sass/tree/directive_node.rb +13 -2
  83. data/lib/sass/tree/each_node.rb +8 -8
  84. data/lib/sass/tree/extend_node.rb +13 -6
  85. data/lib/sass/tree/for_node.rb +4 -4
  86. data/lib/sass/tree/function_node.rb +5 -4
  87. data/lib/sass/tree/if_node.rb +1 -1
  88. data/lib/sass/tree/import_node.rb +4 -5
  89. data/lib/sass/tree/media_node.rb +4 -14
  90. data/lib/sass/tree/mixin_def_node.rb +4 -4
  91. data/lib/sass/tree/mixin_node.rb +21 -8
  92. data/lib/sass/tree/node.rb +29 -12
  93. data/lib/sass/tree/prop_node.rb +38 -18
  94. data/lib/sass/tree/return_node.rb +3 -2
  95. data/lib/sass/tree/root_node.rb +19 -3
  96. data/lib/sass/tree/rule_node.rb +25 -17
  97. data/lib/sass/tree/supports_node.rb +0 -13
  98. data/lib/sass/tree/trace_node.rb +2 -1
  99. data/lib/sass/tree/variable_node.rb +9 -3
  100. data/lib/sass/tree/visitors/base.rb +6 -6
  101. data/lib/sass/tree/visitors/check_nesting.rb +12 -9
  102. data/lib/sass/tree/visitors/convert.rb +63 -38
  103. data/lib/sass/tree/visitors/cssize.rb +63 -23
  104. data/lib/sass/tree/visitors/deep_copy.rb +6 -5
  105. data/lib/sass/tree/visitors/extend.rb +7 -7
  106. data/lib/sass/tree/visitors/perform.rb +256 -151
  107. data/lib/sass/tree/visitors/set_options.rb +6 -6
  108. data/lib/sass/tree/visitors/to_css.rb +231 -81
  109. data/lib/sass/tree/warn_node.rb +2 -2
  110. data/lib/sass/tree/while_node.rb +2 -2
  111. data/lib/sass/util/multibyte_string_scanner.rb +2 -0
  112. data/lib/sass/util/normalized_map.rb +65 -0
  113. data/lib/sass/util/ordered_hash.rb +188 -0
  114. data/lib/sass/util/subset_map.rb +3 -2
  115. data/lib/sass/util/test.rb +9 -0
  116. data/lib/sass/util.rb +220 -34
  117. data/lib/sass/version.rb +9 -9
  118. data/lib/sass.rb +14 -7
  119. data/test/sass/compiler_test.rb +213 -0
  120. data/test/sass/conversion_test.rb +235 -9
  121. data/test/sass/engine_test.rb +230 -60
  122. data/test/sass/exec_test.rb +86 -0
  123. data/test/sass/extend_test.rb +215 -147
  124. data/test/sass/functions_test.rb +584 -99
  125. data/test/sass/importer_test.rb +165 -17
  126. data/test/sass/plugin_test.rb +19 -13
  127. data/test/sass/script_conversion_test.rb +40 -0
  128. data/test/sass/script_test.rb +231 -21
  129. data/test/sass/scss/css_test.rb +14 -5
  130. data/test/sass/scss/scss_test.rb +1266 -66
  131. data/test/sass/source_map_test.rb +879 -0
  132. data/test/sass/templates/bork5.sass +3 -0
  133. data/test/sass/util/normalized_map_test.rb +30 -0
  134. data/test/sass/util_test.rb +90 -0
  135. data/test/sass/value_helpers_test.rb +181 -0
  136. data/test/test_helper.rb +7 -2
  137. metadata +316 -291
  138. data/lib/sass/script/bool.rb +0 -18
  139. data/lib/sass/script/funcall.rb +0 -231
  140. data/lib/sass/script/list.rb +0 -84
  141. data/lib/sass/script/literal.rb +0 -239
  142. data/lib/sass/script/null.rb +0 -34
  143. data/lib/sass/script/variable.rb +0 -58
  144. data/test/Gemfile +0 -3
  145. data/vendor/listen/CHANGELOG.md +0 -221
  146. data/vendor/listen/CONTRIBUTING.md +0 -38
  147. data/vendor/listen/Gemfile +0 -30
  148. data/vendor/listen/Guardfile +0 -8
  149. data/vendor/listen/LICENSE +0 -20
  150. data/vendor/listen/README.md +0 -315
  151. data/vendor/listen/Rakefile +0 -47
  152. data/vendor/listen/Vagrantfile +0 -96
  153. data/vendor/listen/lib/listen/adapter.rb +0 -214
  154. data/vendor/listen/lib/listen/adapters/bsd.rb +0 -112
  155. data/vendor/listen/lib/listen/adapters/darwin.rb +0 -85
  156. data/vendor/listen/lib/listen/adapters/linux.rb +0 -113
  157. data/vendor/listen/lib/listen/adapters/polling.rb +0 -67
  158. data/vendor/listen/lib/listen/adapters/windows.rb +0 -87
  159. data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
  160. data/vendor/listen/lib/listen/directory_record.rb +0 -371
  161. data/vendor/listen/lib/listen/listener.rb +0 -225
  162. data/vendor/listen/lib/listen/multi_listener.rb +0 -143
  163. data/vendor/listen/lib/listen/turnstile.rb +0 -28
  164. data/vendor/listen/lib/listen/version.rb +0 -3
  165. data/vendor/listen/lib/listen.rb +0 -40
  166. data/vendor/listen/listen.gemspec +0 -22
  167. data/vendor/listen/spec/listen/adapter_spec.rb +0 -183
  168. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +0 -36
  169. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +0 -37
  170. data/vendor/listen/spec/listen/adapters/linux_spec.rb +0 -47
  171. data/vendor/listen/spec/listen/adapters/polling_spec.rb +0 -68
  172. data/vendor/listen/spec/listen/adapters/windows_spec.rb +0 -30
  173. data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
  174. data/vendor/listen/spec/listen/directory_record_spec.rb +0 -1225
  175. data/vendor/listen/spec/listen/listener_spec.rb +0 -169
  176. data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
  177. data/vendor/listen/spec/listen/turnstile_spec.rb +0 -56
  178. data/vendor/listen/spec/listen_spec.rb +0 -73
  179. data/vendor/listen/spec/spec_helper.rb +0 -21
  180. data/vendor/listen/spec/support/adapter_helper.rb +0 -629
  181. data/vendor/listen/spec/support/directory_record_helper.rb +0 -55
  182. data/vendor/listen/spec/support/fixtures_helper.rb +0 -29
  183. data/vendor/listen/spec/support/listeners_helper.rb +0 -156
  184. data/vendor/listen/spec/support/platform_helper.rb +0 -15
@@ -1,37 +1,43 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'test/unit'
3
3
  require File.dirname(__FILE__) + '/../test_helper'
4
+ require File.dirname(__FILE__) + '/test_helper'
4
5
  require 'sass/script'
6
+ require 'mock_importer'
5
7
 
6
8
  module Sass::Script::Functions
7
9
  def no_kw_args
8
- Sass::Script::String.new("no-kw-args")
10
+ Sass::Script::Value::String.new("no-kw-args")
9
11
  end
10
12
 
11
13
  def only_var_args(*args)
12
- Sass::Script::String.new("only-var-args("+args.map{|a| a.plus(Sass::Script::Number.new(1)).to_s }.join(", ")+")")
14
+ Sass::Script::Value::String.new("only-var-args("+args.map{|a| a.plus(Sass::Script::Value::Number.new(1)).to_s }.join(", ")+")")
13
15
  end
14
16
  declare :only_var_args, [], :var_args => true
15
17
 
16
18
  def only_kw_args(kwargs)
17
- Sass::Script::String.new("only-kw-args(" + kwargs.keys.map {|a| a.to_s}.sort.join(", ") + ")")
19
+ Sass::Script::Value::String.new("only-kw-args(" + kwargs.keys.map {|a| a.to_s}.sort.join(", ") + ")")
18
20
  end
19
21
  declare :only_kw_args, [], :var_kwargs => true
20
22
  end
21
23
 
22
24
  module Sass::Script::Functions::UserFunctions
23
- def call_options_on_new_literal
24
- str = Sass::Script::String.new("foo")
25
+ def call_options_on_new_value
26
+ str = Sass::Script::Value::String.new("foo")
25
27
  str.options[:foo]
26
28
  str
27
29
  end
28
30
 
29
31
  def user_defined
30
- Sass::Script::String.new("I'm a user-defined string!")
32
+ Sass::Script::Value::String.new("I'm a user-defined string!")
31
33
  end
32
34
 
33
35
  def _preceding_underscore
34
- Sass::Script::String.new("I'm another user-defined string!")
36
+ Sass::Script::Value::String.new("I'm another user-defined string!")
37
+ end
38
+
39
+ def fetch_the_variable
40
+ environment.var('variable')
35
41
  end
36
42
  end
37
43
 
@@ -84,9 +90,9 @@ class SassFunctionTest < Test::Unit::TestCase
84
90
  end
85
91
 
86
92
  def test_hsl_checks_types
87
- assert_error_message("\"foo\" is not a number for `hsl'", "hsl(\"foo\", 10, 12)");
88
- assert_error_message("\"foo\" is not a number for `hsl'", "hsl(10, \"foo\", 12)");
89
- assert_error_message("\"foo\" is not a number for `hsl'", "hsl(10, 10, \"foo\")");
93
+ assert_error_message("$hue: \"foo\" is not a number for `hsl'", "hsl(\"foo\", 10, 12)");
94
+ assert_error_message("$saturation: \"foo\" is not a number for `hsl'", "hsl(10, \"foo\", 12)");
95
+ assert_error_message("$lightness: \"foo\" is not a number for `hsl'", "hsl(10, 10, \"foo\")");
90
96
  end
91
97
 
92
98
  def test_hsla
@@ -104,10 +110,10 @@ class SassFunctionTest < Test::Unit::TestCase
104
110
  end
105
111
 
106
112
  def test_hsla_checks_types
107
- assert_error_message("\"foo\" is not a number for `hsla'", "hsla(\"foo\", 10, 12, 0.3)");
108
- assert_error_message("\"foo\" is not a number for `hsla'", "hsla(10, \"foo\", 12, 0)");
109
- assert_error_message("\"foo\" is not a number for `hsla'", "hsla(10, 10, \"foo\", 1)");
110
- assert_error_message("\"foo\" is not a number for `hsla'", "hsla(10, 10, 10, \"foo\")");
113
+ assert_error_message("$hue: \"foo\" is not a number for `hsla'", "hsla(\"foo\", 10, 12, 0.3)");
114
+ assert_error_message("$saturation: \"foo\" is not a number for `hsla'", "hsla(10, \"foo\", 12, 0)");
115
+ assert_error_message("$lightness: \"foo\" is not a number for `hsla'", "hsla(10, 10, \"foo\", 1)");
116
+ assert_error_message("$alpha: \"foo\" is not a number for `hsla'", "hsla(10, 10, 10, \"foo\")");
111
117
  end
112
118
 
113
119
  def test_percentage
@@ -118,9 +124,9 @@ class SassFunctionTest < Test::Unit::TestCase
118
124
  end
119
125
 
120
126
  def test_percentage_checks_types
121
- assert_error_message("25px is not a unitless number for `percentage'", "percentage(25px)")
122
- assert_error_message("#cccccc is not a unitless number for `percentage'", "percentage(#ccc)")
123
- assert_error_message("\"string\" is not a unitless number for `percentage'", %Q{percentage("string")})
127
+ assert_error_message("$value: 25px is not a unitless number for `percentage'", "percentage(25px)")
128
+ assert_error_message("$value: #cccccc is not a unitless number for `percentage'", "percentage(#ccc)")
129
+ assert_error_message("$value: \"string\" is not a unitless number for `percentage'", %Q{percentage("string")})
124
130
  end
125
131
 
126
132
  def test_round
@@ -129,7 +135,7 @@ class SassFunctionTest < Test::Unit::TestCase
129
135
  assert_equal("5px", evaluate("round(5.49px)"))
130
136
  assert_equal("5px", evaluate("round($value: 5.49px)"))
131
137
 
132
- assert_error_message("#cccccc is not a number for `round'", "round(#ccc)")
138
+ assert_error_message("$value: #cccccc is not a number for `round'", "round(#ccc)")
133
139
  end
134
140
 
135
141
  def test_floor
@@ -137,7 +143,7 @@ class SassFunctionTest < Test::Unit::TestCase
137
143
  assert_equal("4px", evaluate("floor(4.8px)"))
138
144
  assert_equal("4px", evaluate("floor($value: 4.8px)"))
139
145
 
140
- assert_error_message("\"foo\" is not a number for `floor'", "floor(\"foo\")")
146
+ assert_error_message("$value: \"foo\" is not a number for `floor'", "floor(\"foo\")")
141
147
  end
142
148
 
143
149
  def test_ceil
@@ -145,7 +151,7 @@ class SassFunctionTest < Test::Unit::TestCase
145
151
  assert_equal("5px", evaluate("ceil(4.8px)"))
146
152
  assert_equal("5px", evaluate("ceil($value: 4.8px)"))
147
153
 
148
- assert_error_message("\"a\" is not a number for `ceil'", "ceil(\"a\")")
154
+ assert_error_message("$value: \"a\" is not a number for `ceil'", "ceil(\"a\")")
149
155
  end
150
156
 
151
157
  def test_abs
@@ -155,11 +161,11 @@ class SassFunctionTest < Test::Unit::TestCase
155
161
  assert_equal("5px", evaluate("abs(5px)"))
156
162
  assert_equal("5px", evaluate("abs($value: 5px)"))
157
163
 
158
- assert_error_message("#aaaaaa is not a number for `abs'", "abs(#aaa)")
164
+ assert_error_message("$value: #aaaaaa is not a number for `abs'", "abs(#aaa)")
159
165
  end
160
166
 
161
167
  def test_min
162
- #assert_equal("1", evaluate("min(1, 2, 3)"))
168
+ assert_equal("1", evaluate("min(1, 2, 3)"))
163
169
  assert_equal("1", evaluate("min(3px, 2px, 1)"))
164
170
  assert_equal("4em", evaluate("min(4em)"))
165
171
  assert_equal("10cm", evaluate("min(10cm, 6in)"))
@@ -193,31 +199,31 @@ class SassFunctionTest < Test::Unit::TestCase
193
199
  end
194
200
 
195
201
  def test_rgb_tests_bounds
196
- assert_error_message("Color value 256 must be between 0 and 255 for `rgb'",
202
+ assert_error_message("$red: Color value 256 must be between 0 and 255 for `rgb'",
197
203
  "rgb(256, 1, 1)")
198
- assert_error_message("Color value 256 must be between 0 and 255 for `rgb'",
204
+ assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgb'",
199
205
  "rgb(1, 256, 1)")
200
- assert_error_message("Color value 256 must be between 0 and 255 for `rgb'",
206
+ assert_error_message("$blue: Color value 256 must be between 0 and 255 for `rgb'",
201
207
  "rgb(1, 1, 256)")
202
- assert_error_message("Color value 256 must be between 0 and 255 for `rgb'",
208
+ assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgb'",
203
209
  "rgb(1, 256, 257)")
204
- assert_error_message("Color value -1 must be between 0 and 255 for `rgb'",
210
+ assert_error_message("$red: Color value -1 must be between 0 and 255 for `rgb'",
205
211
  "rgb(-1, 1, 1)")
206
212
  end
207
213
 
208
214
  def test_rgb_test_percent_bounds
209
- assert_error_message("Color value 100.1% must be between 0% and 100% for `rgb'",
215
+ assert_error_message("$red: Color value 100.1% must be between 0% and 100% for `rgb'",
210
216
  "rgb(100.1%, 0, 0)")
211
- assert_error_message("Color value -0.1% must be between 0% and 100% for `rgb'",
217
+ assert_error_message("$green: Color value -0.1% must be between 0% and 100% for `rgb'",
212
218
  "rgb(0, -0.1%, 0)")
213
- assert_error_message("Color value 101% must be between 0% and 100% for `rgb'",
219
+ assert_error_message("$blue: Color value 101% must be between 0% and 100% for `rgb'",
214
220
  "rgb(0, 0, 101%)")
215
221
  end
216
222
 
217
223
  def test_rgb_tests_types
218
- assert_error_message("\"foo\" is not a number for `rgb'", "rgb(\"foo\", 10, 12)");
219
- assert_error_message("\"foo\" is not a number for `rgb'", "rgb(10, \"foo\", 12)");
220
- assert_error_message("\"foo\" is not a number for `rgb'", "rgb(10, 10, \"foo\")");
224
+ assert_error_message("$red: \"foo\" is not a number for `rgb'", "rgb(\"foo\", 10, 12)");
225
+ assert_error_message("$green: \"foo\" is not a number for `rgb'", "rgb(10, \"foo\", 12)");
226
+ assert_error_message("$blue: \"foo\" is not a number for `rgb'", "rgb(10, 10, \"foo\")");
221
227
  end
222
228
 
223
229
  def test_rgba
@@ -228,15 +234,15 @@ class SassFunctionTest < Test::Unit::TestCase
228
234
  end
229
235
 
230
236
  def test_rgba_tests_bounds
231
- assert_error_message("Color value 256 must be between 0 and 255 for `rgba'",
237
+ assert_error_message("$red: Color value 256 must be between 0 and 255 for `rgba'",
232
238
  "rgba(256, 1, 1, 0.3)")
233
- assert_error_message("Color value 256 must be between 0 and 255 for `rgba'",
239
+ assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgba'",
234
240
  "rgba(1, 256, 1, 0.3)")
235
- assert_error_message("Color value 256 must be between 0 and 255 for `rgba'",
241
+ assert_error_message("$blue: Color value 256 must be between 0 and 255 for `rgba'",
236
242
  "rgba(1, 1, 256, 0.3)")
237
- assert_error_message("Color value 256 must be between 0 and 255 for `rgba'",
243
+ assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgba'",
238
244
  "rgba(1, 256, 257, 0.3)")
239
- assert_error_message("Color value -1 must be between 0 and 255 for `rgba'",
245
+ assert_error_message("$red: Color value -1 must be between 0 and 255 for `rgba'",
240
246
  "rgba(-1, 1, 1, 0.3)")
241
247
  assert_error_message("Alpha channel -0.2 must be between 0 and 1 for `rgba'",
242
248
  "rgba(1, 1, 1, -0.2)")
@@ -245,10 +251,10 @@ class SassFunctionTest < Test::Unit::TestCase
245
251
  end
246
252
 
247
253
  def test_rgba_tests_types
248
- assert_error_message("\"foo\" is not a number for `rgba'", "rgba(\"foo\", 10, 12, 0.2)");
249
- assert_error_message("\"foo\" is not a number for `rgba'", "rgba(10, \"foo\", 12, 0.1)");
250
- assert_error_message("\"foo\" is not a number for `rgba'", "rgba(10, 10, \"foo\", 0)");
251
- assert_error_message("\"foo\" is not a number for `rgba'", "rgba(10, 10, 10, \"foo\")");
254
+ assert_error_message("$red: \"foo\" is not a number for `rgba'", "rgba(\"foo\", 10, 12, 0.2)");
255
+ assert_error_message("$green: \"foo\" is not a number for `rgba'", "rgba(10, \"foo\", 12, 0.1)");
256
+ assert_error_message("$blue: \"foo\" is not a number for `rgba'", "rgba(10, 10, \"foo\", 0)");
257
+ assert_error_message("$alpha: \"foo\" is not a number for `rgba'", "rgba(10, 10, 10, \"foo\")");
252
258
  end
253
259
 
254
260
  def test_rgba_with_color
@@ -258,8 +264,8 @@ class SassFunctionTest < Test::Unit::TestCase
258
264
  end
259
265
 
260
266
  def test_rgba_with_color_tests_types
261
- assert_error_message("\"foo\" is not a color for `rgba'", "rgba(\"foo\", 0.2)");
262
- assert_error_message("\"foo\" is not a number for `rgba'", "rgba(blue, \"foo\")");
267
+ assert_error_message("$color: \"foo\" is not a color for `rgba'", "rgba(\"foo\", 0.2)");
268
+ assert_error_message("$alpha: \"foo\" is not a number for `rgba'", "rgba(blue, \"foo\")");
263
269
  end
264
270
 
265
271
  def test_rgba_tests_num_args
@@ -275,7 +281,7 @@ class SassFunctionTest < Test::Unit::TestCase
275
281
  end
276
282
 
277
283
  def test_red_exception
278
- assert_error_message("12 is not a color for `red'", "red(12)")
284
+ assert_error_message("$color: 12 is not a color for `red'", "red(12)")
279
285
  end
280
286
 
281
287
  def test_green
@@ -284,7 +290,7 @@ class SassFunctionTest < Test::Unit::TestCase
284
290
  end
285
291
 
286
292
  def test_green_exception
287
- assert_error_message("12 is not a color for `green'", "green(12)")
293
+ assert_error_message("$color: 12 is not a color for `green'", "green(12)")
288
294
  end
289
295
 
290
296
  def test_blue
@@ -293,7 +299,7 @@ class SassFunctionTest < Test::Unit::TestCase
293
299
  end
294
300
 
295
301
  def test_blue_exception
296
- assert_error_message("12 is not a color for `blue'", "blue(12)")
302
+ assert_error_message("$color: 12 is not a color for `blue'", "blue(12)")
297
303
  end
298
304
 
299
305
  def test_hue
@@ -302,7 +308,7 @@ class SassFunctionTest < Test::Unit::TestCase
302
308
  end
303
309
 
304
310
  def test_hue_exception
305
- assert_error_message("12 is not a color for `hue'", "hue(12)")
311
+ assert_error_message("$color: 12 is not a color for `hue'", "hue(12)")
306
312
  end
307
313
 
308
314
  def test_saturation
@@ -312,7 +318,7 @@ class SassFunctionTest < Test::Unit::TestCase
312
318
  end
313
319
 
314
320
  def test_saturation_exception
315
- assert_error_message("12 is not a color for `saturation'", "saturation(12)")
321
+ assert_error_message("$color: 12 is not a color for `saturation'", "saturation(12)")
316
322
  end
317
323
 
318
324
  def test_lightness
@@ -322,7 +328,7 @@ class SassFunctionTest < Test::Unit::TestCase
322
328
  end
323
329
 
324
330
  def test_lightness_exception
325
- assert_error_message("12 is not a color for `lightness'", "lightness(12)")
331
+ assert_error_message("$color: 12 is not a color for `lightness'", "lightness(12)")
326
332
  end
327
333
 
328
334
  def test_alpha
@@ -333,7 +339,7 @@ class SassFunctionTest < Test::Unit::TestCase
333
339
  end
334
340
 
335
341
  def test_alpha_exception
336
- assert_error_message("12 is not a color for `alpha'", "alpha(12)")
342
+ assert_error_message("$color: 12 is not a color for `alpha'", "alpha(12)")
337
343
  end
338
344
 
339
345
  def test_opacity
@@ -345,7 +351,7 @@ class SassFunctionTest < Test::Unit::TestCase
345
351
  end
346
352
 
347
353
  def test_opacity_exception
348
- assert_error_message("\"foo\" is not a color for `opacity'", "opacity(foo)")
354
+ assert_error_message("$color: \"foo\" is not a color for `opacity'", "opacity(foo)")
349
355
  end
350
356
 
351
357
  def test_opacify
@@ -367,16 +373,16 @@ class SassFunctionTest < Test::Unit::TestCase
367
373
  end
368
374
 
369
375
  def test_opacify_tests_types
370
- assert_error_message("\"foo\" is not a color for `opacify'", "opacify(\"foo\", 10%)")
371
- assert_error_message("\"foo\" is not a number for `opacify'", "opacify(#fff, \"foo\")")
376
+ assert_error_message("$color: \"foo\" is not a color for `opacify'", "opacify(\"foo\", 10%)")
377
+ assert_error_message("$amount: \"foo\" is not a number for `opacify'", "opacify(#fff, \"foo\")")
372
378
  end
373
379
 
374
380
  def test_transparentize
375
381
  assert_equal("rgba(0, 0, 0, 0.3)", evaluate("transparentize(rgba(0, 0, 0, 0.5), 0.2)"))
376
382
  assert_equal("rgba(0, 0, 0, 0.1)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 0.1)"))
377
383
  assert_equal("rgba(0, 0, 0, 0.2)", evaluate("fade-out(rgba(0, 0, 0, 0.5), 0.3px)"))
378
- assert_equal("rgba(0, 0, 0, 0)", evaluate("fade_out(rgba(0, 0, 0, 0.2), 0.2)"))
379
- assert_equal("rgba(0, 0, 0, 0)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 1)"))
384
+ assert_equal("transparent", evaluate("fade_out(rgba(0, 0, 0, 0.2), 0.2)"))
385
+ assert_equal("transparent", evaluate("transparentize(rgba(0, 0, 0, 0.2), 1)"))
380
386
  assert_equal("rgba(0, 0, 0, 0.2)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 0)"))
381
387
  assert_equal("rgba(0, 0, 0, 0.2)", evaluate("transparentize($color: rgba(0, 0, 0, 0.2), $amount: 0)"))
382
388
  assert_equal("rgba(0, 0, 0, 0.2)", evaluate("fade-out($color: rgba(0, 0, 0, 0.2), $amount: 0)"))
@@ -390,8 +396,8 @@ class SassFunctionTest < Test::Unit::TestCase
390
396
  end
391
397
 
392
398
  def test_transparentize_tests_types
393
- assert_error_message("\"foo\" is not a color for `transparentize'", "transparentize(\"foo\", 10%)")
394
- assert_error_message("\"foo\" is not a number for `transparentize'", "transparentize(#fff, \"foo\")")
399
+ assert_error_message("$color: \"foo\" is not a color for `transparentize'", "transparentize(\"foo\", 10%)")
400
+ assert_error_message("$amount: \"foo\" is not a number for `transparentize'", "transparentize(#fff, \"foo\")")
395
401
  end
396
402
 
397
403
  def test_lighten
@@ -412,8 +418,8 @@ class SassFunctionTest < Test::Unit::TestCase
412
418
  end
413
419
 
414
420
  def test_lighten_tests_types
415
- assert_error_message("\"foo\" is not a color for `lighten'", "lighten(\"foo\", 10%)")
416
- assert_error_message("\"foo\" is not a number for `lighten'", "lighten(#fff, \"foo\")")
421
+ assert_error_message("$color: \"foo\" is not a color for `lighten'", "lighten(\"foo\", 10%)")
422
+ assert_error_message("$amount: \"foo\" is not a number for `lighten'", "lighten(#fff, \"foo\")")
417
423
  end
418
424
 
419
425
  def test_darken
@@ -434,8 +440,8 @@ class SassFunctionTest < Test::Unit::TestCase
434
440
  end
435
441
 
436
442
  def test_darken_tests_types
437
- assert_error_message("\"foo\" is not a color for `darken'", "darken(\"foo\", 10%)")
438
- assert_error_message("\"foo\" is not a number for `darken'", "darken(#fff, \"foo\")")
443
+ assert_error_message("$color: \"foo\" is not a color for `darken'", "darken(\"foo\", 10%)")
444
+ assert_error_message("$amount: \"foo\" is not a number for `darken'", "darken(#fff, \"foo\")")
439
445
  end
440
446
 
441
447
  def test_saturate
@@ -458,8 +464,8 @@ class SassFunctionTest < Test::Unit::TestCase
458
464
  end
459
465
 
460
466
  def test_saturate_tests_types
461
- assert_error_message("\"foo\" is not a color for `saturate'", "saturate(\"foo\", 10%)")
462
- assert_error_message("\"foo\" is not a number for `saturate'", "saturate(#fff, \"foo\")")
467
+ assert_error_message("$color: \"foo\" is not a color for `saturate'", "saturate(\"foo\", 10%)")
468
+ assert_error_message("$amount: \"foo\" is not a number for `saturate'", "saturate(#fff, \"foo\")")
463
469
  end
464
470
 
465
471
  def test_desaturate
@@ -481,8 +487,8 @@ class SassFunctionTest < Test::Unit::TestCase
481
487
  end
482
488
 
483
489
  def test_desaturate_tests_types
484
- assert_error_message("\"foo\" is not a color for `desaturate'", "desaturate(\"foo\", 10%)")
485
- assert_error_message("\"foo\" is not a number for `desaturate'", "desaturate(#fff, \"foo\")")
490
+ assert_error_message("$color: \"foo\" is not a color for `desaturate'", "desaturate(\"foo\", 10%)")
491
+ assert_error_message("$amount: \"foo\" is not a number for `desaturate'", "desaturate(#fff, \"foo\")")
486
492
  end
487
493
 
488
494
  def test_adjust_hue
@@ -498,8 +504,8 @@ class SassFunctionTest < Test::Unit::TestCase
498
504
  end
499
505
 
500
506
  def test_adjust_hue_tests_types
501
- assert_error_message("\"foo\" is not a color for `adjust-hue'", "adjust-hue(\"foo\", 10%)")
502
- assert_error_message("\"foo\" is not a number for `adjust-hue'", "adjust-hue(#fff, \"foo\")")
507
+ assert_error_message("$color: \"foo\" is not a color for `adjust-hue'", "adjust-hue(\"foo\", 10%)")
508
+ assert_error_message("$degrees: \"foo\" is not a number for `adjust-hue'", "adjust-hue(#fff, \"foo\")")
503
509
  end
504
510
 
505
511
  def test_adjust_color
@@ -557,7 +563,7 @@ class SassFunctionTest < Test::Unit::TestCase
557
563
  end
558
564
 
559
565
  def test_adjust_color_tests_types
560
- assert_error_message("\"foo\" is not a color for `adjust-color'", "adjust-color(foo, $hue: 10)")
566
+ assert_error_message("$color: \"foo\" is not a color for `adjust-color'", "adjust-color(foo, $hue: 10)")
561
567
  # HSL
562
568
  assert_error_message("$hue: \"foo\" is not a number for `adjust-color'",
563
569
  "adjust-color(blue, $hue: foo)")
@@ -663,7 +669,7 @@ class SassFunctionTest < Test::Unit::TestCase
663
669
  end
664
670
 
665
671
  def test_scale_color_tests_types
666
- assert_error_message("\"foo\" is not a color for `scale-color'", "scale-color(foo, $red: 10%)")
672
+ assert_error_message("$color: \"foo\" is not a color for `scale-color'", "scale-color(foo, $red: 10%)")
667
673
  # HSL
668
674
  assert_error_message("$saturation: \"foo\" is not a number for `scale-color'",
669
675
  "scale-color(blue, $saturation: foo)")
@@ -691,9 +697,9 @@ class SassFunctionTest < Test::Unit::TestCase
691
697
  "scale-color(blue, $alpha: -101%)")
692
698
 
693
699
  # Unit
694
- assert_error_message("$saturation: Amount 80 must be a % (e.g. 80%) for `scale-color'",
700
+ assert_error_message("Expected $saturation to have a unit of % but got 80 for `scale-color'",
695
701
  "scale-color(blue, $saturation: 80)")
696
- assert_error_message("$alpha: Amount 0.5 must be a % (e.g. 0.5%) for `scale-color'",
702
+ assert_error_message("Expected $alpha to have a unit of % but got 0.5 for `scale-color'",
697
703
  "scale-color(blue, $alpha: 0.5)")
698
704
 
699
705
  # Unknown argument
@@ -734,7 +740,7 @@ class SassFunctionTest < Test::Unit::TestCase
734
740
  end
735
741
 
736
742
  def test_change_color_tests_types
737
- assert_error_message("\"foo\" is not a color for `change-color'", "change-color(foo, $red: 10%)")
743
+ assert_error_message("$color: \"foo\" is not a color for `change-color'", "change-color(foo, $red: 10%)")
738
744
  # HSL
739
745
  assert_error_message("$saturation: \"foo\" is not a number for `change-color'",
740
746
  "change-color(blue, $saturation: foo)")
@@ -797,9 +803,9 @@ class SassFunctionTest < Test::Unit::TestCase
797
803
  end
798
804
 
799
805
  def test_mix_tests_types
800
- assert_error_message("\"foo\" is not a color for `mix'", "mix(\"foo\", #f00, 10%)")
801
- assert_error_message("\"foo\" is not a color for `mix'", "mix(#f00, \"foo\", 10%)")
802
- assert_error_message("\"foo\" is not a number for `mix'", "mix(#f00, #baf, \"foo\")")
806
+ assert_error_message("$color-1: \"foo\" is not a color for `mix'", "mix(\"foo\", #f00, 10%)")
807
+ assert_error_message("$color-2: \"foo\" is not a color for `mix'", "mix(#f00, \"foo\", 10%)")
808
+ assert_error_message("$weight: \"foo\" is not a number for `mix'", "mix(#f00, #baf, \"foo\")")
803
809
  end
804
810
 
805
811
  def test_mix_tests_bounds
@@ -811,8 +817,8 @@ class SassFunctionTest < Test::Unit::TestCase
811
817
 
812
818
  def test_grayscale
813
819
  assert_equal("#bbbbbb", evaluate("grayscale(#abc)"))
814
- assert_equal("gray", evaluate("grayscale(#f00)"))
815
- assert_equal("gray", evaluate("grayscale(#00f)"))
820
+ assert_equal("grey", evaluate("grayscale(#f00)"))
821
+ assert_equal("grey", evaluate("grayscale(#00f)"))
816
822
  assert_equal("white", evaluate("grayscale(white)"))
817
823
  assert_equal("black", evaluate("grayscale(black)"))
818
824
  assert_equal("black", evaluate("grayscale($color: black)"))
@@ -822,7 +828,7 @@ class SassFunctionTest < Test::Unit::TestCase
822
828
  end
823
829
 
824
830
  def tets_grayscale_tests_types
825
- assert_error_message("\"foo\" is not a color for `grayscale'", "grayscale(\"foo\")")
831
+ assert_error_message("$color: \"foo\" is not a color for `grayscale'", "grayscale(\"foo\")")
826
832
  end
827
833
 
828
834
  def test_complement
@@ -835,7 +841,7 @@ class SassFunctionTest < Test::Unit::TestCase
835
841
  end
836
842
 
837
843
  def tets_complement_tests_types
838
- assert_error_message("\"foo\" is not a color for `complement'", "complement(\"foo\")")
844
+ assert_error_message("$color: \"foo\" is not a color for `complement'", "complement(\"foo\")")
839
845
  end
840
846
 
841
847
  def test_invert
@@ -845,7 +851,7 @@ class SassFunctionTest < Test::Unit::TestCase
845
851
  end
846
852
 
847
853
  def test_invert_tests_types
848
- assert_error_message("\"foo\" is not a color for `invert'", "invert(\"foo\")")
854
+ assert_error_message("$color: \"foo\" is not a color for `invert'", "invert(\"foo\")")
849
855
  end
850
856
 
851
857
  def test_unquote
@@ -861,7 +867,83 @@ class SassFunctionTest < Test::Unit::TestCase
861
867
  end
862
868
 
863
869
  def test_quote_tests_type
864
- assert_error_message("#ff0000 is not a string for `quote'", "quote(#f00)")
870
+ assert_error_message("$string: #ff0000 is not a string for `quote'", "quote(#f00)")
871
+ end
872
+
873
+ def test_str_length
874
+ assert_equal('3', evaluate('str-length(foo)'))
875
+ end
876
+
877
+ def test_str_length_requires_a_string
878
+ assert_error_message("$string: #ff0000 is not a string for `str-length'", "str-length(#f00)")
879
+ end
880
+
881
+ def test_str_insert
882
+ assert_equal('Xabcd', evaluate('str-insert(abcd, X, 0)'))
883
+ assert_equal('Xabcd', evaluate('str-insert(abcd, X, 1)'))
884
+ assert_equal('abcXd', evaluate('str-insert(abcd, X, 4)'))
885
+ assert_equal('abcdX', evaluate('str-insert(abcd, X, 100)'))
886
+ assert_equal('Xabcd', evaluate('str-insert(abcd, X, -100)'))
887
+ assert_equal('aXbcd', evaluate('str-insert(abcd, X, -4)'))
888
+ assert_equal('abcdX', evaluate('str-insert(abcd, X, -1)'))
889
+ end
890
+
891
+ def test_str_insert_maintains_quote_of_primary_string
892
+ assert_equal('"Xfoo"', evaluate('str-insert("foo", X, 1)'))
893
+ assert_equal('"Xfoo"', evaluate('str-insert("foo", "X", 1)'))
894
+ assert_equal('Xfoo', evaluate('str-insert(foo, "X", 1)'))
895
+ end
896
+
897
+ def test_str_insert_asserts_types
898
+ assert_error_message("$string: #ff0000 is not a string for `str-insert'", "str-insert(#f00, X, 1)")
899
+ assert_error_message("$insert: #ff0000 is not a string for `str-insert'", "str-insert(foo, #f00, 1)")
900
+ assert_error_message("$index: #ff0000 is not a number for `str-insert'", "str-insert(foo, X, #f00)")
901
+ assert_error_message("Expected $index to be unitless but got 10px for `str-insert'", "str-insert(foo, X, 10px)")
902
+ end
903
+
904
+ def test_str_index
905
+ assert_equal('1', evaluate('str-index(abcd, a)'))
906
+ assert_equal('1', evaluate('str-index(abcd, ab)'))
907
+ assert_equal('0', evaluate('str-index(abcd, X)'))
908
+ assert_equal('3', evaluate('str-index(abcd, c)'))
909
+ end
910
+
911
+ def test_str_index_asserts_types
912
+ assert_error_message("$string: #ff0000 is not a string for `str-index'", "str-index(#f00, X)")
913
+ assert_error_message("$substring: #ff0000 is not a string for `str-index'", "str-index(asdf, #f00)")
914
+ end
915
+
916
+ def test_to_lower_case
917
+ assert_equal('abcd', evaluate('to-lower-case(ABCD)'))
918
+ assert_equal('"abcd"', evaluate('to-lower-case("ABCD")'))
919
+ assert_error_message("$string: #ff0000 is not a string for `to-lower-case'", "to-lower-case(#f00)")
920
+ end
921
+
922
+ def test_to_upper_case
923
+ assert_equal('ABCD', evaluate('to-upper-case(abcd)'))
924
+ assert_equal('"ABCD"', evaluate('to-upper-case("abcd")'))
925
+ assert_error_message("$string: #ff0000 is not a string for `to-upper-case'", "to-upper-case(#f00)")
926
+ end
927
+
928
+ def test_str_slice
929
+ assert_equal('bc', evaluate('str-slice(abcd,2,3)')) # in the middle of the string
930
+ assert_equal('a', evaluate('str-slice(abcd,1,1)')) # when start = end
931
+ assert_equal('ab', evaluate('str-slice(abcd,1,2)')) # for completeness
932
+ assert_equal('abcd', evaluate('str-slice(abcd,1,4)')) # at the end points
933
+ assert_equal('abcd', evaluate('str-slice(abcd,0,4)')) # when start is before the start of the string
934
+ assert_equal('abcd', evaluate('str-slice(abcd,1,100)')) # when end is past the end of the string
935
+ assert_equal('', evaluate('str-slice(abcd,2,1)')) # when end is before start
936
+ assert_equal('"bc"', evaluate('str-slice("abcd",2,3)')) # when used with a quoted string
937
+ assert_equal('bcd', evaluate('str-slice(abcd,2)')) # when end is omitted, you get the remainder of the string
938
+ assert_equal('cd', evaluate('str-slice(abcd,-2)')) # when start is negative, it counts from the beginning
939
+ assert_equal('bc', evaluate('str-slice(abcd,2,-2)')) # when end is negative it counts in from the end
940
+ assert_equal('', evaluate('str-slice(abcd,3,-3)')) # when end is negative and comes before the start
941
+ assert_equal('bc', evaluate('str-slice(abcd,-3,-2)')) # when both are negative
942
+ assert_error_message("$string: #ff0000 is not a string for `str-slice'", "str-slice(#f00,2,3)")
943
+ assert_error_message("$start-at: #ff0000 is not a number for `str-slice'", "str-slice(abcd,#f00,3)")
944
+ assert_error_message("$end-at: #ff0000 is not a number for `str-slice'", "str-slice(abcd,2,#f00)")
945
+ assert_error_message("Expected $end-at to be unitless but got 3px for `str-slice'", "str-slice(abcd,2,3px)")
946
+ assert_error_message("Expected $start-at to be unitless but got 2px for `str-slice'", "str-slice(abcd,2px,3)")
865
947
  end
866
948
 
867
949
  def test_user_defined_function
@@ -873,12 +955,17 @@ class SassFunctionTest < Test::Unit::TestCase
873
955
  assert_equal("I'm another user-defined string!", evaluate("-preceding-underscore()"))
874
956
  end
875
957
 
876
- def test_options_on_new_literals_fails
877
- assert_error_message(<<MSG, "call-options-on-new-literal()")
878
- The #options attribute is not set on this Sass::Script::String.
958
+ def test_user_defined_function_using_environment
959
+ environment = env('variable' => Sass::Script::Value::String.new('The variable'))
960
+ assert_equal("The variable", evaluate("fetch_the_variable()", environment))
961
+ end
962
+
963
+ def test_options_on_new_values_fails
964
+ assert_error_message(<<MSG, "call-options-on-new-value()")
965
+ The #options attribute is not set on this Sass::Script::Value::String.
879
966
  This error is probably occurring because #to_s was called
880
- on this literal within a custom Sass function without first
881
- setting the #option attribute.
967
+ on this value within a custom Sass function without first
968
+ setting the #options attribute.
882
969
  MSG
883
970
  end
884
971
 
@@ -890,6 +977,22 @@ MSG
890
977
  assert_equal("color", evaluate("type-of(#fff)"))
891
978
  assert_equal("color", evaluate("type-of($value: #fff)"))
892
979
  assert_equal("null", evaluate("type-of(null)"))
980
+ assert_equal("list", evaluate("type-of(1 2 3)"))
981
+ assert_equal("list", evaluate("type-of((1, 2, 3))"))
982
+ assert_equal("list", evaluate("type-of(())"))
983
+ assert_equal("map", evaluate("type-of((foo: bar))"))
984
+ end
985
+
986
+ def test_feature_exists
987
+ assert_raises ArgumentError do
988
+ Sass.add_feature("my-test-feature")
989
+ end
990
+ Sass.add_feature("-my-test-feature")
991
+ assert_equal("true", evaluate("feature-exists(-my-test-feature)"))
992
+ assert_equal("false", evaluate("feature-exists(whatisthisidontevenknow)"))
993
+ assert_equal("true", evaluate("feature-exists($feature: -my-test-feature)"))
994
+ ensure
995
+ Sass::Features::KNOWN_FEATURES.delete("-my-test-feature")
893
996
  end
894
997
 
895
998
  def test_unit
@@ -900,14 +1003,14 @@ MSG
900
1003
  assert_equal(%Q{"em/rem"}, evaluate("unit(10px * 5em / 30cm / 1rem)"))
901
1004
  assert_equal(%Q{"em*vh/cm*rem"}, evaluate("unit(10vh * 5em / 30cm / 1rem)"))
902
1005
  assert_equal(%Q{"px"}, evaluate("unit($number: 100px)"))
903
- assert_error_message("#ff0000 is not a number for `unit'", "unit(#f00)")
1006
+ assert_error_message("$number: #ff0000 is not a number for `unit'", "unit(#f00)")
904
1007
  end
905
1008
 
906
1009
  def test_unitless
907
1010
  assert_equal(%Q{true}, evaluate("unitless(100)"))
908
1011
  assert_equal(%Q{false}, evaluate("unitless(100px)"))
909
1012
  assert_equal(%Q{false}, evaluate("unitless($number: 100px)"))
910
- assert_error_message("#ff0000 is not a number for `unitless'", "unitless(#f00)")
1013
+ assert_error_message("$number: #ff0000 is not a number for `unitless'", "unitless(#f00)")
911
1014
  end
912
1015
 
913
1016
  def test_comparable
@@ -915,8 +1018,8 @@ MSG
915
1018
  assert_equal(%Q{true}, evaluate("comparable(10cm, 3mm)"))
916
1019
  assert_equal(%Q{false}, evaluate("comparable(100px, 3em)"))
917
1020
  assert_equal(%Q{false}, evaluate("comparable($number-1: 100px, $number-2: 3em)"))
918
- assert_error_message("#ff0000 is not a number for `comparable'", "comparable(#f00, 1px)")
919
- assert_error_message("#ff0000 is not a number for `comparable'", "comparable(1px, #f00)")
1021
+ assert_error_message("$number-1: #ff0000 is not a number for `comparable'", "comparable(#f00, 1px)")
1022
+ assert_error_message("$number-2: #ff0000 is not a number for `comparable'", "comparable(1px, #f00)")
920
1023
  end
921
1024
 
922
1025
  def test_length
@@ -927,20 +1030,47 @@ MSG
927
1030
  assert_equal("1", evaluate("length(#f00)"))
928
1031
  assert_equal("0", evaluate("length(())"))
929
1032
  assert_equal("4", evaluate("length(1 2 () 3)"))
1033
+
1034
+ assert_equal("2", evaluate("length((foo: bar, bar: baz))"))
930
1035
  end
931
1036
 
932
1037
  def test_nth
933
1038
  assert_equal("1", evaluate("nth(1 2 3, 1)"))
934
1039
  assert_equal("2", evaluate("nth(1 2 3, 2)"))
1040
+ assert_equal("3", evaluate("nth(1 2 3, -1)"))
1041
+ assert_equal("1", evaluate("nth(1 2 3, -3)"))
935
1042
  assert_equal("3", evaluate("nth((1, 2, 3), 3)"))
1043
+ assert_equal("3", evaluate("nth($list: (1, 2, 3), $n: 3)"))
936
1044
  assert_equal("foo", evaluate("nth(foo, 1)"))
937
1045
  assert_equal("bar baz", evaluate("nth(foo (bar baz) bang, 2)"))
938
- assert_error_message("List index 0 must be greater than or equal to 1 for `nth'", "nth(foo, 0)")
939
- assert_error_message("List index -10 must be greater than or equal to 1 for `nth'", "nth(foo, -10)")
940
- assert_error_message("List index 1.5 must be an integer for `nth'", "nth(foo, 1.5)")
1046
+ assert_error_message("List index 0 must be a non-zero integer for `nth'", "nth(foo, 0)")
1047
+ assert_error_message("List index is -10 but list is only 1 item long for `nth'", "nth(foo, -10)")
1048
+ assert_error_message("List index 1.5 must be a non-zero integer for `nth'", "nth(foo, 1.5)")
941
1049
  assert_error_message("List index is 5 but list is only 4 items long for `nth'", "nth(1 2 3 4, 5)")
942
1050
  assert_error_message("List index is 2 but list is only 1 item long for `nth'", "nth(foo, 2)")
943
1051
  assert_error_message("List index is 1 but list has no items for `nth'", "nth((), 1)")
1052
+ assert_error_message("$n: \"foo\" is not a number for `nth'", "nth(1 2 3, foo)")
1053
+
1054
+ assert_equal("foo bar", evaluate("nth((foo: bar, bar: baz), 1)"))
1055
+ assert_equal("bar baz", evaluate("nth((foo: bar, bar: baz), 2)"))
1056
+ end
1057
+
1058
+ def test_set_nth
1059
+ assert_equal("a 2 3", evaluate("set-nth(1 2 3, 1, a)"))
1060
+ assert_equal("1 a 3", evaluate("set-nth(1 2 3, 2, a)"))
1061
+ assert_equal("1 2 a", evaluate("set-nth(1 2 3, -1, a)"))
1062
+ assert_equal("a 2 3", evaluate("set-nth(1 2 3, -3, a)"))
1063
+ assert_equal("a 2 3", evaluate("set-nth($list: 1 2 3, $n: -3, $value: a)"))
1064
+ assert_equal("1, 2, a", evaluate("set-nth((1, 2, 3), 3, a)"))
1065
+ assert_equal("a", evaluate("set-nth(foo, 1, a)"))
1066
+ assert_equal("foo, a b, baz", evaluate("set-nth((foo, bar, baz), 2, (a b))"))
1067
+ assert_error_message("List index 0 must be a non-zero integer for `set-nth'", "set-nth(foo, 0, a)")
1068
+ assert_error_message("List index is -10 but list is only 1 item long for `set-nth'", "set-nth(foo, -10, a)")
1069
+ assert_error_message("List index 1.5 must be a non-zero integer for `set-nth'", "set-nth(foo, 1.5, a)")
1070
+ assert_error_message("List index is 5 but list is only 4 items long for `set-nth'", "set-nth(1 2 3 4, 5, a)")
1071
+ assert_error_message("List index is 2 but list is only 1 item long for `set-nth'", "set-nth(foo, 2, a)")
1072
+ assert_error_message("List index is 1 but list has no items for `set-nth'", "set-nth((), 1, a)")
1073
+ assert_error_message("$n: \"foo\" is not a number for `set-nth'", "set-nth(1 2 3, foo, a)")
944
1074
  end
945
1075
 
946
1076
  def test_join
@@ -979,6 +1109,20 @@ MSG
979
1109
  assert_equal("false", evaluate("(1, 2, ()) == join((), (1, 2))"))
980
1110
 
981
1111
  assert_error_message("Separator name must be space, comma, or auto for `join'", "join(1, 2, baboon)")
1112
+ assert_error_message("$separator: 12 is not a string for `join'", "join(1, 2, 12)")
1113
+
1114
+ assert_equal("foo bar, bar baz, baz bip, bip bop",
1115
+ perform("join((foo: bar, bar: baz), (baz: bip, bip: bop))").to_sass)
1116
+ assert_equal("(foo bar) (bar baz) (baz bip) (bip bop)",
1117
+ perform("join((foo: bar, bar: baz), (baz: bip, bip: bop), space)").to_sass)
1118
+ assert_equal("foo bar (baz bip) (bip bop)",
1119
+ perform("join(foo bar, (baz: bip, bip: bop))").to_sass)
1120
+ assert_equal("foo bar, bar baz, bip, bop",
1121
+ perform("join((foo: bar, bar: baz), bip bop)").to_sass)
1122
+ assert_equal("baz bip, bip bop",
1123
+ perform("join((), (baz: bip, bip: bop))").to_sass)
1124
+ assert_equal("foo bar, bar baz",
1125
+ perform("join((foo: bar, bar: baz), ())").to_sass)
982
1126
  end
983
1127
 
984
1128
  def test_append
@@ -1013,12 +1157,20 @@ MSG
1013
1157
  assert_equal("true", evaluate("(1 2) == nth(append((), 1 2), 1)"))
1014
1158
 
1015
1159
  assert_error_message("Separator name must be space, comma, or auto for `append'", "append(1, 2, baboon)")
1160
+ assert_error_message("$separator: 12 is not a string for `append'", "append(1, 2, 12)")
1161
+
1162
+ assert_equal("1 2 (foo: bar)", perform("append(1 2, (foo: bar))").to_sass)
1163
+ assert_equal("foo bar, bar baz, 1", perform("append((foo: bar, bar: baz), 1)").to_sass)
1164
+ assert_equal("foo bar, bar baz, (baz: bip)",
1165
+ perform("append((foo: bar, bar: baz), (baz: bip))").to_sass)
1016
1166
  end
1017
1167
 
1018
1168
  def test_zip
1019
1169
  assert_equal("1 3 5, 2 4 6", evaluate("zip(1 2, 3 4, 5 6)"))
1020
1170
  assert_equal("1 4 7, 2 5 8", evaluate("zip(1 2 3, 4 5 6, 7 8)"))
1021
1171
  assert_equal("1 2 3", evaluate("zip(1, 2, 3)"))
1172
+ assert_equal("(foo bar) 1 3, (bar baz) 2 4",
1173
+ perform("zip((foo: bar, bar: baz), 1 2, 3 4)").to_sass)
1022
1174
  end
1023
1175
 
1024
1176
  def test_index
@@ -1029,12 +1181,61 @@ MSG
1029
1181
  assert_equal("false", evaluate("index(1px solid blue, 1em)"))
1030
1182
  assert_equal("false", evaluate("index(1px solid blue, notfound)"))
1031
1183
  assert_equal("false", evaluate("index(1px, #00f)"))
1184
+
1185
+ assert_equal("1", evaluate("index((foo: bar, bar: baz), (foo bar))"))
1186
+ assert_equal("false", evaluate("index((foo: bar, bar: baz), (foo: bar))"))
1187
+ end
1188
+
1189
+ def test_list_separator
1190
+ assert_equal("space", evaluate("list-separator(1 2 3 4 5)"))
1191
+ assert_equal("comma", evaluate("list-separator((foo, bar, baz, bip))"))
1192
+ assert_equal("comma", evaluate("list-separator((foo, bar, baz bip))"))
1193
+ assert_equal("comma", evaluate("list-separator((foo, bar, (baz, bip)))"))
1194
+ assert_equal("space", evaluate("list-separator(#f00)"))
1195
+ assert_equal("space", evaluate("list-separator(())"))
1196
+ assert_equal("space", evaluate("list-separator(1 2 () 3)"))
1197
+
1198
+ assert_equal("comma", evaluate("list-separator((foo: bar, bar: baz))"))
1032
1199
  end
1033
1200
 
1034
1201
  def test_if
1035
1202
  assert_equal("1px", evaluate("if(true, 1px, 2px)"))
1036
1203
  assert_equal("2px", evaluate("if(false, 1px, 2px)"))
1037
1204
  assert_equal("2px", evaluate("if(null, 1px, 2px)"))
1205
+ assert_equal("1px", evaluate("if(true, 1px, $broken)"))
1206
+ assert_equal("1px", evaluate("if(false, $broken, 1px)"))
1207
+ assert_equal("1px", evaluate("if(false, $if-true: $broken, $if-false: 1px)"))
1208
+ assert_equal("1px", evaluate("if(true, $if-true: 1px, $if-false: $broken)"))
1209
+ assert_equal(<<CSS, render(<<SCSS))
1210
+ .if {
1211
+ result: yay; }
1212
+ CSS
1213
+ .if {
1214
+ $something: yay;
1215
+ result: if(true, $if-true: $something, $if-false: $broken);
1216
+ }
1217
+ SCSS
1218
+ assert_equal(<<CSS, render(<<SCSS))
1219
+ .if {
1220
+ result: 1px; }
1221
+ CSS
1222
+ .if {
1223
+ $splat: 1px, 2px;
1224
+ result: if(true, $splat...);
1225
+ }
1226
+ SCSS
1227
+ end
1228
+
1229
+ def test_counter
1230
+ assert_equal("counter(foo)", evaluate("counter(foo)"))
1231
+ assert_equal('counter(item,".")', evaluate('counter(item, ".")'))
1232
+ assert_equal('counter(item,".")', evaluate('counter(item,".")'))
1233
+ end
1234
+
1235
+ def test_counters
1236
+ assert_equal("counters(foo)", evaluate("counters(foo)"))
1237
+ assert_equal('counters(item,".")', evaluate('counters(item, ".")'))
1238
+ assert_equal('counters(item,".")', evaluate('counters(item,".")'))
1038
1239
  end
1039
1240
 
1040
1241
  def test_keyword_args_rgb
@@ -1096,6 +1297,277 @@ MSG
1096
1297
  assert_equal "only-kw-args(a, b, c)", evaluate("only-kw-args($a: 1, $b: 2, $c: 3)")
1097
1298
  end
1098
1299
 
1300
+ def test_unique_id
1301
+ last_id, current_id = nil, evaluate("unique-id()")
1302
+
1303
+ 50.times do
1304
+ last_id, current_id = current_id, evaluate("unique-id()")
1305
+ assert_match(/u[a-z0-9]{8}/, current_id)
1306
+ assert_not_equal last_id, current_id
1307
+ end
1308
+ end
1309
+
1310
+ def test_map_get
1311
+ assert_equal "1", evaluate("map-get((foo: 1, bar: 2), foo)")
1312
+ assert_equal "2", evaluate("map-get((foo: 1, bar: 2), bar)")
1313
+ assert_equal "null", perform("map-get((foo: 1, bar: 2), baz)").to_sass
1314
+ assert_equal "null", perform("map-get((), foo)").to_sass
1315
+
1316
+ assert_warning(<<WARNING) do
1317
+ DEPRECATION WARNING: Passing lists of pairs to map-get is deprecated and will
1318
+ be removed in future versions of Sass. Use Sass maps instead. For details, see
1319
+ http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1320
+ WARNING
1321
+ assert_equal "1", evaluate("map-get((foo 1) (bar 2), foo)")
1322
+ end
1323
+ end
1324
+
1325
+ def test_map_merge
1326
+ assert_equal("(foo: 1, bar: 2, baz: 3)",
1327
+ perform("map-merge((foo: 1, bar: 2), (baz: 3))").to_sass)
1328
+ assert_equal("(foo: 1, bar: 2)",
1329
+ perform("map-merge((), (foo: 1, bar: 2))").to_sass)
1330
+ assert_equal("(foo: 1, bar: 2)",
1331
+ perform("map-merge((foo: 1, bar: 2), ())").to_sass)
1332
+
1333
+ assert_warning(<<WARNING) do
1334
+ DEPRECATION WARNING: Passing lists of pairs to map-merge is deprecated and will
1335
+ be removed in future versions of Sass. Use Sass maps instead. For details, see
1336
+ http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1337
+ WARNING
1338
+ assert_equal("(foo: 1, bar: 2, baz: 3)",
1339
+ perform("map-merge((foo 1, bar 2), (baz: 3))").to_sass)
1340
+ end
1341
+
1342
+ assert_warning(<<WARNING) do
1343
+ DEPRECATION WARNING: Passing lists of pairs to map-merge is deprecated and will
1344
+ be removed in future versions of Sass. Use Sass maps instead. For details, see
1345
+ http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1346
+ WARNING
1347
+ assert_equal("(baz: 3, foo: 1, bar: 2)",
1348
+ perform("map-merge((baz: 3), (foo 1, bar 2))").to_sass)
1349
+ end
1350
+ end
1351
+
1352
+ def test_map_keys
1353
+ assert_equal("foo, bar",
1354
+ perform("map-keys((foo: 1, bar: 2))").to_sass)
1355
+ assert_equal("()", perform("map-keys(())").to_sass)
1356
+
1357
+ assert_warning(<<WARNING) do
1358
+ DEPRECATION WARNING: Passing lists of pairs to map-keys is deprecated and will
1359
+ be removed in future versions of Sass. Use Sass maps instead. For details, see
1360
+ http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1361
+ WARNING
1362
+ assert_equal("foo, bar",
1363
+ perform("map-keys((foo 1, bar 2))").to_sass)
1364
+ end
1365
+ end
1366
+
1367
+ def test_map_values
1368
+ assert_equal("1, 2", perform("map-values((foo: 1, bar: 2))").to_sass)
1369
+ assert_equal("1, 2, 2",
1370
+ perform("map-values((foo: 1, bar: 2, baz: 2))").to_sass)
1371
+ assert_equal("()", perform("map-values(())").to_sass)
1372
+
1373
+ assert_warning(<<WARNING) do
1374
+ DEPRECATION WARNING: Passing lists of pairs to map-values is deprecated and will
1375
+ be removed in future versions of Sass. Use Sass maps instead. For details, see
1376
+ http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1377
+ WARNING
1378
+ assert_equal("1, 2", perform("map-values((foo 1, bar 2))").to_sass)
1379
+ end
1380
+ end
1381
+
1382
+ def test_map_has_key
1383
+ assert_equal "true", evaluate("map-has-key((foo: 1, bar: 1), foo)")
1384
+ assert_equal "false", evaluate("map-has-key((foo: 1, bar: 1), baz)")
1385
+ assert_equal "false", evaluate("map-has-key((), foo)")
1386
+
1387
+ assert_warning(<<WARNING) do
1388
+ DEPRECATION WARNING: Passing lists of pairs to map-has-key is deprecated and will
1389
+ be removed in future versions of Sass. Use Sass maps instead. For details, see
1390
+ http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1391
+ WARNING
1392
+ assert_equal("true", evaluate("map-has-key((foo 1, bar 1), foo)"))
1393
+ end
1394
+ end
1395
+
1396
+ def test_keywords
1397
+ # The actual functionality is tested in tests where real arglists are passed.
1398
+ assert_error_message("12 is not a variable argument list for `keywords'", "keywords(12)")
1399
+ assert_error_message("(1 2 3) is not a variable argument list for `keywords'", "keywords(1 2 3)")
1400
+ end
1401
+
1402
+ def test_partial_list_of_pairs_doesnt_work_as_a_map
1403
+ assert_raises(Sass::SyntaxError) {evaluate("map-get((foo bar, baz bang, bip), 1)")}
1404
+ assert_raises(Sass::SyntaxError) {evaluate("map-get((foo bar, baz bang, bip bap bop), 1)")}
1405
+ assert_raises(Sass::SyntaxError) {evaluate("map-get((foo bar), 1)")}
1406
+ end
1407
+
1408
+ def test_assert_unit
1409
+ ctx = Sass::Script::Functions::EvaluationContext.new(Sass::Environment.new(nil, {}))
1410
+ ctx.assert_unit Sass::Script::Value::Number.new(10, ["px"], []), "px"
1411
+ ctx.assert_unit Sass::Script::Value::Number.new(10, [], []), nil
1412
+
1413
+ begin
1414
+ ctx.assert_unit Sass::Script::Value::Number.new(10, [], []), "px"
1415
+ fail
1416
+ rescue ArgumentError => e
1417
+ assert_equal "Expected 10 to have a unit of px", e.message
1418
+ end
1419
+
1420
+ begin
1421
+ ctx.assert_unit Sass::Script::Value::Number.new(10, ["px"], []), nil
1422
+ fail
1423
+ rescue ArgumentError => e
1424
+ assert_equal "Expected 10px to be unitless", e.message
1425
+ end
1426
+
1427
+ begin
1428
+ ctx.assert_unit Sass::Script::Value::Number.new(10, [], []), "px", "arg"
1429
+ fail
1430
+ rescue ArgumentError => e
1431
+ assert_equal "Expected $arg to have a unit of px but got 10", e.message
1432
+ end
1433
+
1434
+ begin
1435
+ ctx.assert_unit Sass::Script::Value::Number.new(10, ["px"], []), nil, "arg"
1436
+ fail
1437
+ rescue ArgumentError => e
1438
+ assert_equal "Expected $arg to be unitless but got 10px", e.message
1439
+ end
1440
+ end
1441
+
1442
+ def test_call_with_positional_arguments
1443
+ assert_equal evaluate("lighten(blue, 5%)"), evaluate("call(lighten, blue, 5%)")
1444
+ end
1445
+
1446
+ def test_call_with_keyword_arguments
1447
+ assert_equal(
1448
+ evaluate("lighten($color: blue, $amount: 5%)"),
1449
+ evaluate("call(lighten, $color: blue, $amount: 5%)"))
1450
+ end
1451
+
1452
+ def test_call_with_keyword_and_positional_arguments
1453
+ assert_equal(
1454
+ evaluate("lighten(blue, $amount: 5%)"),
1455
+ evaluate("call(lighten, blue, $amount: 5%)"))
1456
+ end
1457
+
1458
+ def test_call_with_dynamic_name
1459
+ assert_equal(
1460
+ evaluate("lighten($color: blue, $amount: 5%)"),
1461
+ evaluate("call($fn, $color: blue, $amount: 5%)",
1462
+ env("fn" => Sass::Script::String.new("lighten"))))
1463
+ end
1464
+
1465
+ def test_call_unknown_function
1466
+ assert_equal evaluate("unknown(red, blue)"), evaluate("call(unknown, red, blue)")
1467
+ end
1468
+
1469
+ def test_call_with_non_string_argument
1470
+ assert_error_message "$name: 3px is not a string for `call'", "call(3px)"
1471
+ end
1472
+
1473
+ def test_errors_in_called_function
1474
+ assert_error_message "$color: 3px is not a color for `lighten'", "call(lighten, 3px, 5%)"
1475
+ end
1476
+
1477
+ def test_variable_exists
1478
+ assert_equal <<CSS, render(<<SCSS)
1479
+ .test {
1480
+ false: false;
1481
+ true: true;
1482
+ true: true;
1483
+ true: true;
1484
+ true: true; }
1485
+ CSS
1486
+ $global-var: has-value;
1487
+ .test {
1488
+ false: variable-exists(foo);
1489
+ $foo: has-value;
1490
+ true: variable-exists(foo);
1491
+ true: variable-exists($name: foo);
1492
+ true: variable-exists(global-var);
1493
+ true: variable-exists($name: global-var);
1494
+ }
1495
+ SCSS
1496
+ end
1497
+
1498
+ def test_global_variable_exists
1499
+ assert_equal <<CSS, render(<<SCSS)
1500
+ .test {
1501
+ false: false;
1502
+ false: false;
1503
+ true: true;
1504
+ true: true;
1505
+ false: false;
1506
+ true: true;
1507
+ true: true; }
1508
+ CSS
1509
+ $g: something;
1510
+ $h: null;
1511
+ $false: global-variable-exists(foo);
1512
+ $true: global-variable-exists(g);
1513
+ $named: global-variable-exists($name: g);
1514
+ .test {
1515
+ $foo: locally-defined;
1516
+ false: global-variable-exists(foo);
1517
+ false: global-variable-exists(foo2);
1518
+ true: global-variable-exists(g);
1519
+ true: global-variable-exists(h);
1520
+ false: $false;
1521
+ true: $true;
1522
+ true: $named;
1523
+ }
1524
+ SCSS
1525
+ end
1526
+
1527
+ def test_function_exists
1528
+ # built-ins
1529
+ assert_equal "true", evaluate("function-exists(lighten)")
1530
+ # with named argument
1531
+ assert_equal "true", evaluate("function-exists($name: lighten)")
1532
+ # user-defined
1533
+ assert_equal <<CSS, render(<<SCSS)
1534
+ .test {
1535
+ foo-exists: true;
1536
+ bar-exists: false; }
1537
+ CSS
1538
+ @function foo() { @return "foo" }
1539
+ .test {
1540
+ foo-exists: function-exists(foo);
1541
+ bar-exists: function-exists(bar);
1542
+ }
1543
+ SCSS
1544
+ end
1545
+
1546
+ def test_mixin_exists
1547
+ assert_equal "false", evaluate("mixin-exists(foo)")
1548
+ # with named argument
1549
+ assert_equal "false", evaluate("mixin-exists($name: foo)")
1550
+ assert_equal <<CSS, render(<<SCSS)
1551
+ .test {
1552
+ foo-exists: true;
1553
+ bar-exists: false; }
1554
+ CSS
1555
+ @mixin foo() { foo: exists }
1556
+ .test {
1557
+ foo-exists: mixin-exists(foo);
1558
+ bar-exists: mixin-exists(bar);
1559
+ }
1560
+ SCSS
1561
+ end
1562
+
1563
+ def test_existence_functions_check_argument_type
1564
+ assert_error_message("2px is not a string for `function-exists'", "function-exists(2px)")
1565
+ assert_error_message("2px is not a string for `mixin-exists'", "mixin-exists(2px)")
1566
+ assert_error_message("2px is not a string for `global-variable-exists'", "global-variable-exists(2px)")
1567
+ assert_error_message("2px is not a string for `variable-exists'", "variable-exists(2px)")
1568
+ end
1569
+
1570
+
1099
1571
  ## Regression Tests
1100
1572
 
1101
1573
  def test_saturation_bounds
@@ -1103,13 +1575,27 @@ MSG
1103
1575
  end
1104
1576
 
1105
1577
  private
1578
+ def env(hash = {}, parent = nil)
1579
+ env = Sass::Environment.new(parent)
1580
+ hash.each {|k, v| env.set_var(k, v)}
1581
+ env
1582
+ end
1583
+
1584
+ def evaluate(value, environment = env)
1585
+ result = perform(value, environment)
1586
+ assert_kind_of Sass::Script::Value::Base, result
1587
+ return result.to_s
1588
+ end
1106
1589
 
1107
- def evaluate(value)
1108
- Sass::Script::Parser.parse(value, 0, 0).perform(Sass::Environment.new).to_s
1590
+ def perform(value, environment = env)
1591
+ Sass::Script::Parser.parse(value, 0, 0).perform(environment)
1109
1592
  end
1110
1593
 
1111
- def perform(value)
1112
- Sass::Script::Parser.parse(value, 0, 0).perform(Sass::Environment.new)
1594
+ def render(sass, options = {})
1595
+ options[:syntax] ||= :scss
1596
+ munge_filename options
1597
+ options[:importer] ||= MockImporter.new
1598
+ Sass::Engine.new(sass, options).render
1113
1599
  end
1114
1600
 
1115
1601
  def assert_error_message(message, value)
@@ -1118,5 +1604,4 @@ MSG
1118
1604
  rescue Sass::SyntaxError => e
1119
1605
  assert_equal(message, e.message)
1120
1606
  end
1121
-
1122
1607
  end