xass 0.1.0

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 (242) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +11 -0
  3. data/CONTRIBUTING +3 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +201 -0
  6. data/Rakefile +349 -0
  7. data/VERSION +1 -0
  8. data/VERSION_NAME +1 -0
  9. data/bin/push +13 -0
  10. data/bin/sass +13 -0
  11. data/bin/sass-convert +12 -0
  12. data/bin/scss +13 -0
  13. data/extra/update_watch.rb +13 -0
  14. data/init.rb +18 -0
  15. data/lib/sass/cache_stores/base.rb +88 -0
  16. data/lib/sass/cache_stores/chain.rb +33 -0
  17. data/lib/sass/cache_stores/filesystem.rb +64 -0
  18. data/lib/sass/cache_stores/memory.rb +47 -0
  19. data/lib/sass/cache_stores/null.rb +25 -0
  20. data/lib/sass/cache_stores.rb +15 -0
  21. data/lib/sass/callbacks.rb +66 -0
  22. data/lib/sass/css.rb +409 -0
  23. data/lib/sass/engine.rb +930 -0
  24. data/lib/sass/environment.rb +101 -0
  25. data/lib/sass/error.rb +201 -0
  26. data/lib/sass/exec.rb +707 -0
  27. data/lib/sass/importers/base.rb +139 -0
  28. data/lib/sass/importers/filesystem.rb +186 -0
  29. data/lib/sass/importers.rb +22 -0
  30. data/lib/sass/logger/base.rb +32 -0
  31. data/lib/sass/logger/log_level.rb +49 -0
  32. data/lib/sass/logger.rb +15 -0
  33. data/lib/sass/media.rb +213 -0
  34. data/lib/sass/plugin/compiler.rb +406 -0
  35. data/lib/sass/plugin/configuration.rb +123 -0
  36. data/lib/sass/plugin/generic.rb +15 -0
  37. data/lib/sass/plugin/merb.rb +48 -0
  38. data/lib/sass/plugin/rack.rb +60 -0
  39. data/lib/sass/plugin/rails.rb +47 -0
  40. data/lib/sass/plugin/staleness_checker.rb +199 -0
  41. data/lib/sass/plugin.rb +133 -0
  42. data/lib/sass/railtie.rb +10 -0
  43. data/lib/sass/repl.rb +57 -0
  44. data/lib/sass/root.rb +7 -0
  45. data/lib/sass/script/arg_list.rb +52 -0
  46. data/lib/sass/script/bool.rb +18 -0
  47. data/lib/sass/script/color.rb +606 -0
  48. data/lib/sass/script/css_lexer.rb +29 -0
  49. data/lib/sass/script/css_parser.rb +31 -0
  50. data/lib/sass/script/funcall.rb +245 -0
  51. data/lib/sass/script/functions.rb +1543 -0
  52. data/lib/sass/script/interpolation.rb +79 -0
  53. data/lib/sass/script/lexer.rb +345 -0
  54. data/lib/sass/script/list.rb +85 -0
  55. data/lib/sass/script/literal.rb +221 -0
  56. data/lib/sass/script/node.rb +99 -0
  57. data/lib/sass/script/null.rb +37 -0
  58. data/lib/sass/script/number.rb +453 -0
  59. data/lib/sass/script/operation.rb +110 -0
  60. data/lib/sass/script/parser.rb +502 -0
  61. data/lib/sass/script/string.rb +51 -0
  62. data/lib/sass/script/string_interpolation.rb +103 -0
  63. data/lib/sass/script/unary_operation.rb +69 -0
  64. data/lib/sass/script/variable.rb +58 -0
  65. data/lib/sass/script.rb +39 -0
  66. data/lib/sass/scss/css_parser.rb +36 -0
  67. data/lib/sass/scss/parser.rb +1180 -0
  68. data/lib/sass/scss/rx.rb +133 -0
  69. data/lib/sass/scss/script_lexer.rb +15 -0
  70. data/lib/sass/scss/script_parser.rb +25 -0
  71. data/lib/sass/scss/static_parser.rb +54 -0
  72. data/lib/sass/scss.rb +16 -0
  73. data/lib/sass/selector/abstract_sequence.rb +94 -0
  74. data/lib/sass/selector/comma_sequence.rb +92 -0
  75. data/lib/sass/selector/sequence.rb +507 -0
  76. data/lib/sass/selector/simple.rb +119 -0
  77. data/lib/sass/selector/simple_sequence.rb +215 -0
  78. data/lib/sass/selector.rb +452 -0
  79. data/lib/sass/shared.rb +76 -0
  80. data/lib/sass/supports.rb +229 -0
  81. data/lib/sass/tree/charset_node.rb +22 -0
  82. data/lib/sass/tree/comment_node.rb +82 -0
  83. data/lib/sass/tree/content_node.rb +9 -0
  84. data/lib/sass/tree/css_import_node.rb +60 -0
  85. data/lib/sass/tree/debug_node.rb +18 -0
  86. data/lib/sass/tree/directive_node.rb +42 -0
  87. data/lib/sass/tree/each_node.rb +24 -0
  88. data/lib/sass/tree/extend_node.rb +36 -0
  89. data/lib/sass/tree/for_node.rb +36 -0
  90. data/lib/sass/tree/function_node.rb +34 -0
  91. data/lib/sass/tree/if_node.rb +52 -0
  92. data/lib/sass/tree/import_node.rb +75 -0
  93. data/lib/sass/tree/media_node.rb +58 -0
  94. data/lib/sass/tree/mixin_def_node.rb +38 -0
  95. data/lib/sass/tree/mixin_node.rb +39 -0
  96. data/lib/sass/tree/node.rb +196 -0
  97. data/lib/sass/tree/prop_node.rb +152 -0
  98. data/lib/sass/tree/return_node.rb +18 -0
  99. data/lib/sass/tree/root_node.rb +78 -0
  100. data/lib/sass/tree/rule_node.rb +132 -0
  101. data/lib/sass/tree/supports_node.rb +51 -0
  102. data/lib/sass/tree/trace_node.rb +32 -0
  103. data/lib/sass/tree/variable_node.rb +30 -0
  104. data/lib/sass/tree/visitors/base.rb +75 -0
  105. data/lib/sass/tree/visitors/check_nesting.rb +147 -0
  106. data/lib/sass/tree/visitors/convert.rb +316 -0
  107. data/lib/sass/tree/visitors/cssize.rb +241 -0
  108. data/lib/sass/tree/visitors/deep_copy.rb +102 -0
  109. data/lib/sass/tree/visitors/extend.rb +68 -0
  110. data/lib/sass/tree/visitors/perform.rb +446 -0
  111. data/lib/sass/tree/visitors/set_options.rb +125 -0
  112. data/lib/sass/tree/visitors/to_css.rb +228 -0
  113. data/lib/sass/tree/warn_node.rb +18 -0
  114. data/lib/sass/tree/while_node.rb +18 -0
  115. data/lib/sass/util/multibyte_string_scanner.rb +155 -0
  116. data/lib/sass/util/subset_map.rb +109 -0
  117. data/lib/sass/util/test.rb +10 -0
  118. data/lib/sass/util.rb +948 -0
  119. data/lib/sass/version.rb +126 -0
  120. data/lib/sass.rb +95 -0
  121. data/rails/init.rb +1 -0
  122. data/test/Gemfile +3 -0
  123. data/test/Gemfile.lock +10 -0
  124. data/test/sass/cache_test.rb +89 -0
  125. data/test/sass/callbacks_test.rb +61 -0
  126. data/test/sass/conversion_test.rb +1760 -0
  127. data/test/sass/css2sass_test.rb +458 -0
  128. data/test/sass/data/hsl-rgb.txt +319 -0
  129. data/test/sass/engine_test.rb +3244 -0
  130. data/test/sass/exec_test.rb +86 -0
  131. data/test/sass/extend_test.rb +1482 -0
  132. data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
  133. data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
  134. data/test/sass/functions_test.rb +1139 -0
  135. data/test/sass/importer_test.rb +192 -0
  136. data/test/sass/logger_test.rb +58 -0
  137. data/test/sass/mock_importer.rb +49 -0
  138. data/test/sass/more_results/more1.css +9 -0
  139. data/test/sass/more_results/more1_with_line_comments.css +26 -0
  140. data/test/sass/more_results/more_import.css +29 -0
  141. data/test/sass/more_templates/_more_partial.sass +2 -0
  142. data/test/sass/more_templates/more1.sass +23 -0
  143. data/test/sass/more_templates/more_import.sass +11 -0
  144. data/test/sass/plugin_test.rb +564 -0
  145. data/test/sass/results/alt.css +4 -0
  146. data/test/sass/results/basic.css +9 -0
  147. data/test/sass/results/cached_import_option.css +3 -0
  148. data/test/sass/results/compact.css +5 -0
  149. data/test/sass/results/complex.css +86 -0
  150. data/test/sass/results/compressed.css +1 -0
  151. data/test/sass/results/expanded.css +19 -0
  152. data/test/sass/results/filename_fn.css +3 -0
  153. data/test/sass/results/if.css +3 -0
  154. data/test/sass/results/import.css +31 -0
  155. data/test/sass/results/import_charset.css +5 -0
  156. data/test/sass/results/import_charset_1_8.css +5 -0
  157. data/test/sass/results/import_charset_ibm866.css +5 -0
  158. data/test/sass/results/import_content.css +1 -0
  159. data/test/sass/results/line_numbers.css +49 -0
  160. data/test/sass/results/mixins.css +95 -0
  161. data/test/sass/results/multiline.css +24 -0
  162. data/test/sass/results/nested.css +22 -0
  163. data/test/sass/results/options.css +1 -0
  164. data/test/sass/results/parent_ref.css +13 -0
  165. data/test/sass/results/script.css +16 -0
  166. data/test/sass/results/scss_import.css +31 -0
  167. data/test/sass/results/scss_importee.css +2 -0
  168. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  169. data/test/sass/results/subdir/subdir.css +3 -0
  170. data/test/sass/results/units.css +11 -0
  171. data/test/sass/results/warn.css +0 -0
  172. data/test/sass/results/warn_imported.css +0 -0
  173. data/test/sass/script_conversion_test.rb +299 -0
  174. data/test/sass/script_test.rb +622 -0
  175. data/test/sass/scss/css_test.rb +1100 -0
  176. data/test/sass/scss/rx_test.rb +156 -0
  177. data/test/sass/scss/scss_test.rb +2106 -0
  178. data/test/sass/scss/test_helper.rb +37 -0
  179. data/test/sass/templates/_cached_import_option_partial.scss +1 -0
  180. data/test/sass/templates/_double_import_loop2.sass +1 -0
  181. data/test/sass/templates/_filename_fn_import.scss +11 -0
  182. data/test/sass/templates/_imported_charset_ibm866.sass +4 -0
  183. data/test/sass/templates/_imported_charset_utf8.sass +4 -0
  184. data/test/sass/templates/_imported_content.sass +3 -0
  185. data/test/sass/templates/_partial.sass +2 -0
  186. data/test/sass/templates/_same_name_different_partiality.scss +1 -0
  187. data/test/sass/templates/alt.sass +16 -0
  188. data/test/sass/templates/basic.sass +23 -0
  189. data/test/sass/templates/bork1.sass +2 -0
  190. data/test/sass/templates/bork2.sass +2 -0
  191. data/test/sass/templates/bork3.sass +2 -0
  192. data/test/sass/templates/bork4.sass +2 -0
  193. data/test/sass/templates/bork5.sass +3 -0
  194. data/test/sass/templates/cached_import_option.scss +3 -0
  195. data/test/sass/templates/compact.sass +17 -0
  196. data/test/sass/templates/complex.sass +305 -0
  197. data/test/sass/templates/compressed.sass +15 -0
  198. data/test/sass/templates/double_import_loop1.sass +1 -0
  199. data/test/sass/templates/expanded.sass +17 -0
  200. data/test/sass/templates/filename_fn.scss +18 -0
  201. data/test/sass/templates/if.sass +11 -0
  202. data/test/sass/templates/import.sass +12 -0
  203. data/test/sass/templates/import_charset.sass +9 -0
  204. data/test/sass/templates/import_charset_1_8.sass +6 -0
  205. data/test/sass/templates/import_charset_ibm866.sass +11 -0
  206. data/test/sass/templates/import_content.sass +4 -0
  207. data/test/sass/templates/importee.less +2 -0
  208. data/test/sass/templates/importee.sass +19 -0
  209. data/test/sass/templates/line_numbers.sass +13 -0
  210. data/test/sass/templates/mixin_bork.sass +5 -0
  211. data/test/sass/templates/mixins.sass +76 -0
  212. data/test/sass/templates/multiline.sass +20 -0
  213. data/test/sass/templates/nested.sass +25 -0
  214. data/test/sass/templates/nested_bork1.sass +2 -0
  215. data/test/sass/templates/nested_bork2.sass +2 -0
  216. data/test/sass/templates/nested_bork3.sass +2 -0
  217. data/test/sass/templates/nested_bork4.sass +2 -0
  218. data/test/sass/templates/nested_import.sass +2 -0
  219. data/test/sass/templates/nested_mixin_bork.sass +6 -0
  220. data/test/sass/templates/options.sass +2 -0
  221. data/test/sass/templates/parent_ref.sass +25 -0
  222. data/test/sass/templates/same_name_different_ext.sass +2 -0
  223. data/test/sass/templates/same_name_different_ext.scss +1 -0
  224. data/test/sass/templates/same_name_different_partiality.scss +1 -0
  225. data/test/sass/templates/script.sass +101 -0
  226. data/test/sass/templates/scss_import.scss +11 -0
  227. data/test/sass/templates/scss_importee.scss +1 -0
  228. data/test/sass/templates/single_import_loop.sass +1 -0
  229. data/test/sass/templates/subdir/import_up1.scss +1 -0
  230. data/test/sass/templates/subdir/import_up2.scss +1 -0
  231. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  232. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  233. data/test/sass/templates/subdir/subdir.sass +6 -0
  234. data/test/sass/templates/units.sass +11 -0
  235. data/test/sass/templates/warn.sass +3 -0
  236. data/test/sass/templates/warn_imported.sass +4 -0
  237. data/test/sass/test_helper.rb +8 -0
  238. data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
  239. data/test/sass/util/subset_map_test.rb +91 -0
  240. data/test/sass/util_test.rb +382 -0
  241. data/test/test_helper.rb +80 -0
  242. metadata +354 -0
