sass 3.1.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (260) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING +1 -1
  3. data/MIT-LICENSE +2 -2
  4. data/README.md +29 -17
  5. data/Rakefile +43 -9
  6. data/VERSION +1 -1
  7. data/VERSION_DATE +1 -0
  8. data/VERSION_NAME +1 -1
  9. data/bin/sass +6 -1
  10. data/bin/sass-convert +6 -1
  11. data/bin/scss +6 -1
  12. data/ext/mkrf_conf.rb +27 -0
  13. data/lib/sass/cache_stores/base.rb +7 -3
  14. data/lib/sass/cache_stores/chain.rb +3 -2
  15. data/lib/sass/cache_stores/filesystem.rb +5 -7
  16. data/lib/sass/cache_stores/memory.rb +1 -1
  17. data/lib/sass/cache_stores/null.rb +2 -2
  18. data/lib/sass/callbacks.rb +2 -1
  19. data/lib/sass/css.rb +168 -53
  20. data/lib/sass/engine.rb +502 -174
  21. data/lib/sass/environment.rb +151 -111
  22. data/lib/sass/error.rb +7 -7
  23. data/lib/sass/exec.rb +176 -60
  24. data/lib/sass/features.rb +40 -0
  25. data/lib/sass/importers/base.rb +46 -7
  26. data/lib/sass/importers/deprecated_path.rb +51 -0
  27. data/lib/sass/importers/filesystem.rb +113 -30
  28. data/lib/sass/importers.rb +1 -0
  29. data/lib/sass/logger/base.rb +30 -0
  30. data/lib/sass/logger/log_level.rb +45 -0
  31. data/lib/sass/logger.rb +12 -0
  32. data/lib/sass/media.rb +213 -0
  33. data/lib/sass/plugin/compiler.rb +194 -104
  34. data/lib/sass/plugin/configuration.rb +18 -25
  35. data/lib/sass/plugin/merb.rb +1 -1
  36. data/lib/sass/plugin/staleness_checker.rb +37 -11
  37. data/lib/sass/plugin.rb +10 -13
  38. data/lib/sass/railtie.rb +2 -1
  39. data/lib/sass/repl.rb +5 -6
  40. data/lib/sass/script/css_lexer.rb +8 -4
  41. data/lib/sass/script/css_parser.rb +5 -2
  42. data/lib/sass/script/functions.rb +1547 -618
  43. data/lib/sass/script/lexer.rb +122 -72
  44. data/lib/sass/script/parser.rb +304 -135
  45. data/lib/sass/script/tree/funcall.rb +306 -0
  46. data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
  47. data/lib/sass/script/tree/list_literal.rb +77 -0
  48. data/lib/sass/script/tree/literal.rb +45 -0
  49. data/lib/sass/script/tree/map_literal.rb +64 -0
  50. data/lib/sass/script/{node.rb → tree/node.rb} +30 -12
  51. data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
  52. data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
  53. data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
  54. data/lib/sass/script/tree/variable.rb +57 -0
  55. data/lib/sass/script/tree.rb +15 -0
  56. data/lib/sass/script/value/arg_list.rb +36 -0
  57. data/lib/sass/script/value/base.rb +238 -0
  58. data/lib/sass/script/value/bool.rb +40 -0
  59. data/lib/sass/script/{color.rb → value/color.rb} +256 -74
  60. data/lib/sass/script/value/deprecated_false.rb +55 -0
  61. data/lib/sass/script/value/helpers.rb +155 -0
  62. data/lib/sass/script/value/list.rb +128 -0
  63. data/lib/sass/script/value/map.rb +70 -0
  64. data/lib/sass/script/value/null.rb +49 -0
  65. data/lib/sass/script/{number.rb → value/number.rb} +115 -62
  66. data/lib/sass/script/{string.rb → value/string.rb} +9 -11
  67. data/lib/sass/script/value.rb +12 -0
  68. data/lib/sass/script.rb +35 -9
  69. data/lib/sass/scss/css_parser.rb +2 -12
  70. data/lib/sass/scss/parser.rb +657 -230
  71. data/lib/sass/scss/rx.rb +17 -12
  72. data/lib/sass/scss/static_parser.rb +37 -6
  73. data/lib/sass/scss.rb +0 -1
  74. data/lib/sass/selector/abstract_sequence.rb +35 -3
  75. data/lib/sass/selector/comma_sequence.rb +29 -14
  76. data/lib/sass/selector/sequence.rb +371 -74
  77. data/lib/sass/selector/simple.rb +28 -13
  78. data/lib/sass/selector/simple_sequence.rb +163 -36
  79. data/lib/sass/selector.rb +138 -36
  80. data/lib/sass/shared.rb +3 -5
  81. data/lib/sass/source/map.rb +196 -0
  82. data/lib/sass/source/position.rb +39 -0
  83. data/lib/sass/source/range.rb +41 -0
  84. data/lib/sass/stack.rb +126 -0
  85. data/lib/sass/supports.rb +228 -0
  86. data/lib/sass/tree/at_root_node.rb +82 -0
  87. data/lib/sass/tree/comment_node.rb +34 -29
  88. data/lib/sass/tree/content_node.rb +9 -0
  89. data/lib/sass/tree/css_import_node.rb +60 -0
  90. data/lib/sass/tree/debug_node.rb +3 -3
  91. data/lib/sass/tree/directive_node.rb +33 -3
  92. data/lib/sass/tree/each_node.rb +9 -9
  93. data/lib/sass/tree/extend_node.rb +20 -6
  94. data/lib/sass/tree/for_node.rb +6 -6
  95. data/lib/sass/tree/function_node.rb +12 -4
  96. data/lib/sass/tree/if_node.rb +2 -15
  97. data/lib/sass/tree/import_node.rb +11 -5
  98. data/lib/sass/tree/media_node.rb +27 -11
  99. data/lib/sass/tree/mixin_def_node.rb +15 -4
  100. data/lib/sass/tree/mixin_node.rb +27 -7
  101. data/lib/sass/tree/node.rb +69 -35
  102. data/lib/sass/tree/prop_node.rb +47 -31
  103. data/lib/sass/tree/return_node.rb +4 -3
  104. data/lib/sass/tree/root_node.rb +20 -4
  105. data/lib/sass/tree/rule_node.rb +37 -26
  106. data/lib/sass/tree/supports_node.rb +38 -0
  107. data/lib/sass/tree/trace_node.rb +33 -0
  108. data/lib/sass/tree/variable_node.rb +10 -4
  109. data/lib/sass/tree/visitors/base.rb +5 -8
  110. data/lib/sass/tree/visitors/check_nesting.rb +67 -52
  111. data/lib/sass/tree/visitors/convert.rb +134 -53
  112. data/lib/sass/tree/visitors/cssize.rb +245 -51
  113. data/lib/sass/tree/visitors/deep_copy.rb +102 -0
  114. data/lib/sass/tree/visitors/extend.rb +68 -0
  115. data/lib/sass/tree/visitors/perform.rb +331 -105
  116. data/lib/sass/tree/visitors/set_options.rb +125 -0
  117. data/lib/sass/tree/visitors/to_css.rb +259 -95
  118. data/lib/sass/tree/warn_node.rb +3 -3
  119. data/lib/sass/tree/while_node.rb +3 -3
  120. data/lib/sass/util/cross_platform_random.rb +19 -0
  121. data/lib/sass/util/multibyte_string_scanner.rb +157 -0
  122. data/lib/sass/util/normalized_map.rb +130 -0
  123. data/lib/sass/util/ordered_hash.rb +192 -0
  124. data/lib/sass/util/subset_map.rb +11 -2
  125. data/lib/sass/util/test.rb +9 -0
  126. data/lib/sass/util.rb +565 -39
  127. data/lib/sass/version.rb +27 -15
  128. data/lib/sass.rb +39 -4
  129. data/test/sass/cache_test.rb +15 -0
  130. data/test/sass/compiler_test.rb +223 -0
  131. data/test/sass/conversion_test.rb +901 -107
  132. data/test/sass/css2sass_test.rb +94 -0
  133. data/test/sass/engine_test.rb +1059 -164
  134. data/test/sass/exec_test.rb +86 -0
  135. data/test/sass/extend_test.rb +933 -837
  136. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  137. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  138. data/test/sass/functions_test.rb +995 -136
  139. data/test/sass/importer_test.rb +338 -18
  140. data/test/sass/logger_test.rb +58 -0
  141. data/test/sass/more_results/more_import.css +2 -2
  142. data/test/sass/plugin_test.rb +114 -30
  143. data/test/sass/results/cached_import_option.css +3 -0
  144. data/test/sass/results/filename_fn.css +3 -0
  145. data/test/sass/results/import.css +2 -2
  146. data/test/sass/results/import_charset.css +1 -0
  147. data/test/sass/results/import_charset_1_8.css +1 -0
  148. data/test/sass/results/import_charset_ibm866.css +1 -0
  149. data/test/sass/results/import_content.css +1 -0
  150. data/test/sass/results/script.css +1 -1
  151. data/test/sass/results/scss_import.css +2 -2
  152. data/test/sass/results/units.css +2 -2
  153. data/test/sass/script_conversion_test.rb +43 -1
  154. data/test/sass/script_test.rb +380 -36
  155. data/test/sass/scss/css_test.rb +257 -75
  156. data/test/sass/scss/scss_test.rb +2322 -110
  157. data/test/sass/source_map_test.rb +887 -0
  158. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  159. data/test/sass/templates/_double_import_loop2.sass +1 -0
  160. data/test/sass/templates/_filename_fn_import.scss +11 -0
  161. data/test/sass/templates/_imported_content.sass +3 -0
  162. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  163. data/test/sass/templates/bork5.sass +3 -0
  164. data/test/sass/templates/cached_import_option.scss +3 -0
  165. data/test/sass/templates/double_import_loop1.sass +1 -0
  166. data/test/sass/templates/filename_fn.scss +18 -0
  167. data/test/sass/templates/import_charset.sass +2 -0
  168. data/test/sass/templates/import_charset_1_8.sass +2 -0
  169. data/test/sass/templates/import_charset_ibm866.sass +2 -0
  170. data/test/sass/templates/import_content.sass +4 -0
  171. data/test/sass/templates/same_name_different_ext.sass +2 -0
  172. data/test/sass/templates/same_name_different_ext.scss +1 -0
  173. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  174. data/test/sass/templates/single_import_loop.sass +1 -0
  175. data/test/sass/templates/subdir/import_up1.scss +1 -0
  176. data/test/sass/templates/subdir/import_up2.scss +1 -0
  177. data/test/sass/test_helper.rb +1 -1
  178. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  179. data/test/sass/util/normalized_map_test.rb +51 -0
  180. data/test/sass/util_test.rb +183 -0
  181. data/test/sass/value_helpers_test.rb +181 -0
  182. data/test/test_helper.rb +45 -5
  183. data/vendor/listen/CHANGELOG.md +228 -0
  184. data/vendor/listen/CONTRIBUTING.md +38 -0
  185. data/vendor/listen/Gemfile +30 -0
  186. data/vendor/listen/Guardfile +8 -0
  187. data/vendor/{fssm → listen}/LICENSE +1 -1
  188. data/vendor/listen/README.md +315 -0
  189. data/vendor/listen/Rakefile +47 -0
  190. data/vendor/listen/Vagrantfile +96 -0
  191. data/vendor/listen/lib/listen/adapter.rb +214 -0
  192. data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
  193. data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
  194. data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
  195. data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
  196. data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
  197. data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
  198. data/vendor/listen/lib/listen/directory_record.rb +371 -0
  199. data/vendor/listen/lib/listen/listener.rb +225 -0
  200. data/vendor/listen/lib/listen/multi_listener.rb +143 -0
  201. data/vendor/listen/lib/listen/turnstile.rb +28 -0
  202. data/vendor/listen/lib/listen/version.rb +3 -0
  203. data/vendor/listen/lib/listen.rb +40 -0
  204. data/vendor/listen/listen.gemspec +22 -0
  205. data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
  206. data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
  207. data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
  208. data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
  209. data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
  210. data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
  211. data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
  212. data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
  213. data/vendor/listen/spec/listen/listener_spec.rb +169 -0
  214. data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
  215. data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
  216. data/vendor/listen/spec/listen_spec.rb +73 -0
  217. data/vendor/listen/spec/spec_helper.rb +21 -0
  218. data/vendor/listen/spec/support/adapter_helper.rb +629 -0
  219. data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
  220. data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
  221. data/vendor/listen/spec/support/listeners_helper.rb +156 -0
  222. data/vendor/listen/spec/support/platform_helper.rb +15 -0
  223. metadata +344 -271
  224. data/lib/sass/less.rb +0 -382
  225. data/lib/sass/script/bool.rb +0 -18
  226. data/lib/sass/script/funcall.rb +0 -162
  227. data/lib/sass/script/list.rb +0 -76
  228. data/lib/sass/script/literal.rb +0 -245
  229. data/lib/sass/script/variable.rb +0 -54
  230. data/lib/sass/scss/sass_parser.rb +0 -11
  231. data/test/sass/less_conversion_test.rb +0 -653
  232. data/vendor/fssm/README.markdown +0 -55
  233. data/vendor/fssm/Rakefile +0 -59
  234. data/vendor/fssm/VERSION.yml +0 -5
  235. data/vendor/fssm/example.rb +0 -9
  236. data/vendor/fssm/fssm.gemspec +0 -77
  237. data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
  238. data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
  239. data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
  240. data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
  241. data/vendor/fssm/lib/fssm/monitor.rb +0 -26
  242. data/vendor/fssm/lib/fssm/path.rb +0 -91
  243. data/vendor/fssm/lib/fssm/pathname.rb +0 -502
  244. data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
  245. data/vendor/fssm/lib/fssm/state/file.rb +0 -24
  246. data/vendor/fssm/lib/fssm/support.rb +0 -63
  247. data/vendor/fssm/lib/fssm/tree.rb +0 -176
  248. data/vendor/fssm/lib/fssm.rb +0 -33
  249. data/vendor/fssm/profile/prof-cache.rb +0 -40
  250. data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
  251. data/vendor/fssm/profile/prof-pathname.rb +0 -68
  252. data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
  253. data/vendor/fssm/profile/prof.html +0 -2379
  254. data/vendor/fssm/spec/path_spec.rb +0 -75
  255. data/vendor/fssm/spec/root/duck/quack.txt +0 -0
  256. data/vendor/fssm/spec/root/file.css +0 -0
  257. data/vendor/fssm/spec/root/file.rb +0 -0
  258. data/vendor/fssm/spec/root/file.yml +0 -0
  259. data/vendor/fssm/spec/root/moo/cow.txt +0 -0
  260. data/vendor/fssm/spec/spec_helper.rb +0 -14
