sass 3.3.0.rc.2 → 3.3.0.rc.3

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 (76) hide show
  1. checksums.yaml +15 -0
  2. data/CONTRIBUTING +1 -1
  3. data/README.md +7 -7
  4. data/Rakefile +4 -2
  5. data/VERSION +1 -1
  6. data/VERSION_DATE +1 -1
  7. data/bin/sass +5 -1
  8. data/bin/sass-convert +5 -1
  9. data/bin/scss +5 -1
  10. data/ext/mkrf_conf.rb +23 -0
  11. data/lib/sass/css.rb +1 -1
  12. data/lib/sass/engine.rb +19 -9
  13. data/lib/sass/environment.rb +8 -0
  14. data/lib/sass/exec.rb +4 -4
  15. data/lib/sass/features.rb +0 -1
  16. data/lib/sass/importers/base.rb +13 -6
  17. data/lib/sass/importers/deprecated_path.rb +8 -2
  18. data/lib/sass/importers/filesystem.rb +33 -7
  19. data/lib/sass/logger.rb +1 -4
  20. data/lib/sass/logger/base.rb +0 -2
  21. data/lib/sass/logger/log_level.rb +0 -2
  22. data/lib/sass/plugin.rb +2 -2
  23. data/lib/sass/plugin/compiler.rb +23 -11
  24. data/lib/sass/plugin/configuration.rb +0 -1
  25. data/lib/sass/railtie.rb +1 -0
  26. data/lib/sass/script/css_lexer.rb +0 -1
  27. data/lib/sass/script/css_parser.rb +0 -1
  28. data/lib/sass/script/functions.rb +158 -96
  29. data/lib/sass/script/lexer.rb +29 -35
  30. data/lib/sass/script/parser.rb +10 -3
  31. data/lib/sass/script/tree.rb +0 -1
  32. data/lib/sass/script/tree/funcall.rb +21 -5
  33. data/lib/sass/script/tree/list_literal.rb +0 -1
  34. data/lib/sass/script/value/arg_list.rb +7 -3
  35. data/lib/sass/script/value/bool.rb +0 -1
  36. data/lib/sass/script/value/null.rb +0 -1
  37. data/lib/sass/script/value/number.rb +2 -6
  38. data/lib/sass/scss/css_parser.rb +0 -1
  39. data/lib/sass/scss/parser.rb +5 -5
  40. data/lib/sass/scss/script_lexer.rb +0 -1
  41. data/lib/sass/scss/script_parser.rb +0 -1
  42. data/lib/sass/selector.rb +11 -1
  43. data/lib/sass/selector/comma_sequence.rb +3 -4
  44. data/lib/sass/selector/sequence.rb +11 -7
  45. data/lib/sass/selector/simple_sequence.rb +42 -11
  46. data/lib/sass/source/map.rb +6 -19
  47. data/lib/sass/tree/at_root_node.rb +1 -1
  48. data/lib/sass/tree/mixin_node.rb +2 -2
  49. data/lib/sass/tree/prop_node.rb +0 -1
  50. data/lib/sass/tree/variable_node.rb +0 -5
  51. data/lib/sass/tree/visitors/check_nesting.rb +0 -1
  52. data/lib/sass/tree/visitors/convert.rb +2 -2
  53. data/lib/sass/tree/visitors/cssize.rb +184 -84
  54. data/lib/sass/tree/visitors/deep_copy.rb +0 -1
  55. data/lib/sass/tree/visitors/perform.rb +14 -44
  56. data/lib/sass/util.rb +59 -12
  57. data/lib/sass/util/cross_platform_random.rb +19 -0
  58. data/lib/sass/util/normalized_map.rb +17 -1
  59. data/test/sass/compiler_test.rb +10 -0
  60. data/test/sass/conversion_test.rb +36 -0
  61. data/test/sass/css2sass_test.rb +19 -0
  62. data/test/sass/engine_test.rb +54 -105
  63. data/test/sass/functions_test.rb +233 -26
  64. data/test/sass/importer_test.rb +72 -10
  65. data/test/sass/plugin_test.rb +14 -0
  66. data/test/sass/script_conversion_test.rb +4 -4
  67. data/test/sass/script_test.rb +58 -21
  68. data/test/sass/scss/css_test.rb +8 -1
  69. data/test/sass/scss/scss_test.rb +376 -179
  70. data/test/sass/source_map_test.rb +8 -0
  71. data/test/sass/templates/subdir/import_up1.scss +1 -0
  72. data/test/sass/templates/subdir/import_up2.scss +1 -0
  73. data/test/sass/util_test.rb +16 -0
  74. data/test/test_helper.rb +12 -4
  75. metadata +269 -287
  76. data/lib/sass/script/tree/selector.rb +0 -30
