sass 3.3.14 → 3.4.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +5 -5
  4. data/VERSION +1 -1
  5. data/VERSION_DATE +1 -1
  6. data/VERSION_NAME +1 -1
  7. data/bin/sass +1 -1
  8. data/bin/scss +1 -1
  9. data/lib/sass.rb +0 -5
  10. data/lib/sass/css.rb +1 -3
  11. data/lib/sass/engine.rb +28 -39
  12. data/lib/sass/environment.rb +13 -17
  13. data/lib/sass/error.rb +6 -9
  14. data/lib/sass/exec.rb +5 -771
  15. data/lib/sass/exec/base.rb +187 -0
  16. data/lib/sass/exec/sass_convert.rb +264 -0
  17. data/lib/sass/exec/sass_scss.rb +419 -0
  18. data/lib/sass/features.rb +6 -0
  19. data/lib/sass/importers.rb +0 -1
  20. data/lib/sass/importers/base.rb +5 -1
  21. data/lib/sass/importers/filesystem.rb +4 -21
  22. data/lib/sass/media.rb +1 -4
  23. data/lib/sass/plugin/compiler.rb +32 -136
  24. data/lib/sass/script/css_lexer.rb +1 -1
  25. data/lib/sass/script/functions.rb +363 -39
  26. data/lib/sass/script/lexer.rb +68 -50
  27. data/lib/sass/script/parser.rb +29 -14
  28. data/lib/sass/script/tree.rb +1 -0
  29. data/lib/sass/script/tree/funcall.rb +1 -1
  30. data/lib/sass/script/tree/interpolation.rb +19 -1
  31. data/lib/sass/script/tree/selector.rb +26 -0
  32. data/lib/sass/script/value.rb +0 -1
  33. data/lib/sass/script/value/bool.rb +0 -5
  34. data/lib/sass/script/value/color.rb +32 -12
  35. data/lib/sass/script/value/helpers.rb +107 -0
  36. data/lib/sass/script/value/list.rb +0 -15
  37. data/lib/sass/script/value/null.rb +0 -5
  38. data/lib/sass/script/value/number.rb +60 -14
  39. data/lib/sass/script/value/string.rb +53 -9
  40. data/lib/sass/scss/css_parser.rb +8 -2
  41. data/lib/sass/scss/parser.rb +175 -319
  42. data/lib/sass/scss/rx.rb +14 -5
  43. data/lib/sass/scss/static_parser.rb +298 -1
  44. data/lib/sass/selector.rb +56 -193
  45. data/lib/sass/selector/abstract_sequence.rb +28 -13
  46. data/lib/sass/selector/comma_sequence.rb +91 -12
  47. data/lib/sass/selector/pseudo.rb +256 -0
  48. data/lib/sass/selector/sequence.rb +99 -31
  49. data/lib/sass/selector/simple.rb +14 -25
  50. data/lib/sass/selector/simple_sequence.rb +101 -37
  51. data/lib/sass/shared.rb +1 -1
  52. data/lib/sass/source/map.rb +23 -9
  53. data/lib/sass/stack.rb +0 -6
  54. data/lib/sass/supports.rb +1 -1
  55. data/lib/sass/tree/at_root_node.rb +1 -0
  56. data/lib/sass/tree/directive_node.rb +7 -1
  57. data/lib/sass/tree/error_node.rb +18 -0
  58. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  59. data/lib/sass/tree/prop_node.rb +1 -1
  60. data/lib/sass/tree/rule_node.rb +11 -6
  61. data/lib/sass/tree/visitors/check_nesting.rb +3 -4
  62. data/lib/sass/tree/visitors/convert.rb +8 -17
  63. data/lib/sass/tree/visitors/cssize.rb +12 -24
  64. data/lib/sass/tree/visitors/deep_copy.rb +5 -0
  65. data/lib/sass/tree/visitors/perform.rb +43 -28
  66. data/lib/sass/tree/visitors/set_options.rb +5 -0
  67. data/lib/sass/tree/visitors/to_css.rb +14 -13
  68. data/lib/sass/util.rb +94 -90
  69. data/test/sass/cache_test.rb +1 -1
  70. data/test/sass/callbacks_test.rb +1 -1
  71. data/test/sass/compiler_test.rb +5 -14
  72. data/test/sass/conversion_test.rb +47 -1
  73. data/test/sass/css2sass_test.rb +3 -3
  74. data/test/sass/encoding_test.rb +219 -0
  75. data/test/sass/engine_test.rb +128 -191
  76. data/test/sass/exec_test.rb +2 -2
  77. data/test/sass/extend_test.rb +234 -17
  78. data/test/sass/functions_test.rb +268 -213
  79. data/test/sass/importer_test.rb +31 -21
  80. data/test/sass/logger_test.rb +1 -1
  81. data/test/sass/more_results/more_import.css +1 -1
  82. data/test/sass/plugin_test.rb +12 -11
  83. data/test/sass/results/compact.css +1 -1
  84. data/test/sass/results/complex.css +4 -4
  85. data/test/sass/results/expanded.css +1 -1
  86. data/test/sass/results/import.css +1 -1
  87. data/test/sass/results/import_charset_ibm866.css +2 -2
  88. data/test/sass/results/mixins.css +17 -17
  89. data/test/sass/results/nested.css +1 -1
  90. data/test/sass/results/parent_ref.css +2 -2
  91. data/test/sass/results/script.css +3 -3
  92. data/test/sass/results/scss_import.css +1 -1
  93. data/test/sass/script_conversion_test.rb +7 -4
  94. data/test/sass/script_test.rb +202 -79
  95. data/test/sass/scss/css_test.rb +95 -25
  96. data/test/sass/scss/rx_test.rb +4 -4
  97. data/test/sass/scss/scss_test.rb +363 -19
  98. data/test/sass/source_map_test.rb +48 -41
  99. data/test/sass/superselector_test.rb +191 -0
  100. data/test/sass/templates/scss_import.scss +2 -1
  101. data/test/sass/test_helper.rb +1 -1
  102. data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
  103. data/test/sass/util/normalized_map_test.rb +1 -1
  104. data/test/sass/util/subset_map_test.rb +2 -2
  105. data/test/sass/util_test.rb +1 -1
  106. data/test/sass/value_helpers_test.rb +3 -3
  107. data/test/test_helper.rb +2 -2
  108. metadata +30 -7
  109. data/lib/sass/importers/deprecated_path.rb +0 -51
  110. data/lib/sass/script/value/deprecated_false.rb +0 -55
@@ -3,7 +3,7 @@ require File.dirname(__FILE__) + '/../test_helper'
3
3
  require 'sass/util/test'
4
4
  require 'tmpdir'
5
5
 
6
- class ExecTest < Test::Unit::TestCase
6
+ class ExecTest < MiniTest::Test
7
7
  include Sass::Util::Test
8
8
 
9
9
  def setup
@@ -19,7 +19,7 @@ class ExecTest < Test::Unit::TestCase
19
19
  src = get_path("src.scss")
20
20
  dest = get_path("dest.css")
21
21
  write(src, ".ruleset { margin: 0 }")
22
- assert(exec(*%w[scss -t expanded --unix-newlines].push(src, dest)))
22
+ assert(exec(*%w[scss --sourcemap=none -t expanded --unix-newlines].push(src, dest)))
23
23
  assert_equal(".ruleset {\n margin: 0;\n}\n", read(dest))
24
24
  end