@@ -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
 
@@ -47,25 +53,29 @@ class SassFunctionTest < Test::Unit::TestCase
47
53
  hsls, rgbs = chunk.strip.split("====")
48
54
  hsls.strip.split("\n").zip(rgbs.strip.split("\n")) do |hsl, rgb|
49
55
  hsl_method = "test_hsl: #{hsl} = #{rgb}"
50
- define_method(hsl_method) do
51
- assert_equal(evaluate(rgb), evaluate(hsl))
56
+ unless method_defined?(hsl_method)
57
+ define_method(hsl_method) do
58
+ assert_equal(evaluate(rgb), evaluate(hsl))
59
+ end
52
60
  end
53
61
 
54
62
  rgb_to_hsl_method = "test_rgb_to_hsl: #{rgb} = #{hsl}"
55
- define_method(rgb_to_hsl_method) do
56
- rgb_color = perform(rgb)
57
- hsl_color = perform(hsl)
58
-
59
- white = hsl_color.lightness == 100
60
- black = hsl_color.lightness == 0
61
- grayscale = white || black || hsl_color.saturation == 0
62
-
63
- assert_in_delta(hsl_color.hue, rgb_color.hue, 0.0001,
64
- "Hues should be equal") unless grayscale
65
- assert_in_delta(hsl_color.saturation, rgb_color.saturation, 0.0001,
66
- "Saturations should be equal") unless white || black
67
- assert_in_delta(hsl_color.lightness, rgb_color.lightness, 0.0001,
68
- "Lightnesses should be equal")
63
+ unless method_defined?(rgb_to_hsl_method)
64
+ define_method(rgb_to_hsl_method) do
65
+ rgb_color = perform(rgb)
66
+ hsl_color = perform(hsl)
67
+
68
+ white = hsl_color.lightness == 100
69
+ black = hsl_color.lightness == 0
70
+ grayscale = white || black || hsl_color.saturation == 0
71
+
72
+ assert_in_delta(hsl_color.hue, rgb_color.hue, 0.0001,
73
+ "Hues should be equal") unless grayscale
74
+ assert_in_delta(hsl_color.saturation, rgb_color.saturation, 0.0001,
75
+ "Saturations should be equal") unless white || black
76
+ assert_in_delta(hsl_color.lightness, rgb_color.lightness, 0.0001,
77
+ "Lightnesses should be equal")
78
+ end
69
79
  end
70
80
  end
71
81
  end
@@ -76,13 +86,13 @@ class SassFunctionTest < Test::Unit::TestCase
76
86
 
77
87
  def test_hsl_checks_bounds
78
88
  assert_error_message("Saturation -114 must be between 0% and 100% for `hsl'", "hsl(10, -114, 12)");
79
- assert_error_message("Lightness 256 must be between 0% and 100% for `hsl'", "hsl(10, 10, 256%)");
89
+ assert_error_message("Lightness 256% must be between 0% and 100% for `hsl'", "hsl(10, 10, 256%)");
80
90
  end
81
91
 
82
92
  def test_hsl_checks_types
83
- assert_error_message("\"foo\" is not a number for `hsl'", "hsl(\"foo\", 10, 12)");
84
- assert_error_message("\"foo\" is not a number for `hsl'", "hsl(10, \"foo\", 12)");
85
- 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\")");
86
96
  end
87
97
 
88
98
  def test_hsla
@@ -94,54 +104,84 @@ class SassFunctionTest < Test::Unit::TestCase
94
104
 
95
105
  def test_hsla_checks_bounds
96
106
  assert_error_message("Saturation -114 must be between 0% and 100% for `hsla'", "hsla(10, -114, 12, 1)");
97
- assert_error_message("Lightness 256 must be between 0% and 100% for `hsla'", "hsla(10, 10, 256%, 0)");
107
+ assert_error_message("Lightness 256% must be between 0% and 100% for `hsla'", "hsla(10, 10, 256%, 0)");
98
108
  assert_error_message("Alpha channel -0.1 must be between 0 and 1 for `hsla'", "hsla(10, 10, 10, -0.1)");
99
109
  assert_error_message("Alpha channel 1.1 must be between 0 and 1 for `hsla'", "hsla(10, 10, 10, 1.1)");
100
110
  end
101
111
 
102
112
  def test_hsla_checks_types
103
- assert_error_message("\"foo\" is not a number for `hsla'", "hsla(\"foo\", 10, 12, 0.3)");
104
- assert_error_message("\"foo\" is not a number for `hsla'", "hsla(10, \"foo\", 12, 0)");
105
- assert_error_message("\"foo\" is not a number for `hsla'", "hsla(10, 10, \"foo\", 1)");
106
- 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\")");
107
117
  end
108
118
 
109
119
  def test_percentage
110
120
  assert_equal("50%", evaluate("percentage(.5)"))
111
121
  assert_equal("100%", evaluate("percentage(1)"))
112
122
  assert_equal("25%", evaluate("percentage(25px / 100px)"))
113
- assert_equal("50%", evaluate("percentage($value: 0.5)"))
123
+ assert_equal("50%", evaluate("percentage($number: 0.5)"))
124
+ end
125
+
126
+ def test_percentage_deprecated_arg_name
127
+ assert_warning(<<WARNING) {assert_equal("50%", evaluate("percentage($value: 0.5)"))}
128
+ DEPRECATION WARNING: The `$value' argument for `percentage()' has been renamed to `$number'.
129
+ WARNING
114
130
  end
115
131
 
116
132
  def test_percentage_checks_types
117
- assert_error_message("25px is not a unitless number for `percentage'", "percentage(25px)")
118
- assert_error_message("#cccccc is not a unitless number for `percentage'", "percentage(#ccc)")
119
- assert_error_message("\"string\" is not a unitless number for `percentage'", %Q{percentage("string")})
133
+ assert_error_message("$number: 25px is not a unitless number for `percentage'", "percentage(25px)")
134
+ assert_error_message("$number: #cccccc is not a unitless number for `percentage'", "percentage(#ccc)")
135
+ assert_error_message("$number: \"string\" is not a unitless number for `percentage'", %Q{percentage("string")})
120
136
  end
121
137
 
122
138
  def test_round
123
139
  assert_equal("5", evaluate("round(4.8)"))
124
140
  assert_equal("5px", evaluate("round(4.8px)"))
125
141
  assert_equal("5px", evaluate("round(5.49px)"))
126
- assert_equal("5px", evaluate("round($value: 5.49px)"))
142
+ assert_equal("5px", evaluate("round($number: 5.49px)"))
143
+ end
144
+
145
+ def test_round_deprecated_arg_name
146
+ assert_warning(<<WARNING) {assert_equal("5px", evaluate("round($value: 5.49px)"))}
147
+ DEPRECATION WARNING: The `$value' argument for `round()' has been renamed to `$number'.
148
+ WARNING
149
+ end
127
150
 
128
- assert_error_message("#cccccc is not a number for `round'", "round(#ccc)")
151
+ def test_round_checks_types
152
+ assert_error_message("$value: #cccccc is not a number for `round'", "round(#ccc)")
129
153
  end
130
154
 
131
155
  def test_floor
132
156
  assert_equal("4", evaluate("floor(4.8)"))
133
157
  assert_equal("4px", evaluate("floor(4.8px)"))
134
- assert_equal("4px", evaluate("floor($value: 4.8px)"))
158
+ assert_equal("4px", evaluate("floor($number: 4.8px)"))
159
+ end
160
+
161
+ def test_floor_deprecated_arg_name
162
+ assert_warning(<<WARNING) {assert_equal("4px", evaluate("floor($value: 4.8px)"))}
163
+ DEPRECATION WARNING: The `$value' argument for `floor()' has been renamed to `$number'.
164
+ WARNING
165
+ end
135
166
 
136
- assert_error_message("\"foo\" is not a number for `floor'", "floor(\"foo\")")
167
+ def test_floor_checks_types
168
+ assert_error_message("$value: \"foo\" is not a number for `floor'", "floor(\"foo\")")
137
169
  end
138
170
 
139
171
  def test_ceil
140
172
  assert_equal("5", evaluate("ceil(4.1)"))
141
173
  assert_equal("5px", evaluate("ceil(4.8px)"))
142
- assert_equal("5px", evaluate("ceil($value: 4.8px)"))
174
+ assert_equal("5px", evaluate("ceil($number: 4.8px)"))
175
+ end
143
176
 
144
- assert_error_message("\"a\" is not a number for `ceil'", "ceil(\"a\")")
177
+ def test_ceil_deprecated_arg_name
178
+ assert_warning(<<WARNING) {assert_equal("5px", evaluate("ceil($value: 4.8px)"))}
179
+ DEPRECATION WARNING: The `$value' argument for `ceil()' has been renamed to `$number'.
180
+ WARNING
181
+ end
182
+
183
+ def test_ceil_checks_types
184
+ assert_error_message("$value: \"a\" is not a number for `ceil'", "ceil(\"a\")")
145
185
  end
146
186
 
147
187
  def test_abs
@@ -149,51 +189,79 @@ class SassFunctionTest < Test::Unit::TestCase
149
189
  assert_equal("5px", evaluate("abs(-5px)"))
150
190
  assert_equal("5", evaluate("abs(5)"))
151
191
  assert_equal("5px", evaluate("abs(5px)"))
152
- assert_equal("5px", evaluate("abs($value: 5px)"))
192
+ assert_equal("5px", evaluate("abs($number: 5px)"))
193
+ end
194
+
195
+ def test_abs_deprecated_arg_name
196
+ assert_warning(<<WARNING) {assert_equal("5px", evaluate("abs($value: 5px)"))}
197
+ DEPRECATION WARNING: The `$value' argument for `abs()' has been renamed to `$number'.
198
+ WARNING
199
+ end
153
200
 
154
- assert_error_message("#aaaaaa is not a number for `abs'", "abs(#aaa)")
201
+ def test_abs_checks_types
202
+ assert_error_message("$value: #aaaaaa is not a number for `abs'", "abs(#aaa)")
203
+ end
204
+
205
+ def test_min
206
+ assert_equal("1", evaluate("min(1, 2, 3)"))
207
+ assert_equal("1", evaluate("min(3px, 2px, 1)"))
208
+ assert_equal("4em", evaluate("min(4em)"))
209
+ assert_equal("10cm", evaluate("min(10cm, 6in)"))
210
+
211
+ assert_error_message("#aaaaaa is not a number for `min'", "min(#aaa)")
212
+ assert_error_message("Incompatible units: 'px' and 'em'.", "min(3em, 4em, 1px)")
213
+ end
214
+
215
+ def test_max
216
+ assert_equal("3", evaluate("max(1, 2, 3)"))
217
+ assert_equal("3", evaluate("max(3, 2px, 1px)"))
218
+ assert_equal("4em", evaluate("max(4em)"))
219
+ assert_equal("6in", evaluate("max(10cm, 6in)"))
220
+
221
+ assert_error_message("#aaaaaa is not a number for `max'", "max(#aaa)")
222
+ assert_error_message("Incompatible units: 'px' and 'em'.", "max(3em, 4em, 1px)")
155
223
  end