@@ -0,0 +1,1139 @@
1
+ #!/usr/bin/env ruby
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/../test_helper'
4
+ require 'sass/script'
5
+
6
+ module Sass::Script::Functions
7
+ def no_kw_args
8
+ Sass::Script::String.new("no-kw-args")
9
+ end
10
+
11
+ 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(", ")+")")
13
+ end
14
+ declare :only_var_args, [], :var_args => true
15
+
16
+ def only_kw_args(kwargs)
17
+ Sass::Script::String.new("only-kw-args(" + kwargs.keys.map {|a| a.to_s}.sort.join(", ") + ")")
18
+ end
19
+ declare :only_kw_args, [], :var_kwargs => true
20
+ end
21
+
22
+ module Sass::Script::Functions::UserFunctions
23
+ def call_options_on_new_literal
24
+ str = Sass::Script::String.new("foo")
25
+ str.options[:foo]
26
+ str
27
+ end
28
+
29
+ def user_defined
30
+ Sass::Script::String.new("I'm a user-defined string!")
31
+ end
32
+
33
+ def _preceding_underscore
34
+ Sass::Script::String.new("I'm another user-defined string!")
35
+ end
36
+ end
37
+
38
+ module Sass::Script::Functions
39
+ include Sass::Script::Functions::UserFunctions
40
+ end
41
+
42
+ class SassFunctionTest < Test::Unit::TestCase
43
+ # Tests taken from:
44
+ # http://www.w3.org/Style/CSS/Test/CSS3/Color/20070927/html4/t040204-hsl-h-rotating-b.htm
45
+ # http://www.w3.org/Style/CSS/Test/CSS3/Color/20070927/html4/t040204-hsl-values-b.htm
46
+ File.read(File.dirname(__FILE__) + "/data/hsl-rgb.txt").split("\n\n").each do |chunk|
47
+ hsls, rgbs = chunk.strip.split("====")
48
+ hsls.strip.split("\n").zip(rgbs.strip.split("\n")) do |hsl, rgb|
49
+ hsl_method = "test_hsl: #{hsl} = #{rgb}"
50
+ unless method_defined?(hsl_method)
51
+ define_method(hsl_method) do
52
+ assert_equal(evaluate(rgb), evaluate(hsl))
53
+ end
54
+ end
55
+
56
+ rgb_to_hsl_method = "test_rgb_to_hsl: #{rgb} = #{hsl}"
57
+ unless method_defined?(rgb_to_hsl_method)
58
+ define_method(rgb_to_hsl_method) do
59
+ rgb_color = perform(rgb)
60
+ hsl_color = perform(hsl)
61
+
62
+ white = hsl_color.lightness == 100
63
+ black = hsl_color.lightness == 0
64
+ grayscale = white || black || hsl_color.saturation == 0
65
+
66
+ assert_in_delta(hsl_color.hue, rgb_color.hue, 0.0001,
67
+ "Hues should be equal") unless grayscale
68
+ assert_in_delta(hsl_color.saturation, rgb_color.saturation, 0.0001,
69
+ "Saturations should be equal") unless white || black
70
+ assert_in_delta(hsl_color.lightness, rgb_color.lightness, 0.0001,
71
+ "Lightnesses should be equal")
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ def test_hsl_kwargs
78
+ assert_equal "#33cccc", evaluate("hsl($hue: 180, $saturation: 60%, $lightness: 50%)")
79
+ end
80
+
81
+ def test_hsl_checks_bounds
82
+ assert_error_message("Saturation -114 must be between 0% and 100% for `hsl'", "hsl(10, -114, 12)");
83
+ assert_error_message("Lightness 256% must be between 0% and 100% for `hsl'", "hsl(10, 10, 256%)");
84
+ end
85
+
86
+ def test_hsl_checks_types
87
+ assert_error_message("$hue: \"foo\" is not a number for `hsl'", "hsl(\"foo\", 10, 12)");
88
+ assert_error_message("$saturation: \"foo\" is not a number for `hsl'", "hsl(10, \"foo\", 12)");
89
+ assert_error_message("$lightness: \"foo\" is not a number for `hsl'", "hsl(10, 10, \"foo\")");
90
+ end
91
+
92
+ def test_hsla
93
+ assert_equal "rgba(51, 204, 204, 0.4)", evaluate("hsla(180, 60%, 50%, 0.4)")
94
+ assert_equal "#33cccc", evaluate("hsla(180, 60%, 50%, 1)")
95
+ assert_equal "rgba(51, 204, 204, 0)", evaluate("hsla(180, 60%, 50%, 0)")
96
+ assert_equal "rgba(51, 204, 204, 0.4)", evaluate("hsla($hue: 180, $saturation: 60%, $lightness: 50%, $alpha: 0.4)")
97
+ end
98
+
99
+ def test_hsla_checks_bounds
100
+ assert_error_message("Saturation -114 must be between 0% and 100% for `hsla'", "hsla(10, -114, 12, 1)");
101
+ assert_error_message("Lightness 256% must be between 0% and 100% for `hsla'", "hsla(10, 10, 256%, 0)");
102
+ assert_error_message("Alpha channel -0.1 must be between 0 and 1 for `hsla'", "hsla(10, 10, 10, -0.1)");
103
+ assert_error_message("Alpha channel 1.1 must be between 0 and 1 for `hsla'", "hsla(10, 10, 10, 1.1)");
104
+ end
105
+
106
+ def test_hsla_checks_types
107
+ assert_error_message("$hue: \"foo\" is not a number for `hsla'", "hsla(\"foo\", 10, 12, 0.3)");
108
+ assert_error_message("$saturation: \"foo\" is not a number for `hsla'", "hsla(10, \"foo\", 12, 0)");
109
+ assert_error_message("$lightness: \"foo\" is not a number for `hsla'", "hsla(10, 10, \"foo\", 1)");
110
+ assert_error_message("$alpha: \"foo\" is not a number for `hsla'", "hsla(10, 10, 10, \"foo\")");
111
+ end
112
+
113
+ def test_percentage
114
+ assert_equal("50%", evaluate("percentage(.5)"))
115
+ assert_equal("100%", evaluate("percentage(1)"))
116
+ assert_equal("25%", evaluate("percentage(25px / 100px)"))
117
+ assert_equal("50%", evaluate("percentage($value: 0.5)"))
118
+ end
119
+
120
+ def test_percentage_checks_types
121
+ assert_error_message("$value: 25px is not a unitless number for `percentage'", "percentage(25px)")
122
+ assert_error_message("$value: #cccccc is not a unitless number for `percentage'", "percentage(#ccc)")
123
+ assert_error_message("$value: \"string\" is not a unitless number for `percentage'", %Q{percentage("string")})
124
+ end
125
+
126
+ def test_round
127
+ assert_equal("5", evaluate("round(4.8)"))
128
+ assert_equal("5px", evaluate("round(4.8px)"))
129
+ assert_equal("5px", evaluate("round(5.49px)"))
130
+ assert_equal("5px", evaluate("round($value: 5.49px)"))
131
+
132
+ assert_error_message("$value: #cccccc is not a number for `round'", "round(#ccc)")
133
+ end
134
+
135
+ def test_floor
136
+ assert_equal("4", evaluate("floor(4.8)"))
137
+ assert_equal("4px", evaluate("floor(4.8px)"))
138
+ assert_equal("4px", evaluate("floor($value: 4.8px)"))
139
+
140
+ assert_error_message("$value: \"foo\" is not a number for `floor'", "floor(\"foo\")")
141
+ end
142
+
143
+ def test_ceil
144
+ assert_equal("5", evaluate("ceil(4.1)"))
145
+ assert_equal("5px", evaluate("ceil(4.8px)"))
146
+ assert_equal("5px", evaluate("ceil($value: 4.8px)"))
147
+
148
+ assert_error_message("$value: \"a\" is not a number for `ceil'", "ceil(\"a\")")
149
+ end
150
+
151
+ def test_abs
152
+ assert_equal("5", evaluate("abs(-5)"))
153
+ assert_equal("5px", evaluate("abs(-5px)"))
154
+ assert_equal("5", evaluate("abs(5)"))
155
+ assert_equal("5px", evaluate("abs(5px)"))
156
+ assert_equal("5px", evaluate("abs($value: 5px)"))
157
+
158
+ assert_error_message("$value: #aaaaaa is not a number for `abs'", "abs(#aaa)")
159
+ end
160
+
161
+ def test_min
162
+ #assert_equal("1", evaluate("min(1, 2, 3)"))
163
+ assert_equal("1", evaluate("min(3px, 2px, 1)"))
164
+ assert_equal("4em", evaluate("min(4em)"))
165
+ assert_equal("10cm", evaluate("min(10cm, 6in)"))
166
+
167
+ assert_error_message("#aaaaaa is not a number for `min'", "min(#aaa)")
168
+ assert_error_message("Incompatible units: 'px' and 'em'.", "min(3em, 4em, 1px)")
169
+ end
170
+
171
+ def test_max
172
+ assert_equal("3", evaluate("max(1, 2, 3)"))
173
+ assert_equal("3", evaluate("max(3, 2px, 1px)"))
174
+ assert_equal("4em", evaluate("max(4em)"))
175
+ assert_equal("6in", evaluate("max(10cm, 6in)"))
176
+
177
+ assert_error_message("#aaaaaa is not a number for `max'", "max(#aaa)")
178
+ assert_error_message("Incompatible units: 'px' and 'em'.", "max(3em, 4em, 1px)")
179
+ end
180
+
181
+ def test_rgb
182
+ assert_equal("#123456", evaluate("rgb(18, 52, 86)"))
183
+ assert_equal("#beaded", evaluate("rgb(190, 173, 237)"))
184
+ assert_equal("springgreen", evaluate("rgb(0, 255, 127)"))
185
+ assert_equal("springgreen", evaluate("rgb($red: 0, $green: 255, $blue: 127)"))
186
+ end
187
+
188
+ def test_rgb_percent
189
+ assert_equal("#123456", evaluate("rgb(7.1%, 20.4%, 34%)"))
190
+ assert_equal("#beaded", evaluate("rgb(74.7%, 173, 93%)"))
191
+ assert_equal("#beaded", evaluate("rgb(190, 68%, 237)"))
192
+ assert_equal("springgreen", evaluate("rgb(0%, 100%, 50%)"))
193
+ end
194
+
195
+ def test_rgb_tests_bounds
196
+ assert_error_message("$red: Color value 256 must be between 0 and 255 for `rgb'",
197
+ "rgb(256, 1, 1)")
198
+ assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgb'",
199
+ "rgb(1, 256, 1)")
200
+ assert_error_message("$blue: Color value 256 must be between 0 and 255 for `rgb'",
201
+ "rgb(1, 1, 256)")
202
+ assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgb'",
203
+ "rgb(1, 256, 257)")
204
+ assert_error_message("$red: Color value -1 must be between 0 and 255 for `rgb'",
205
+ "rgb(-1, 1, 1)")
206
+ end
207
+
208
+ def test_rgb_test_percent_bounds
209
+ assert_error_message("$red: Color value 100.1% must be between 0% and 100% for `rgb'",
210
+ "rgb(100.1%, 0, 0)")
211
+ assert_error_message("$green: Color value -0.1% must be between 0% and 100% for `rgb'",
212
+ "rgb(0, -0.1%, 0)")
213
+ assert_error_message("$blue: Color value 101% must be between 0% and 100% for `rgb'",
214
+ "rgb(0, 0, 101%)")
215
+ end
216
+
217
+ def test_rgb_tests_types
218
+ assert_error_message("$red: \"foo\" is not a number for `rgb'", "rgb(\"foo\", 10, 12)");
219
+ assert_error_message("$green: \"foo\" is not a number for `rgb'", "rgb(10, \"foo\", 12)");
220
+ assert_error_message("$blue: \"foo\" is not a number for `rgb'", "rgb(10, 10, \"foo\")");
221
+ end
222
+
223
+ def test_rgba
224
+ assert_equal("rgba(18, 52, 86, 0.5)", evaluate("rgba(18, 52, 86, 0.5)"))
225
+ assert_equal("#beaded", evaluate("rgba(190, 173, 237, 1)"))
226
+ assert_equal("rgba(0, 255, 127, 0)", evaluate("rgba(0, 255, 127, 0)"))
227
+ assert_equal("rgba(0, 255, 127, 0)", evaluate("rgba($red: 0, $green: 255, $blue: 127, $alpha: 0)"))
228
+ end
229
+
230
+ def test_rgba_tests_bounds
231
+ assert_error_message("$red: Color value 256 must be between 0 and 255 for `rgba'",
232
+ "rgba(256, 1, 1, 0.3)")
233
+ assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgba'",
234
+ "rgba(1, 256, 1, 0.3)")
235
+ assert_error_message("$blue: Color value 256 must be between 0 and 255 for `rgba'",
236
+ "rgba(1, 1, 256, 0.3)")
237
+ assert_error_message("$green: Color value 256 must be between 0 and 255 for `rgba'",
238
+ "rgba(1, 256, 257, 0.3)")
239
+ assert_error_message("$red: Color value -1 must be between 0 and 255 for `rgba'",
240
+ "rgba(-1, 1, 1, 0.3)")
241
+ assert_error_message("Alpha channel -0.2 must be between 0 and 1 for `rgba'",
242
+ "rgba(1, 1, 1, -0.2)")
243
+ assert_error_message("Alpha channel 1.2 must be between 0 and 1 for `rgba'",
244
+ "rgba(1, 1, 1, 1.2)")
245
+ end
246
+
247
+ def test_rgba_tests_types
248
+ assert_error_message("$red: \"foo\" is not a number for `rgba'", "rgba(\"foo\", 10, 12, 0.2)");
249
+ assert_error_message("$green: \"foo\" is not a number for `rgba'", "rgba(10, \"foo\", 12, 0.1)");
250
+ assert_error_message("$blue: \"foo\" is not a number for `rgba'", "rgba(10, 10, \"foo\", 0)");
251
+ assert_error_message("$alpha: \"foo\" is not a number for `rgba'", "rgba(10, 10, 10, \"foo\")");
252
+ end
253
+
254
+ def test_rgba_with_color
255
+ assert_equal "rgba(16, 32, 48, 0.5)", evaluate("rgba(#102030, 0.5)")
256
+ assert_equal "rgba(0, 0, 255, 0.5)", evaluate("rgba(blue, 0.5)")
257
+ assert_equal "rgba(0, 0, 255, 0.5)", evaluate("rgba($color: blue, $alpha: 0.5)")
258
+ end
259
+
260
+ def test_rgba_with_color_tests_types
261
+ assert_error_message("$color: \"foo\" is not a color for `rgba'", "rgba(\"foo\", 0.2)");
262
+ assert_error_message("$alpha: \"foo\" is not a number for `rgba'", "rgba(blue, \"foo\")");
263
+ end
264
+
265
+ def test_rgba_tests_num_args
266
+ assert_error_message("wrong number of arguments (0 for 4) for `rgba'", "rgba()");
267
+ assert_error_message("wrong number of arguments (1 for 4) for `rgba'", "rgba(blue)");
268
+ assert_error_message("wrong number of arguments (3 for 4) for `rgba'", "rgba(1, 2, 3)");
269
+ assert_error_message("wrong number of arguments (5 for 4) for `rgba'", "rgba(1, 2, 3, 0.4, 5)");
270
+ end
271
+
272
+ def test_red
273
+ assert_equal("18", evaluate("red(#123456)"))
274
+ assert_equal("18", evaluate("red($color: #123456)"))
275
+ end
276
+
277
+ def test_red_exception
278
+ assert_error_message("$color: 12 is not a color for `red'", "red(12)")
279
+ end
280
+
281
+ def test_green
282
+ assert_equal("52", evaluate("green(#123456)"))
283
+ assert_equal("52", evaluate("green($color: #123456)"))
284
+ end
285
+
286
+ def test_green_exception
287
+ assert_error_message("$color: 12 is not a color for `green'", "green(12)")
288
+ end
289
+
290
+ def test_blue
291
+ assert_equal("86", evaluate("blue(#123456)"))
292
+ assert_equal("86", evaluate("blue($color: #123456)"))
293
+ end
294
+
295
+ def test_blue_exception
296
+ assert_error_message("$color: 12 is not a color for `blue'", "blue(12)")
297
+ end
298
+
299
+ def test_hue
300
+ assert_equal("18deg", evaluate("hue(hsl(18, 50%, 20%))"))
301
+ assert_equal("18deg", evaluate("hue($color: hsl(18, 50%, 20%))"))
302
+ end
303
+
304
+ def test_hue_exception
305
+ assert_error_message("$color: 12 is not a color for `hue'", "hue(12)")
306
+ end
307
+
308
+ def test_saturation
309
+ assert_equal("52%", evaluate("saturation(hsl(20, 52%, 20%))"))
310
+ assert_equal("52%", evaluate("saturation(hsl(20, 52, 20%))"))
311
+ assert_equal("52%", evaluate("saturation($color: hsl(20, 52, 20%))"))
312
+ end
313
+
314
+ def test_saturation_exception
315
+ assert_error_message("$color: 12 is not a color for `saturation'", "saturation(12)")
316
+ end
317
+
318
+ def test_lightness
319
+ assert_equal("86%", evaluate("lightness(hsl(120, 50%, 86%))"))
320
+ assert_equal("86%", evaluate("lightness(hsl(120, 50%, 86))"))
321
+ assert_equal("86%", evaluate("lightness($color: hsl(120, 50%, 86))"))
322
+ end
323
+
324
+ def test_lightness_exception
325
+ assert_error_message("$color: 12 is not a color for `lightness'", "lightness(12)")
326
+ end
327
+
328
+ def test_alpha
329
+ assert_equal("1", evaluate("alpha(#123456)"))
330
+ assert_equal("0.34", evaluate("alpha(rgba(0, 1, 2, 0.34))"))
331
+ assert_equal("0", evaluate("alpha(hsla(0, 1, 2, 0))"))
332
+ assert_equal("0", evaluate("alpha($color: hsla(0, 1, 2, 0))"))
333
+ end
334
+
335
+ def test_alpha_exception
336
+ assert_error_message("$color: 12 is not a color for `alpha'", "alpha(12)")
337
+ end
338
+
339
+ def test_opacity
340
+ assert_equal("1", evaluate("opacity(#123456)"))
341
+ assert_equal("0.34", evaluate("opacity(rgba(0, 1, 2, 0.34))"))
342
+ assert_equal("0", evaluate("opacity(hsla(0, 1, 2, 0))"))
343
+ assert_equal("0", evaluate("opacity($color: hsla(0, 1, 2, 0))"))
344
+ assert_equal("opacity(20%)", evaluate("opacity(20%)"))
345
+ end
346
+
347
+ def test_opacity_exception
348
+ assert_error_message("$color: \"foo\" is not a color for `opacity'", "opacity(foo)")
349
+ end
350
+
351
+ def test_opacify
352
+ assert_equal("rgba(0, 0, 0, 0.75)", evaluate("opacify(rgba(0, 0, 0, 0.5), 0.25)"))
353
+ assert_equal("rgba(0, 0, 0, 0.3)", evaluate("opacify(rgba(0, 0, 0, 0.2), 0.1)"))
354
+ assert_equal("rgba(0, 0, 0, 0.7)", evaluate("fade-in(rgba(0, 0, 0, 0.2), 0.5px)"))
355
+ assert_equal("black", evaluate("fade_in(rgba(0, 0, 0, 0.2), 0.8)"))
356
+ assert_equal("black", evaluate("opacify(rgba(0, 0, 0, 0.2), 1)"))
357
+ assert_equal("rgba(0, 0, 0, 0.2)", evaluate("opacify(rgba(0, 0, 0, 0.2), 0%)"))
358
+ assert_equal("rgba(0, 0, 0, 0.2)", evaluate("opacify($color: rgba(0, 0, 0, 0.2), $amount: 0%)"))
359
+ assert_equal("rgba(0, 0, 0, 0.2)", evaluate("fade-in($color: rgba(0, 0, 0, 0.2), $amount: 0%)"))
360
+ end
361
+
362
+ def test_opacify_tests_bounds
363
+ assert_error_message("Amount -0.001 must be between 0 and 1 for `opacify'",
364
+ "opacify(rgba(0, 0, 0, 0.2), -0.001)")
365
+ assert_error_message("Amount 1.001 must be between 0 and 1 for `opacify'",
366
+ "opacify(rgba(0, 0, 0, 0.2), 1.001)")
367
+ end
368
+
369
+ def test_opacify_tests_types
370
+ assert_error_message("$color: \"foo\" is not a color for `opacify'", "opacify(\"foo\", 10%)")
371
+ assert_error_message("$amount: \"foo\" is not a number for `opacify'", "opacify(#fff, \"foo\")")
372
+ end
373
+
374
+ def test_transparentize
375
+ assert_equal("rgba(0, 0, 0, 0.3)", evaluate("transparentize(rgba(0, 0, 0, 0.5), 0.2)"))
376
+ assert_equal("rgba(0, 0, 0, 0.1)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 0.1)"))
377
+ 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)"))
380
+ assert_equal("rgba(0, 0, 0, 0.2)", evaluate("transparentize(rgba(0, 0, 0, 0.2), 0)"))
381
+ assert_equal("rgba(0, 0, 0, 0.2)", evaluate("transparentize($color: rgba(0, 0, 0, 0.2), $amount: 0)"))
382
+ assert_equal("rgba(0, 0, 0, 0.2)", evaluate("fade-out($color: rgba(0, 0, 0, 0.2), $amount: 0)"))
383
+ end
384
+
385
+ def test_transparentize_tests_bounds
386
+ assert_error_message("Amount -0.001 must be between 0 and 1 for `transparentize'",
387
+ "transparentize(rgba(0, 0, 0, 0.2), -0.001)")
388
+ assert_error_message("Amount 1.001 must be between 0 and 1 for `transparentize'",
389
+ "transparentize(rgba(0, 0, 0, 0.2), 1.001)")
390
+ end
391
+
392
+ def test_transparentize_tests_types
393
+ assert_error_message("$color: \"foo\" is not a color for `transparentize'", "transparentize(\"foo\", 10%)")
394
+ assert_error_message("$amount: \"foo\" is not a number for `transparentize'", "transparentize(#fff, \"foo\")")
395
+ end
396
+
397
+ def test_lighten
398
+ assert_equal("#4d4d4d", evaluate("lighten(hsl(0, 0, 0), 30%)"))
399
+ assert_equal("#ee0000", evaluate("lighten(#800, 20%)"))
400
+ assert_equal("white", evaluate("lighten(#fff, 20%)"))
401
+ assert_equal("white", evaluate("lighten(#800, 100%)"))
402
+ assert_equal("#880000", evaluate("lighten(#800, 0%)"))
403
+ assert_equal("rgba(238, 0, 0, 0.5)", evaluate("lighten(rgba(136, 0, 0, 0.5), 20%)"))
404
+ assert_equal("rgba(238, 0, 0, 0.5)", evaluate("lighten($color: rgba(136, 0, 0, 0.5), $amount: 20%)"))
405
+ end
406
+
407
+ def test_lighten_tests_bounds
408
+ assert_error_message("Amount -0.001 must be between 0% and 100% for `lighten'",
409
+ "lighten(#123, -0.001)")
410
+ assert_error_message("Amount 100.001 must be between 0% and 100% for `lighten'",
411
+ "lighten(#123, 100.001)")
412
+ end
413
+
414
+ def test_lighten_tests_types
415
+ assert_error_message("$color: \"foo\" is not a color for `lighten'", "lighten(\"foo\", 10%)")
416
+ assert_error_message("$amount: \"foo\" is not a number for `lighten'", "lighten(#fff, \"foo\")")
417
+ end
418
+
419
+ def test_darken
420
+ assert_equal("#ff6a00", evaluate("darken(hsl(25, 100, 80), 30%)"))
421
+ assert_equal("#220000", evaluate("darken(#800, 20%)"))
422
+ assert_equal("black", evaluate("darken(#000, 20%)"))
423
+ assert_equal("black", evaluate("darken(#800, 100%)"))
424
+ assert_equal("#880000", evaluate("darken(#800, 0%)"))
425
+ assert_equal("rgba(34, 0, 0, 0.5)", evaluate("darken(rgba(136, 0, 0, 0.5), 20%)"))
426
+ assert_equal("rgba(34, 0, 0, 0.5)", evaluate("darken($color: rgba(136, 0, 0, 0.5), $amount: 20%)"))
427
+ end
428
+
429
+ def test_darken_tests_bounds
430
+ assert_error_message("Amount -0.001 must be between 0% and 100% for `darken'",
431
+ "darken(#123, -0.001)")
432
+ assert_error_message("Amount 100.001 must be between 0% and 100% for `darken'",
433
+ "darken(#123, 100.001)")
434
+ end
435
+
436
+ def test_darken_tests_types
437
+ assert_error_message("$color: \"foo\" is not a color for `darken'", "darken(\"foo\", 10%)")
438
+ assert_error_message("$amount: \"foo\" is not a number for `darken'", "darken(#fff, \"foo\")")
439
+ end
440
+
441
+ def test_saturate
442
+ assert_equal("#d9f2d9", evaluate("saturate(hsl(120, 30, 90), 20%)"))
443
+ assert_equal("#9e3f3f", evaluate("saturate(#855, 20%)"))
444
+ assert_equal("black", evaluate("saturate(#000, 20%)"))
445
+ assert_equal("white", evaluate("saturate(#fff, 20%)"))
446
+ assert_equal("#33ff33", evaluate("saturate(#8a8, 100%)"))
447
+ assert_equal("#88aa88", evaluate("saturate(#8a8, 0%)"))
448
+ assert_equal("rgba(158, 63, 63, 0.5)", evaluate("saturate(rgba(136, 85, 85, 0.5), 20%)"))
449
+ assert_equal("rgba(158, 63, 63, 0.5)", evaluate("saturate($color: rgba(136, 85, 85, 0.5), $amount: 20%)"))
450
+ assert_equal("saturate(50%)", evaluate("saturate(50%)"))
451
+ end
452
+
453
+ def test_saturate_tests_bounds
454
+ assert_error_message("Amount -0.001 must be between 0% and 100% for `saturate'",
455
+ "saturate(#123, -0.001)")
456
+ assert_error_message("Amount 100.001 must be between 0% and 100% for `saturate'",
457
+ "saturate(#123, 100.001)")
458
+ end
459
+
460
+ def test_saturate_tests_types
461
+ assert_error_message("$color: \"foo\" is not a color for `saturate'", "saturate(\"foo\", 10%)")
462
+ assert_error_message("$amount: \"foo\" is not a number for `saturate'", "saturate(#fff, \"foo\")")
463
+ end
464
+
465
+ def test_desaturate
466
+ assert_equal("#e3e8e3", evaluate("desaturate(hsl(120, 30, 90), 20%)"))
467
+ assert_equal("#726b6b", evaluate("desaturate(#855, 20%)"))
468
+ assert_equal("black", evaluate("desaturate(#000, 20%)"))
469
+ assert_equal("white", evaluate("desaturate(#fff, 20%)"))
470
+ assert_equal("#999999", evaluate("desaturate(#8a8, 100%)"))
471
+ assert_equal("#88aa88", evaluate("desaturate(#8a8, 0%)"))
472
+ assert_equal("rgba(114, 107, 107, 0.5)", evaluate("desaturate(rgba(136, 85, 85, 0.5), 20%)"))
473
+ assert_equal("rgba(114, 107, 107, 0.5)", evaluate("desaturate($color: rgba(136, 85, 85, 0.5), $amount: 20%)"))
474
+ end
475
+
476
+ def test_desaturate_tests_bounds
477
+ assert_error_message("Amount -0.001 must be between 0% and 100% for `desaturate'",
478
+ "desaturate(#123, -0.001)")
479
+ assert_error_message("Amount 100.001 must be between 0% and 100% for `desaturate'",
480
+ "desaturate(#123, 100.001)")
481
+ end
482
+
483
+ def test_desaturate_tests_types
484
+ assert_error_message("$color: \"foo\" is not a color for `desaturate'", "desaturate(\"foo\", 10%)")
485
+ assert_error_message("$amount: \"foo\" is not a number for `desaturate'", "desaturate(#fff, \"foo\")")
486
+ end
487
+
488
+ def test_adjust_hue
489
+ assert_equal("#deeded", evaluate("adjust-hue(hsl(120, 30, 90), 60deg)"))
490
+ assert_equal("#ededde", evaluate("adjust-hue(hsl(120, 30, 90), -60deg)"))
491
+ assert_equal("#886a11", evaluate("adjust-hue(#811, 45deg)"))
492
+ assert_equal("black", evaluate("adjust-hue(#000, 45deg)"))
493
+ assert_equal("white", evaluate("adjust-hue(#fff, 45deg)"))
494
+ assert_equal("#88aa88", evaluate("adjust-hue(#8a8, 360deg)"))
495
+ assert_equal("#88aa88", evaluate("adjust-hue(#8a8, 0deg)"))
496
+ assert_equal("rgba(136, 106, 17, 0.5)", evaluate("adjust-hue(rgba(136, 17, 17, 0.5), 45deg)"))
497
+ assert_equal("rgba(136, 106, 17, 0.5)", evaluate("adjust-hue($color: rgba(136, 17, 17, 0.5), $degrees: 45deg)"))
498
+ end
499
+
500
+ def test_adjust_hue_tests_types
501
+ assert_error_message("$color: \"foo\" is not a color for `adjust-hue'", "adjust-hue(\"foo\", 10%)")
502
+ assert_error_message("$degrees: \"foo\" is not a number for `adjust-hue'", "adjust-hue(#fff, \"foo\")")
503
+ end
504
+
505
+ def test_adjust_color
506
+ # HSL
507
+ assert_equal(evaluate("hsl(180, 30, 90)"),
508
+ evaluate("adjust-color(hsl(120, 30, 90), $hue: 60deg)"))
509
+ assert_equal(evaluate("hsl(120, 50, 90)"),
510
+ evaluate("adjust-color(hsl(120, 30, 90), $saturation: 20%)"))
511
+ assert_equal(evaluate("hsl(120, 30, 60)"),
512
+ evaluate("adjust-color(hsl(120, 30, 90), $lightness: -30%)"))
513
+ # RGB
514
+ assert_equal(evaluate("rgb(15, 20, 30)"),
515
+ evaluate("adjust-color(rgb(10, 20, 30), $red: 5)"))
516
+ assert_equal(evaluate("rgb(10, 15, 30)"),
517
+ evaluate("adjust-color(rgb(10, 20, 30), $green: -5)"))
518
+ assert_equal(evaluate("rgb(10, 20, 40)"),
519
+ evaluate("adjust-color(rgb(10, 20, 30), $blue: 10)"))
520
+ # Alpha
521
+ assert_equal(evaluate("hsla(120, 30, 90, 0.65)"),
522
+ evaluate("adjust-color(hsl(120, 30, 90), $alpha: -0.35)"))
523
+ assert_equal(evaluate("rgba(10, 20, 30, 0.9)"),
524
+ evaluate("adjust-color(rgba(10, 20, 30, 0.4), $alpha: 0.5)"))
525
+
526
+ # HSL composability
527
+ assert_equal(evaluate("hsl(180, 20, 90)"),
528
+ evaluate("adjust-color(hsl(120, 30, 90), $hue: 60deg, $saturation: -10%)"))
529
+ assert_equal(evaluate("hsl(180, 20, 95)"),
530
+ evaluate("adjust-color(hsl(120, 30, 90), $hue: 60deg, $saturation: -10%, $lightness: 5%)"))
531
+ assert_equal(evaluate("hsla(120, 20, 95, 0.3)"),
532
+ evaluate("adjust-color(hsl(120, 30, 90), $saturation: -10%, $lightness: 5%, $alpha: -0.7)"))
533
+
534
+ # RGB composability
535
+ assert_equal(evaluate("rgb(15, 20, 29)"),
536
+ evaluate("adjust-color(rgb(10, 20, 30), $red: 5, $blue: -1)"))
537
+ assert_equal(evaluate("rgb(15, 45, 29)"),
538
+ evaluate("adjust-color(rgb(10, 20, 30), $red: 5, $green: 25, $blue: -1)"))
539
+ assert_equal(evaluate("rgba(10, 25, 29, 0.7)"),
540
+ evaluate("adjust-color(rgb(10, 20, 30), $green: 5, $blue: -1, $alpha: -0.3)"))
541
+
542
+ # HSL range restriction
543
+ assert_equal(evaluate("hsl(120, 30, 90)"),
544
+ evaluate("adjust-color(hsl(120, 30, 90), $hue: 720deg)"))
545
+ assert_equal(evaluate("hsl(120, 0, 90)"),
546
+ evaluate("adjust-color(hsl(120, 30, 90), $saturation: -90%)"))
547
+ assert_equal(evaluate("hsl(120, 30, 100)"),
548
+ evaluate("adjust-color(hsl(120, 30, 90), $lightness: 30%)"))
549
+
550
+ # RGB range restriction
551
+ assert_equal(evaluate("rgb(255, 20, 30)"),
552
+ evaluate("adjust-color(rgb(10, 20, 30), $red: 250)"))
553
+ assert_equal(evaluate("rgb(10, 0, 30)"),
554
+ evaluate("adjust-color(rgb(10, 20, 30), $green: -30)"))
555
+ assert_equal(evaluate("rgb(10, 20, 0)"),
556
+ evaluate("adjust-color(rgb(10, 20, 30), $blue: -40)"))
557
+ end
558
+
559
+ def test_adjust_color_tests_types
560
+ assert_error_message("$color: \"foo\" is not a color for `adjust-color'", "adjust-color(foo, $hue: 10)")
561
+ # HSL
562
+ assert_error_message("$hue: \"foo\" is not a number for `adjust-color'",
563
+ "adjust-color(blue, $hue: foo)")
564
+ assert_error_message("$saturation: \"foo\" is not a number for `adjust-color'",
565
+ "adjust-color(blue, $saturation: foo)")
566
+ assert_error_message("$lightness: \"foo\" is not a number for `adjust-color'",
567
+ "adjust-color(blue, $lightness: foo)")
568
+ # RGB
569
+ assert_error_message("$red: \"foo\" is not a number for `adjust-color'",
570
+ "adjust-color(blue, $red: foo)")
571
+ assert_error_message("$green: \"foo\" is not a number for `adjust-color'",
572
+ "adjust-color(blue, $green: foo)")
573
+ assert_error_message("$blue: \"foo\" is not a number for `adjust-color'",
574
+ "adjust-color(blue, $blue: foo)")
575
+ # Alpha
576
+ assert_error_message("$alpha: \"foo\" is not a number for `adjust-color'",
577
+ "adjust-color(blue, $alpha: foo)")
578
+ end
579
+
580
+ def test_adjust_color_tests_arg_range
581
+ # HSL
582
+ assert_error_message("$saturation: Amount 101% must be between -100% and 100% for `adjust-color'",
583
+ "adjust-color(blue, $saturation: 101%)")
584
+ assert_error_message("$saturation: Amount -101% must be between -100% and 100% for `adjust-color'",
585
+ "adjust-color(blue, $saturation: -101%)")
586
+ assert_error_message("$lightness: Amount 101% must be between -100% and 100% for `adjust-color'",
587
+ "adjust-color(blue, $lightness: 101%)")
588
+ assert_error_message("$lightness: Amount -101% must be between -100% and 100% for `adjust-color'",
589
+ "adjust-color(blue, $lightness: -101%)")
590
+ # RGB
591
+ assert_error_message("$red: Amount 256 must be between -255 and 255 for `adjust-color'",
592
+ "adjust-color(blue, $red: 256)")
593
+ assert_error_message("$red: Amount -256 must be between -255 and 255 for `adjust-color'",
594
+ "adjust-color(blue, $red: -256)")
595
+ assert_error_message("$green: Amount 256 must be between -255 and 255 for `adjust-color'",
596
+ "adjust-color(blue, $green: 256)")
597
+ assert_error_message("$green: Amount -256 must be between -255 and 255 for `adjust-color'",
598
+ "adjust-color(blue, $green: -256)")
599
+ assert_error_message("$blue: Amount 256 must be between -255 and 255 for `adjust-color'",
600
+ "adjust-color(blue, $blue: 256)")
601
+ assert_error_message("$blue: Amount -256 must be between -255 and 255 for `adjust-color'",
602
+ "adjust-color(blue, $blue: -256)")
603
+ # Alpha
604
+ assert_error_message("$alpha: Amount 1.1 must be between -1 and 1 for `adjust-color'",
605
+ "adjust-color(blue, $alpha: 1.1)")
606
+ assert_error_message("$alpha: Amount -1.1 must be between -1 and 1 for `adjust-color'",
607
+ "adjust-color(blue, $alpha: -1.1)")
608
+ end
609
+
610
+ def test_adjust_color_argument_errors
611
+ assert_error_message("Unknown argument $hoo (260deg) for `adjust-color'",
612
+ "adjust-color(blue, $hoo: 260deg)")
613
+ assert_error_message("Cannot specify HSL and RGB values for a color at the same time for `adjust-color'",
614
+ "adjust-color(blue, $hue: 120deg, $red: 10)");
615
+ assert_error_message("10px is not a keyword argument for `adjust_color'",
616
+ "adjust-color(blue, 10px)")
617
+ assert_error_message("10px is not a keyword argument for `adjust_color'",
618
+ "adjust-color(blue, 10px, 20px)")
619
+ assert_error_message("10px is not a keyword argument for `adjust_color'",
620
+ "adjust-color(blue, 10px, $hue: 180deg)")
621
+ end
622
+
623
+ def test_scale_color
624
+ # HSL
625
+ assert_equal(evaluate("hsl(120, 51, 90)"),
626
+ evaluate("scale-color(hsl(120, 30, 90), $saturation: 30%)"))
627
+ assert_equal(evaluate("hsl(120, 30, 76.5)"),
628
+ evaluate("scale-color(hsl(120, 30, 90), $lightness: -15%)"))
629
+ # RGB
630
+ assert_equal(evaluate("rgb(157, 20, 30)"),
631
+ evaluate("scale-color(rgb(10, 20, 30), $red: 60%)"))
632
+ assert_equal(evaluate("rgb(10, 38.8, 30)"),
633
+ evaluate("scale-color(rgb(10, 20, 30), $green: 8%)"))
634
+ assert_equal(evaluate("rgb(10, 20, 20)"),
635
+ evaluate("scale-color(rgb(10, 20, 30), $blue: -(1/3)*100%)"))
636
+ # Alpha
637
+ assert_equal(evaluate("hsla(120, 30, 90, 0.86)"),
638
+ evaluate("scale-color(hsl(120, 30, 90), $alpha: -14%)"))
639
+ assert_equal(evaluate("rgba(10, 20, 30, 0.82)"),
640
+ evaluate("scale-color(rgba(10, 20, 30, 0.8), $alpha: 10%)"))
641
+
642
+ # HSL composability
643
+ assert_equal(evaluate("hsl(120, 51, 76.5)"),
644
+ evaluate("scale-color(hsl(120, 30, 90), $saturation: 30%, $lightness: -15%)"))
645
+ assert_equal(evaluate("hsla(120, 51, 90, 0.2)"),
646
+ evaluate("scale-color(hsl(120, 30, 90), $saturation: 30%, $alpha: -80%)"))
647
+
648
+ # RGB composability
649
+ assert_equal(evaluate("rgb(157, 38.8, 30)"),
650
+ evaluate("scale-color(rgb(10, 20, 30), $red: 60%, $green: 8%)"))
651
+ assert_equal(evaluate("rgb(157, 38.8, 20)"),
652
+ evaluate("scale-color(rgb(10, 20, 30), $red: 60%, $green: 8%, $blue: -(1/3)*100%)"))
653
+ assert_equal(evaluate("rgba(10, 38.8, 20, 0.55)"),
654
+ evaluate("scale-color(rgba(10, 20, 30, 0.5), $green: 8%, $blue: -(1/3)*100%, $alpha: 10%)"))
655
+
656
+ # Extremes
657
+ assert_equal(evaluate("hsl(120, 100, 90)"),
658
+ evaluate("scale-color(hsl(120, 30, 90), $saturation: 100%)"))
659
+ assert_equal(evaluate("hsl(120, 30, 90)"),
660
+ evaluate("scale-color(hsl(120, 30, 90), $saturation: 0%)"))
661
+ assert_equal(evaluate("hsl(120, 0, 90)"),
662
+ evaluate("scale-color(hsl(120, 30, 90), $saturation: -100%)"))
663
+ end
664
+
665
+ def test_scale_color_tests_types
666
+ assert_error_message("$color: \"foo\" is not a color for `scale-color'", "scale-color(foo, $red: 10%)")
667
+ # HSL
668
+ assert_error_message("$saturation: \"foo\" is not a number for `scale-color'",
669
+ "scale-color(blue, $saturation: foo)")
670
+ assert_error_message("$lightness: \"foo\" is not a number for `scale-color'",
671
+ "scale-color(blue, $lightness: foo)")
672
+ # RGB
673
+ assert_error_message("$red: \"foo\" is not a number for `scale-color'",
674
+ "scale-color(blue, $red: foo)")
675
+ assert_error_message("$green: \"foo\" is not a number for `scale-color'",
676
+ "scale-color(blue, $green: foo)")
677
+ assert_error_message("$blue: \"foo\" is not a number for `scale-color'",
678
+ "scale-color(blue, $blue: foo)")
679
+ # Alpha
680
+ assert_error_message("$alpha: \"foo\" is not a number for `scale-color'",
681
+ "scale-color(blue, $alpha: foo)")
682
+ end
683
+
684
+ def test_scale_color_argument_errors
685
+ # Range
686
+ assert_error_message("$saturation: Amount 101% must be between -100% and 100% for `scale-color'",
687
+ "scale-color(blue, $saturation: 101%)")
688
+ assert_error_message("$red: Amount -101% must be between -100% and 100% for `scale-color'",
689
+ "scale-color(blue, $red: -101%)")
690
+ assert_error_message("$alpha: Amount -101% must be between -100% and 100% for `scale-color'",
691
+ "scale-color(blue, $alpha: -101%)")
692
+
693
+ # Unit
694
+ assert_error_message("$saturation: Amount 80 must be a % (e.g. 80%) for `scale-color'",
695
+ "scale-color(blue, $saturation: 80)")
696
+ assert_error_message("$alpha: Amount 0.5 must be a % (e.g. 0.5%) for `scale-color'",
697
+ "scale-color(blue, $alpha: 0.5)")
698
+
699
+ # Unknown argument
700
+ assert_error_message("Unknown argument $hue (80%) for `scale-color'", "scale-color(blue, $hue: 80%)")
701
+
702
+ # Non-keyword arg
703
+ assert_error_message("10px is not a keyword argument for `scale_color'", "scale-color(blue, 10px)")
704
+
705
+ # HSL/RGB
706
+ assert_error_message("Cannot specify HSL and RGB values for a color at the same time for `scale-color'",
707
+ "scale-color(blue, $lightness: 10%, $red: 20%)");
708
+ end
709
+
710
+ def test_change_color
711
+ # HSL
712
+ assert_equal(evaluate("hsl(195, 30, 90)"),
713
+ evaluate("change-color(hsl(120, 30, 90), $hue: 195deg)"))
714
+ assert_equal(evaluate("hsl(120, 50, 90)"),
715
+ evaluate("change-color(hsl(120, 30, 90), $saturation: 50%)"))
716
+ assert_equal(evaluate("hsl(120, 30, 40)"),
717
+ evaluate("change-color(hsl(120, 30, 90), $lightness: 40%)"))
718
+ # RGB
719
+ assert_equal(evaluate("rgb(123, 20, 30)"),
720
+ evaluate("change-color(rgb(10, 20, 30), $red: 123)"))
721
+ assert_equal(evaluate("rgb(10, 234, 30)"),
722
+ evaluate("change-color(rgb(10, 20, 30), $green: 234)"))
723
+ assert_equal(evaluate("rgb(10, 20, 198)"),
724
+ evaluate("change-color(rgb(10, 20, 30), $blue: 198)"))
725
+ # Alpha
726
+ assert_equal(evaluate("rgba(10, 20, 30, 0.76)"),
727
+ evaluate("change-color(rgb(10, 20, 30), $alpha: 0.76)"))
728
+
729
+ # HSL composability
730
+ assert_equal(evaluate("hsl(56, 30, 47)"),
731
+ evaluate("change-color(hsl(120, 30, 90), $hue: 56deg, $lightness: 47%)"))
732
+ assert_equal(evaluate("hsla(56, 30, 47, 0.9)"),
733
+ evaluate("change-color(hsl(120, 30, 90), $hue: 56deg, $lightness: 47%, $alpha: 0.9)"))
734
+ end
735
+
736
+ def test_change_color_tests_types
737
+ assert_error_message("$color: \"foo\" is not a color for `change-color'", "change-color(foo, $red: 10%)")
738
+ # HSL
739
+ assert_error_message("$saturation: \"foo\" is not a number for `change-color'",
740
+ "change-color(blue, $saturation: foo)")
741
+ assert_error_message("$lightness: \"foo\" is not a number for `change-color'",
742
+ "change-color(blue, $lightness: foo)")
743
+ # RGB
744
+ assert_error_message("$red: \"foo\" is not a number for `change-color'", "change-color(blue, $red: foo)")
745
+ assert_error_message("$green: \"foo\" is not a number for `change-color'", "change-color(blue, $green: foo)")
746
+ assert_error_message("$blue: \"foo\" is not a number for `change-color'", "change-color(blue, $blue: foo)")
747
+ # Alpha
748
+ assert_error_message("$alpha: \"foo\" is not a number for `change-color'", "change-color(blue, $alpha: foo)")
749
+ end
750
+
751
+ def test_change_color_argument_errors
752
+ # Range
753
+ assert_error_message("Saturation 101% must be between 0% and 100% for `change-color'",
754
+ "change-color(blue, $saturation: 101%)")
755
+ assert_error_message("Lightness 101% must be between 0% and 100% for `change-color'",
756
+ "change-color(blue, $lightness: 101%)")
757
+ assert_error_message("Red value -1 must be between 0 and 255 for `change-color'",
758
+ "change-color(blue, $red: -1)")
759
+ assert_error_message("Green value 256 must be between 0 and 255 for `change-color'",
760
+ "change-color(blue, $green: 256)")
761
+ assert_error_message("Blue value 500 must be between 0 and 255 for `change-color'",
762
+ "change-color(blue, $blue: 500)")
763
+
764
+ # Unknown argument
765
+ assert_error_message("Unknown argument $hoo (80%) for `change-color'", "change-color(blue, $hoo: 80%)")
766
+
767
+ # Non-keyword arg
768
+ assert_error_message("10px is not a keyword argument for `change_color'", "change-color(blue, 10px)")
769
+
770
+ # HSL/RGB
771
+ assert_error_message("Cannot specify HSL and RGB values for a color at the same time for `change-color'",
772
+ "change-color(blue, $lightness: 10%, $red: 120)");
773
+ end
774
+
775
+ def test_ie_hex_str
776
+ assert_equal("#FFAA11CC", evaluate('ie-hex-str(#aa11cc)'))
777
+ assert_equal("#FFAA11CC", evaluate('ie-hex-str(#a1c)'))
778
+ assert_equal("#FFAA11CC", evaluate('ie-hex-str(#A1c)'))
779
+ assert_equal("#80FF0000", evaluate('ie-hex-str(rgba(255, 0, 0, 0.5))'))
780
+ end
781
+
782
+ def test_mix
783
+ assert_equal("#7f007f", evaluate("mix(#f00, #00f)"))
784
+ assert_equal("#7f7f7f", evaluate("mix(#f00, #0ff)"))
785
+ assert_equal("#7f9055", evaluate("mix(#f70, #0aa)"))
786
+ assert_equal("#3f00bf", evaluate("mix(#f00, #00f, 25%)"))
787
+ assert_equal("rgba(63, 0, 191, 0.75)", evaluate("mix(rgba(255, 0, 0, 0.5), #00f)"))
788
+ assert_equal("red", evaluate("mix(#f00, #00f, 100%)"))
789
+ assert_equal("blue", evaluate("mix(#f00, #00f, 0%)"))
790
+ assert_equal("rgba(255, 0, 0, 0.5)", evaluate("mix(#f00, transparentize(#00f, 1))"))
791
+ assert_equal("rgba(0, 0, 255, 0.5)", evaluate("mix(transparentize(#f00, 1), #00f)"))
792
+ assert_equal("red", evaluate("mix(#f00, transparentize(#00f, 1), 100%)"))
793
+ assert_equal("blue", evaluate("mix(transparentize(#f00, 1), #00f, 0%)"))
794
+ assert_equal("rgba(0, 0, 255, 0)", evaluate("mix(#f00, transparentize(#00f, 1), 0%)"))
795
+ assert_equal("rgba(255, 0, 0, 0)", evaluate("mix(transparentize(#f00, 1), #00f, 100%)"))
796
+ assert_equal("rgba(255, 0, 0, 0)", evaluate("mix($color-1: transparentize(#f00, 1), $color-2: #00f, $weight: 100%)"))
797
+ end
798
+
799
+ def test_mix_tests_types
800
+ assert_error_message("$color-1: \"foo\" is not a color for `mix'", "mix(\"foo\", #f00, 10%)")
801
+ assert_error_message("$color-2: \"foo\" is not a color for `mix'", "mix(#f00, \"foo\", 10%)")
802
+ assert_error_message("$weight: \"foo\" is not a number for `mix'", "mix(#f00, #baf, \"foo\")")
803
+ end
804
+
805
+ def test_mix_tests_bounds
806
+ assert_error_message("Weight -0.001 must be between 0% and 100% for `mix'",
807
+ "mix(#123, #456, -0.001)")
808
+ assert_error_message("Weight 100.001 must be between 0% and 100% for `mix'",
809
+ "mix(#123, #456, 100.001)")
810
+ end
811
+
812
+ def test_grayscale
813
+ assert_equal("#bbbbbb", evaluate("grayscale(#abc)"))
814
+ assert_equal("gray", evaluate("grayscale(#f00)"))
815
+ assert_equal("gray", evaluate("grayscale(#00f)"))
816
+ assert_equal("white", evaluate("grayscale(white)"))
817
+ assert_equal("black", evaluate("grayscale(black)"))
818
+ assert_equal("black", evaluate("grayscale($color: black)"))
819
+
820
+ assert_equal("grayscale(2)", evaluate("grayscale(2)"))
821
+ assert_equal("grayscale(-5px)", evaluate("grayscale(-5px)"))
822
+ end
823
+
824
+ def tets_grayscale_tests_types
825
+ assert_error_message("$color: \"foo\" is not a color for `grayscale'", "grayscale(\"foo\")")
826
+ end
827
+
828
+ def test_complement
829
+ assert_equal("#ccbbaa", evaluate("complement(#abc)"))
830
+ assert_equal("cyan", evaluate("complement(red)"))
831
+ assert_equal("red", evaluate("complement(cyan)"))
832
+ assert_equal("white", evaluate("complement(white)"))
833
+ assert_equal("black", evaluate("complement(black)"))
834
+ assert_equal("black", evaluate("complement($color: black)"))
835
+ end
836
+
837
+ def tets_complement_tests_types
838
+ assert_error_message("$color: \"foo\" is not a color for `complement'", "complement(\"foo\")")
839
+ end
840
+
841
+ def test_invert
842
+ assert_equal("#112233", evaluate("invert(#edc)"))
843
+ assert_equal("rgba(245, 235, 225, 0.5)", evaluate("invert(rgba(10, 20, 30, 0.5))"))
844
+ assert_equal("invert(20%)", evaluate("invert(20%)"))
845
+ end
846
+
847
+ def test_invert_tests_types
848
+ assert_error_message("$color: \"foo\" is not a color for `invert'", "invert(\"foo\")")
849
+ end
850
+
851
+ def test_unquote
852
+ assert_equal('foo', evaluate('unquote("foo")'))
853
+ assert_equal('foo', evaluate('unquote(foo)'))
854
+ assert_equal('foo', evaluate('unquote($string: foo)'))
855
+ end
856
+
857
+ def test_quote
858
+ assert_equal('"foo"', evaluate('quote(foo)'))
859
+ assert_equal('"foo"', evaluate('quote("foo")'))
860
+ assert_equal('"foo"', evaluate('quote($string: "foo")'))
861
+ end
862
+
863
+ def test_quote_tests_type
864
+ assert_error_message("$string: #ff0000 is not a string for `quote'", "quote(#f00)")
865
+ end
866
+
867
+ def test_user_defined_function
868
+ assert_equal("I'm a user-defined string!", evaluate("user_defined()"))
869
+ end
870
+
871
+ def test_user_defined_function_with_preceding_underscore
872
+ assert_equal("I'm another user-defined string!", evaluate("_preceding_underscore()"))
873
+ assert_equal("I'm another user-defined string!", evaluate("-preceding-underscore()"))
874
+ end
875
+
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.
879
+ 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.
882
+ MSG
883
+ end
884
+
885
+ def test_type_of
886
+ assert_equal("string", evaluate("type-of(\"asdf\")"))
887
+ assert_equal("string", evaluate("type-of(asdf)"))
888
+ assert_equal("number", evaluate("type-of(1px)"))
889
+ assert_equal("bool", evaluate("type-of(true)"))
890
+ assert_equal("color", evaluate("type-of(#fff)"))
891
+ assert_equal("color", evaluate("type-of($value: #fff)"))
892
+ assert_equal("null", evaluate("type-of(null)"))
893
+ end
894
+
895
+ def test_unit
896
+ assert_equal(%Q{""}, evaluate("unit(100)"))
897
+ assert_equal(%Q{"px"}, evaluate("unit(100px)"))
898
+ assert_equal(%Q{"em*px"}, evaluate("unit(10px * 5em)"))
899
+ assert_equal(%Q{"em*px"}, evaluate("unit(5em * 10px)"))
900
+ assert_equal(%Q{"em/rem"}, evaluate("unit(10px * 5em / 30cm / 1rem)"))
901
+ assert_equal(%Q{"em*vh/cm*rem"}, evaluate("unit(10vh * 5em / 30cm / 1rem)"))
902
+ assert_equal(%Q{"px"}, evaluate("unit($number: 100px)"))
903
+ assert_error_message("$number: #ff0000 is not a number for `unit'", "unit(#f00)")
904
+ end
905
+
906
+ def test_unitless
907
+ assert_equal(%Q{true}, evaluate("unitless(100)"))
908
+ assert_equal(%Q{false}, evaluate("unitless(100px)"))
909
+ assert_equal(%Q{false}, evaluate("unitless($number: 100px)"))
910
+ assert_error_message("$number: #ff0000 is not a number for `unitless'", "unitless(#f00)")
911
+ end
912
+
913
+ def test_comparable
914
+ assert_equal(%Q{true}, evaluate("comparable(2px, 1px)"))
915
+ assert_equal(%Q{true}, evaluate("comparable(10cm, 3mm)"))
916
+ assert_equal(%Q{false}, evaluate("comparable(100px, 3em)"))
917
+ assert_equal(%Q{false}, evaluate("comparable($number-1: 100px, $number-2: 3em)"))
918
+ assert_error_message("$number-1: #ff0000 is not a number for `comparable'", "comparable(#f00, 1px)")
919
+ assert_error_message("$number-2: #ff0000 is not a number for `comparable'", "comparable(1px, #f00)")
920
+ end
921
+
922
+ def test_length
923
+ assert_equal("5", evaluate("length(1 2 3 4 5)"))
924
+ assert_equal("4", evaluate("length((foo, bar, baz, bip))"))
925
+ assert_equal("3", evaluate("length((foo, bar, baz bip))"))
926
+ assert_equal("3", evaluate("length((foo, bar, (baz, bip)))"))
927
+ assert_equal("1", evaluate("length(#f00)"))
928
+ assert_equal("0", evaluate("length(())"))
929
+ assert_equal("4", evaluate("length(1 2 () 3)"))
930
+ end
931
+
932
+ def test_nth
933
+ assert_equal("1", evaluate("nth(1 2 3, 1)"))
934
+ assert_equal("2", evaluate("nth(1 2 3, 2)"))
935
+ assert_equal("3", evaluate("nth((1, 2, 3), 3)"))
936
+ assert_equal("foo", evaluate("nth(foo, 1)"))
937
+ 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)")
941
+ assert_error_message("List index is 5 but list is only 4 items long for `nth'", "nth(1 2 3 4, 5)")
942
+ assert_error_message("List index is 2 but list is only 1 item long for `nth'", "nth(foo, 2)")
943
+ assert_error_message("List index is 1 but list has no items for `nth'", "nth((), 1)")
944
+ assert_error_message("$n: \"foo\" is not a number for `nth'", "nth(1 2 3, foo)")
945
+ end
946
+
947
+ def test_join
948
+ assert_equal("1 2 3", evaluate("join(1 2, 3)"))
949
+ assert_equal("1 2 3", evaluate("join(1, 2 3)"))
950
+ assert_equal("1 2 3 4", evaluate("join(1 2, 3 4)"))
951
+ assert_equal("true", evaluate("(1 2 3 4) == join(1 2, 3 4)"))
952
+ assert_equal("false", evaluate("(1 2 (3 4)) == join(1 2, 3 4)"))
953
+ assert_equal("1, 2, 3", evaluate("join((1, 2), 3)"))
954
+ assert_equal("1, 2, 3", evaluate("join(1, (2, 3))"))
955
+ assert_equal("1, 2, 3, 4", evaluate("join((1, 2), (3, 4))"))
956
+ assert_equal("true", evaluate("(1, 2, 3, 4) == join((1, 2), (3, 4))"))
957
+ assert_equal("false", evaluate("(1, 2, (3, 4)) == join((1, 2), (3, 4))"))
958
+
959
+ assert_equal("1 2", evaluate("join(1, 2)"))
960
+ assert_equal("1 2 3 4", evaluate("join(1 2, (3, 4))"))
961
+ assert_equal("1, 2, 3, 4", evaluate("join((1, 2), 3 4)"))
962
+
963
+ assert_equal("1 2", evaluate("join(1, 2, auto)"))
964
+ assert_equal("1, 2, 3, 4", evaluate("join(1 2, 3 4, comma)"))
965
+ assert_equal("1 2 3 4", evaluate("join((1, 2), (3, 4), space)"))
966
+ assert_equal("1, 2", evaluate("join(1, 2, comma)"))
967
+
968
+ assert_equal("1 2", evaluate("join(1 2, ())"))
969
+ assert_equal("1, 2", evaluate("join((1, 2), ())"))
970
+ assert_equal("true", evaluate("(1 2) == join(1 2, ())"))
971
+ assert_equal("true", evaluate("(1, 2) == join((1, 2), ())"))
972
+ assert_equal("false", evaluate("(1 2 ()) == join(1 2, ())"))
973
+ assert_equal("false", evaluate("(1, 2, ()) == join((1, 2), ())"))
974
+
975
+ assert_equal("1 2", evaluate("join((), 1 2)"))
976
+ assert_equal("1, 2", evaluate("join((), (1, 2))"))
977
+ assert_equal("true", evaluate("(1 2) == join((), 1 2)"))
978
+ assert_equal("true", evaluate("(1, 2) == join((), (1, 2))"))
979
+ assert_equal("false", evaluate("(1 2 ()) == join((), 1 2)"))
980
+ assert_equal("false", evaluate("(1, 2, ()) == join((), (1, 2))"))
981
+
982
+ assert_error_message("Separator name must be space, comma, or auto for `join'", "join(1, 2, baboon)")
983
+ assert_error_message("$separator: 12 is not a string for `join'", "join(1, 2, 12)")
984
+ end
985
+
986
+ def test_append
987
+ assert_equal("1 2 3", evaluate("append(1 2, 3)"))
988
+ assert_equal("1 2 3 4", evaluate("append(1 2, 3 4)"))
989
+ assert_equal("false", evaluate("(1 2 3 4) == append(1 2, 3 4)"))
990
+ assert_equal("true", evaluate("(1 2 (3 4)) == append(1 2, 3 4)"))
991
+ assert_equal("1, 2, 3", evaluate("append((1, 2), 3)"))
992
+ assert_equal("1, 2, 3, 4", evaluate("append((1, 2), (3, 4))"))
993
+ assert_equal("false", evaluate("(1, 2, 3, 4) == append((1, 2), (3, 4))"))
994
+ assert_equal("true", evaluate("(1, 2, (3, 4)) == append((1, 2), (3, 4))"))
995
+
996
+ assert_equal("1 2", evaluate("append(1, 2)"))
997
+ assert_equal("1 2 3, 4", evaluate("append(1 2, (3, 4))"))
998
+ assert_equal("true", evaluate("(1 2 (3, 4)) == append(1 2, (3, 4))"))
999
+ assert_equal("1, 2, 3 4", evaluate("append((1, 2), 3 4)"))
1000
+ assert_equal("true", evaluate("(1, 2, 3 4) == append((1, 2), 3 4)"))
1001
+
1002
+ assert_equal("1 2", evaluate("append(1, 2, auto)"))
1003
+ assert_equal("1, 2, 3 4", evaluate("append(1 2, 3 4, comma)"))
1004
+ assert_equal("1 2 3, 4", evaluate("append((1, 2), (3, 4), space)"))
1005
+ assert_equal("1, 2", evaluate("append(1, 2, comma)"))
1006
+
1007
+ assert_equal("1 2", evaluate("append(1 2, ())"))
1008
+ assert_equal("1, 2", evaluate("append((1, 2), ())"))
1009
+ assert_equal("true", evaluate("(1 2 ()) == append(1 2, ())"))
1010
+ assert_equal("true", evaluate("(1, 2, ()) == append((1, 2), ())"))
1011
+
1012
+ assert_equal("1 2", evaluate("append((), 1 2)"))
1013
+ assert_equal("1, 2", evaluate("append((), (1, 2))"))
1014
+ assert_equal("false", evaluate("(1 2) == append((), 1 2)"))
1015
+ assert_equal("true", evaluate("(1 2) == nth(append((), 1 2), 1)"))
1016
+
1017
+ assert_error_message("Separator name must be space, comma, or auto for `append'", "append(1, 2, baboon)")
1018
+ assert_error_message("$separator: 12 is not a string for `append'", "append(1, 2, 12)")
1019
+ end
1020
+
1021
+ def test_zip
1022
+ assert_equal("1 3 5, 2 4 6", evaluate("zip(1 2, 3 4, 5 6)"))
1023
+ assert_equal("1 4 7, 2 5 8", evaluate("zip(1 2 3, 4 5 6, 7 8)"))
1024
+ assert_equal("1 2 3", evaluate("zip(1, 2, 3)"))
1025
+ end
1026
+
1027
+ def test_index
1028
+ assert_equal("1", evaluate("index(1px solid blue, 1px)"))
1029
+ assert_equal("2", evaluate("index(1px solid blue, solid)"))
1030
+ assert_equal("3", evaluate("index(1px solid blue, #00f)"))
1031
+ assert_equal("1", evaluate("index(1px, 1px)"))
1032
+ assert_equal("false", evaluate("index(1px solid blue, 1em)"))
1033
+ assert_equal("false", evaluate("index(1px solid blue, notfound)"))
1034
+ assert_equal("false", evaluate("index(1px, #00f)"))
1035
+ end
1036
+
1037
+ def test_if
1038
+ assert_equal("1px", evaluate("if(true, 1px, 2px)"))
1039
+ assert_equal("2px", evaluate("if(false, 1px, 2px)"))
1040
+ assert_equal("2px", evaluate("if(null, 1px, 2px)"))
1041
+ end
1042
+
1043
+ def test_counter
1044
+ assert_equal("counter(foo)", evaluate("counter(foo)"))
1045
+ assert_equal('counter(item,".")', evaluate('counter(item, ".")'))
1046
+ assert_equal('counter(item,".")', evaluate('counter(item,".")'))
1047
+ end
1048
+
1049
+ def test_counters
1050
+ assert_equal("counters(foo)", evaluate("counters(foo)"))
1051
+ assert_equal('counters(item,".")', evaluate('counters(item, ".")'))
1052
+ assert_equal('counters(item,".")', evaluate('counters(item,".")'))
1053
+ end
1054
+
1055
+ def test_keyword_args_rgb
1056
+ assert_equal(%Q{white}, evaluate("rgb($red: 255, $green: 255, $blue: 255)"))
1057
+ end
1058
+
1059
+ def test_keyword_args_rgba
1060
+ assert_equal(%Q{rgba(255, 255, 255, 0.5)}, evaluate("rgba($red: 255, $green: 255, $blue: 255, $alpha: 0.5)"))
1061
+ assert_equal(%Q{rgba(255, 255, 255, 0.5)}, evaluate("rgba($color: #fff, $alpha: 0.5)"))
1062
+ end
1063
+
1064
+ def test_keyword_args_rgba_with_extra_args
1065
+ evaluate("rgba($red: 255, $green: 255, $blue: 255, $alpha: 0.5, $extra: error)")
1066
+ flunk("Expected exception")
1067
+ rescue Sass::SyntaxError => e
1068
+ assert_equal("Function rgba doesn't have an argument named $extra", e.message)
1069
+ end
1070
+
1071
+ def test_keyword_args_must_have_signature
1072
+ evaluate("no-kw-args($fake: value)")
1073
+ flunk("Expected exception")
1074
+ rescue Sass::SyntaxError => e
1075
+ assert_equal("Function no_kw_args doesn't support keyword arguments", e.message)
1076
+ end
1077
+
1078
+ def test_keyword_args_with_missing_argument
1079
+ evaluate("rgb($red: 255, $green: 255)")
1080
+ flunk("Expected exception")
1081
+ rescue Sass::SyntaxError => e
1082
+ assert_equal("Function rgb requires an argument named $blue", e.message)
1083
+ end
1084
+
1085
+ def test_keyword_args_with_extra_argument
1086
+ evaluate("rgb($red: 255, $green: 255, $blue: 255, $purple: 255)")
1087
+ flunk("Expected exception")
1088
+ rescue Sass::SyntaxError => e
1089
+ assert_equal("Function rgb doesn't have an argument named $purple", e.message)
1090
+ end
1091
+
1092
+ def test_keyword_args_with_positional_and_keyword_argument
1093
+ evaluate("rgb(255, 255, 255, $red: 255)")
1094
+ flunk("Expected exception")
1095
+ rescue Sass::SyntaxError => e
1096
+ assert_equal("Function rgb was passed argument $red both by position and by name", e.message)
1097
+ end
1098
+
1099
+ def test_keyword_args_with_keyword_before_positional_argument
1100
+ evaluate("rgb($red: 255, 255, 255)")
1101
+ flunk("Expected exception")
1102
+ rescue Sass::SyntaxError => e
1103
+ assert_equal("Positional arguments must come before keyword arguments.", e.message)
1104
+ end
1105
+
1106
+ def test_only_var_args
1107
+ assert_equal "only-var-args(2px, 3px, 4px)", evaluate("only-var-args(1px, 2px, 3px)")
1108
+ end
1109
+
1110
+ def test_only_kw_args
1111
+ assert_equal "only-kw-args(a, b, c)", evaluate("only-kw-args($a: 1, $b: 2, $c: 3)")
1112
+ end
1113
+
1114
+ ## Regression Tests
1115
+
1116
+ def test_saturation_bounds
1117
+ assert_equal "#fbfdff", evaluate("hsl(hue(#fbfdff), saturation(#fbfdff), lightness(#fbfdff))")
1118
+ end
1119
+
1120
+ private
1121
+
1122
+ def evaluate(value)
1123
+ result = perform(value)
1124
+ assert_kind_of Sass::Script::Literal, result
1125
+ return result.to_s
1126
+ end
1127
+
1128
+ def perform(value)
1129
+ Sass::Script::Parser.parse(value, 0, 0).perform(Sass::Environment.new)
1130
+ end
1131
+
1132
+ def assert_error_message(message, value)
1133
+ evaluate(value)
1134
+ flunk("Error message expected but not raised: #{message}")
1135
+ rescue Sass::SyntaxError => e
1136
+ assert_equal(message, e.message)
1137
+ end
1138
+
1139
+ end