@@ -120,37 +120,67 @@ class SassFunctionTest < Test::Unit::TestCase
120
120
  assert_equal("50%", evaluate("percentage(.5)"))
121
121
  assert_equal("100%", evaluate("percentage(1)"))
122
122
  assert_equal("25%", evaluate("percentage(25px / 100px)"))
123
- 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
124
130
  end
125
131
 
126
132
  def test_percentage_checks_types
127
- assert_error_message("$value: 25px is not a unitless number for `percentage'", "percentage(25px)")
128
- assert_error_message("$value: #cccccc is not a unitless number for `percentage'", "percentage(#ccc)")
129
- assert_error_message("$value: \"string\" is not a unitless number for `percentage'", %Q{percentage("string")})
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")})
130
136
  end
131
137
 
132
138
  def test_round
133
139
  assert_equal("5", evaluate("round(4.8)"))
134
140
  assert_equal("5px", evaluate("round(4.8px)"))
135
141
  assert_equal("5px", evaluate("round(5.49px)"))
136
- 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
137
150
 
151
+ def test_round_checks_types
138
152
  assert_error_message("$value: #cccccc is not a number for `round'", "round(#ccc)")
139
153
  end
140
154
 
141
155
  def test_floor
142
156
  assert_equal("4", evaluate("floor(4.8)"))
143
157
  assert_equal("4px", evaluate("floor(4.8px)"))
144
- 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
145
166
 
167
+ def test_floor_checks_types
146
168
  assert_error_message("$value: \"foo\" is not a number for `floor'", "floor(\"foo\")")
147
169
  end
148
170
 
149
171
  def test_ceil
150
172
  assert_equal("5", evaluate("ceil(4.1)"))
151
173
  assert_equal("5px", evaluate("ceil(4.8px)"))
152
- assert_equal("5px", evaluate("ceil($value: 4.8px)"))
174
+ assert_equal("5px", evaluate("ceil($number: 4.8px)"))
175
+ end
153
176
 
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
154
184
  assert_error_message("$value: \"a\" is not a number for `ceil'", "ceil(\"a\")")
155
185
  end
156
186
 
@@ -159,8 +189,16 @@ class SassFunctionTest < Test::Unit::TestCase
159
189
  assert_equal("5px", evaluate("abs(-5px)"))
160
190
  assert_equal("5", evaluate("abs(5)"))
161
191
  assert_equal("5px", evaluate("abs(5px)"))
162
- 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
163
200
 
201
+ def test_abs_checks_types
164
202
  assert_error_message("$value: #aaaaaa is not a number for `abs'", "abs(#aaa)")
165
203
  end
166
204
 
@@ -799,12 +837,38 @@ class SassFunctionTest < Test::Unit::TestCase
799
837
  assert_equal("blue", evaluate("mix(transparentize(#f00, 1), #00f, 0%)"))
800
838
  assert_equal("rgba(0, 0, 255, 0)", evaluate("mix(#f00, transparentize(#00f, 1), 0%)"))