156
224
 
157
225
  def test_rgb
158
226
  assert_equal("#123456", evaluate("rgb(18, 52, 86)"))
159
227
  assert_equal("#beaded", evaluate("rgb(190, 173, 237)"))
160
- assert_equal("#00ff7f", evaluate("rgb(0, 255, 127)"))
161
- assert_equal("#00ff7f", evaluate("rgb($red: 0, $green: 255, $blue: 127)"))
228
+ assert_equal("springgreen", evaluate("rgb(0, 255, 127)"))
229
+ assert_equal("springgreen", evaluate("rgb($red: 0, $green: 255, $blue: 127)"))
162
230
  end
163
231
 
164
232
  def test_rgb_percent
165
233
  assert_equal("#123456", evaluate("rgb(7.1%, 20.4%, 34%)"))
166
234
  assert_equal("#beaded", evaluate("rgb(74.7%, 173, 93%)"))
167
235
  assert_equal("#beaded", evaluate("rgb(190, 68%, 237)"))
168
- assert_equal("#00ff7f", evaluate("rgb(0%, 100%, 50%)"))
236
+ assert_equal("springgreen", evaluate("rgb(0%, 100%, 50%)"))
169
237
  end
170
238
 
171
239
  def test_rgb_tests_bounds
172
- assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgb'",
240
+ assert_error_message("$red: Color value 256 must be between 0 and 255 for `rgb'",
173
241
  "rgb(256, 1, 1)")
174
- assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgb'",
242
+ assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgb'",
175
243
  "rgb(1, 256, 1)")
176
- assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgb'",
244
+ assert_error_message("$blue: Color value 256 must be between 0 and 255 for `rgb'",
177
245
  "rgb(1, 1, 256)")
178
- assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgb'",
246
+ assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgb'",
179
247
  "rgb(1, 256, 257)")