25
25
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  require File.dirname(__FILE__) + '/../test_helper'
3
3
 
4
- class ExtendTest < Test::Unit::TestCase
4
+ class ExtendTest < MiniTest::Test
5
5
  def test_basic
6
6
  assert_equal <<CSS, render(<<SCSS)
7
7
  .foo, .bar {
@@ -310,9 +310,183 @@ SCSS
310
310
  end
311
311
 
312
312
  def test_negation_unification
313
- assert_unification ':not(.foo).baz', ':not(.bar) {@extend .baz}', ':not(.foo).baz, :not(.foo):not(.bar)'
314
- assert_unification ':not(.foo).baz', ':not(.foo) {@extend .baz}', ':not(.foo)'
315
- assert_unification ':not([a=b]).baz', ':not([a = b]) {@extend .baz}', ':not([a=b])'
313
+ assert_extends ':not(.foo).baz', ':not(.bar) {@extend .baz}', ':not(.foo).baz, :not(.foo):not(.bar)'
314
+ # Unifying to :not(.foo) here would reduce the specificity of the original selector.
315
+ assert_extends ':not(.foo).baz', ':not(.foo) {@extend .baz}', ':not(.foo).baz, :not(.foo)'
316
+ end
317
+
318
+ def test_prefixed_pseudoclass_unification
319
+ assert_unification(
320
+ ':nth-child(2n+1 of .foo).baz',
321
+ ':nth-child(2n of .foo) {@extend .baz}',
322
+ ':nth-child(2n+1 of .foo).baz, :nth-child(2n+1 of .foo):nth-child(2n of .foo)')
323
+
324
+ assert_unification(
325
+ ':nth-child(2n+1 of .foo).baz',
326
+ ':nth-child(2n+1 of .bar) {@extend .baz}',
327
+ ':nth-child(2n+1 of .foo).baz, :nth-child(2n+1 of .foo):nth-child(2n+1 of .bar)')
328
+
329
+ assert_unification(
330
+ ':nth-child(2n+1 of .foo).baz',
331
+ ':nth-child(2n+1 of .foo) {@extend .baz}',
332
+ ':nth-child(2n+1 of .foo)')
333
+ end
334
+
335
+ def test_extend_into_not
336
+ assert_extends(':not(.foo)', '.x {@extend .foo}', ':not(.foo, .x)')
337
+ assert_extends(':not(.foo.bar)', '.x {@extend .bar}', ':not(.foo.bar, .foo.x)')
338
+ assert_extends(
339
+ ':not(.foo.bar, .baz.bar)',
340
+ '.x {@extend .bar}',
341
+ ':not(.foo.bar, .foo.x, .baz.bar, .baz.x)')
342
+ end
343
+
344
+ def test_extend_into_mergeable_pseudoclasses
345
+ assert_extends(':matches(.foo)', '.x {@extend .foo}', ':matches(.foo, .x)')
346
+ assert_extends(':matches(.foo.bar)', '.x {@extend .bar}', ':matches(.foo.bar, .foo.x)')
347
+ assert_extends(
348
+ ':matches(.foo.bar, .baz.bar)',
349
+ '.x {@extend .bar}',
350
+ ':matches(.foo.bar, .foo.x, .baz.bar, .baz.x)')
351
+
352
+ assert_extends(':-moz-any(.foo)', '.x {@extend .foo}', ':-moz-any(.foo, .x)')
353
+ assert_extends(':current(.foo)', '.x {@extend .foo}', ':current(.foo, .x)')
354
+ assert_extends(':has(.foo)', '.x {@extend .foo}', ':has(.foo, .x)')
355
+ assert_extends(':host(.foo)', '.x {@extend .foo}', ':host(.foo, .x)')
356
+ assert_extends(':host-context(.foo)', '.x {@extend .foo}', ':host-context(.foo, .x)')
357
+ assert_extends(':nth-child(n of .foo)', '.x {@extend .foo}', ':nth-child(n of .foo, .x)')
358
+ assert_extends(
359
+ ':nth-last-child(n of .foo)',
360
+ '.x {@extend .foo}',
361
+ ':nth-last-child(n of .foo, .x)')
362
+ end
363
+
364
+ def test_complex_extend_into_pseudoclass
365
+ assert_extends(':not(.bar)', '.x .y {@extend .bar}', ':not(.bar, .x .y)')
366
+ assert_extends(':matches(.bar)', '.x .y {@extend .bar}', ':matches(.bar, .x .y)')
367
+ assert_extends(':current(.bar)', '.x .y {@extend .bar}', ':current(.bar, .x .y)')
368
+ assert_extends(':has(.bar)', '.x .y {@extend .bar}', ':has(.bar, .x .y)')
369
+ assert_extends(':host(.bar)', '.x .y {@extend .bar}', ':host(.bar, .x .y)')
370
+ assert_extends(':host-context(.bar)', '.x .y {@extend .bar}', ':host-context(.bar, .x .y)')
371
+ assert_extends(
372
+ ':-moz-any(.bar)',
373
+ '.x .y {@extend .bar}',
374
+ ':-moz-any(.bar, .x .y)')
375
+ assert_extends(
376
+ ':nth-child(n of .bar)',
377
+ '.x .y {@extend .bar}',
378
+ ':nth-child(n of .bar, .x .y)')
379
+ assert_extends(
380
+ ':nth-last-child(n of .bar)',
381
+ '.x .y {@extend .bar}',
382
+ ':nth-last-child(n of .bar, .x .y)')
383
+ end
384
+
385
+ def test_extend_over_selector_pseudoclass
386
+ assert_extends(':not(.foo)', '.x {@extend :not(.foo)}', ':not(.foo), .x')
387
+ assert_extends(
388
+ ':matches(.foo, .bar)',
389
+ '.x {@extend :matches(.foo, .bar)}',
390
+ ':matches(.foo, .bar), .x')
391
+ end
392
+
393
+ def test_matches_within_not
394
+ assert_extends(
395
+ ':not(.foo, .bar)',
396
+ ':matches(.x, .y) {@extend .foo}',
397
+ ':not(.foo, .x, .y, .bar)')
398
+ end
399
+
400
+ def test_pseudoclasses_merge
401
+ assert_extends(':matches(.foo)', ':matches(.bar) {@extend .foo}', ':matches(.foo, .bar)')
402
+ assert_extends(':-moz-any(.foo)', ':-moz-any(.bar) {@extend .foo}', ':-moz-any(.foo, .bar)')
403
+ assert_extends(':current(.foo)', ':current(.bar) {@extend .foo}', ':current(.foo, .bar)')
404
+ assert_extends(
405
+ ':nth-child(n of .foo)',
406
+ ':nth-child(n of .bar) {@extend .foo}',
407
+ ':nth-child(n of .foo, .bar)')
408
+ assert_extends(
409
+ ':nth-last-child(n of .foo)',
410
+ ':nth-last-child(n of .bar) {@extend .foo}',
411
+ ':nth-last-child(n of .foo, .bar)')
412
+ end
413
+
414
+ def test_nesting_pseudoclasses_merge
415
+ assert_extends(':has(.foo)', ':has(.bar) {@extend .foo}', ':has(.foo, :has(.bar))')
416
+ assert_extends(':host(.foo)', ':host(.bar) {@extend .foo}', ':host(.foo, :host(.bar))')
417
+ assert_extends(
418
+ ':host-context(.foo)',
419
+ ':host-context(.bar) {@extend .foo}',
420
+ ':host-context(.foo, :host-context(.bar))')
421
+ end
422
+
423
+ def test_not_unifies_with_unique_values
424
+ assert_unification('foo', ':not(bar) {@extend foo}', ':not(bar)')
425
+ assert_unification('#foo', ':not(#bar) {@extend #foo}', ':not(#bar)')
426
+ end
427
+
428
+ def test_not_adds_no_specificity
429
+ assert_specificity_equals(':not(.foo)', '.foo')
430
+ end
431
+
432
+ def test_matches_has_a_specificity_range
433
+ # `:matches(.foo, #bar)` has minimum specificity equal to that of `.foo`,
434
+ # which means `:matches(.foo, #bar) .a` can have less specificity than
435
+ # `#b.a`. Thus the selector generated by `#b.a` should be preserved.
436
+ assert_equal <<CSS, render(<<SCSS)
437
+ :matches(.foo, #bar) .a, :matches(.foo, #bar) #b.a {
438
+ a: b; }
439
+ CSS
440
+ :matches(.foo, #bar) %x {a: b}
441
+ .a {@extend %x}
442
+ #b.a {@extend %x}
443
+ SCSS
444
+
445
+ # `:matches(.foo, #bar)` has maximum specificity equal to that of `#bar`,
446
+ # which means `:matches(.foo, #bar).b` can have greater specificity than `.a
447
+ # .b`. Thus the selector generated by `:matches(.foo, #bar).b` should be
448
+ # preserved.
449
+ assert_equal <<CSS, render(<<SCSS)
450
+ .a .b, .a .b:matches(.foo, #bar) {
451
+ a: b; }
452
+ CSS
453
+ .a %x {a: b}
454
+ .b {@extend %x}
455
+ .b:matches(.foo, #bar) {@extend %x}
456
+ SCSS
457
+ end
458
+
459
+ def test_extend_into_not_and_normal_extend
460
+ assert_equal <<CSS, render(<<SCSS)
461
+ .x:not(.y, .bar), .foo:not(.y, .bar) {
462
+ a: b; }
463
+ CSS
464
+ .x:not(.y) {a: b}
465
+ .foo {@extend .x}
466
+ .bar {@extend .y}
467
+ SCSS
468
+ end
469
+
470
+ def test_extend_into_matches_and_normal_extend
471
+ assert_equal <<CSS, render(<<SCSS)
472
+ .x:matches(.y, .bar), .foo:matches(.y, .bar) {
473
+ a: b; }
474
+ CSS
475
+ .x:matches(.y) {a: b}
476
+ .foo {@extend .x}
477
+ .bar {@extend .y}
478
+ SCSS
479
+ end
480
+
481
+ def test_multilayer_pseudoclass_extend
482
+ assert_equal <<CSS, render(<<SCSS)
483
+ :matches(.x, .foo, .bar) {
484
+ a: b; }
485
+ CSS
486
+ :matches(.x) {a: b}
487
+ .foo {@extend .x}
488
+ .bar {@extend .foo}
489
+ SCSS
316
490
  end
317
491
 
318
492
  def test_comma_extendee
@@ -516,7 +690,7 @@ SCSS
516
690
  end
517
691
 
518
692
  def test_nested_extender_with_trailing_child_selector
519
- assert_raise(Sass::SyntaxError, "bar > can't extend: invalid selector") do
693
+ assert_raises(Sass::SyntaxError, "bar > can't extend: invalid selector") do
520
694
  render("bar > {@extend .baz}")
521
695
  end
522
696
  end
@@ -650,10 +824,10 @@ SCSS
650
824
 
651
825
  def test_basic_extend_loop
652
826
  assert_equal <<CSS, render(<<SCSS)
653
- .bar, .foo {
827
+ .foo, .bar {
654
828
  a: b; }
655
829
 
656
- .foo, .bar {
830
+ .bar, .foo {
657
831
  c: d; }
658
832
  CSS
659
833
  .foo {a: b; @extend .bar}
@@ -663,13 +837,13 @@ SCSS
663
837
 
664
838
  def test_three_level_extend_loop
665
839
  assert_equal <<CSS, render(<<SCSS)
666
- .baz, .bar, .foo {
840
+ .foo, .baz, .bar {
667
841
  a: b; }
668
842
 
669
- .foo, .baz, .bar {
843
+ .bar, .foo, .baz {
670
844
  c: d; }
671
845
 
672
- .bar, .foo, .baz {
846
+ .baz, .bar, .foo {
673
847
  e: f; }
674
848
  CSS
675
849
  .foo {a: b; @extend .bar}
@@ -692,6 +866,18 @@ CSS
692
866
  SCSS
693
867
  end
694
868
 
869
+ def test_cross_loop
870
+ # The first law of extend means the selector should stick around.
871
+ assert_equal <<CSS, render(<<SCSS)
872
+ .foo.bar, .foo, .bar {
873
+ a: b; }
874
+ CSS
875
+ .foo.bar {a: b}
876
+ .foo {@extend .bar}
877
+ .bar {@extend .foo}
878
+ SCSS
879
+ end
880
+
695
881
  def test_multiple_extender_merges_with_superset_selector
696
882
  assert_equal <<CSS, render(<<SCSS)
697
883
  a.bar.baz, a.foo {
@@ -830,6 +1016,17 @@ $foo: foo;
830
1016
  SCSS
831
1017
  end
832
1018
 
1019
+ def test_placeholder_in_selector_pseudoclass
1020
+ assert_equal <<CSS, render(<<SCSS)
1021
+ :matches(.bar, .baz) {
1022
+ color: blue; }
1023
+ CSS
1024
+ :matches(%foo) {color: blue}
1025
+ .bar {@extend %foo}
1026
+ .baz {@extend %foo}
1027
+ SCSS
1028
+ end
1029
+
833
1030
  def test_media_in_placeholder_selector
834
1031
  assert_equal <<CSS, render(<<SCSS)
835
1032
  .baz {
@@ -1005,7 +1202,7 @@ SCSS
1005
1202
  end
1006
1203
 
1007
1204
  def test_extend_with_subject_transfers_subject_to_extender
1008
- assert_equal(<<CSS, render(<<SCSS))
1205
+ silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1009
1206
  foo bar! baz, foo .bip .bap! baz, .bip foo .bap! baz {
1010
1207
  a: b; }
1011
1208
  CSS
@@ -1013,7 +1210,7 @@ foo bar! baz {a: b}
1013
1210
  .bip .bap {@extend bar}
1014
1211
  SCSS
1015
1212
 
1016
- assert_equal(<<CSS, render(<<SCSS))
1213
+ silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1017
1214
  foo.x bar.y! baz.z, foo.x .bip bar.bap! baz.z, .bip foo.x bar.bap! baz.z {
1018
1215
  a: b; }
1019
1216
  CSS
@@ -1023,7 +1220,7 @@ SCSS
1023
1220
  end
1024
1221
 
1025
1222
  def test_extend_with_subject_retains_subject_on_target
1026
- assert_equal(<<CSS, render(<<SCSS))
1223
+ silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1027
1224
  .foo! .bar, .foo! .bip .bap, .bip .foo! .bap {
1028
1225
  a: b; }
1029
1226
  CSS
@@ -1033,7 +1230,7 @@ SCSS
1033
1230
  end
1034
1231
 
1035
1232
  def test_extend_with_subject_transfers_subject_to_target
1036
- assert_equal(<<CSS, render(<<SCSS))
1233
+ silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1037
1234
  a.foo .bar, .bip a.bap! .bar {
1038
1235
  a: b; }
1039
1236
  CSS
@@ -1043,7 +1240,7 @@ SCSS
1043
1240
  end
1044
1241
 
1045
1242
  def test_extend_with_subject_retains_subject_on_extender
1046
- assert_equal(<<CSS, render(<<SCSS))
1243
+ silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1047
1244
  .foo .bar, .foo .bip! .bap, .bip! .foo .bap {
1048
1245
  a: b; }
1049
1246
  CSS
@@ -1053,7 +1250,7 @@ SCSS
1053
1250
  end
1054
1251
 
1055
1252
  def test_extend_with_subject_fails_with_conflicting_subject
1056
- assert_equal(<<CSS, render(<<SCSS))
1253
+ silence_warnings {assert_equal(<<CSS, render(<<SCSS))}
1057
1254
  x! .bar {
1058
1255
  a: b; }
1059
1256
  CSS
@@ -1408,7 +1605,7 @@ Use "@extend #{target} !optional" if the extend should be able to fail.
1408
1605
  ERR
1409
1606
  end
1410
1607
 
1411
- def assert_unification(selector, extension, unified)
1608
+ def assert_unification(selector, extension, unified, nested = true)
1412
1609
  # Do some trickery so the first law of extend doesn't get in our way.
1413
1610
  assert_extends(
1414
1611
  "%-a #{selector}",
@@ -1416,6 +1613,22 @@ ERR
1416
1613
  unified.split(', ').map {|s| "-a #{s}"}.join(', '))
1417
1614
  end
1418
1615
 
1616
+ def assert_specificity_equals(sel1, sel2)
1617
+ assert_specificity_gte(sel1, sel2)
1618
+ assert_specificity_gte(sel2, sel1)
1619
+ end
1620
+
1621
+ def assert_specificity_gte(sel1, sel2)
1622
+ assert_equal <<CSS, render(<<SCSS)
1623
+ #{sel1} .a {
1624
+ a: b; }
1625
+ CSS
1626
+ #{sel1} %-a {a: b}
1627
+ .a {@extend %-a}
1628
+ #{sel2}.a {@extend %-a}
1629
+ SCSS
1630
+ end
1631
+
1419
1632
  def render_unification(selector, extension)
1420
1633
  render_extends(
1421
1634
  "%-a #{selector}",
@@ -1429,6 +1642,10 @@ ERR
1429
1642
  CSS
1430
1643
  end
1431
1644
 
1645
+ def assert_extends_to_nothing(selector, extension)
1646
+ assert_equal '', render_extends(selector, extension)
1647
+ end
1648
+
1432
1649
  def render_extends(selector, extension)
1433
1650
  render(<<SCSS)
1434
1651
  #{selector} {a: b}
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- require 'test/unit'
2
+ require 'minitest/autorun'
3
3
  require File.dirname(__FILE__) + '/../test_helper'
4
4
  require File.dirname(__FILE__) + '/test_helper'
5
5
  require 'sass/script'
@@ -19,6 +19,12 @@ module Sass::Script::Functions
19
19
  Sass::Script::Value::String.new("only-kw-args(" + kwargs.keys.map {|a| a.to_s}.sort.join(", ") + ")")
20
20
  end
21
21
  declare :only_kw_args, [], :var_kwargs => true
22
+
23
+ def deprecated_arg_fn(arg1, arg2, arg3 = nil)
24
+ Sass::Script::Value::List.new([arg1, arg2, arg3 || Sass::Script::Value::Null.new], :space)
25
+ end
26
+ declare :deprecated_arg_fn, [:arg1, :arg2, :arg3], :deprecated => [:arg_1, :arg_2, :arg3]
27
+ declare :deprecated_arg_fn, [:arg1, :arg2], :deprecated => [:arg_1, :arg_2]
22
28
  end
23
29
 
24
30
  module Sass::Script::Functions::UserFunctions
@@ -45,7 +51,7 @@ module Sass::Script::Functions
45
51
  include Sass::Script::Functions::UserFunctions
46
52
  end
47
53
 
48
- class SassFunctionTest < Test::Unit::TestCase
54
+ class SassFunctionTest < MiniTest::Test
49
55
  # Tests taken from:
50
56
  # http://www.w3.org/Style/CSS/Test/CSS3/Color/20070927/html4/t040204-hsl-h-rotating-b.htm
51
57
  # http://www.w3.org/Style/CSS/Test/CSS3/Color/20070927/html4/t040204-hsl-values-b.htm
@@ -123,12 +129,6 @@ class SassFunctionTest < Test::Unit::TestCase
123
129
  assert_equal("50%", evaluate("percentage($number: 0.5)"))
124
130
  end
125
131
 
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
130
- end
131
-
132
132
  def test_percentage_checks_types
133
133
  assert_error_message("$number: 25px is not a unitless number for `percentage'", "percentage(25px)")
134
134
  assert_error_message("$number: #cccccc is not a unitless number for `percentage'", "percentage(#ccc)")
@@ -142,12 +142,6 @@ WARNING
142
142
  assert_equal("5px", evaluate("round($number: 5.49px)"))
143
143
  end
144
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
150
-
151
145
  def test_round_checks_types
152
146
  assert_error_message("$value: #cccccc is not a number for `round'", "round(#ccc)")
153
147
  end
@@ -158,12 +152,6 @@ WARNING
158
152
  assert_equal("4px", evaluate("floor($number: 4.8px)"))
159
153
  end
160
154
 
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
166
-
167
155
  def test_floor_checks_types
168
156
  assert_error_message("$value: \"foo\" is not a number for `floor'", "floor(\"foo\")")
169
157
  end
@@ -174,12 +162,6 @@ WARNING
174
162
  assert_equal("5px", evaluate("ceil($number: 4.8px)"))
175
163
  end
176
164
 
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
165
  def test_ceil_checks_types
184
166
  assert_error_message("$value: \"a\" is not a number for `ceil'", "ceil(\"a\")")
185
167
  end
@@ -192,12 +174,6 @@ WARNING
192
174
  assert_equal("5px", evaluate("abs($number: 5px)"))
193
175
  end
194
176
 
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
200
-
201
177
  def test_abs_checks_types
202
178
  assert_error_message("$value: #aaaaaa is not a number for `abs'", "abs(#aaa)")
203
179
  end
@@ -840,32 +816,6 @@ WARNING
840
816
  assert_equal("rgba(255, 0, 0, 0)", evaluate("mix($color1: transparentize(#f00, 1), $color2: #00f, $weight: 100%)"))
841
817
  end
842
818
 
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
867
- end
868
-
869
819
  def test_mix_tests_types
870
820
  assert_error_message("$color1: \"foo\" is not a color for `mix'", "mix(\"foo\", #f00, 10%)")
871
821
  assert_error_message("$color2: \"foo\" is not a color for `mix'", "mix(#f00, \"foo\", 10%)")
@@ -995,7 +945,6 @@ WARNING
995
945
  assert_equal('ab', evaluate('str-slice(abcd,1,2)')) # for completeness
996
946
  assert_equal('abcd', evaluate('str-slice(abcd,1,4)')) # at the end points
997
947
  assert_equal('abcd', evaluate('str-slice(abcd,0,4)')) # when start is before the start of the string
998
- assert_equal('', evaluate('str-slice(abcd,1,0)')) # when end is before the start of the string
999
948
  assert_equal('abcd', evaluate('str-slice(abcd,1,100)')) # when end is past the end of the string
1000
949
  assert_equal('', evaluate('str-slice(abcd,2,1)')) # when end is before start
1001
950
  assert_equal('"bc"', evaluate('str-slice("abcd",2,3)')) # when used with a quoted string
@@ -1085,22 +1034,6 @@ MSG
1085
1034
  assert_equal(%Q{false}, evaluate("comparable($number1: 100px, $number2: 3em)"))
1086
1035
  end
1087
1036
 
1088
- def test_comparable_deprecated_arg_name
1089
- assert_warning <<WARNING do
1090
- DEPRECATION WARNING: The `$number-1' argument for `comparable()' has been renamed to `$number1'.
1091
- DEPRECATION WARNING: The `$number-2' argument for `comparable()' has been renamed to `$number2'.
1092
- WARNING
1093
- assert_equal("false", evaluate("comparable($number-1: 100px, $number-2: 3em)"))
1094
- end
1095
-
1096
- assert_warning <<WARNING do
1097
- DEPRECATION WARNING: The `$number_1' argument for `comparable()' has been renamed to `$number1'.
1098
- DEPRECATION WARNING: The `$number_2' argument for `comparable()' has been renamed to `$number2'.
1099
- WARNING
1100
- assert_equal("false", evaluate("comparable($number_1: 100px, $number_2: 3em)"))
1101
- end
1102
- end
1103
-
1104
1037
  def test_comparable_checks_types
1105
1038
  assert_error_message("$number1: #ff0000 is not a number for `comparable'", "comparable(#f00, 1px)")
1106
1039
  assert_error_message("$number2: #ff0000 is not a number for `comparable'", "comparable(1px, #f00)")
@@ -1258,76 +1191,17 @@ WARNING
1258
1191
  end
1259
1192
 
1260
1193
  def test_index
1194
+ null = Sass::Script::Value::Null.new
1261
1195
  assert_equal("1", evaluate("index(1px solid blue, 1px)"))
1262
1196
  assert_equal("2", evaluate("index(1px solid blue, solid)"))
1263
1197
  assert_equal("3", evaluate("index(1px solid blue, #00f)"))
1264
1198
  assert_equal("1", evaluate("index(1px, 1px)"))
1265
- assert_equal("false", evaluate("index(1px solid blue, 1em)"))
1266
- assert_equal("false", evaluate("index(1px solid blue, notfound)"))
1267
- assert_equal("false", evaluate("index(1px, #00f)"))
1199
+ assert_equal(null, perform("index(1px solid blue, 1em)"))
1200
+ assert_equal(null, perform("index(1px solid blue, notfound)"))
1201
+ assert_equal(null, perform("index(1px, #00f)"))
1268
1202
 
1269
1203
  assert_equal("1", evaluate("index((foo: bar, bar: baz), (foo bar))"))
1270
- assert_equal("false", evaluate("index((foo: bar, bar: baz), (foo: bar))"))
1271
- end
1272
-
1273
- def test_index_deprecation_warning
1274
- assert_warning(<<WARNING) do
1275
- DEPRECATION WARNING: The return value of index() will change from "false" to
1276
- "null" in future versions of Sass. For compatibility, avoid using "== false" on
1277
- the return value. For example, instead of "@if index(...) == false", just write
1278
- "@if not index(...)".
1279
- WARNING
1280
- assert_equal("true", evaluate("index(1, 2 3 4) == false"))
1281
- end
1282
-
1283
- assert_warning(<<WARNING) do
1284
- DEPRECATION WARNING: The return value of index() will change from "false" to
1285
- "null" in future versions of Sass. For compatibility, avoid using "!= null" on
1286
- the return value.
1287
- WARNING
1288
- assert_equal("true", evaluate("index(1, 2 3 4) != null"))
1289
- end
1290
-
1291
- assert_warning(<<WARNING) do
1292
- DEPRECATION WARNING: The return value of index() will change from "false" to
1293
- "null" in future versions of Sass. For compatibility, avoid using "== false" on
1294
- the return value. For example, instead of "@if index(...) == false", just write
1295
- "@if not index(...)".
1296
- WARNING
1297
- assert_equal("true", evaluate("false == index(1, 2 3 4)"))
1298
- end
1299
-
1300
- assert_warning(<<WARNING) do
1301
- DEPRECATION WARNING: The return value of index() will change from "false" to
1302
- "null" in future versions of Sass. For compatibility, avoid using "!= null" on
1303
- the return value.
1304
- WARNING
1305
- assert_equal("true", evaluate("null != index(1, 2 3 4)"))
1306
- end
1307
- end
1308
-
1309
- def test_index_deprecation_warning_is_only_emitted_once_per_call
1310
- assert_warning(<<WARNING) do
1311
- DEPRECATION WARNING: The return value of index() will change from "false" to
1312
- "null" in future versions of Sass. For compatibility, avoid using "== false" on
1313
- the return value. For example, instead of "@if index(...) == false", just write
1314
- "@if not index(...)".
1315
- on line 3 of test_index_deprecation_warning_is_only_emitted_once_per_call_inline.scss
1316
- DEPRECATION WARNING: The return value of index() will change from "false" to
1317
- "null" in future versions of Sass. For compatibility, avoid using "== false" on
1318
- the return value. For example, instead of "@if index(...) == false", just write
1319
- "@if not index(...)".
1320
- on line 6 of test_index_deprecation_warning_is_only_emitted_once_per_call_inline.scss
1321
- WARNING
1322
- render(<<SCSS)
1323
- @for $i from 1 to 10 {
1324
- $var1: index(1, 2 3 4);
1325
- $var2: $var1 == false;
1326
- $var3: $var1 != null;
1327
- }
1328
- $var4: index(1, 2 3 4) == false;
1329
- SCSS
1330
- end
1204
+ assert_equal(null, perform("index((foo: bar, bar: baz), (foo: bar))"))
1331
1205
  end
1332
1206
 
1333
1207
  def test_list_separator
@@ -1447,7 +1321,7 @@ SCSS
1447
1321
  50.times do
1448
1322
  last_id, current_id = current_id, evaluate("unique-id()")
1449
1323
  assert_match(/u[a-z0-9]{8}/, current_id)
1450
- assert_not_equal last_id, current_id
1324
+ refute_equal last_id, current_id
1451
1325
  end
1452
1326
  end
1453
1327
 
@@ -1458,16 +1332,6 @@ SCSS
1458
1332
  assert_equal "null", perform("map-get((), foo)").to_sass
1459
1333
  end
1460
1334
 
1461
- def test_map_get_deprecation_warning
1462
- assert_warning(<<WARNING) do
1463
- DEPRECATION WARNING: Passing lists of pairs to map-get is deprecated and will
1464
- be removed in future versions of Sass. Use Sass maps instead. For details, see
1465
- http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1466
- WARNING
1467
- assert_equal "1", evaluate("map-get((foo 1) (bar 2), foo)")
1468
- end
1469
- end
1470
-
1471
1335
  def test_map_get_checks_type
1472
1336
  assert_error_message("$map: 12 is not a map for `map-get'", "map-get(12, bar)")
1473
1337
  end
@@ -1481,26 +1345,6 @@ WARNING
1481
1345
  perform("map-merge((foo: 1, bar: 2), ())").to_sass)
1482
1346
  end
1483
1347
 
1484
- def test_map_merge_deprecation_warning
1485
- assert_warning(<<WARNING) do
1486
- DEPRECATION WARNING: Passing lists of pairs to map-merge is deprecated and will
1487
- be removed in future versions of Sass. Use Sass maps instead. For details, see
1488
- http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1489
- WARNING
1490
- assert_equal("(foo: 1, bar: 2, baz: 3)",
1491
- perform("map-merge((foo 1, bar 2), (baz: 3))").to_sass)
1492
- end
1493
-
1494
- assert_warning(<<WARNING) do
1495
- DEPRECATION WARNING: Passing lists of pairs to map-merge is deprecated and will
1496
- be removed in future versions of Sass. Use Sass maps instead. For details, see
1497
- http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1498
- WARNING
1499
- assert_equal("(baz: 3, foo: 1, bar: 2)",
1500
- perform("map-merge((baz: 3), (foo 1, bar 2))").to_sass)
1501
- end
1502
- end
1503
-
1504
1348
  def test_map_merge_checks_type
1505
1349
  assert_error_message("$map1: 12 is not a map for `map-merge'", "map-merge(12, (foo: 1))")
1506
1350
  assert_error_message("$map2: 12 is not a map for `map-merge'", "map-merge((foo: 1), 12)")
@@ -1509,18 +1353,12 @@ WARNING
1509
1353
  def test_map_remove
1510
1354
  assert_equal("(foo: 1, baz: 3)",
1511
1355
  perform("map-remove((foo: 1, bar: 2, baz: 3), bar)").to_sass)
1356
+ assert_equal("(foo: 1, baz: 3)",
1357
+ perform("map-remove($map: (foo: 1, bar: 2, baz: 3), $key: bar)").to_sass)
1358
+ assert_equal("()",
1359
+ perform("map-remove((foo: 1, bar: 2, baz: 3), foo, bar, baz)").to_sass)
1512
1360
  assert_equal("()", perform("map-remove((), foo)").to_sass)
1513
- end
1514
-
1515
- def test_map_remove_deprecation_warning
1516
- assert_warning(<<WARNING) do
1517
- DEPRECATION WARNING: Passing lists of pairs to map-remove is deprecated and will
1518
- be removed in future versions of Sass. Use Sass maps instead. For details, see
1519
- http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1520
- WARNING
1521
- assert_equal("(foo: 1, baz: 3)",
1522
- perform("map-remove((foo 1, bar 2, baz 3), bar)").to_sass)
1523
- end
1361
+ assert_equal("()", perform("map-remove((), foo, bar)").to_sass)
1524
1362
  end
1525
1363
 
1526
1364
  def test_map_remove_checks_type
@@ -1533,17 +1371,6 @@ WARNING
1533
1371
  assert_equal("()", perform("map-keys(())").to_sass)
1534
1372
  end
1535
1373
 
1536
- def test_map_keys_deprecation_warning
1537
- assert_warning(<<WARNING) do
1538
- DEPRECATION WARNING: Passing lists of pairs to map-keys is deprecated and will
1539
- be removed in future versions of Sass. Use Sass maps instead. For details, see
1540
- http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1541
- WARNING
1542
- assert_equal("foo, bar",
1543
- perform("map-keys((foo 1, bar 2))").to_sass)
1544
- end
1545
- end
1546
-
1547
1374
  def test_map_keys_checks_type
1548
1375
  assert_error_message("$map: 12 is not a map for `map-keys'", "map-keys(12)")
1549
1376
  end
@@ -1555,16 +1382,6 @@ WARNING
1555
1382
  assert_equal("()", perform("map-values(())").to_sass)
1556
1383
  end
1557
1384
 
1558
- def test_map_values_deprecation_warning
1559
- assert_warning(<<WARNING) do
1560
- DEPRECATION WARNING: Passing lists of pairs to map-values is deprecated and will
1561
- be removed in future versions of Sass. Use Sass maps instead. For details, see
1562
- http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1563
- WARNING
1564
- assert_equal("1, 2", perform("map-values((foo 1, bar 2))").to_sass)
1565
- end
1566
- end
1567
-
1568
1385
  def test_map_values_checks_type
1569
1386
  assert_error_message("$map: 12 is not a map for `map-values'", "map-values(12)")
1570
1387
  end
@@ -1575,16 +1392,6 @@ WARNING
1575
1392
  assert_equal "false", evaluate("map-has-key((), foo)")
1576
1393
  end
1577
1394
 
1578
- def test_map_has_key_deprecation_warning
1579
- assert_warning(<<WARNING) do
1580
- DEPRECATION WARNING: Passing lists of pairs to map-has-key is deprecated and will
1581
- be removed in future versions of Sass. Use Sass maps instead. For details, see
1582
- http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#maps.
1583
- WARNING
1584
- assert_equal("true", evaluate("map-has-key((foo 1, bar 1), foo)"))
1585
- end
1586
- end
1587
-
1588
1395
  def test_map_has_key_checks_type
1589
1396
  assert_error_message("$map: 12 is not a map for `map-has-key'", "map-has-key(12, foo)")
1590
1397
  end
@@ -1839,7 +1646,255 @@ SCSS
1839
1646
  if Sass::Script::Functions.instance_variable_defined?("@random_number_generator")
1840
1647
  Sass::Script::Functions.send(:remove_instance_variable, "@random_number_generator")
1841
1648
  end
1842
- assert_not_equal evaluate("random()"), evaluate("random()")
1649
+ refute_equal evaluate("random()"), evaluate("random()")
1650
+ end
1651
+
1652
+ def test_deprecated_arg_names
1653
+ assert_warning <<WARNING do
1654
+ DEPRECATION WARNING: The `$arg-1' argument for `deprecated-arg-fn()' has been renamed to `$arg1'.
1655
+ DEPRECATION WARNING: The `$arg-2' argument for `deprecated-arg-fn()' has been renamed to `$arg2'.
1656
+ WARNING
1657
+ assert_equal("1 2 3",
1658
+ evaluate("deprecated-arg-fn($arg-1: 1, $arg-2: 2, $arg3: 3)"))
1659
+ end
1660
+
1661
+ assert_warning <<WARNING do
1662
+ DEPRECATION WARNING: The `$arg-1' argument for `deprecated-arg-fn()' has been renamed to `$arg1'.
1663
+ DEPRECATION WARNING: The `$arg-2' argument for `deprecated-arg-fn()' has been renamed to `$arg2'.
1664
+ WARNING
1665
+ assert_equal("1 2",
1666
+ evaluate("deprecated-arg-fn($arg-1: 1, $arg-2: 2)"))
1667
+ end
1668
+
1669
+ assert_warning <<WARNING do
1670
+ DEPRECATION WARNING: The `$arg_1' argument for `deprecated-arg-fn()' has been renamed to `$arg1'.
1671
+ DEPRECATION WARNING: The `$arg_2' argument for `deprecated-arg-fn()' has been renamed to `$arg2'.
1672
+ WARNING
1673
+ assert_equal("1 2",
1674
+ evaluate("deprecated-arg-fn($arg_1: 1, $arg_2: 2)"))
1675
+ end
1676
+ end
1677
+
1678
+ def test_non_deprecated_arg_names
1679
+ assert_equal("1 2 3", evaluate("deprecated-arg-fn($arg1: 1, $arg2: 2, $arg3: 3)"))
1680
+ assert_equal("1 2", evaluate("deprecated-arg-fn($arg1: 1, $arg2: 2)"))
1681
+ end
1682
+
1683
+ ## Selector Functions
1684
+
1685
+ def test_selector_argument_parsing
1686
+ assert_equal("true", evaluate("selector-parse('.foo') == (join(('.foo',), (), space),)"))
1687
+ assert_equal("true", evaluate("selector-parse('.foo .bar') == ('.foo' '.bar',)"))
1688
+ assert_equal("true",
1689
+ evaluate("selector-parse('.foo .bar, .baz .bang') == ('.foo' '.bar', '.baz' '.bang')"))
1690
+
1691
+ assert_equal(".foo %bar", evaluate("selector-parse('.foo %bar')"))
1692
+
1693
+ assert_equal("true",
1694
+ evaluate("selector-parse(('.foo', '.bar')) == selector-parse('.foo, .bar')"))
1695
+ assert_equal("true",
1696
+ evaluate("selector-parse('.foo' '.bar') == selector-parse('.foo .bar')"))
1697
+
1698
+ assert_equal("true", evaluate("selector-parse(('.foo' '.bar', '.baz' '.bang')) == " +
1699
+ "selector-parse('.foo .bar, .baz .bang')"))
1700
+ assert_equal("true", evaluate("selector-parse(('.foo .bar', '.baz .bang')) == " +
1701
+ "selector-parse('.foo .bar, .baz .bang')"))
1702
+
1703
+ # This may throw an error in the future.
1704
+ assert_equal("true", evaluate("selector-parse(('.foo, .bar' '.baz, .bang')) == " +
1705
+ "selector-parse('.foo, .bar .baz, .bang')"))
1706
+ end
1707
+
1708
+ def test_selector_argument_validation
1709
+ assert_error_message("$selector: 12 is not a valid selector: it must be a string,\n" +
1710
+ "a list of strings, or a list of lists of strings for `selector-parse'", "selector-parse(12)")
1711
+ assert_error_message("$selector: (((\".foo\" \".bar\"), \".baz\") (\".bang\", \".qux\")) is not a valid selector: it must be a string,\n" +
1712
+ "a list of strings, or a list of lists of strings for `selector-parse'",
1713
+ "selector-parse(('.foo' '.bar', '.baz') ('.bang', '.qux'))")
1714
+ assert_error_message("$selector: \".#\" is not a valid selector: Invalid CSS after \".\": " +
1715
+ "expected class name, was \"#\" for `selector-parse'", "selector-parse('.#')")
1716
+ assert_error_message("$selector: \"&.foo\" is not a valid selector: Invalid CSS after \"\": " +
1717
+ "expected selector, was \"&.foo\" for `selector-parse'", "selector-parse('&.foo')")
1718
+ end
1719
+
1720
+ def test_selector_nest
1721
+ assert_equal(".foo", evaluate("selector-nest('.foo')"))
1722
+ assert_equal(".foo .bar", evaluate("selector-nest('.foo', '.bar')"))
1723
+ assert_equal(".foo .bar .baz", evaluate("selector-nest('.foo', '.bar', '.baz')"))
1724
+ assert_equal(".a .foo .b .bar", evaluate("selector-nest('.a .foo', '.b .bar')"))
1725
+ assert_equal(".foo.bar", evaluate("selector-nest('.foo', '&.bar')"))
1726
+ assert_equal(".baz .foo.bar", evaluate("selector-nest('.foo', '&.bar', '.baz &')"))
1727
+ end
1728
+
1729
+ def test_selector_nest_checks_types
1730
+ assert_error_message("$selectors: 12 is not a valid selector: it must be a string,\n" +
1731
+ "a list of strings, or a list of lists of strings for `selector-nest'",
1732
+ "selector-nest(12)")
1733
+ assert_error_message("$selectors: 12 is not a valid selector: it must be a string,\n" +
1734
+ "a list of strings, or a list of lists of strings for `selector-nest'",
1735
+ "selector-nest('.foo', 12)")
1736
+ end
1737
+
1738
+ def test_selector_nest_argument_validation
1739
+ assert_error_message("$selectors: At least one selector must be passed for `selector-nest'",
1740
+ "selector-nest()")
1741
+ end
1742
+
1743
+ def test_selector_append
1744
+ assert_equal(".foo.bar", evaluate("selector-append('.foo', '.bar')"))
1745
+ assert_equal(".a .foo.b .bar", evaluate("selector-append('.a .foo', '.b .bar')"))
1746
+ assert_equal(".foo-suffix", evaluate("selector-append('.foo', '-suffix')"))
1747
+ assert_equal(".foo.bar, .foo-suffix", evaluate("selector-append('.foo', '.bar, -suffix')"))
1748
+ assert_equal(".foo--suffix", evaluate("selector-append('.foo', '--suffix')"))
1749
+ assert_equal(".foo.bar, .foo--suffix", evaluate("selector-append('.foo', '.bar, --suffix')"))
1750
+ end
1751
+
1752
+ def test_selector_append_checks_types
1753
+ assert_error_message("$selectors: 12 is not a valid selector: it must be a string,\n" +
1754
+ "a list of strings, or a list of lists of strings for `selector-append'",
1755
+ "selector-append(12)")
1756
+ assert_error_message("$selectors: 12 is not a valid selector: it must be a string,\n" +
1757
+ "a list of strings, or a list of lists of strings for `selector-append'",
1758
+ "selector-append('.foo', 12)")
1759
+ end
1760
+
1761
+ def test_selector_append_errors
1762
+ assert_error_message("$selectors: At least one selector must be passed for `selector-append'",
1763
+ "selector-append()")
1764
+ assert_error_message("Can't append \"> .bar\" to \".foo\" for `selector-append'",
1765
+ "selector-append('.foo', '> .bar')")
1766
+ assert_error_message("Can't append \"*.bar\" to \".foo\" for `selector-append'",
1767
+ "selector-append('.foo', '*.bar')")
1768
+ assert_error_message("Can't append \"ns|suffix\" to \".foo\" for `selector-append'",
1769
+ "selector-append('.foo', 'ns|suffix')")
1770
+ end
1771
+
1772
+ def test_selector_extend
1773
+ assert_equal(".foo .x, .foo .a .bar, .a .foo .bar",
1774
+ evaluate("selector-extend('.foo .x', '.x', '.a .bar')"))
1775
+ assert_equal(".foo .x, .foo .bang, .x.bar, .bar.bang",
1776
+ evaluate("selector-extend('.foo .x, .x.bar', '.x', '.bang')"))
1777
+ assert_equal(".y .x, .foo .x, .y .foo, .foo .foo",
1778
+ evaluate("selector-extend('.y .x', '.x, .y', '.foo')"))
1779
+ assert_equal(".foo .x, .foo .bar, .foo .bang",
1780
+ evaluate("selector-extend('.foo .x', '.x', '.bar, .bang')"))
1781
+ assert_equal(".foo.x, .foo",
1782
+ evaluate("selector-extend('.foo.x', '.x', '.foo')"))
1783
+ end
1784
+
1785
+ def test_selector_extend_checks_types
1786
+ assert_error_message("$selector: 12 is not a valid selector: it must be a string,\n" +
1787
+ "a list of strings, or a list of lists of strings for `selector-extend'",
1788
+ "selector-extend(12, '.foo', '.bar')")
1789
+ assert_error_message("$extendee: 12 is not a valid selector: it must be a string,\n" +
1790
+ "a list of strings, or a list of lists of strings for `selector-extend'",
1791
+ "selector-extend('.foo', 12, '.bar')")
1792
+ assert_error_message("$extender: 12 is not a valid selector: it must be a string,\n" +
1793
+ "a list of strings, or a list of lists of strings for `selector-extend'",
1794
+ "selector-extend('.foo', '.bar', 12)")
1795
+ end
1796
+
1797
+ def test_selector_extend_errors
1798
+ assert_error_message("Can't extend .bar .baz: can't extend nested selectors for " +
1799
+ "`selector-extend'", "selector-extend('.foo', '.bar .baz', '.bang')")
1800
+ assert_error_message("Can't extend >: invalid selector for `selector-extend'",
1801
+ "selector-extend('.foo', '>', '.bang')")
1802
+ assert_error_message(".bang > can't extend: invalid selector for `selector-extend'",
1803
+ "selector-extend('.foo', '.bar', '.bang >')")
1804
+ end
1805
+
1806
+ def test_selector_replace
1807
+ assert_equal(".bar", evaluate("selector-replace('.foo', '.foo', '.bar')"))
1808
+ assert_equal(".foo.baz", evaluate("selector-replace('.foo.bar', '.bar', '.baz')"))
1809
+ assert_equal(".a .foo.baz", evaluate("selector-replace('.foo.bar', '.bar', '.a .baz')"))
1810
+ assert_equal(".foo.bar", evaluate("selector-replace('.foo.bar', '.baz.bar', '.qux')"))
1811
+ assert_equal(".bar.qux", evaluate("selector-replace('.foo.bar.baz', '.foo.baz', '.qux')"))
1812
+
1813
+ assert_equal(":not(.bar)", evaluate("selector-replace(':not(.foo)', '.foo', '.bar')"))
1814
+ assert_equal(".bar", evaluate("selector-replace(':not(.foo)', ':not(.foo)', '.bar')"))
1815
+ end
1816
+
1817
+ def test_selector_replace_checks_types
1818
+ assert_error_message("$selector: 12 is not a valid selector: it must be a string,\n" +
1819
+ "a list of strings, or a list of lists of strings for `selector-replace'",
1820
+ "selector-replace(12, '.foo', '.bar')")
1821
+ assert_error_message("$original: 12 is not a valid selector: it must be a string,\n" +
1822
+ "a list of strings, or a list of lists of strings for `selector-replace'",
1823
+ "selector-replace('.foo', 12, '.bar')")
1824
+ assert_error_message("$replacement: 12 is not a valid selector: it must be a string,\n" +
1825
+ "a list of strings, or a list of lists of strings for `selector-replace'",
1826
+ "selector-replace('.foo', '.bar', 12)")
1827
+ end
1828
+
1829
+ def test_selector_replace_errors
1830
+ assert_error_message("Can't extend .bar .baz: can't extend nested selectors for " +
1831
+ "`selector-replace'", "selector-replace('.foo', '.bar .baz', '.bang')")
1832
+ assert_error_message("Can't extend >: invalid selector for `selector-replace'",
1833
+ "selector-replace('.foo', '>', '.bang')")
1834
+ assert_error_message(".bang > can't extend: invalid selector for `selector-replace'",
1835
+ "selector-replace('.foo', '.bar', '.bang >')")
1836
+ end
1837
+
1838
+ def test_selector_unify
1839
+ assert_equal(".foo", evaluate("selector-unify('.foo', '.foo')"))
1840
+ assert_equal(".foo.bar", evaluate("selector-unify('.foo', '.bar')"))
1841
+ assert_equal(".foo.bar.baz", evaluate("selector-unify('.foo.bar', '.bar.baz')"))
1842
+ assert_equal(".a .b .foo.bar, .b .a .foo.bar", evaluate("selector-unify('.a .foo', '.b .bar')"))
1843
+ assert_equal(".a .foo.bar", evaluate("selector-unify('.a .foo', '.a .bar')"))
1844
+ assert_equal("", evaluate("selector-unify('p', 'a')"))
1845
+ assert_equal("", evaluate("selector-unify('.foo >', '.bar')"))
1846
+ assert_equal("", evaluate("selector-unify('.foo', '.bar >')"))
1847
+ assert_equal(".foo.baz, .foo.bang, .bar.baz, .bar.bang",
1848
+ evaluate("selector-unify('.foo, .bar', '.baz, .bang')"))
1849
+ end
1850
+
1851
+ def test_selector_unify_checks_types
1852
+ assert_error_message("$selector1: 12 is not a valid selector: it must be a string,\n" +
1853
+ "a list of strings, or a list of lists of strings for `selector-unify'",
1854
+ "selector-unify(12, '.foo')")
1855
+ assert_error_message("$selector2: 12 is not a valid selector: it must be a string,\n" +
1856
+ "a list of strings, or a list of lists of strings for `selector-unify'",
1857
+ "selector-unify('.foo', 12)")
1858
+ end
1859
+
1860
+ def test_simple_selectors
1861
+ assert_equal('(.foo,)', evaluate("inspect(simple-selectors('.foo'))"))
1862
+ assert_equal('.foo, .bar', evaluate("inspect(simple-selectors('.foo.bar'))"))
1863
+ assert_equal('.foo, .bar, :pseudo("flip, flap")',
1864
+ evaluate("inspect(simple-selectors('.foo.bar:pseudo(\"flip, flap\")'))"))
1865
+ end
1866
+
1867
+ def test_simple_selectors_checks_types
1868
+ assert_error_message("$selector: 12 is not a string for `simple-selectors'",
1869
+ "simple-selectors(12)")
1870
+ end
1871
+
1872
+ def test_simple_selectors_errors
1873
+ assert_error_message("$selector: \".foo .bar\" is not a compound selector for `simple-selectors'",
1874
+ "simple-selectors('.foo .bar')")
1875
+ assert_error_message("$selector: \".foo,.bar\" is not a compound selector for `simple-selectors'",
1876
+ "simple-selectors('.foo,.bar')")
1877
+ assert_error_message("$selector: \".#\" is not a valid selector: Invalid CSS after \".\": " +
1878
+ "expected class name, was \"#\" for `simple-selectors'", "simple-selectors('.#')")
1879
+ end
1880
+
1881
+ def test_is_superselector
1882
+ assert_equal("true", evaluate("is-superselector('.foo', '.foo.bar')"))
1883
+ assert_equal("false", evaluate("is-superselector('.foo.bar', '.foo')"))
1884
+ assert_equal("true", evaluate("is-superselector('.foo', '.foo')"))
1885
+ assert_equal("true", evaluate("is-superselector('.bar', '.foo .bar')"))
1886
+ assert_equal("false", evaluate("is-superselector('.foo .bar', '.bar')"))
1887
+ assert_equal("true", evaluate("is-superselector('.foo .bar', '.foo > .bar')"))
1888
+ assert_equal("false", evaluate("is-superselector('.foo > .bar', '.foo .bar')"))
1889
+ end
1890
+
1891
+ def test_is_superselector_checks_types
1892
+ assert_error_message("$super: 12 is not a valid selector: it must be a string,\n" +
1893
+ "a list of strings, or a list of lists of strings for `is-superselector'",
1894
+ "is-superselector(12, '.foo')")
1895
+ assert_error_message("$sub: 12 is not a valid selector: it must be a string,\n" +
1896
+ "a list of strings, or a list of lists of strings for `is-superselector'",
1897
+ "is-superselector('.foo', 12)")
1843
1898
  end
1844
1899
 
1845
1900
  ## Regression Tests