801
839
  assert_equal("rgba(255, 0, 0, 0)", evaluate("mix(transparentize(#f00, 1), #00f, 100%)"))
802
- 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
803
867
  end
804
868
 
805
869
  def test_mix_tests_types
806
- assert_error_message("$color-1: \"foo\" is not a color for `mix'", "mix(\"foo\", #f00, 10%)")
807
- assert_error_message("$color-2: \"foo\" is not a color for `mix'", "mix(#f00, \"foo\", 10%)")
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%)")
808
872
  assert_error_message("$weight: \"foo\" is not a number for `mix'", "mix(#f00, #baf, \"foo\")")
809
873
  end
810
874
 
@@ -904,7 +968,7 @@ class SassFunctionTest < Test::Unit::TestCase
904
968
  def test_str_index
905
969
  assert_equal('1', evaluate('str-index(abcd, a)'))
906
970
  assert_equal('1', evaluate('str-index(abcd, ab)'))
907
- assert_equal('0', evaluate('str-index(abcd, X)'))
971
+ assert_equal(Sass::Script::Value::Null.new, perform('str-index(abcd, X)'))
908
972
  assert_equal('3', evaluate('str-index(abcd, c)'))
909
973
  end
910
974
 
@@ -1017,9 +1081,28 @@ MSG
1017
1081
  assert_equal(%Q{true}, evaluate("comparable(2px, 1px)"))
1018
1082
  assert_equal(%Q{true}, evaluate("comparable(10cm, 3mm)"))
1019
1083
  assert_equal(%Q{false}, evaluate("comparable(100px, 3em)"))
1020
- assert_equal(%Q{false}, evaluate("comparable($number-1: 100px, $number-2: 3em)"))
1021
- assert_error_message("$number-1: #ff0000 is not a number for `comparable'", "comparable(#f00, 1px)")
1022
- assert_error_message("$number-2: #ff0000 is not a number for `comparable'", "comparable(1px, #f00)")
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)")
1023
1106
  end
1024
1107
 
1025
1108
  def test_length
@@ -1174,16 +1257,17 @@ MSG
1174
1257
  end
1175
1258
 
1176
1259
  def test_index
1260
+ null = Sass::Script::Value::Null.new
1177
1261
  assert_equal("1", evaluate("index(1px solid blue, 1px)"))
1178
1262
  assert_equal("2", evaluate("index(1px solid blue, solid)"))
1179
1263
  assert_equal("3", evaluate("index(1px solid blue, #00f)"))
1180
1264
  assert_equal("1", evaluate("index(1px, 1px)"))
1181
- assert_equal("false", evaluate("index(1px solid blue, 1em)"))
1182
- assert_equal("false", evaluate("index(1px solid blue, notfound)"))
1183
- assert_equal("false", evaluate("index(1px, #00f)"))
1265
+ assert_equal(null, perform("index(1px solid blue, 1em)"))
1266
+ assert_equal(null, perform("index(1px solid blue, notfound)"))
1267
+ assert_equal(null, perform("index(1px, #00f)"))
1184
1268
 
1185
1269
  assert_equal("1", evaluate("index((foo: bar, bar: baz), (foo bar))"))
1186
- assert_equal("false", evaluate("index((foo: bar, bar: baz), (foo: bar))"))
1270
+ assert_equal(null, perform("index((foo: bar, bar: baz), (foo: bar))"))
1187
1271
  end
1188
1272
 
1189
1273
  def test_list_separator
@@ -1312,7 +1396,9 @@ SCSS
1312
1396
  assert_equal "2", evaluate("map-get((foo: 1, bar: 2), bar)")
1313
1397
  assert_equal "null", perform("map-get((foo: 1, bar: 2), baz)").to_sass
1314
1398
  assert_equal "null", perform("map-get((), foo)").to_sass
1399
+ end
1315
1400
 
1401
+ def test_map_get_deprecation_warning
1316
1402
  assert_warning(<<WARNING) do