180
- assert_error_message("Color value -1 must be between 0 and 255 inclusive for `rgb'",
248
+ assert_error_message("$red: Color value -1 must be between 0 and 255 for `rgb'",
181
249
  "rgb(-1, 1, 1)")
182
250
  end
183
251
 
184
252
  def test_rgb_test_percent_bounds
185
- assert_error_message("Color value 100.1% must be between 0% and 100% inclusive for `rgb'",
253
+ assert_error_message("$red: Color value 100.1% must be between 0% and 100% for `rgb'",
186
254
  "rgb(100.1%, 0, 0)")
187
- assert_error_message("Color value -0.1% must be between 0% and 100% inclusive for `rgb'",
255
+ assert_error_message("$green: Color value -0.1% must be between 0% and 100% for `rgb'",
188
256
  "rgb(0, -0.1%, 0)")
189
- assert_error_message("Color value 101% must be between 0% and 100% inclusive for `rgb'",
257
+ assert_error_message("$blue: Color value 101% must be between 0% and 100% for `rgb'",
190
258
  "rgb(0, 0, 101%)")
191
259
  end
192
260
 
193
261
  def test_rgb_tests_types
194
- assert_error_message("\"foo\" is not a number for `rgb'", "rgb(\"foo\", 10, 12)");
195
- assert_error_message("\"foo\" is not a number for `rgb'", "rgb(10, \"foo\", 12)");
196
- assert_error_message("\"foo\" is not a number for `rgb'", "rgb(10, 10, \"foo\")");
262
+ assert_error_message("$red: \"foo\" is not a number for `rgb'", "rgb(\"foo\", 10, 12)");
263
+ assert_error_message("$green: \"foo\" is not a number for `rgb'", "rgb(10, \"foo\", 12)");
264
+ assert_error_message("$blue: \"foo\" is not a number for `rgb'", "rgb(10, 10, \"foo\")");
197
265
  end
198
266
 
199
267
  def test_rgba
@@ -203,28 +271,28 @@ class SassFunctionTest < Test::Unit::TestCase
203
271
  assert_equal("rgba(0, 255, 127, 0)", evaluate("rgba($red: 0, $green: 255, $blue: 127, $alpha: 0)"))
204
272
  end
205
273
 
206
- def test_rgb_tests_bounds
207
- assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgba'",
274
+ def test_rgba_tests_bounds
275
+ assert_error_message("$red: Color value 256 must be between 0 and 255 for `rgba'",
208
276
  "rgba(256, 1, 1, 0.3)")
209
- assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgba'",
277
+ assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgba'",
210
278
  "rgba(1, 256, 1, 0.3)")
211
- assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgba'",
279
+ assert_error_message("$blue: Color value 256 must be between 0 and 255 for `rgba'",
212
280
  "rgba(1, 1, 256, 0.3)")
213
- assert_error_message("Color value 256 must be between 0 and 255 inclusive for `rgba'",
281
+ assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgba'",
214
282
  "rgba(1, 256, 257, 0.3)")
215
- assert_error_message("Color value -1 must be between 0 and 255 inclusive for `rgba'",
283
+ assert_error_message("$red: Color value -1 must be between 0 and 255 for `rgba'",
216
284
  "rgba(-1, 1, 1, 0.3)")
217
- assert_error_message("Alpha channel -0.2 must be between 0 and 1 inclusive for `rgba'",
285
+ assert_error_message("Alpha channel -0.2 must be between 0 and 1 for `rgba'",
218
286
  "rgba(1, 1, 1, -0.2)")
219
- assert_error_message("Alpha channel 1.2 must be between 0 and 1 inclusive for `rgba'",
287
+ assert_error_message("Alpha channel 1.2 must be between 0 and 1 for `rgba'",
220
288
  "rgba(1, 1, 1, 1.2)")
221
289
  end
222
290
 
223
291
  def test_rgba_tests_types
224
- assert_error_message("\"foo\" is not a number for `rgba'", "rgba(\"foo\", 10, 12, 0.2)");
225
- assert_error_message("\"foo\" is not a number for `rgba'", "rgba(10, \"foo\", 12, 0.1)");
226
- assert_error_message("\"foo\" is not a number for `rgba'", "rgba(10, 10, \"foo\", 0)");
227
- assert_error_message("\"foo\" is not a number for `rgba'", "rgba(10, 10, 10, \"foo\")");
292
+ assert_error_message("$red: \"foo\" is not a number for `rgba'", "rgba(\"foo\", 10, 12, 0.2)");
293
+ assert_error_message("$green: \"foo\" is not a number for `rgba'", "rgba(10, \"foo\", 12, 0.1)");
294
+ assert_error_message("$blue: \"foo\" is not a number for `rgba'", "rgba(10, 10, \"foo\", 0)");
295
+ assert_error_message("$alpha: \"foo\" is not a number for `rgba'", "rgba(10, 10, 10, \"foo\")");
228
296
  end
229
297
 
230
298
  def test_rgba_with_color
@@ -234,8 +302,8 @@ class SassFunctionTest < Test::Unit::TestCase
234
302
  end
235
303
 
236
304
  def test_rgba_with_color_tests_types
237
- assert_error_message("\"foo\" is not a color for `rgba'", "rgba(\"foo\", 0.2)");
238
- assert_error_message("\"foo\" is not a number for `rgba'", "rgba(blue, \"foo\")");
305
+ assert_error_message("$color: \"foo\" is not a color for `rgba'", "rgba(\"foo\", 0.2)");
306
+ assert_error_message("$alpha: \"foo\" is not a number for `rgba'", "rgba(blue, \"foo\")");
239
307
  end
240
308
 
241
309
  def test_rgba_tests_num_args
@@ -251,7 +319,7 @@ class SassFunctionTest < Test::Unit::TestCase
251
319
  end
252
320
 
253
321
  def test_red_exception
254
- assert_error_message("12 is not a color for `red'", "red(12)")
322
+ assert_error_message("$color: 12 is not a color for `red'", "red(12)")
255
323
  end
256
324
 
257
325
  def test_green
@@ -260,7 +328,7 @@ class SassFunctionTest < Test::Unit::TestCase
260
328
  end
261
329
 
262
330
  def test_green_exception
263
- assert_error_message("12 is not a color for `green'", "green(12)")
331
+ assert_error_message("$color: 12 is not a color for `green'", "green(12)")
264
332
  end
265
333
 
266
334
  def test_blue
@@ -269,7 +337,7 @@ class SassFunctionTest < Test::Unit::TestCase
269
337
  end
270
338
 
271
339
  def test_blue_exception
272
- assert_error_message("12 is not a color for `blue'", "blue(12)")
340
+ assert_error_message("$color: 12 is not a color for `blue'", "blue(12)")
273
341
  end
274
342
 
275
343
  def test_hue
@@ -278,7 +346,7 @@ class SassFunctionTest < Test::Unit::TestCase
278
346
  end
279
347
 
280
348
  def test_hue_exception
281
- assert_error_message("12 is not a color for `hue'", "hue(12)")
349
+ assert_error_message("$color: 12 is not a color for `hue'", "hue(12)")
282
350
  end
283
351
 
284
352
  def test_saturation
@@ -288,7 +356,7 @@ class SassFunctionTest < Test::Unit::TestCase
288
356
  end
289
357
 
290
358
  def test_saturation_exception
291
- assert_error_message("12 is not a color for `saturation'", "saturation(12)")
359
+ assert_error_message("$color: 12 is not a color for `saturation'", "saturation(12)")
292
360
  end
293
361
 
294
362
  def test_lightness
@@ -298,7 +366,7 @@ class SassFunctionTest < Test::Unit::TestCase
298
366
  end
299
367
 
300
368
  def test_lightness_exception
301
- assert_error_message("12 is not a color for `lightness'", "lightness(12)")
369
+ assert_error_message("$color: 12 is not a color for `lightness'", "lightness(12)")
302
370
  end
303
371
 
304
372
  def test_alpha
@@ -309,7 +377,19 @@ class SassFunctionTest < Test::Unit::TestCase
309
377
  end
310
378
 
311
379
  def test_alpha_exception
312
- assert_error_message("12 is not a color for `alpha'", "alpha(12)")
380
+ assert_error_message("$color: 12 is not a color for `alpha'", "alpha(12)")
381
+ end
382
+
383
+ def test_opacity
384
+ assert_equal("1", evaluate("opacity(#123456)"))
385
+ assert_equal("0.34", evaluate("opacity(rgba(0, 1, 2, 0.34))"))
386
+ assert_equal("0", evaluate("opacity(hsla(0, 1, 2, 0))"))
387
+ assert_equal("0", evaluate("opacity($color: hsla(0, 1, 2, 0))"))
388
+ assert_equal("opacity(20%)", evaluate("opacity(20%)"))
389
+ end
390
+
391
+ def test_opacity_exception
392
+ assert_error_message("$color: \"foo\" is not a color for `opacity'", "opacity(foo)")
313
393
  end
314
394
 
315
395
  def test_opacify
@@ -331,16 +411,16 @@ class SassFunctionTest < Test::Unit::TestCase
331
411
  end
332
412
 
333
413
  def test_opacify_tests_types
334
- assert_error_message("\"foo\" is not a color for `opacify'", "opacify(\"foo\", 10%)")
335
- assert_error_message("\"foo\" is not a number for `opacify'", "opacify(#fff, \"foo\")")
414
+ assert_error_message("$color: \"foo\" is not a color for `opacify'", "opacify(\"foo\", 10%)")
415
+ assert_error_message("$amount: \"foo\" is not a number for `opacify'", "opacify(#fff, \"foo\")")
336
416
  end
337
417
 
338
418
  def test_transparentize
339
419
  assert_equal("rgba(0, 0, 0, 0.3)", evaluate("transparentize(rgba(0, 0, 0, 0.5), 0.2)"))
340
420
  assert_equal("rgba(0, 0, 0, 0.1)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 0.1)"))
341
421
  assert_equal("rgba(0, 0, 0, 0.2)", evaluate("fade-out(rgba(0, 0, 0, 0.5), 0.3px)"))
342
- assert_equal("rgba(0, 0, 0, 0)", evaluate("fade_out(rgba(0, 0, 0, 0.2), 0.2)"))
343
- assert_equal("rgba(0, 0, 0, 0)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 1)"))
422
+ assert_equal("transparent", evaluate("fade_out(rgba(0, 0, 0, 0.2), 0.2)"))
423
+ assert_equal("transparent", evaluate("transparentize(rgba(0, 0, 0, 0.2), 1)"))
344
424
  assert_equal("rgba(0, 0, 0, 0.2)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 0)"))
345
425
  assert_equal("rgba(0, 0, 0, 0.2)", evaluate("transparentize($color: rgba(0, 0, 0, 0.2), $amount: 0)"))
346
426
  assert_equal("rgba(0, 0, 0, 0.2)", evaluate("fade-out($color: rgba(0, 0, 0, 0.2), $amount: 0)"))
@@ -354,8 +434,8 @@ class SassFunctionTest < Test::Unit::TestCase
354
434
  end
355
435
 
356
436
  def test_transparentize_tests_types
357
- assert_error_message("\"foo\" is not a color for `transparentize'", "transparentize(\"foo\", 10%)")
358
- assert_error_message("\"foo\" is not a number for `transparentize'", "transparentize(#fff, \"foo\")")
437
+ assert_error_message("$color: \"foo\" is not a color for `transparentize'", "transparentize(\"foo\", 10%)")
438
+ assert_error_message("$amount: \"foo\" is not a number for `transparentize'", "transparentize(#fff, \"foo\")")
359
439
  end
360
440
 
361
441
  def test_lighten
@@ -376,8 +456,8 @@ class SassFunctionTest < Test::Unit::TestCase
376
456
  end
377
457
 
378
458
  def test_lighten_tests_types
379
- assert_error_message("\"foo\" is not a color for `lighten'", "lighten(\"foo\", 10%)")
380
- assert_error_message("\"foo\" is not a number for `lighten'", "lighten(#fff, \"foo\")")
459
+ assert_error_message("$color: \"foo\" is not a color for `lighten'", "lighten(\"foo\", 10%)")
460
+ assert_error_message("$amount: \"foo\" is not a number for `lighten'", "lighten(#fff, \"foo\")")
381
461
  end
382
462
 
383
463
  def test_darken
@@ -398,8 +478,8 @@ class SassFunctionTest < Test::Unit::TestCase
398
478
  end
399
479
 
400
480
  def test_darken_tests_types
401
- assert_error_message("\"foo\" is not a color for `darken'", "darken(\"foo\", 10%)")
402
- assert_error_message("\"foo\" is not a number for `darken'", "darken(#fff, \"foo\")")
481
+ assert_error_message("$color: \"foo\" is not a color for `darken'", "darken(\"foo\", 10%)")
482
+ assert_error_message("$amount: \"foo\" is not a number for `darken'", "darken(#fff, \"foo\")")
403
483
  end
404
484
 
405
485
  def test_saturate
@@ -411,6 +491,7 @@ class SassFunctionTest < Test::Unit::TestCase
411
491
  assert_equal("#88aa88", evaluate("saturate(#8a8, 0%)"))
412
492
  assert_equal("rgba(158, 63, 63, 0.5)", evaluate("saturate(rgba(136, 85, 85, 0.5), 20%)"))
413
493
  assert_equal("rgba(158, 63, 63, 0.5)", evaluate("saturate($color: rgba(136, 85, 85, 0.5), $amount: 20%)"))
494
+ assert_equal("saturate(50%)", evaluate("saturate(50%)"))
414
495
  end
415
496
 
416
497
  def test_saturate_tests_bounds
@@ -421,8 +502,8 @@ class SassFunctionTest < Test::Unit::TestCase
421
502
  end
422
503
 
423
504
  def test_saturate_tests_types
424
- assert_error_message("\"foo\" is not a color for `saturate'", "saturate(\"foo\", 10%)")
425
- assert_error_message("\"foo\" is not a number for `saturate'", "saturate(#fff, \"foo\")")
505
+ assert_error_message("$color: \"foo\" is not a color for `saturate'", "saturate(\"foo\", 10%)")
506
+ assert_error_message("$amount: \"foo\" is not a number for `saturate'", "saturate(#fff, \"foo\")")
426
507
  end
427
508
 
428
509
  def test_desaturate
@@ -444,8 +525,8 @@ class SassFunctionTest < Test::Unit::TestCase
444
525
  end
445
526
 
446
527
  def test_desaturate_tests_types
447
- assert_error_message("\"foo\" is not a color for `desaturate'", "desaturate(\"foo\", 10%)")
448
- assert_error_message("\"foo\" is not a number for `desaturate'", "desaturate(#fff, \"foo\")")
528
+ assert_error_message("$color: \"foo\" is not a color for `desaturate'", "desaturate(\"foo\", 10%)")
529
+ assert_error_message("$amount: \"foo\" is not a number for `desaturate'", "desaturate(#fff, \"foo\")")
449
530
  end
450
531
 
451
532
  def test_adjust_hue
@@ -461,8 +542,8 @@ class SassFunctionTest < Test::Unit::TestCase
461
542
  end
462
543
 
463
544
  def test_adjust_hue_tests_types
464
- assert_error_message("\"foo\" is not a color for `adjust-hue'", "adjust-hue(\"foo\", 10%)")
465
- assert_error_message("\"foo\" is not a number for `adjust-hue'", "adjust-hue(#fff, \"foo\")")
545
+ assert_error_message("$color: \"foo\" is not a color for `adjust-hue'", "adjust-hue(\"foo\", 10%)")
546
+ assert_error_message("$degrees: \"foo\" is not a number for `adjust-hue'", "adjust-hue(#fff, \"foo\")")
466
547
  end
467
548
 
468
549
  def test_adjust_color
@@ -520,7 +601,7 @@ class SassFunctionTest < Test::Unit::TestCase
520
601
  end
521
602
 
522
603
  def test_adjust_color_tests_types
523
- assert_error_message("\"foo\" is not a color for `adjust-color'", "adjust-color(foo, $hue: 10)")
604
+ assert_error_message("$color: \"foo\" is not a color for `adjust-color'", "adjust-color(foo, $hue: 10)")
524
605
  # HSL
525
606
  assert_error_message("$hue: \"foo\" is not a number for `adjust-color'",
526
607
  "adjust-color(blue, $hue: foo)")
@@ -626,7 +707,7 @@ class SassFunctionTest < Test::Unit::TestCase
626
707
  end
627
708
 
628
709
  def test_scale_color_tests_types
629
- assert_error_message("\"foo\" is not a color for `scale-color'", "scale-color(foo, $red: 10%)")
710
+ assert_error_message("$color: \"foo\" is not a color for `scale-color'", "scale-color(foo, $red: 10%)")
630
711
  # HSL
631
712
  assert_error_message("$saturation: \"foo\" is not a number for `scale-color'",
632
713
  "scale-color(blue, $saturation: foo)")
@@ -654,9 +735,9 @@ class SassFunctionTest < Test::Unit::TestCase
654
735
  "scale-color(blue, $alpha: -101%)")
655
736
 
656
737
  # Unit
657
- assert_error_message("$saturation: Amount 80 must be a % (e.g. 80%) for `scale-color'",
738
+ assert_error_message("Expected $saturation to have a unit of % but got 80 for `scale-color'",
658
739
  "scale-color(blue, $saturation: 80)")
659
- assert_error_message("$alpha: Amount 0.5 must be a % (e.g. 0.5%) for `scale-color'",
740
+ assert_error_message("Expected $alpha to have a unit of % but got 0.5 for `scale-color'",
660
741
  "scale-color(blue, $alpha: 0.5)")
661
742
 
662
743
  # Unknown argument
@@ -697,7 +778,7 @@ class SassFunctionTest < Test::Unit::TestCase
697
778
  end
698
779
 
699
780
  def test_change_color_tests_types
700
- assert_error_message("\"foo\" is not a color for `change-color'", "change-color(foo, $red: 10%)")
781
+ assert_error_message("$color: \"foo\" is not a color for `change-color'", "change-color(foo, $red: 10%)")
701
782
  # HSL
702
783
  assert_error_message("$saturation: \"foo\" is not a number for `change-color'",
703
784
  "change-color(blue, $saturation: foo)")
@@ -713,15 +794,15 @@ class SassFunctionTest < Test::Unit::TestCase
713
794
 
714
795
  def test_change_color_argument_errors
715
796
  # Range
716
- assert_error_message("Saturation must be between 0 and 100 for `change-color'",
797
+ assert_error_message("Saturation 101% must be between 0% and 100% for `change-color'",
717
798
  "change-color(blue, $saturation: 101%)")
718
- assert_error_message("Lightness must be between 0 and 100 for `change-color'",
799
+ assert_error_message("Lightness 101% must be between 0% and 100% for `change-color'",
719
800
  "change-color(blue, $lightness: 101%)")
720
- assert_error_message("Red value must be between 0 and 255 for `change-color'",
801
+ assert_error_message("Red value -1 must be between 0 and 255 for `change-color'",
721
802
  "change-color(blue, $red: -1)")
722
- assert_error_message("Green value must be between 0 and 255 for `change-color'",
803
+ assert_error_message("Green value 256 must be between 0 and 255 for `change-color'",
723
804
  "change-color(blue, $green: 256)")
724
- assert_error_message("Blue value must be between 0 and 255 for `change-color'",
805
+ assert_error_message("Blue value 500 must be between 0 and 255 for `change-color'",
725
806
  "change-color(blue, $blue: 500)")
726
807
 
727
808
  # Unknown argument
@@ -735,6 +816,13 @@ class SassFunctionTest < Test::Unit::TestCase
735
816
  "change-color(blue, $lightness: 10%, $red: 120)");
736
817
  end
737
818
 
819
+ def test_ie_hex_str
820
+ assert_equal("#FFAA11CC", evaluate('ie-hex-str(#aa11cc)'))
821
+ assert_equal("#FFAA11CC", evaluate('ie-hex-str(#a1c)'))
822
+ assert_equal("#FFAA11CC", evaluate('ie-hex-str(#A1c)'))
823
+ assert_equal("#80FF0000", evaluate('ie-hex-str(rgba(255, 0, 0, 0.5))'))
824
+ end
825
+
738
826
  def test_mix
739
827
  assert_equal("#7f007f", evaluate("mix(#f00, #00f)"))
740
828
  assert_equal("#7f7f7f", evaluate("mix(#f00, #0ff)"))
@@ -749,13 +837,39 @@ class SassFunctionTest < Test::Unit::TestCase
749
837
  assert_equal("blue", evaluate("mix(transparentize(#f00, 1), #00f, 0%)"))
750
838
  assert_equal("rgba(0, 0, 255, 0)", evaluate("mix(#f00, transparentize(#00f, 1), 0%)"))
751
839
  assert_equal("rgba(255, 0, 0, 0)", evaluate("mix(transparentize(#f00, 1), #00f, 100%)"))
752
- assert_equal("rgba(255, 0, 0, 0)", evaluate("mix($color-1: transparentize(#f00, 1), $color-2: #00f, $weight: 100%)"))
840
+ assert_equal("rgba(255, 0, 0, 0)", evaluate("mix($color1: transparentize(#f00, 1), $color2: #00f, $weight: 100%)"))
841
+ end
842
+
843
+ def test_mix_deprecated_arg_name
844
+ assert_warning <<WARNING do
845
+ DEPRECATION WARNING: The `$color-1' argument for `mix()' has been renamed to `$color1'.
846
+ DEPRECATION WARNING: The `$color-2' argument for `mix()' has been renamed to `$color2'.
847
+ WARNING
848
+ assert_equal("rgba(255, 0, 0, 0)",
849
+ evaluate("mix($color-1: transparentize(#f00, 1), $color-2: #00f, $weight: 100%)"))
850
+ end
851
+
852
+ assert_warning <<WARNING do
853
+ DEPRECATION WARNING: The `$color-1' argument for `mix()' has been renamed to `$color1'.
854
+ DEPRECATION WARNING: The `$color-2' argument for `mix()' has been renamed to `$color2'.
855
+ WARNING
856
+ assert_equal("rgba(0, 0, 255, 0.5)",
857
+ evaluate("mix($color-1: transparentize(#f00, 1), $color-2: #00f)"))
858
+ end
859
+
860
+ assert_warning <<WARNING do
861
+ DEPRECATION WARNING: The `$color_1' argument for `mix()' has been renamed to `$color1'.
862
+ DEPRECATION WARNING: The `$color_2' argument for `mix()' has been renamed to `$color2'.
863
+ WARNING
864
+ assert_equal("rgba(0, 0, 255, 0.5)",
865
+ evaluate("mix($color_1: transparentize(#f00, 1), $color_2: #00f)"))
866
+ end
753
867
  end
754
868
 
755
869
  def test_mix_tests_types
756
- assert_error_message("\"foo\" is not a color for `mix'", "mix(\"foo\", #f00, 10%)")
757
- assert_error_message("\"foo\" is not a color for `mix'", "mix(#f00, \"foo\", 10%)")
758
- assert_error_message("\"foo\" is not a number for `mix'", "mix(#f00, #baf, \"foo\")")
870
+ assert_error_message("$color1: \"foo\" is not a color for `mix'", "mix(\"foo\", #f00, 10%)")
871
+ assert_error_message("$color2: \"foo\" is not a color for `mix'", "mix(#f00, \"foo\", 10%)")
872
+ assert_error_message("$weight: \"foo\" is not a number for `mix'", "mix(#f00, #baf, \"foo\")")
759
873
  end
760
874
 
761
875
  def test_mix_tests_bounds
@@ -772,32 +886,36 @@ class SassFunctionTest < Test::Unit::TestCase
772
886
  assert_equal("white", evaluate("grayscale(white)"))
773
887
  assert_equal("black", evaluate("grayscale(black)"))
774
888
  assert_equal("black", evaluate("grayscale($color: black)"))
889
+
890
+ assert_equal("grayscale(2)", evaluate("grayscale(2)"))
891
+ assert_equal("grayscale(-5px)", evaluate("grayscale(-5px)"))
775
892
  end
776
893
 
777
894
  def tets_grayscale_tests_types
778
- assert_error_message("\"foo\" is not a color for `grayscale'", "grayscale(\"foo\")")
895
+ assert_error_message("$color: \"foo\" is not a color for `grayscale'", "grayscale(\"foo\")")
779
896
  end
780
897
 
781
898
  def test_complement
782
899
  assert_equal("#ccbbaa", evaluate("complement(#abc)"))
783
- assert_equal("aqua", evaluate("complement(red)"))
784
- assert_equal("red", evaluate("complement(aqua)"))
900
+ assert_equal("cyan", evaluate("complement(red)"))
901
+ assert_equal("red", evaluate("complement(cyan)"))
785
902
  assert_equal("white", evaluate("complement(white)"))
786
903
  assert_equal("black", evaluate("complement(black)"))
787
904
  assert_equal("black", evaluate("complement($color: black)"))
788
905
  end
789
906
 
790
907
  def tets_complement_tests_types
791
- assert_error_message("\"foo\" is not a color for `complement'", "complement(\"foo\")")
908
+ assert_error_message("$color: \"foo\" is not a color for `complement'", "complement(\"foo\")")
792
909
  end
793
910
 
794
911
  def test_invert
795
912
  assert_equal("#112233", evaluate("invert(#edc)"))
796
913
  assert_equal("rgba(245, 235, 225, 0.5)", evaluate("invert(rgba(10, 20, 30, 0.5))"))
914
+ assert_equal("invert(20%)", evaluate("invert(20%)"))
797
915
  end
798
916
 
799
917
  def test_invert_tests_types
800
- assert_error_message("\"foo\" is not a color for `invert'", "invert(\"foo\")")
918
+ assert_error_message("$color: \"foo\" is not a color for `invert'", "invert(\"foo\")")
801
919
  end
802
920
 
803
921
  def test_unquote
@@ -813,7 +931,83 @@ class SassFunctionTest < Test::Unit::TestCase
813
931
  end
814
932
 
815
933
  def test_quote_tests_type
816
- assert_error_message("#ff0000 is not a string for `quote'", "quote(#f00)")
934
+ assert_error_message("$string: #ff0000 is not a string for `quote'", "quote(#f00)")
935
+ end
936
+
937
+ def test_str_length
938
+ assert_equal('3', evaluate('str-length(foo)'))
939
+ end
940
+
941
+ def test_str_length_requires_a_string
942
+ assert_error_message("$string: #ff0000 is not a string for `str-length'", "str-length(#f00)")
943
+ end
944
+
945
+ def test_str_insert
946
+ assert_equal('Xabcd', evaluate('str-insert(abcd, X, 0)'))
947
+ assert_equal('Xabcd', evaluate('str-insert(abcd, X, 1)'))
948
+ assert_equal('abcXd', evaluate('str-insert(abcd, X, 4)'))
949
+ assert_equal('abcdX', evaluate('str-insert(abcd, X, 100)'))
950
+ assert_equal('Xabcd', evaluate('str-insert(abcd, X, -100)'))
951
+ assert_equal('aXbcd', evaluate('str-insert(abcd, X, -4)'))
952
+ assert_equal('abcdX', evaluate('str-insert(abcd, X, -1)'))
953
+ end
954
+
955
+ def test_str_insert_maintains_quote_of_primary_string
956
+ assert_equal('"Xfoo"', evaluate('str-insert("foo", X, 1)'))
957
+ assert_equal('"Xfoo"', evaluate('str-insert("foo", "X", 1)'))
958
+ assert_equal('Xfoo', evaluate('str-insert(foo, "X", 1)'))
959
+ end
960
+
961
+ def test_str_insert_asserts_types
962
+ assert_error_message("$string: #ff0000 is not a string for `str-insert'", "str-insert(#f00, X, 1)")
963
+ assert_error_message("$insert: #ff0000 is not a string for `str-insert'", "str-insert(foo, #f00, 1)")
964
+ assert_error_message("$index: #ff0000 is not a number for `str-insert'", "str-insert(foo, X, #f00)")
965
+ assert_error_message("Expected $index to be unitless but got 10px for `str-insert'", "str-insert(foo, X, 10px)")
966
+ end
967
+
968
+ def test_str_index
969
+ assert_equal('1', evaluate('str-index(abcd, a)'))
970
+ assert_equal('1', evaluate('str-index(abcd, ab)'))
971
+ assert_equal(Sass::Script::Value::Null.new, perform('str-index(abcd, X)'))
972
+ assert_equal('3', evaluate('str-index(abcd, c)'))
973
+ end
974
+
975
+ def test_str_index_asserts_types
976
+ assert_error_message("$string: #ff0000 is not a string for `str-index'", "str-index(#f00, X)")
977
+ assert_error_message("$substring: #ff0000 is not a string for `str-index'", "str-index(asdf, #f00)")
978
+ end
979
+
980
+ def test_to_lower_case
981
+ assert_equal('abcd', evaluate('to-lower-case(ABCD)'))
982
+ assert_equal('"abcd"', evaluate('to-lower-case("ABCD")'))
983
+ assert_error_message("$string: #ff0000 is not a string for `to-lower-case'", "to-lower-case(#f00)")
984
+ end
985
+
986
+ def test_to_upper_case
987
+ assert_equal('ABCD', evaluate('to-upper-case(abcd)'))
988
+ assert_equal('"ABCD"', evaluate('to-upper-case("abcd")'))
989
+ assert_error_message("$string: #ff0000 is not a string for `to-upper-case'", "to-upper-case(#f00)")
990
+ end
991
+
992
+ def test_str_slice
993
+ assert_equal('bc', evaluate('str-slice(abcd,2,3)')) # in the middle of the string
994
+ assert_equal('a', evaluate('str-slice(abcd,1,1)')) # when start = end
995
+ assert_equal('ab', evaluate('str-slice(abcd,1,2)')) # for completeness
996
+ assert_equal('abcd', evaluate('str-slice(abcd,1,4)')) # at the end points
997
+ assert_equal('abcd', evaluate('str-slice(abcd,0,4)')) # when start is before the start of the string
998
+ assert_equal('abcd', evaluate('str-slice(abcd,1,100)')) # when end is past the end of the string
999
+ assert_equal('', evaluate('str-slice(abcd,2,1)')) # when end is before start
1000
+ assert_equal('"bc"', evaluate('str-slice("abcd",2,3)')) # when used with a quoted string
1001
+ assert_equal('bcd', evaluate('str-slice(abcd,2)')) # when end is omitted, you get the remainder of the string
1002
+ assert_equal('cd', evaluate('str-slice(abcd,-2)')) # when start is negative, it counts from the beginning
1003
+ assert_equal('bc', evaluate('str-slice(abcd,2,-2)')) # when end is negative it counts in from the end
1004
+ assert_equal('', evaluate('str-slice(abcd,3,-3)')) # when end is negative and comes before the start
1005
+ assert_equal('bc', evaluate('str-slice(abcd,-3,-2)')) # when both are negative
1006
+ assert_error_message("$string: #ff0000 is not a string for `str-slice'", "str-slice(#f00,2,3)")
1007
+ assert_error_message("$start-at: #ff0000 is not a number for `str-slice'", "str-slice(abcd,#f00,3)")
1008
+ assert_error_message("$end-at: #ff0000 is not a number for `str-slice'", "str-slice(abcd,2,#f00)")
1009
+ assert_error_message("Expected $end-at to be unitless but got 3px for `str-slice'", "str-slice(abcd,2,3px)")
1010
+ assert_error_message("Expected $start-at to be unitless but got 2px for `str-slice'", "str-slice(abcd,2px,3)")
817
1011
  end
818
1012
 
819
1013
  def test_user_defined_function
@@ -825,12 +1019,17 @@ class SassFunctionTest < Test::Unit::TestCase
825
1019
  assert_equal("I'm another user-defined string!", evaluate("-preceding-underscore()"))
826
1020
  end
827
1021
 
828
- def test_options_on_new_literals_fails
829
- assert_error_message(<<MSG, "call-options-on-new-literal()")
830
- The #options attribute is not set on this Sass::Script::String.
1022
+ def test_user_defined_function_using_environment
1023
+ environment = env('variable' => Sass::Script::Value::String.new('The variable'))
1024
+ assert_equal("The variable", evaluate("fetch_the_variable()", environment))
1025
+ end
1026
+
1027
+ def test_options_on_new_values_fails
1028
+ assert_error_message(<<MSG, "call-options-on-new-value()")
1029
+ The #options attribute is not set on this Sass::Script::Value::String.
831
1030
  This error is probably occurring because #to_s was called
832
- on this literal within a custom Sass function without first
833
- setting the #option attribute.
1031
+ on this value within a custom Sass function without first
1032
+ setting the #options attribute.
834
1033
  MSG
835
1034
  end
836
1035
 
@@ -841,6 +1040,23 @@ MSG
841
1040
  assert_equal("bool", evaluate("type-of(true)"))
842
1041
  assert_equal("color", evaluate("type-of(#fff)"))
843
1042
  assert_equal("color", evaluate("type-of($value: #fff)"))
1043
+ assert_equal("null", evaluate("type-of(null)"))
1044
+ assert_equal("list", evaluate("type-of(1 2 3)"))
1045
+ assert_equal("list", evaluate("type-of((1, 2, 3))"))
1046
+ assert_equal("list", evaluate("type-of(())"))
1047
+ assert_equal("map", evaluate("type-of((foo: bar))"))
1048
+ end
1049
+
1050
+ def test_feature_exists
1051
+ assert_raises ArgumentError do
1052
+ Sass.add_feature("my-test-feature")
1053
+ end
1054
+ Sass.add_feature("-my-test-feature")
1055
+ assert_equal("true", evaluate("feature-exists(-my-test-feature)"))
1056
+ assert_equal("false", evaluate("feature-exists(whatisthisidontevenknow)"))
1057
+ assert_equal("true", evaluate("feature-exists($feature: -my-test-feature)"))
1058
+ ensure
1059
+ Sass::Features::KNOWN_FEATURES.delete("-my-test-feature")
844
1060
  end
845
1061
 
846
1062
  def test_unit
@@ -848,25 +1064,45 @@ MSG
848
1064
  assert_equal(%Q{"px"}, evaluate("unit(100px)"))
849
1065
  assert_equal(%Q{"em*px"}, evaluate("unit(10px * 5em)"))
850
1066
  assert_equal(%Q{"em*px"}, evaluate("unit(5em * 10px)"))
851
- assert_equal(%Q{"em*px/cm*rem"}, evaluate("unit(10px * 5em / 30cm / 1rem)"))
1067
+ assert_equal(%Q{"em/rem"}, evaluate("unit(10px * 5em / 30cm / 1rem)"))
1068
+ assert_equal(%Q{"em*vh/cm*rem"}, evaluate("unit(10vh * 5em / 30cm / 1rem)"))
852
1069
  assert_equal(%Q{"px"}, evaluate("unit($number: 100px)"))
853
- assert_error_message("#ff0000 is not a number for `unit'", "unit(#f00)")
1070
+ assert_error_message("$number: #ff0000 is not a number for `unit'", "unit(#f00)")
854
1071
  end
855
1072
 
856
1073
  def test_unitless
857
1074
  assert_equal(%Q{true}, evaluate("unitless(100)"))
858
1075
  assert_equal(%Q{false}, evaluate("unitless(100px)"))
859
1076
  assert_equal(%Q{false}, evaluate("unitless($number: 100px)"))
860
- assert_error_message("#ff0000 is not a number for `unitless'", "unitless(#f00)")
1077
+ assert_error_message("$number: #ff0000 is not a number for `unitless'", "unitless(#f00)")
861
1078
  end
862
1079
 
863
1080
  def test_comparable
864
1081
  assert_equal(%Q{true}, evaluate("comparable(2px, 1px)"))
865
1082
  assert_equal(%Q{true}, evaluate("comparable(10cm, 3mm)"))
866
1083
  assert_equal(%Q{false}, evaluate("comparable(100px, 3em)"))
867
- assert_equal(%Q{false}, evaluate("comparable($number-1: 100px, $number-2: 3em)"))
868
- assert_error_message("#ff0000 is not a number for `comparable'", "comparable(#f00, 1px)")
869
- assert_error_message("#ff0000 is not a number for `comparable'", "comparable(1px, #f00)")
1084
+ assert_equal(%Q{false}, evaluate("comparable($number1: 100px, $number2: 3em)"))
1085
+ end
1086
+
1087
+ def test_comparable_deprecated_arg_name
1088
+ assert_warning <<WARNING do
1089
+ DEPRECATION WARNING: The `$number-1' argument for `comparable()' has been renamed to `$number1'.
1090
+ DEPRECATION WARNING: The `$number-2' argument for `comparable()' has been renamed to `$number2'.
1091
+ WARNING
1092
+ assert_equal("false", evaluate("comparable($number-1: 100px, $number-2: 3em)"))
1093
+ end
1094
+
1095
+ assert_warning <<WARNING do
1096
+ DEPRECATION WARNING: The `$number_1' argument for `comparable()' has been renamed to `$number1'.
1097
+ DEPRECATION WARNING: The `$number_2' argument for `comparable()' has been renamed to `$number2'.
1098
+ WARNING
1099
+ assert_equal("false", evaluate("comparable($number_1: 100px, $number_2: 3em)"))
1100
+ end
1101
+ end
1102
+
1103
+ def test_comparable_checks_types
1104
+ assert_error_message("$number1: #ff0000 is not a number for `comparable'", "comparable(#f00, 1px)")
1105
+ assert_error_message("$number2: #ff0000 is not a number for `comparable'", "comparable(1px, #f00)")
870
1106
  end
871
1107
 
872
1108
  def test_length
@@ -877,20 +1113,47 @@ MSG
877
1113
  assert_equal("1", evaluate("length(#f00)"))
878
1114
  assert_equal("0", evaluate("length(())"))
879
1115
  assert_equal("4", evaluate("length(1 2 () 3)"))
1116
+
1117
+ assert_equal("2", evaluate("length((foo: bar, bar: baz))"))
880
1118
  end
881
1119
 
882
1120
  def test_nth
883
1121
  assert_equal("1", evaluate("nth(1 2 3, 1)"))
884
1122
  assert_equal("2", evaluate("nth(1 2 3, 2)"))
1123
+ assert_equal("3", evaluate("nth(1 2 3, -1)"))
1124
+ assert_equal("1", evaluate("nth(1 2 3, -3)"))
885
1125
  assert_equal("3", evaluate("nth((1, 2, 3), 3)"))
1126
+ assert_equal("3", evaluate("nth($list: (1, 2, 3), $n: 3)"))
886
1127
  assert_equal("foo", evaluate("nth(foo, 1)"))
887
1128
  assert_equal("bar baz", evaluate("nth(foo (bar baz) bang, 2)"))
888
- assert_error_message("List index 0 must be greater than or equal to 1 for `nth'", "nth(foo, 0)")
889
- assert_error_message("List index -10 must be greater than or equal to 1 for `nth'", "nth(foo, -10)")
890
- assert_error_message("List index 1.5 must be an integer for `nth'", "nth(foo, 1.5)")
1129
+ assert_error_message("List index 0 must be a non-zero integer for `nth'", "nth(foo, 0)")
1130
+ assert_error_message("List index is -10 but list is only 1 item long for `nth'", "nth(foo, -10)")
1131
+ assert_error_message("List index 1.5 must be a non-zero integer for `nth'", "nth(foo, 1.5)")
891
1132
  assert_error_message("List index is 5 but list is only 4 items long for `nth'", "nth(1 2 3 4, 5)")
892
1133
  assert_error_message("List index is 2 but list is only 1 item long for `nth'", "nth(foo, 2)")
893
1134
  assert_error_message("List index is 1 but list has no items for `nth'", "nth((), 1)")
1135
+ assert_error_message("$n: \"foo\" is not a number for `nth'", "nth(1 2 3, foo)")
1136
+
1137
+ assert_equal("foo bar", evaluate("nth((foo: bar, bar: baz), 1)"))
1138
+ assert_equal("bar baz", evaluate("nth((foo: bar, bar: baz), 2)"))
1139
+ end
1140
+
1141
+ def test_set_nth
1142
+ assert_equal("a 2 3", evaluate("set-nth(1 2 3, 1, a)"))
1143
+ assert_equal("1 a 3", evaluate("set-nth(1 2 3, 2, a)"))
1144
+ assert_equal("1 2 a", evaluate("set-nth(1 2 3, -1, a)"))
1145
+ assert_equal("a 2 3", evaluate("set-nth(1 2 3, -3, a)"))
1146
+ assert_equal("a 2 3", evaluate("set-nth($list: 1 2 3, $n: -3, $value: a)"))
1147
+ assert_equal("1, 2, a", evaluate("set-nth((1, 2, 3), 3, a)"))
1148
+ assert_equal("a", evaluate("set-nth(foo, 1, a)"))
1149
+ assert_equal("foo, a b, baz", evaluate("set-nth((foo, bar, baz), 2, (a b))"))
1150
+ assert_error_message("List index 0 must be a non-zero integer for `set-nth'", "set-nth(foo, 0, a)")
1151
+ assert_error_message("List index is -10 but list is only 1 item long for `set-nth'", "set-nth(foo, -10, a)")
1152
+ assert_error_message("List index 1.5 must be a non-zero integer for `set-nth'", "set-nth(foo, 1.5, a)")
1153
+ 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)")
1154
+ assert_error_message("List index is 2 but list is only 1 item long for `set-nth'", "set-nth(foo, 2, a)")
1155
+ assert_error_message("List index is 1 but list has no items for `set-nth'", "set-nth((), 1, a)")
1156
+ assert_error_message("$n: \"foo\" is not a number for `set-nth'", "set-nth(1 2 3, foo, a)")
894
1157
  end
895
1158
 
896
1159
  def test_join
@@ -929,6 +1192,20 @@ MSG
929
1192
  assert_equal("false", evaluate("(1, 2, ()) == join((), (1, 2))"))
930
1193
 
931
1194
  assert_error_message("Separator name must be space, comma, or auto for `join'", "join(1, 2, baboon)")
1195
+ assert_error_message("$separator: 12 is not a string for `join'", "join(1, 2, 12)")
1196
+
1197
+ assert_equal("foo bar, bar baz, baz bip, bip bop",
1198
+ perform("join((foo: bar, bar: baz), (baz: bip, bip: bop))").to_sass)
1199
+ assert_equal("(foo bar) (bar baz) (baz bip) (bip bop)",
1200
+ perform("join((foo: bar, bar: baz), (baz: bip, bip: bop), space)").to_sass)
1201
+ assert_equal("foo bar (baz bip) (bip bop)",
1202
+ perform("join(foo bar, (baz: bip, bip: bop))").to_sass)
1203
+ assert_equal("foo bar, bar baz, bip, bop",
1204
+ perform("join((foo: bar, bar: baz), bip bop)").to_sass)
1205
+ assert_equal("baz bip, bip bop",
1206
+ perform("join((), (baz: bip, bip: bop))").to_sass)
1207
+ assert_equal("foo bar, bar baz",
1208
+ perform("join((foo: bar, bar: baz), ())").to_sass)
932
1209
  end
933
1210
 
934
1211
  def test_append
@@ -963,11 +1240,145 @@ MSG
963
1240
  assert_equal("true", evaluate("(1 2) == nth(append((), 1 2), 1)"))
964
1241
 
965
1242
  assert_error_message("Separator name must be space, comma, or auto for `append'", "append(1, 2, baboon)")
1243
+ assert_error_message("$separator: 12 is not a string for `append'", "append(1, 2, 12)")
1244
+
1245
+ assert_equal("1 2 (foo: bar)", perform("append(1 2, (foo: bar))").to_sass)
1246
+ assert_equal("foo bar, bar baz, 1", perform("append((foo: bar, bar: baz), 1)").to_sass)
1247
+ assert_equal("foo bar, bar baz, (baz: bip)",
1248
+ perform("append((foo: bar, bar: baz), (baz: bip))").to_sass)
1249
+ end
1250
+
1251
+ def test_zip
1252
+ assert_equal("1 3 5, 2 4 6", evaluate("zip(1 2, 3 4, 5 6)"))
1253
+ assert_equal("1 4 7, 2 5 8", evaluate("zip(1 2 3, 4 5 6, 7 8)"))
1254
+ assert_equal("1 2 3", evaluate("zip(1, 2, 3)"))
1255
+ assert_equal("(foo bar) 1 3, (bar baz) 2 4",
1256
+ perform("zip((foo: bar, bar: baz), 1 2, 3 4)").to_sass)
1257
+ end
1258
+
1259
+ def test_index
1260
+ assert_equal("1", evaluate("index(1px solid blue, 1px)"))
1261
+ assert_equal("2", evaluate("index(1px solid blue, solid)"))
1262
+ assert_equal("3", evaluate("index(1px solid blue, #00f)"))
1263
+ assert_equal("1", evaluate("index(1px, 1px)"))
1264
+ assert_equal("false", evaluate("index(1px solid blue, 1em)"))
1265
+ assert_equal("false", evaluate("index(1px solid blue, notfound)"))
1266
+ assert_equal("false", evaluate("index(1px, #00f)"))
1267
+
1268
+ assert_equal("1", evaluate("index((foo: bar, bar: baz), (foo bar))"))
1269
+ assert_equal("false", evaluate("index((foo: bar, bar: baz), (foo: bar))"))
1270
+ end
1271
+
1272
+ def test_index_deprecation_warning
1273
+ assert_warning(<<WARNING) do
1274
+ DEPRECATION WARNING: The return value of index() will change from "false" to
1275
+ "null" in future versions of Sass. For compatibility, avoid using "== false" on
1276
+ the return value. For example, instead of "@if index(...) == false", just write
1277
+ "@if index(...)".
1278
+ WARNING
1279
+ assert_equal("true", evaluate("index(1, 2 3 4) == false"))
1280
+ end
1281
+
1282
+ assert_warning(<<WARNING) do
1283
+ DEPRECATION WARNING: The return value of index() will change from "false" to
1284
+ "null" in future versions of Sass. For compatibility, avoid using "!= null" on
1285
+ the return value.
1286
+ WARNING
1287
+ assert_equal("true", evaluate("index(1, 2 3 4) != null"))
1288
+ end
1289
+
1290
+ assert_warning(<<WARNING) do
1291
+ DEPRECATION WARNING: The return value of index() will change from "false" to
1292
+ "null" in future versions of Sass. For compatibility, avoid using "== false" on
1293
+ the return value. For example, instead of "@if index(...) == false", just write
1294
+ "@if index(...)".
1295
+ WARNING
1296
+ assert_equal("true", evaluate("false == index(1, 2 3 4)"))
1297
+ end
1298
+
1299
+ assert_warning(<<WARNING) do
1300
+ DEPRECATION WARNING: The return value of index() will change from "false" to
1301
+ "null" in future versions of Sass. For compatibility, avoid using "!= null" on
1302
+ the return value.
1303
+ WARNING
1304
+ assert_equal("true", evaluate("null != index(1, 2 3 4)"))
1305
+ end
1306
+ end
1307
+
1308
+ def test_index_deprecation_warning_is_only_emitted_once_per_call
1309
+ assert_warning(<<WARNING) do
1310
+ DEPRECATION WARNING: The return value of index() will change from "false" to
1311
+ "null" in future versions of Sass. For compatibility, avoid using "== false" on
1312
+ the return value. For example, instead of "@if index(...) == false", just write
1313
+ "@if index(...)".
1314
+ on line 3 of test_index_deprecation_warning_is_only_emitted_once_per_call_inline.scss
1315
+ DEPRECATION WARNING: The return value of index() will change from "false" to
1316
+ "null" in future versions of Sass. For compatibility, avoid using "== false" on
1317
+ the return value. For example, instead of "@if index(...) == false", just write
1318
+ "@if index(...)".
1319
+ on line 6 of test_index_deprecation_warning_is_only_emitted_once_per_call_inline.scss
1320
+ WARNING
1321
+ render(<<SCSS)
1322
+ @for $i from 1 to 10 {
1323
+ $var1: index(1, 2 3 4);
1324
+ $var2: $var1 == false;
1325
+ $var3: $var1 != null;
1326
+ }
1327
+ $var4: index(1, 2 3 4) == false;
1328
+ SCSS
1329
+ end
1330
+ end
1331
+
1332
+ def test_list_separator
1333
+ assert_equal("space", evaluate("list-separator(1 2 3 4 5)"))
1334
+ assert_equal("comma", evaluate("list-separator((foo, bar, baz, bip))"))
1335
+ assert_equal("comma", evaluate("list-separator((foo, bar, baz bip))"))
1336
+ assert_equal("comma", evaluate("list-separator((foo, bar, (baz, bip)))"))
1337
+ assert_equal("space", evaluate("list-separator(#f00)"))
1338
+ assert_equal("space", evaluate("list-separator(())"))
1339
+ assert_equal("space", evaluate("list-separator(1 2 () 3)"))
1340
+
1341
+ assert_equal("comma", evaluate("list-separator((foo: bar, bar: baz))"))
966
1342
  end
967
1343
 
968
1344
  def test_if
969
1345
  assert_equal("1px", evaluate("if(true, 1px, 2px)"))
970
1346
  assert_equal("2px", evaluate("if(false, 1px, 2px)"))
1347
+ assert_equal("2px", evaluate("if(null, 1px, 2px)"))
1348
+ assert_equal("1px", evaluate("if(true, 1px, $broken)"))
1349
+ assert_equal("1px", evaluate("if(false, $broken, 1px)"))
1350
+ assert_equal("1px", evaluate("if(false, $if-true: $broken, $if-false: 1px)"))
1351
+ assert_equal("1px", evaluate("if(true, $if-true: 1px, $if-false: $broken)"))
1352
+ assert_equal(<<CSS, render(<<SCSS))
1353
+ .if {
1354
+ result: yay; }
1355
+ CSS
1356
+ .if {
1357
+ $something: yay;
1358
+ result: if(true, $if-true: $something, $if-false: $broken);
1359
+ }
1360
+ SCSS
1361
+ assert_equal(<<CSS, render(<<SCSS))
1362
+ .if {
1363
+ result: 1px; }
1364
+ CSS
1365
+ .if {
1366
+ $splat: 1px, 2px;
1367
+ result: if(true, $splat...);
1368
+ }
1369
+ SCSS
1370
+ end
1371
+
1372
+ def test_counter
1373
+ assert_equal("counter(foo)", evaluate("counter(foo)"))
1374
+ assert_equal('counter(item,".")', evaluate('counter(item, ".")'))
1375
+ assert_equal('counter(item,".")', evaluate('counter(item,".")'))
1376
+ end
1377
+
1378
+ def test_counters
1379
+ assert_equal("counters(foo)", evaluate("counters(foo)"))
1380
+ assert_equal('counters(item,".")', evaluate('counters(item, ".")'))
1381
+ assert_equal('counters(item,".")', evaluate('counters(item,".")'))
971
1382
  end
972
1383
 
973
1384
  def test_keyword_args_rgb
@@ -980,23 +1391,47 @@ MSG
980
1391
  end
981
1392
 
982
1393
  def test_keyword_args_rgba_with_extra_args
983
- assert_equal(%Q{rgba(255, 255, 255, 0.5)}, evaluate("rgba($red: 255, $green: 255, $blue: 255, $alpha: 0.5, $extra: error)"))
1394
+ evaluate("rgba($red: 255, $green: 255, $blue: 255, $alpha: 0.5, $extra: error)")
1395
+ flunk("Expected exception")
984
1396
  rescue Sass::SyntaxError => e
985
- assert_equal("Function rgba doesn't take an argument named $extra", e.message)
1397
+ assert_equal("Function rgba doesn't have an argument named $extra", e.message)
986
1398
  end
987
1399
 
988
1400
  def test_keyword_args_must_have_signature
989
1401
  evaluate("no-kw-args($fake: value)")
1402
+ flunk("Expected exception")
990
1403
  rescue Sass::SyntaxError => e
991
1404
  assert_equal("Function no_kw_args doesn't support keyword arguments", e.message)
992
1405
  end
993
1406
 
994
1407
  def test_keyword_args_with_missing_argument
995
1408
  evaluate("rgb($red: 255, $green: 255)")
1409
+ flunk("Expected exception")
996
1410
  rescue Sass::SyntaxError => e
997
1411
  assert_equal("Function rgb requires an argument named $blue", e.message)
998
1412
  end
999
1413
 
1414
+ def test_keyword_args_with_extra_argument
1415
+ evaluate("rgb($red: 255, $green: 255, $blue: 255, $purple: 255)")
1416
+ flunk("Expected exception")
1417
+ rescue Sass::SyntaxError => e
1418
+ assert_equal("Function rgb doesn't have an argument named $purple", e.message)
1419
+ end
1420
+
1421
+ def test_keyword_args_with_positional_and_keyword_argument
1422
+ evaluate("rgb(255, 255, 255, $red: 255)")
1423
+ flunk("Expected exception")
1424
+ rescue Sass::SyntaxError => e
1425
+ assert_equal("Function rgb was passed argument $red both by position and by name", e.message)
1426
+ end
1427
+
1428
+ def test_keyword_args_with_keyword_before_positional_argument
1429
+ evaluate("rgb($red: 255, 255, 255)")
1430
+ flunk("Expected exception")
1431
+ rescue Sass::SyntaxError => e
1432
+ assert_equal("Positional arguments must come before keyword arguments.", e.message)
1433
+ end
1434
+
1000
1435
  def test_only_var_args
1001
1436
  assert_equal "only-var-args(2px, 3px, 4px)", evaluate("only-var-args(1px, 2px, 3px)")
1002
1437
  end
@@ -1005,14 +1440,439 @@ MSG
1005
1440
  assert_equal "only-kw-args(a, b, c)", evaluate("only-kw-args($a: 1, $b: 2, $c: 3)")
1006
1441
  end
1007
1442
 
1443
+ def test_unique_id
1444
+ last_id, current_id = nil, evaluate("unique-id()")
1445
+
1446
+ 50.times do
1447
+ last_id, current_id = current_id, evaluate("unique-id()")
1448
+ assert_match(/u[a-z0-9]{8}/, current_id)
1449
+ assert_not_equal last_id, current_id
1450
+ end
1451
+ end
1452
+
1453
+ def test_map_get
1454
+ assert_equal "1", evaluate("map-get((foo: 1, bar: 2), foo)")
1455
+ assert_equal "2", evaluate("map-get((foo: 1, bar: 2), bar)")
1456
+ assert_equal "null", perform("map-get((foo: 1, bar: 2), baz)").to_sass
1457
+ assert_equal "null", perform("map-get((), foo)").to_sass
1458
+ end
1459
+
1460
+ def test_map_get_deprecation_warning
1461
+ assert_warning(<<WARNING) do
1462
+ DEPRECATION WARNING: Passing lists of pairs to map-get is deprecated and will
1463
+ be removed in future versions of Sass. Use Sass maps instead. For details, see
1464
+ http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1465
+ WARNING
1466
+ assert_equal "1", evaluate("map-get((foo 1) (bar 2), foo)")
1467
+ end
1468
+ end
1469
+
1470
+ def test_map_get_checks_type
1471
+ assert_error_message("$map: 12 is not a map for `map-get'", "map-get(12, bar)")
1472
+ end
1473
+
1474
+ def test_map_merge
1475
+ assert_equal("(foo: 1, bar: 2, baz: 3)",
1476
+ perform("map-merge((foo: 1, bar: 2), (baz: 3))").to_sass)
1477
+ assert_equal("(foo: 1, bar: 2)",
1478
+ perform("map-merge((), (foo: 1, bar: 2))").to_sass)
1479
+ assert_equal("(foo: 1, bar: 2)",
1480
+ perform("map-merge((foo: 1, bar: 2), ())").to_sass)
1481
+ end
1482
+
1483
+ def test_map_merge_deprecation_warning
1484
+ assert_warning(<<WARNING) do
1485
+ DEPRECATION WARNING: Passing lists of pairs to map-merge is deprecated and will
1486
+ be removed in future versions of Sass. Use Sass maps instead. For details, see
1487
+ http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1488
+ WARNING
1489
+ assert_equal("(foo: 1, bar: 2, baz: 3)",
1490
+ perform("map-merge((foo 1, bar 2), (baz: 3))").to_sass)
1491
+ end
1492
+
1493
+ assert_warning(<<WARNING) do
1494
+ DEPRECATION WARNING: Passing lists of pairs to map-merge is deprecated and will
1495
+ be removed in future versions of Sass. Use Sass maps instead. For details, see
1496
+ http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1497
+ WARNING
1498
+ assert_equal("(baz: 3, foo: 1, bar: 2)",
1499
+ perform("map-merge((baz: 3), (foo 1, bar 2))").to_sass)
1500
+ end
1501
+ end
1502
+
1503
+ def test_map_merge_checks_type
1504
+ assert_error_message("$map1: 12 is not a map for `map-merge'", "map-merge(12, (foo: 1))")
1505
+ assert_error_message("$map2: 12 is not a map for `map-merge'", "map-merge((foo: 1), 12)")
1506
+ end
1507
+
1508
+ def test_map_remove
1509
+ assert_equal("(foo: 1, baz: 3)",
1510
+ perform("map-remove((foo: 1, bar: 2, baz: 3), bar)").to_sass)
1511
+ assert_equal("()", perform("map-remove((), foo)").to_sass)
1512
+ end
1513
+
1514
+ def test_map_remove_deprecation_warning
1515
+ assert_warning(<<WARNING) do
1516
+ DEPRECATION WARNING: Passing lists of pairs to map-remove is deprecated and will
1517
+ be removed in future versions of Sass. Use Sass maps instead. For details, see
1518
+ http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1519
+ WARNING
1520
+ assert_equal("(foo: 1, baz: 3)",
1521
+ perform("map-remove((foo 1, bar 2, baz 3), bar)").to_sass)
1522
+ end
1523
+ end
1524
+
1525
+ def test_map_remove_checks_type
1526
+ assert_error_message("$map: 12 is not a map for `map-remove'", "map-remove(12, foo)")
1527
+ end
1528
+
1529
+ def test_map_keys
1530
+ assert_equal("foo, bar",
1531
+ perform("map-keys((foo: 1, bar: 2))").to_sass)
1532
+ assert_equal("()", perform("map-keys(())").to_sass)
1533
+ end
1534
+
1535
+ def test_map_keys_deprecation_warning
1536
+ assert_warning(<<WARNING) do
1537
+ DEPRECATION WARNING: Passing lists of pairs to map-keys is deprecated and will
1538
+ be removed in future versions of Sass. Use Sass maps instead. For details, see
1539
+ http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1540
+ WARNING
1541
+ assert_equal("foo, bar",
1542
+ perform("map-keys((foo 1, bar 2))").to_sass)
1543
+ end
1544
+ end
1545
+
1546
+ def test_map_keys_checks_type
1547
+ assert_error_message("$map: 12 is not a map for `map-keys'", "map-keys(12)")
1548
+ end
1549
+
1550
+ def test_map_values
1551
+ assert_equal("1, 2", perform("map-values((foo: 1, bar: 2))").to_sass)
1552
+ assert_equal("1, 2, 2",
1553
+ perform("map-values((foo: 1, bar: 2, baz: 2))").to_sass)
1554
+ assert_equal("()", perform("map-values(())").to_sass)
1555
+ end
1556
+
1557
+ def test_map_values_deprecation_warning
1558
+ assert_warning(<<WARNING) do
1559
+ DEPRECATION WARNING: Passing lists of pairs to map-values is deprecated and will
1560
+ be removed in future versions of Sass. Use Sass maps instead. For details, see
1561
+ http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1562
+ WARNING
1563
+ assert_equal("1, 2", perform("map-values((foo 1, bar 2))").to_sass)
1564
+ end
1565
+ end
1566
+
1567
+ def test_map_values_checks_type
1568
+ assert_error_message("$map: 12 is not a map for `map-values'", "map-values(12)")
1569
+ end
1570
+
1571
+ def test_map_has_key
1572
+ assert_equal "true", evaluate("map-has-key((foo: 1, bar: 1), foo)")
1573
+ assert_equal "false", evaluate("map-has-key((foo: 1, bar: 1), baz)")
1574
+ assert_equal "false", evaluate("map-has-key((), foo)")
1575
+ end
1576
+
1577
+ def test_map_has_key_deprecation_warning
1578
+ assert_warning(<<WARNING) do
1579
+ DEPRECATION WARNING: Passing lists of pairs to map-has-key is deprecated and will
1580
+ be removed in future versions of Sass. Use Sass maps instead. For details, see
1581
+ http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1582
+ WARNING
1583
+ assert_equal("true", evaluate("map-has-key((foo 1, bar 1), foo)"))
1584
+ end
1585
+ end
1586
+
1587
+ def test_map_has_key_checks_type
1588
+ assert_error_message("$map: 12 is not a map for `map-has-key'", "map-has-key(12, foo)")
1589
+ end
1590
+
1591
+ def test_keywords
1592
+ # The actual functionality is tested in tests where real arglists are passed.
1593
+ assert_error_message("$args: 12 is not a variable argument list for `keywords'", "keywords(12)")
1594
+ assert_error_message(
1595
+ "$args: (1 2 3) is not a variable argument list for `keywords'", "keywords(1 2 3)")
1596
+ end
1597
+
1598
+ def test_partial_list_of_pairs_doesnt_work_as_a_map
1599
+ assert_raises(Sass::SyntaxError) {evaluate("map-get((foo bar, baz bang, bip), 1)")}
1600
+ assert_raises(Sass::SyntaxError) {evaluate("map-get((foo bar, baz bang, bip bap bop), 1)")}
1601
+ assert_raises(Sass::SyntaxError) {evaluate("map-get((foo bar), 1)")}
1602
+ end
1603
+
1604
+ def test_assert_unit
1605
+ ctx = Sass::Script::Functions::EvaluationContext.new(Sass::Environment.new(nil, {}))
1606
+ ctx.assert_unit Sass::Script::Value::Number.new(10, ["px"], []), "px"
1607
+ ctx.assert_unit Sass::Script::Value::Number.new(10, [], []), nil
1608
+
1609
+ begin
1610
+ ctx.assert_unit Sass::Script::Value::Number.new(10, [], []), "px"
1611
+ fail
1612
+ rescue ArgumentError => e
1613
+ assert_equal "Expected 10 to have a unit of px", e.message
1614
+ end
1615
+
1616
+ begin
1617
+ ctx.assert_unit Sass::Script::Value::Number.new(10, ["px"], []), nil
1618
+ fail
1619
+ rescue ArgumentError => e
1620
+ assert_equal "Expected 10px to be unitless", e.message
1621
+ end
1622
+
1623
+ begin
1624
+ ctx.assert_unit Sass::Script::Value::Number.new(10, [], []), "px", "arg"
1625
+ fail
1626
+ rescue ArgumentError => e
1627
+ assert_equal "Expected $arg to have a unit of px but got 10", e.message
1628
+ end
1629
+
1630
+ begin
1631
+ ctx.assert_unit Sass::Script::Value::Number.new(10, ["px"], []), nil, "arg"
1632
+ fail
1633
+ rescue ArgumentError => e
1634
+ assert_equal "Expected $arg to be unitless but got 10px", e.message
1635
+ end
1636
+ end
1637
+
1638
+ def test_call_with_positional_arguments
1639
+ assert_equal evaluate("lighten(blue, 5%)"), evaluate("call(lighten, blue, 5%)")
1640
+ end
1641
+
1642
+ def test_call_with_keyword_arguments
1643
+ assert_equal(
1644
+ evaluate("lighten($color: blue, $amount: 5%)"),
1645
+ evaluate("call(lighten, $color: blue, $amount: 5%)"))
1646
+ end
1647
+
1648
+ def test_call_with_keyword_and_positional_arguments
1649
+ assert_equal(
1650
+ evaluate("lighten(blue, $amount: 5%)"),
1651
+ evaluate("call(lighten, blue, $amount: 5%)"))
1652
+ end
1653
+
1654
+ def test_call_with_dynamic_name
1655
+ assert_equal(
1656
+ evaluate("lighten($color: blue, $amount: 5%)"),
1657
+ evaluate("call($fn, $color: blue, $amount: 5%)",
1658
+ env("fn" => Sass::Script::String.new("lighten"))))
1659
+ end
1660
+
1661
+ def test_call_uses_local_scope
1662
+ assert_equal <<CSS, render(<<SCSS)
1663
+ .first-scope {
1664
+ a: local; }
1665
+
1666
+ .second-scope {
1667
+ a: global; }
1668
+ CSS
1669
+ @function foo() {@return global}
1670
+
1671
+ .first-scope {
1672
+ @function foo() {@return local}
1673
+ a: call(foo);
1674
+ }
1675
+
1676
+ .second-scope {
1677
+ a: call(foo);
1678
+ }
1679
+ SCSS
1680
+ end
1681
+
1682
+ def test_call_unknown_function
1683
+ assert_equal evaluate("unknown(red, blue)"), evaluate("call(unknown, red, blue)")
1684
+ end
1685
+
1686
+ def test_call_with_non_string_argument
1687
+ assert_error_message "$name: 3px is not a string for `call'", "call(3px)"
1688
+ end
1689
+
1690
+ def test_errors_in_called_function
1691
+ assert_error_message "$color: 3px is not a color for `lighten'", "call(lighten, 3px, 5%)"
1692
+ end
1693
+
1694
+ def test_variable_exists
1695
+ assert_equal <<CSS, render(<<SCSS)
1696
+ .test {
1697
+ false: false;
1698
+ true: true;
1699
+ true: true;
1700
+ true: true;
1701
+ true: true; }
1702
+ CSS
1703
+ $global-var: has-value;
1704
+ .test {
1705
+ false: variable-exists(foo);
1706
+ $foo: has-value;
1707
+ true: variable-exists(foo);
1708
+ true: variable-exists($name: foo);
1709
+ true: variable-exists(global-var);
1710
+ true: variable-exists($name: global-var);
1711
+ }
1712
+ SCSS
1713
+ end
1714
+
1715
+ def test_variable_exists_checks_type
1716
+ assert_error_message("$name: 1 is not a string for `variable-exists'", "variable-exists(1)")
1717
+ end
1718
+
1719
+ def test_global_variable_exists
1720
+ assert_equal <<CSS, render(<<SCSS)
1721
+ .test {
1722
+ false: false;
1723
+ false: false;
1724
+ true: true;
1725
+ true: true;
1726
+ false: false;
1727
+ true: true;
1728
+ true: true; }
1729
+ CSS
1730
+ $g: something;
1731
+ $h: null;
1732
+ $false: global-variable-exists(foo);
1733
+ $true: global-variable-exists(g);
1734
+ $named: global-variable-exists($name: g);
1735
+ .test {
1736
+ $foo: locally-defined;
1737
+ false: global-variable-exists(foo);
1738
+ false: global-variable-exists(foo2);
1739
+ true: global-variable-exists(g);
1740
+ true: global-variable-exists(h);
1741
+ false: $false;
1742
+ true: $true;
1743
+ true: $named;
1744
+ }
1745
+ SCSS
1746
+ end
1747
+
1748
+ def test_global_variable_exists_checks_type
1749
+ assert_error_message("$name: 1 is not a string for `global-variable-exists'",
1750
+ "global-variable-exists(1)")
1751
+ end
1752
+
1753
+ def test_function_exists
1754
+ # built-ins
1755
+ assert_equal "true", evaluate("function-exists(lighten)")
1756
+ # with named argument
1757
+ assert_equal "true", evaluate("function-exists($name: lighten)")
1758
+ # user-defined
1759
+ assert_equal <<CSS, render(<<SCSS)
1760
+ .test {
1761
+ foo-exists: true;
1762
+ bar-exists: false; }
1763
+ CSS
1764
+ @function foo() { @return "foo" }
1765
+ .test {
1766
+ foo-exists: function-exists(foo);
1767
+ bar-exists: function-exists(bar);
1768
+ }
1769
+ SCSS
1770
+ end
1771
+
1772
+ def test_function_exists_checks_type
1773
+ assert_error_message("$name: 1 is not a string for `function-exists'", "function-exists(1)")
1774
+ end
1775
+
1776
+ def test_mixin_exists
1777
+ assert_equal "false", evaluate("mixin-exists(foo)")
1778
+ # with named argument
1779
+ assert_equal "false", evaluate("mixin-exists($name: foo)")
1780
+ assert_equal <<CSS, render(<<SCSS)
1781
+ .test {
1782
+ foo-exists: true;
1783
+ bar-exists: false; }
1784
+ CSS
1785
+ @mixin foo() { foo: exists }
1786
+ .test {
1787
+ foo-exists: mixin-exists(foo);
1788
+ bar-exists: mixin-exists(bar);
1789
+ }
1790
+ SCSS
1791
+ end
1792
+
1793
+ def test_mixin_exists_checks_type
1794
+ assert_error_message("$name: 1 is not a string for `mixin-exists'", "mixin-exists(1)")
1795
+ end
1796
+
1797
+ def test_inspect
1798
+ assert_equal "()", evaluate("inspect(())")
1799
+ assert_equal "null", evaluate("inspect(null)")
1800
+ assert_equal "1px null 3px", evaluate("inspect(1px null 3px)")
1801
+ assert_equal "(a: 1, b: 2)", evaluate("inspect((a: 1, b: 2))")
1802
+ end
1803
+
1804
+ def test_random
1805
+ Sass::Script::Functions.random_seed = 1
1806
+ assert_equal "0.41702", evaluate("random()")
1807
+ assert_equal "13", evaluate("random(100)")
1808
+ end
1809
+
1810
+ def test_random_works_without_a_seed
1811
+ if Sass::Script::Functions.instance_variable_defined?("@random_number_generator")
1812
+ Sass::Script::Functions.send(:remove_instance_variable, "@random_number_generator")
1813
+ end
1814
+
1815
+ result = perform("random()")
1816
+ assert_kind_of Sass::Script::Number, result
1817
+ assert result.value >= 0, "Random number was below 0"
1818
+ assert result.value <= 1, "Random number was above 1"
1819
+ end
1820
+
1821
+ def test_random_with_limit_one
1822
+ # Passing 1 as the limit should always return 1, since limit calls return
1823
+ # integers from 1 to the argument, so when the argument is 1, its a predicatble
1824
+ # outcome
1825
+ assert "1", evaluate("random(1)")
1826
+ end
1827
+
1828
+ def test_random_with_limit_too_low
1829
+ assert_error_message("$limit 0 must be greater than or equal to 1 for `random'", "random(0)")
1830
+ end
1831
+
1832
+ def test_random_with_non_integer_limit
1833
+ assert_error_message("Expected $limit to be an integer but got 1.5 for `random'", "random(1.5)")
1834
+ end
1835
+
1836
+ # This could *possibly* fail, but exceedingly unlikely
1837
+ def test_random_is_semi_unique
1838
+ if Sass::Script::Functions.instance_variable_defined?("@random_number_generator")
1839
+ Sass::Script::Functions.send(:remove_instance_variable, "@random_number_generator")
1840
+ end
1841
+ assert_not_equal evaluate("random()"), evaluate("random()")
1842
+ end
1843
+
1844
+ ## Regression Tests
1845
+
1846
+ def test_inspect_nested_empty_lists
1847
+ assert_equal "() ()", evaluate("inspect(() ())")
1848
+ end
1849
+
1850
+ def test_saturation_bounds
1851
+ assert_equal "#fbfdff", evaluate("hsl(hue(#fbfdff), saturation(#fbfdff), lightness(#fbfdff))")
1852
+ end
1853
+
1008
1854
  private
1855
+ def env(hash = {}, parent = nil)
1856
+ env = Sass::Environment.new(parent)
1857
+ hash.each {|k, v| env.set_var(k, v)}
1858
+ env
1859
+ end
1009
1860
 
1010
- def evaluate(value)
1011
- Sass::Script::Parser.parse(value, 0, 0).perform(Sass::Environment.new).to_s
1861
+ def evaluate(value, environment = env)
1862
+ result = perform(value, environment)
1863
+ assert_kind_of Sass::Script::Value::Base, result
1864
+ return result.to_s
1012
1865
  end
1013
1866
 
1014
- def perform(value)
1015
- Sass::Script::Parser.parse(value, 0, 0).perform(Sass::Environment.new)
1867
+ def perform(value, environment = env)
1868
+ Sass::Script::Parser.parse(value, 0, 0).perform(environment)
1869
+ end
1870
+
1871
+ def render(sass, options = {})
1872
+ options[:syntax] ||= :scss
1873
+ munge_filename options
1874
+ options[:importer] ||= MockImporter.new
1875
+ Sass::Engine.new(sass, options).render
1016
1876
  end
1017
1877
 
1018
1878
  def assert_error_message(message, value)
@@ -1021,5 +1881,4 @@ MSG
1021
1881
  rescue Sass::SyntaxError => e
1022
1882
  assert_equal(message, e.message)
1023
1883
  end
1024
-
1025
1884
  end