sass 3.3.0 → 3.4.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 (151) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +58 -50
  4. data/Rakefile +1 -4
  5. data/VERSION +1 -1
  6. data/VERSION_DATE +1 -1
  7. data/VERSION_NAME +1 -1
  8. data/bin/sass +1 -1
  9. data/bin/scss +1 -1
  10. data/lib/sass/cache_stores/filesystem.rb +6 -2
  11. data/lib/sass/css.rb +1 -3
  12. data/lib/sass/engine.rb +37 -46
  13. data/lib/sass/environment.rb +13 -17
  14. data/lib/sass/error.rb +6 -9
  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 +424 -0
  18. data/lib/sass/exec.rb +5 -771
  19. data/lib/sass/features.rb +7 -0
  20. data/lib/sass/importers/base.rb +7 -2
  21. data/lib/sass/importers/filesystem.rb +9 -25
  22. data/lib/sass/importers.rb +0 -1
  23. data/lib/sass/media.rb +1 -4
  24. data/lib/sass/plugin/compiler.rb +200 -83
  25. data/lib/sass/plugin/staleness_checker.rb +1 -1
  26. data/lib/sass/plugin.rb +3 -3
  27. data/lib/sass/script/css_lexer.rb +1 -1
  28. data/lib/sass/script/functions.rb +622 -268
  29. data/lib/sass/script/lexer.rb +99 -34
  30. data/lib/sass/script/parser.rb +24 -23
  31. data/lib/sass/script/tree/funcall.rb +1 -1
  32. data/lib/sass/script/tree/interpolation.rb +20 -2
  33. data/lib/sass/script/tree/selector.rb +26 -0
  34. data/lib/sass/script/tree/string_interpolation.rb +1 -1
  35. data/lib/sass/script/tree.rb +1 -0
  36. data/lib/sass/script/value/base.rb +7 -5
  37. data/lib/sass/script/value/bool.rb +0 -5
  38. data/lib/sass/script/value/color.rb +39 -21
  39. data/lib/sass/script/value/helpers.rb +107 -0
  40. data/lib/sass/script/value/list.rb +0 -15
  41. data/lib/sass/script/value/null.rb +0 -5
  42. data/lib/sass/script/value/number.rb +62 -14
  43. data/lib/sass/script/value/string.rb +59 -11
  44. data/lib/sass/script/value.rb +0 -1
  45. data/lib/sass/scss/css_parser.rb +8 -2
  46. data/lib/sass/scss/parser.rb +190 -328
  47. data/lib/sass/scss/rx.rb +15 -6
  48. data/lib/sass/scss/static_parser.rb +298 -1
  49. data/lib/sass/selector/abstract_sequence.rb +28 -13
  50. data/lib/sass/selector/comma_sequence.rb +92 -13
  51. data/lib/sass/selector/pseudo.rb +256 -0
  52. data/lib/sass/selector/sequence.rb +94 -24
  53. data/lib/sass/selector/simple.rb +14 -25
  54. data/lib/sass/selector/simple_sequence.rb +97 -33
  55. data/lib/sass/selector.rb +57 -194
  56. data/lib/sass/shared.rb +1 -1
  57. data/lib/sass/source/map.rb +26 -12
  58. data/lib/sass/stack.rb +0 -6
  59. data/lib/sass/supports.rb +2 -3
  60. data/lib/sass/tree/at_root_node.rb +1 -0
  61. data/lib/sass/tree/charset_node.rb +1 -1
  62. data/lib/sass/tree/directive_node.rb +8 -2
  63. data/lib/sass/tree/error_node.rb +18 -0
  64. data/lib/sass/tree/extend_node.rb +1 -1
  65. data/lib/sass/tree/function_node.rb +4 -0
  66. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  67. data/lib/sass/tree/prop_node.rb +1 -1
  68. data/lib/sass/tree/rule_node.rb +12 -7
  69. data/lib/sass/tree/visitors/check_nesting.rb +38 -10
  70. data/lib/sass/tree/visitors/convert.rb +16 -18
  71. data/lib/sass/tree/visitors/cssize.rb +29 -29
  72. data/lib/sass/tree/visitors/deep_copy.rb +5 -0
  73. data/lib/sass/tree/visitors/perform.rb +45 -33
  74. data/lib/sass/tree/visitors/set_options.rb +14 -0
  75. data/lib/sass/tree/visitors/to_css.rb +15 -14
  76. data/lib/sass/util/subset_map.rb +1 -1
  77. data/lib/sass/util.rb +222 -99
  78. data/lib/sass/version.rb +5 -5
  79. data/lib/sass.rb +0 -5
  80. data/test/sass/cache_test.rb +62 -20
  81. data/test/sass/callbacks_test.rb +1 -1
  82. data/test/sass/compiler_test.rb +19 -10
  83. data/test/sass/conversion_test.rb +58 -1
  84. data/test/sass/css2sass_test.rb +23 -4
  85. data/test/sass/encoding_test.rb +219 -0
  86. data/test/sass/engine_test.rb +136 -199
  87. data/test/sass/exec_test.rb +2 -2
  88. data/test/sass/extend_test.rb +236 -19
  89. data/test/sass/functions_test.rb +295 -253
  90. data/test/sass/importer_test.rb +31 -21
  91. data/test/sass/logger_test.rb +1 -1
  92. data/test/sass/more_results/more_import.css +1 -1
  93. data/test/sass/plugin_test.rb +14 -13
  94. data/test/sass/results/compact.css +1 -1
  95. data/test/sass/results/complex.css +4 -4
  96. data/test/sass/results/expanded.css +1 -1
  97. data/test/sass/results/import.css +1 -1
  98. data/test/sass/results/import_charset_ibm866.css +2 -2
  99. data/test/sass/results/mixins.css +17 -17
  100. data/test/sass/results/nested.css +1 -1
  101. data/test/sass/results/parent_ref.css +2 -2
  102. data/test/sass/results/script.css +3 -3
  103. data/test/sass/results/scss_import.css +1 -1
  104. data/test/sass/script_conversion_test.rb +10 -7
  105. data/test/sass/script_test.rb +288 -74
  106. data/test/sass/scss/css_test.rb +141 -24
  107. data/test/sass/scss/rx_test.rb +4 -4
  108. data/test/sass/scss/scss_test.rb +457 -18
  109. data/test/sass/source_map_test.rb +115 -25
  110. data/test/sass/superselector_test.rb +191 -0
  111. data/test/sass/templates/scss_import.scss +2 -1
  112. data/test/sass/test_helper.rb +1 -1
  113. data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
  114. data/test/sass/util/normalized_map_test.rb +1 -1
  115. data/test/sass/util/subset_map_test.rb +2 -2
  116. data/test/sass/util_test.rb +31 -1
  117. data/test/sass/value_helpers_test.rb +5 -7
  118. data/test/test_helper.rb +2 -2
  119. data/vendor/listen/CHANGELOG.md +1 -228
  120. data/vendor/listen/Gemfile +5 -15
  121. data/vendor/listen/README.md +111 -77
  122. data/vendor/listen/Rakefile +0 -42
  123. data/vendor/listen/lib/listen/adapter.rb +195 -82
  124. data/vendor/listen/lib/listen/adapters/bsd.rb +27 -64
  125. data/vendor/listen/lib/listen/adapters/darwin.rb +21 -58
  126. data/vendor/listen/lib/listen/adapters/linux.rb +23 -55
  127. data/vendor/listen/lib/listen/adapters/polling.rb +25 -34
  128. data/vendor/listen/lib/listen/adapters/windows.rb +50 -46
  129. data/vendor/listen/lib/listen/directory_record.rb +96 -61
  130. data/vendor/listen/lib/listen/listener.rb +135 -37
  131. data/vendor/listen/lib/listen/turnstile.rb +9 -5
  132. data/vendor/listen/lib/listen/version.rb +1 -1
  133. data/vendor/listen/lib/listen.rb +33 -19
  134. data/vendor/listen/listen.gemspec +6 -0
  135. data/vendor/listen/spec/listen/adapter_spec.rb +43 -77
  136. data/vendor/listen/spec/listen/adapters/polling_spec.rb +8 -8
  137. data/vendor/listen/spec/listen/directory_record_spec.rb +81 -56
  138. data/vendor/listen/spec/listen/listener_spec.rb +128 -39
  139. data/vendor/listen/spec/listen_spec.rb +15 -21
  140. data/vendor/listen/spec/spec_helper.rb +4 -0
  141. data/vendor/listen/spec/support/adapter_helper.rb +52 -15
  142. data/vendor/listen/spec/support/directory_record_helper.rb +7 -5
  143. data/vendor/listen/spec/support/listeners_helper.rb +30 -7
  144. metadata +25 -22
  145. data/ext/mkrf_conf.rb +0 -27
  146. data/lib/sass/importers/deprecated_path.rb +0 -51
  147. data/lib/sass/script/value/deprecated_false.rb +0 -55
  148. data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
  149. data/vendor/listen/lib/listen/multi_listener.rb +0 -143
  150. data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
  151. data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
@@ -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 {
@@ -145,8 +145,8 @@ SCSS
145
145
  end
146
146
 
147
147
  def test_class_unification
148
- assert_unification '.foo.bar', '.baz {@extend .foo}', '.foo.bar, .bar.baz'
149
- assert_unification '.foo.baz', '.baz {@extend .foo}', '.baz'
148
+ assert_unification '.foo.bar', '.baz {@extend .foo}', '.foo.bar, .bar.baz'
149
+ assert_unification '.foo.baz', '.baz {@extend .foo}', '.baz'
150
150
  end
151
151
 
152
152
  def test_id_unification
@@ -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}