1317
1403
  DEPRECATION WARNING: Passing lists of pairs to map-get is deprecated and will
1318
1404
  be removed in future versions of Sass. Use Sass maps instead. For details, see
@@ -1322,6 +1408,10 @@ WARNING
1322
1408
  end
1323
1409
  end
1324
1410
 
1411
+ def test_map_get_checks_type
1412
+ assert_error_message("$map: 12 is not a map for `map-get'", "map-get(12, bar)")
1413
+ end
1414
+
1325
1415
  def test_map_merge
1326
1416
  assert_equal("(foo: 1, bar: 2, baz: 3)",
1327
1417
  perform("map-merge((foo: 1, bar: 2), (baz: 3))").to_sass)
@@ -1329,7 +1419,9 @@ WARNING
1329
1419
  perform("map-merge((), (foo: 1, bar: 2))").to_sass)
1330
1420
  assert_equal("(foo: 1, bar: 2)",
1331
1421
  perform("map-merge((foo: 1, bar: 2), ())").to_sass)
1422
+ end
1332
1423
 
1424
+ def test_map_merge_deprecation_warning
1333
1425
  assert_warning(<<WARNING) do
1334
1426
  DEPRECATION WARNING: Passing lists of pairs to map-merge is deprecated and will
1335
1427
  be removed in future versions of Sass. Use Sass maps instead. For details, see
@@ -1349,11 +1441,39 @@ WARNING
1349
1441
  end
1350
1442
  end
1351
1443
 
1444
+ def test_map_merge_checks_type
1445
+ assert_error_message("$map1: 12 is not a map for `map-merge'", "map-merge(12, (foo: 1))")
1446
+ assert_error_message("$map2: 12 is not a map for `map-merge'", "map-merge((foo: 1), 12)")
1447
+ end
1448
+
1449
+ def test_map_remove
1450
+ assert_equal("(foo: 1, baz: 3)",
1451
+ perform("map-remove((foo: 1, bar: 2, baz: 3), bar)").to_sass)
1452
+ assert_equal("()", perform("map-remove((), foo)").to_sass)
1453
+ end
1454
+
1455
+ def test_map_remove_deprecation_warning
1456
+ assert_warning(<<WARNING) do
1457
+ DEPRECATION WARNING: Passing lists of pairs to map-remove is deprecated and will
1458
+ be removed in future versions of Sass. Use Sass maps instead. For details, see
1459
+ http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1460
+ WARNING
1461
+ assert_equal("(foo: 1, baz: 3)",
1462
+ perform("map-remove((foo 1, bar 2, baz 3), bar)").to_sass)
1463
+ end
1464
+ end
1465
+
1466
+ def test_map_remove_checks_type
1467
+ assert_error_message("$map: 12 is not a map for `map-remove'", "map-remove(12, foo)")
1468
+ end
1469
+
1352
1470
  def test_map_keys
1353
1471
  assert_equal("foo, bar",
1354
1472
  perform("map-keys((foo: 1, bar: 2))").to_sass)
1355
1473
  assert_equal("()", perform("map-keys(())").to_sass)
1474
+ end
1356
1475
 
1476
+ def test_map_keys_deprecation_warning
1357
1477
  assert_warning(<<WARNING) do
1358
1478
  DEPRECATION WARNING: Passing lists of pairs to map-keys is deprecated and will
1359
1479
  be removed in future versions of Sass. Use Sass maps instead. For details, see
@@ -1364,12 +1484,18 @@ WARNING
1364
1484
  end
1365
1485
  end
1366
1486
 
1487
+ def test_map_keys_checks_type
1488
+ assert_error_message("$map: 12 is not a map for `map-keys'", "map-keys(12)")
1489
+ end
1490
+
1367
1491
  def test_map_values
1368
1492
  assert_equal("1, 2", perform("map-values((foo: 1, bar: 2))").to_sass)
1369
1493
  assert_equal("1, 2, 2",
1370
1494
  perform("map-values((foo: 1, bar: 2, baz: 2))").to_sass)
1371
1495
  assert_equal("()", perform("map-values(())").to_sass)
1496
+ end
1372
1497
 
1498
+ def test_map_values_deprecation_warning
1373
1499
  assert_warning(<<WARNING) do
1374
1500
  DEPRECATION WARNING: Passing lists of pairs to map-values is deprecated and will
1375
1501
  be removed in future versions of Sass. Use Sass maps instead. For details, see
@@ -1379,11 +1505,17 @@ WARNING
1379
1505
  end
1380
1506
  end
1381
1507
 
1508
+ def test_map_values_checks_type
1509
+ assert_error_message("$map: 12 is not a map for `map-values'", "map-values(12)")
1510
+ end
1511
+
1382
1512
  def test_map_has_key
1383
1513
  assert_equal "true", evaluate("map-has-key((foo: 1, bar: 1), foo)")
1384
1514
  assert_equal "false", evaluate("map-has-key((foo: 1, bar: 1), baz)")
1385
1515
  assert_equal "false", evaluate("map-has-key((), foo)")
1516
+ end
1386
1517
 
1518
+ def test_map_has_key_deprecation_warning
1387
1519
  assert_warning(<<WARNING) do
1388
1520
  DEPRECATION WARNING: Passing lists of pairs to map-has-key is deprecated and will
1389
1521
  be removed in future versions of Sass. Use Sass maps instead. For details, see
@@ -1393,10 +1525,15 @@ WARNING
1393
1525
  end
1394
1526
  end
1395
1527
 
1528
+ def test_map_has_key_checks_type
1529
+ assert_error_message("$map: 12 is not a map for `map-has-key'", "map-has-key(12, foo)")
1530
+ end
1531
+
1396
1532
  def test_keywords
1397
1533
  # The actual functionality is tested in tests where real arglists are passed.
1398
- assert_error_message("12 is not a variable argument list for `keywords'", "keywords(12)")
1399
- assert_error_message("(1 2 3) is not a variable argument list for `keywords'", "keywords(1 2 3)")
1534
+ assert_error_message("$args: 12 is not a variable argument list for `keywords'", "keywords(12)")
1535
+ assert_error_message(
1536
+ "$args: (1 2 3) is not a variable argument list for `keywords'", "keywords(1 2 3)")
1400
1537
  end
1401
1538
 
1402
1539
  def test_partial_list_of_pairs_doesnt_work_as_a_map
@@ -1462,6 +1599,27 @@ WARNING
1462
1599
  env("fn" => Sass::Script::String.new("lighten"))))
1463
1600
  end
1464
1601
 
1602
+ def test_call_uses_local_scope
1603
+ assert_equal <<CSS, render(<<SCSS)
1604
+ .first-scope {
1605
+ a: local; }
1606
+
1607
+ .second-scope {
1608
+ a: global; }
1609
+ CSS
1610
+ @function foo() {@return global}
1611
+
1612
+ .first-scope {
1613
+ @function foo() {@return local}
1614
+ a: call(foo);
1615
+ }
1616
+
1617
+ .second-scope {
1618
+ a: call(foo);
1619
+ }
1620
+ SCSS
1621
+ end
1622
+
1465
1623
  def test_call_unknown_function
1466
1624
  assert_equal evaluate("unknown(red, blue)"), evaluate("call(unknown, red, blue)")
1467
1625
  end
@@ -1495,6 +1653,10 @@ $global-var: has-value;
1495
1653
  SCSS
1496
1654
  end
1497
1655
 
1656
+ def test_variable_exists_checks_type
1657
+ assert_error_message("$name: 1 is not a string for `variable-exists'", "variable-exists(1)")
1658
+ end
1659
+
1498
1660
  def test_global_variable_exists
1499
1661
  assert_equal <<CSS, render(<<SCSS)
1500
1662
  .test {
@@ -1524,6 +1686,11 @@ $named: global-variable-exists($name: g);
1524
1686
  SCSS
1525
1687
  end
1526
1688
 
1689
+ def test_global_variable_exists_checks_type
1690
+ assert_error_message("$name: 1 is not a string for `global-variable-exists'",
1691
+ "global-variable-exists(1)")
1692
+ end
1693
+
1527
1694
  def test_function_exists
1528
1695
  # built-ins
1529
1696
  assert_equal "true", evaluate("function-exists(lighten)")
@@ -1543,6 +1710,10 @@ CSS
1543
1710
  SCSS
1544
1711
  end
1545
1712
 
1713
+ def test_function_exists_checks_type
1714
+ assert_error_message("$name: 1 is not a string for `function-exists'", "function-exists(1)")
1715
+ end
1716
+
1546
1717
  def test_mixin_exists
1547
1718
  assert_equal "false", evaluate("mixin-exists(foo)")
1548
1719
  # with named argument
@@ -1560,11 +1731,8 @@ CSS
1560
1731
  SCSS
1561
1732
  end
1562
1733
 
1563
- def test_existence_functions_check_argument_type
1564
- assert_error_message("2px is not a string for `function-exists'", "function-exists(2px)")
1565
- assert_error_message("2px is not a string for `mixin-exists'", "mixin-exists(2px)")
1566
- assert_error_message("2px is not a string for `global-variable-exists'", "global-variable-exists(2px)")
1567
- assert_error_message("2px is not a string for `variable-exists'", "variable-exists(2px)")
1734
+ def test_mixin_exists_checks_type
1735
+ assert_error_message("$name: 1 is not a string for `mixin-exists'", "mixin-exists(1)")
1568
1736
  end
1569
1737
 
1570
1738
  def test_inspect
@@ -1574,6 +1742,45 @@ SCSS
1574
1742
  assert_equal "(a: 1, b: 2)", evaluate("inspect((a: 1, b: 2))")
1575
1743
  end
1576
1744
 
1745
+ def test_random
1746
+ Sass::Script::Functions.random_seed = 1
1747
+ assert_equal "0.41702", evaluate("random()")
1748
+ assert_equal "13", evaluate("random(100)")
1749
+ end
1750
+
1751
+ def test_random_works_without_a_seed
1752
+ if Sass::Script::Functions.instance_variable_defined?("@random_number_generator")
1753
+ Sass::Script::Functions.send(:remove_instance_variable, "@random_number_generator")
1754
+ end
1755
+
1756
+ result = perform("random()")
1757
+ assert_kind_of Sass::Script::Number, result
1758
+ assert result.value >= 0, "Random number was below 0"
1759
+ assert result.value <= 1, "Random number was above 1"
1760
+ end
1761
+
1762
+ def test_random_with_limit_one
1763
+ # Passing 1 as the limit should always return 1, since limit calls return
1764
+ # integers from 1 to the argument, so when the argument is 1, its a predicatble
1765
+ # outcome
1766
+ assert "1", evaluate("random(1)")
1767
+ end
1768
+
1769
+ def test_random_with_limit_too_low
1770
+ assert_error_message("$limit 0 must be greater than or equal to 1 for `random'", "random(0)")
1771
+ end
1772
+
1773
+ def test_random_with_non_integer_limit
1774
+ assert_error_message("Expected $limit to be an integer but got 1.5 for `random'", "random(1.5)")
1775
+ end
1776
+
1777
+ # This could *possibly* fail, but exceedingly unlikely
1778
+ def test_random_is_semi_unique
1779
+ if Sass::Script::Functions.instance_variable_defined?("@random_number_generator")
1780
+ Sass::Script::Functions.send(:remove_instance_variable, "@random_number_generator")
1781
+ end
1782
+ assert_not_equal evaluate("random()"), evaluate("random()")
1783
+ end
1577
1784
 
1578
1785
  ## Regression Tests
1579
1786
 
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
  require File.dirname(__FILE__) + '/../test_helper'
3
3
  require File.dirname(__FILE__) + '/test_helper'
4
-
4
+ require 'mock_importer'
5
5
  require 'sass/plugin'
6
6
 
7
7
  class ImporterTest < Test::Unit::TestCase
8
-
8
+
9
9
  class FruitImporter < Sass::Importers::Base
10
10
  def find(name, context = nil)
11
11
  fruit = parse(name)
@@ -31,7 +31,7 @@ class ImporterTest < Test::Unit::TestCase
31
31
  [self.class.name, name]
32
32
  end
33
33
 
34
- def public_url(name)
34
+ def public_url(name, sourcemap_directory = nil)
35
35
  "http://#{parse(name)}.example.com/style.scss"
36
36
  end
37
37
 
@@ -42,6 +42,18 @@ class ImporterTest < Test::Unit::TestCase
42
42
  end
43
43
  end
44
44
 
45
+ class NoPublicUrlImporter < FruitImporter
46
+ def public_url(name, sourcemap_directory = nil)
47
+ nil
48
+ end
49
+
50
+ private
51
+
52
+ def parse(name)
53
+ name[%r{ephemeral/(\w+)(\.s[ac]ss)?}, 1]
54
+ end
55
+ end
56
+
45
57
  # This class proves that you can override the extension scheme for importers
46
58
  class ReversedExtImporter < Sass::Importers::Filesystem
47
59
  def extensions
@@ -207,15 +219,61 @@ SCSS
207
219
  "version": 3,
208
220
  "mappings": "AAAA,QAAS;EACP,KAAK,EAAE,IAAI",
209
221
  "sources": ["http://orange.example.com/style.scss"],
222
+ "names": [],
210
223
  "file": "css_uri"
211
224
  }
212
225
  JSON
213
226
  end
214
227
 
228
+ def test_source_map_with_only_css_uri_can_have_no_public_url_without_warning
229
+ ephemeral_importer = NoPublicUrlImporter.new
230
+ mock_importer = MockImporter.new
231
+ def mock_importer.public_url(name, sourcemap_directory = nil)
232
+ "css_uri"
233
+ end
234
+
235
+ options = {
236
+ :filename => filename_for_test,
237
+ :sourcemap_filename => sourcemap_filename_for_test,
238
+ :importer => mock_importer,
239
+ :syntax => :scss,
240
+ :load_paths => [ephemeral_importer],
241
+ :cache => false
242
+ }
243
+
244
+ engine = Sass::Engine.new(<<SCSS, options)
245
+ @import "ephemeral/orange";
246
+ .orange {
247
+ @include orange;
248
+ }
249
+ SCSS
250
+
251
+ assert_warning("") do
252
+ css_output, sourcemap = engine.render_with_sourcemap('sourcemap_uri')
253
+ assert_equal <<CSS.strip, css_output.strip
254
+ .orange {
255
+ color: orange; }
256
+
257
+ /*# sourceMappingURL=sourcemap_uri */
258
+ CSS
259
+ map = sourcemap.to_json(:css_uri => 'css_uri')
260
+ assert_equal <<JSON.strip, map
261
+ {
262
+ "version": 3,
263
+ "mappings": "AACA,OAAQ",
264
+ "sources": ["css_uri"],
265
+ "names": [],
266
+ "file": "css_uri"
267
+ }
268
+ JSON
269
+ end
270
+ end
271
+
215
272
  def test_source_map_with_only_css_uri_doesnt_support_filesystem_importer
216
273
  file_system_importer = Sass::Importers::Filesystem.new('.')
217
274
  options = {
218
275
  :filename => filename_for_test(:scss),
276
+ :sourcemap_filename => sourcemap_filename_for_test,
219
277
  :importer => file_system_importer,
220
278
  :syntax => :scss
221
279
  }
@@ -229,7 +287,6 @@ SCSS
229
287
  assert_warning(<<WARNING) {sourcemap.to_json(:css_uri => 'css_uri')}
230
288
  WARNING: Couldn't determine public URL for "#{filename_for_test(:scss)}" while generating sourcemap.
231
289
  Without a public URL, there's nothing for the source map to link to.
232
- Custom importers should define the #public_url method.
233
290
  WARNING
234
291
  end
235
292
 
@@ -237,6 +294,7 @@ WARNING
237
294
  file_system_importer = Sass::Importers::Filesystem.new('.')
238
295
  options = {
239
296
  :filename => filename_for_test(:scss),
297
+ :sourcemap_filename => sourcemap_filename_for_test,
240
298
  :importer => file_system_importer,
241
299
  :syntax => :scss
242
300
  }
@@ -250,14 +308,16 @@ SCSS
250
308
  assert_warning(<<WARNING) {sourcemap.to_json(:css_uri => 'css_uri', :css_path => 'css_path')}
251
309
  WARNING: Couldn't determine public URL for "#{filename_for_test(:scss)}" while generating sourcemap.
252
310
  Without a public URL, there's nothing for the source map to link to.
253
- Custom importers should define the #public_url method.
254
311
  WARNING
255
312
  end
256
313
 
257
314
  def test_source_map_with_css_uri_and_sourcemap_path_supports_filesystem_importer
258
315
  file_system_importer = Sass::Importers::Filesystem.new('.')
316
+ css_uri = 'css_uri'
317
+ sourcemap_path = 'map/style.map'
259
318
  options = {
260
319
  :filename => 'sass/style.scss',
320
+ :sourcemap_filename => sourcemap_path,
261
321
  :importer => file_system_importer,
262
322
  :syntax => :scss
263
323
  }
@@ -270,13 +330,12 @@ SCSS
270
330
 
271
331
 
272
332
  rendered, sourcemap = engine.render_with_sourcemap('http://map.example.com/map/style.map')
273
- css_uri = 'css_uri'
274
- sourcemap_path = 'map/style.map'
275
333
  assert_equal <<JSON.strip, sourcemap.to_json(:css_uri => css_uri, :sourcemap_path => sourcemap_path)
276
334
  {
277
335
  "version": 3,
278
336
  "mappings": "AAAA,IAAK;EAAC,CAAC,EAAE,CAAC",
279
337
  "sources": ["../sass/style.scss"],
338
+ "names": [],
280
339
  "file": "css_uri"
281
340
  }
282
341
  JSON
@@ -284,8 +343,12 @@ JSON
284
343
 
285
344
  def test_source_map_with_css_path_and_sourcemap_path_supports_file_system_importer
286
345
  file_system_importer = Sass::Importers::Filesystem.new('.')
346
+ sass_path = 'sass/style.scss'
347
+ css_path = 'static/style.css'
348
+ sourcemap_path = 'map/style.map'
287
349
  options = {
288
- :filename => 'sass/style.scss',
350
+ :filename => sass_path,
351
+ :sourcemap_filename => sourcemap_path,
289
352
  :importer => file_system_importer,
290
353
  :syntax => :scss
291
354
  }
@@ -295,13 +358,12 @@ JSON
295
358
  SCSS
296
359
 
297
360
  _, sourcemap = engine.render_with_sourcemap('http://map.example.com/map/style.map')
298
- css_path = 'static/style.css'
299
- sourcemap_path = 'map/style.map'
300
361
  assert_equal <<JSON.strip, sourcemap.to_json(:css_path => css_path, :sourcemap_path => sourcemap_path)
301
362
  {
302
363
  "version": 3,
303
364
  "mappings": "AAAA,IAAK;EAAC,CAAC,EAAE,CAAC",
304
365
  "sources": ["../sass/style.scss"],
366
+ "names": [],
305
367
  "file": "../static/style.css"
306
368
  }
307
369
  JSON