sass 3.2.19 → 3.4.25

Sign up to get free protection for your applications and to get access to all the features.
Files changed (246) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +3 -1
  3. data/CODE_OF_CONDUCT.md +10 -0
  4. data/CONTRIBUTING.md +148 -0
  5. data/MIT-LICENSE +1 -1
  6. data/README.md +87 -61
  7. data/Rakefile +119 -15
  8. data/VERSION +1 -1
  9. data/VERSION_DATE +1 -1
  10. data/VERSION_NAME +1 -1
  11. data/bin/sass +1 -1
  12. data/bin/scss +1 -1
  13. data/extra/sass-spec-ref.sh +32 -0
  14. data/extra/update_watch.rb +1 -1
  15. data/lib/sass/cache_stores/base.rb +2 -2
  16. data/lib/sass/cache_stores/chain.rb +2 -1
  17. data/lib/sass/cache_stores/filesystem.rb +8 -12
  18. data/lib/sass/cache_stores/memory.rb +5 -6
  19. data/lib/sass/cache_stores/null.rb +2 -2
  20. data/lib/sass/callbacks.rb +3 -2
  21. data/lib/sass/css.rb +22 -23
  22. data/lib/sass/deprecation.rb +55 -0
  23. data/lib/sass/engine.rb +487 -191
  24. data/lib/sass/environment.rb +172 -58
  25. data/lib/sass/error.rb +21 -24
  26. data/lib/sass/exec/base.rb +199 -0
  27. data/lib/sass/exec/sass_convert.rb +283 -0
  28. data/lib/sass/exec/sass_scss.rb +440 -0
  29. data/lib/sass/exec.rb +5 -703
  30. data/lib/sass/features.rb +47 -0
  31. data/lib/sass/importers/base.rb +50 -7
  32. data/lib/sass/importers/deprecated_path.rb +51 -0
  33. data/lib/sass/importers/filesystem.rb +54 -21
  34. data/lib/sass/importers.rb +1 -0
  35. data/lib/sass/logger/base.rb +9 -5
  36. data/lib/sass/logger/delayed.rb +50 -0
  37. data/lib/sass/logger/log_level.rb +3 -7
  38. data/lib/sass/logger.rb +9 -7
  39. data/lib/sass/media.rb +20 -23
  40. data/lib/sass/plugin/compiler.rb +321 -145
  41. data/lib/sass/plugin/configuration.rb +45 -34
  42. data/lib/sass/plugin/merb.rb +3 -3
  43. data/lib/sass/plugin/rack.rb +3 -3
  44. data/lib/sass/plugin/rails.rb +1 -1
  45. data/lib/sass/plugin/staleness_checker.rb +6 -6
  46. data/lib/sass/plugin.rb +9 -8
  47. data/lib/sass/repl.rb +3 -3
  48. data/lib/sass/script/css_lexer.rb +8 -4
  49. data/lib/sass/script/css_parser.rb +4 -2
  50. data/lib/sass/script/css_variable_warning.rb +52 -0
  51. data/lib/sass/script/functions.rb +1583 -433
  52. data/lib/sass/script/lexer.rb +198 -79
  53. data/lib/sass/script/parser.rb +463 -133
  54. data/lib/sass/script/tree/funcall.rb +313 -0
  55. data/lib/sass/script/tree/interpolation.rb +223 -0
  56. data/lib/sass/script/tree/list_literal.rb +104 -0
  57. data/lib/sass/script/tree/literal.rb +49 -0
  58. data/lib/sass/script/tree/map_literal.rb +64 -0
  59. data/lib/sass/script/{node.rb → tree/node.rb} +42 -14
  60. data/lib/sass/script/tree/operation.rb +156 -0
  61. data/lib/sass/script/tree/selector.rb +26 -0
  62. data/lib/sass/script/tree/string_interpolation.rb +125 -0
  63. data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +6 -6
  64. data/lib/sass/script/tree/variable.rb +57 -0
  65. data/lib/sass/script/tree.rb +16 -0
  66. data/lib/sass/script/{arg_list.rb → value/arg_list.rb} +9 -25
  67. data/lib/sass/script/value/base.rb +241 -0
  68. data/lib/sass/script/value/bool.rb +35 -0
  69. data/lib/sass/script/value/color.rb +698 -0
  70. data/lib/sass/script/value/helpers.rb +272 -0
  71. data/lib/sass/script/value/list.rb +113 -0
  72. data/lib/sass/script/value/map.rb +70 -0
  73. data/lib/sass/script/{null.rb → value/null.rb} +14 -7
  74. data/lib/sass/script/{number.rb → value/number.rb} +196 -86
  75. data/lib/sass/script/value/string.rb +138 -0
  76. data/lib/sass/script/value.rb +11 -0
  77. data/lib/sass/script.rb +38 -11
  78. data/lib/sass/scss/css_parser.rb +25 -5
  79. data/lib/sass/scss/parser.rb +532 -458
  80. data/lib/sass/scss/rx.rb +21 -14
  81. data/lib/sass/scss/static_parser.rb +328 -9
  82. data/lib/sass/scss.rb +0 -2
  83. data/lib/sass/selector/abstract_sequence.rb +36 -19
  84. data/lib/sass/selector/comma_sequence.rb +125 -26
  85. data/lib/sass/selector/pseudo.rb +266 -0
  86. data/lib/sass/selector/sequence.rb +200 -71
  87. data/lib/sass/selector/simple.rb +30 -32
  88. data/lib/sass/selector/simple_sequence.rb +193 -64
  89. data/lib/sass/selector.rb +65 -194
  90. data/lib/sass/shared.rb +2 -2
  91. data/lib/sass/source/map.rb +213 -0
  92. data/lib/sass/source/position.rb +39 -0
  93. data/lib/sass/source/range.rb +41 -0
  94. data/lib/sass/stack.rb +120 -0
  95. data/lib/sass/supports.rb +19 -23
  96. data/lib/sass/tree/at_root_node.rb +83 -0
  97. data/lib/sass/tree/charset_node.rb +1 -1
  98. data/lib/sass/tree/comment_node.rb +4 -4
  99. data/lib/sass/tree/css_import_node.rb +19 -11
  100. data/lib/sass/tree/debug_node.rb +2 -2
  101. data/lib/sass/tree/directive_node.rb +21 -4
  102. data/lib/sass/tree/each_node.rb +8 -8
  103. data/lib/sass/tree/error_node.rb +18 -0
  104. data/lib/sass/tree/extend_node.rb +14 -7
  105. data/lib/sass/tree/for_node.rb +4 -4
  106. data/lib/sass/tree/function_node.rb +14 -4
  107. data/lib/sass/tree/if_node.rb +1 -1
  108. data/lib/sass/tree/import_node.rb +10 -10
  109. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  110. data/lib/sass/tree/media_node.rb +4 -14
  111. data/lib/sass/tree/mixin_def_node.rb +4 -4
  112. data/lib/sass/tree/mixin_node.rb +21 -8
  113. data/lib/sass/tree/node.rb +59 -15
  114. data/lib/sass/tree/prop_node.rb +42 -24
  115. data/lib/sass/tree/return_node.rb +3 -2
  116. data/lib/sass/tree/root_node.rb +19 -3
  117. data/lib/sass/tree/rule_node.rb +49 -26
  118. data/lib/sass/tree/supports_node.rb +0 -13
  119. data/lib/sass/tree/trace_node.rb +2 -1
  120. data/lib/sass/tree/variable_node.rb +9 -3
  121. data/lib/sass/tree/visitors/base.rb +5 -8
  122. data/lib/sass/tree/visitors/check_nesting.rb +62 -36
  123. data/lib/sass/tree/visitors/convert.rb +111 -76
  124. data/lib/sass/tree/visitors/cssize.rb +206 -74
  125. data/lib/sass/tree/visitors/deep_copy.rb +11 -6
  126. data/lib/sass/tree/visitors/extend.rb +19 -17
  127. data/lib/sass/tree/visitors/perform.rb +308 -190
  128. data/lib/sass/tree/visitors/set_options.rb +21 -7
  129. data/lib/sass/tree/visitors/to_css.rb +273 -92
  130. data/lib/sass/tree/warn_node.rb +2 -2
  131. data/lib/sass/tree/while_node.rb +2 -2
  132. data/lib/sass/util/cross_platform_random.rb +19 -0
  133. data/lib/sass/util/normalized_map.rb +129 -0
  134. data/lib/sass/util/ordered_hash.rb +192 -0
  135. data/lib/sass/util/subset_map.rb +5 -5
  136. data/lib/sass/util/test.rb +0 -1
  137. data/lib/sass/util.rb +620 -193
  138. data/lib/sass/version.rb +22 -24
  139. data/lib/sass.rb +27 -13
  140. data/test/sass/cache_test.rb +62 -20
  141. data/test/sass/callbacks_test.rb +1 -1
  142. data/test/sass/compiler_test.rb +236 -0
  143. data/test/sass/conversion_test.rb +472 -44
  144. data/test/sass/css2sass_test.rb +73 -5
  145. data/test/sass/css_variable_test.rb +132 -0
  146. data/test/sass/encoding_test.rb +219 -0
  147. data/test/sass/engine_test.rb +618 -415
  148. data/test/sass/exec_test.rb +12 -2
  149. data/test/sass/extend_test.rb +419 -168
  150. data/test/sass/functions_test.rb +931 -93
  151. data/test/sass/importer_test.rb +250 -21
  152. data/test/sass/logger_test.rb +1 -1
  153. data/test/sass/more_results/more_import.css +1 -1
  154. data/test/sass/more_templates/more1.sass +10 -10
  155. data/test/sass/more_templates/more_import.sass +2 -2
  156. data/test/sass/plugin_test.rb +26 -34
  157. data/test/sass/results/compact.css +1 -1
  158. data/test/sass/results/complex.css +4 -4
  159. data/test/sass/results/expanded.css +1 -1
  160. data/test/sass/results/import.css +1 -1
  161. data/test/sass/results/import_charset_ibm866.css +2 -2
  162. data/test/sass/results/mixins.css +17 -17
  163. data/test/sass/results/nested.css +1 -1
  164. data/test/sass/results/parent_ref.css +2 -2
  165. data/test/sass/results/script.css +5 -5
  166. data/test/sass/results/scss_import.css +1 -1
  167. data/test/sass/script_conversion_test.rb +97 -39
  168. data/test/sass/script_test.rb +911 -102
  169. data/test/sass/scss/css_test.rb +215 -34
  170. data/test/sass/scss/rx_test.rb +8 -4
  171. data/test/sass/scss/scss_test.rb +2424 -325
  172. data/test/sass/source_map_test.rb +1055 -0
  173. data/test/sass/superselector_test.rb +210 -0
  174. data/test/sass/templates/_partial.sass +1 -1
  175. data/test/sass/templates/basic.sass +10 -10
  176. data/test/sass/templates/bork1.sass +1 -1
  177. data/test/sass/templates/bork5.sass +1 -1
  178. data/test/sass/templates/compact.sass +10 -10
  179. data/test/sass/templates/complex.sass +187 -187
  180. data/test/sass/templates/compressed.sass +10 -10
  181. data/test/sass/templates/expanded.sass +10 -10
  182. data/test/sass/templates/import.sass +2 -2
  183. data/test/sass/templates/importee.sass +3 -3
  184. data/test/sass/templates/mixins.sass +22 -22
  185. data/test/sass/templates/multiline.sass +4 -4
  186. data/test/sass/templates/nested.sass +13 -13
  187. data/test/sass/templates/parent_ref.sass +12 -12
  188. data/test/sass/templates/script.sass +70 -70
  189. data/test/sass/templates/scss_import.scss +2 -1
  190. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +1 -1
  191. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +2 -2
  192. data/test/sass/templates/subdir/subdir.sass +3 -3
  193. data/test/sass/templates/units.sass +10 -10
  194. data/test/sass/test_helper.rb +1 -1
  195. data/test/sass/util/multibyte_string_scanner_test.rb +11 -3
  196. data/test/sass/util/normalized_map_test.rb +51 -0
  197. data/test/sass/util/subset_map_test.rb +2 -2
  198. data/test/sass/util_test.rb +99 -43
  199. data/test/sass/value_helpers_test.rb +179 -0
  200. data/test/sass-spec.yml +3 -0
  201. data/test/test_helper.rb +42 -12
  202. data/vendor/listen/CHANGELOG.md +1 -228
  203. data/vendor/listen/Gemfile +5 -15
  204. data/vendor/listen/README.md +111 -77
  205. data/vendor/listen/Rakefile +0 -42
  206. data/vendor/listen/lib/listen/adapter.rb +195 -82
  207. data/vendor/listen/lib/listen/adapters/bsd.rb +27 -64
  208. data/vendor/listen/lib/listen/adapters/darwin.rb +21 -58
  209. data/vendor/listen/lib/listen/adapters/linux.rb +23 -55
  210. data/vendor/listen/lib/listen/adapters/polling.rb +25 -34
  211. data/vendor/listen/lib/listen/adapters/windows.rb +50 -46
  212. data/vendor/listen/lib/listen/directory_record.rb +96 -61
  213. data/vendor/listen/lib/listen/listener.rb +135 -37
  214. data/vendor/listen/lib/listen/turnstile.rb +9 -5
  215. data/vendor/listen/lib/listen/version.rb +1 -1
  216. data/vendor/listen/lib/listen.rb +33 -19
  217. data/vendor/listen/listen.gemspec +6 -0
  218. data/vendor/listen/spec/listen/adapter_spec.rb +43 -77
  219. data/vendor/listen/spec/listen/adapters/polling_spec.rb +8 -8
  220. data/vendor/listen/spec/listen/directory_record_spec.rb +81 -56
  221. data/vendor/listen/spec/listen/listener_spec.rb +128 -39
  222. data/vendor/listen/spec/listen_spec.rb +15 -21
  223. data/vendor/listen/spec/spec_helper.rb +4 -0
  224. data/vendor/listen/spec/support/adapter_helper.rb +52 -15
  225. data/vendor/listen/spec/support/directory_record_helper.rb +7 -5
  226. data/vendor/listen/spec/support/listeners_helper.rb +30 -7
  227. metadata +161 -111
  228. data/CONTRIBUTING +0 -3
  229. data/lib/sass/script/bool.rb +0 -18
  230. data/lib/sass/script/color.rb +0 -606
  231. data/lib/sass/script/funcall.rb +0 -245
  232. data/lib/sass/script/interpolation.rb +0 -79
  233. data/lib/sass/script/list.rb +0 -85
  234. data/lib/sass/script/literal.rb +0 -221
  235. data/lib/sass/script/operation.rb +0 -110
  236. data/lib/sass/script/string.rb +0 -51
  237. data/lib/sass/script/string_interpolation.rb +0 -103
  238. data/lib/sass/script/variable.rb +0 -58
  239. data/lib/sass/scss/script_lexer.rb +0 -15
  240. data/lib/sass/scss/script_parser.rb +0 -25
  241. data/test/Gemfile +0 -3
  242. data/test/Gemfile.lock +0 -10
  243. data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
  244. data/vendor/listen/lib/listen/multi_listener.rb +0 -143
  245. data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
  246. data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
@@ -2,7 +2,7 @@
2
2
  # -*- coding: utf-8 -*-
3
3
  require File.dirname(__FILE__) + '/test_helper'
4
4
 
5
- class ScssTest < Test::Unit::TestCase
5
+ class ScssTest < MiniTest::Test
6
6
  include ScssTestHelper
7
7
 
8
8
  ## One-Line Comments
@@ -115,6 +115,14 @@ SCSS
115
115
  end
116
116
  end
117
117
 
118
+ def test_error_directive
119
+ assert_raise_message(Sass::SyntaxError, "hello world!") {render(<<SCSS)}
120
+ foo {a: b}
121
+ @error "hello world!";
122
+ bar {c: d}
123
+ SCSS
124
+ end
125
+
118
126
  def test_warn_directive
119
127
  expected_warning = <<EXPECTATION
120
128
  WARNING: this is a warning
@@ -163,6 +171,51 @@ CSS
163
171
  SCSS
164
172
  end
165
173
 
174
+ def test_for_directive_with_same_start_and_end
175
+ assert_equal <<CSS, render(<<SCSS)
176
+ CSS
177
+ .foo {
178
+ @for $var from 1 to 1 {a: $var;}
179
+ }
180
+ SCSS
181
+
182
+ assert_equal <<CSS, render(<<SCSS)
183
+ .foo {
184
+ a: 1; }
185
+ CSS
186
+ .foo {
187
+ @for $var from 1 through 1 {a: $var;}
188
+ }
189
+ SCSS
190
+ end
191
+
192
+ def test_decrementing_estfor_directive
193
+ assert_equal <<CSS, render(<<SCSS)
194
+ .foo {
195
+ a: 5;
196
+ a: 4;
197
+ a: 3;
198
+ a: 2;
199
+ a: 1; }
200
+ CSS
201
+ .foo {
202
+ @for $var from 5 through 1 {a: $var;}
203
+ }
204
+ SCSS
205
+
206
+ assert_equal <<CSS, render(<<SCSS)
207
+ .foo {
208
+ a: 5;
209
+ a: 4;
210
+ a: 3;
211
+ a: 2; }
212
+ CSS
213
+ .foo {
214
+ @for $var from 5 to 1 {a: $var;}
215
+ }
216
+ SCSS
217
+ end
218
+
166
219
  def test_if_directive
167
220
  assert_equal <<CSS, render(<<SCSS)
168
221
  foo {
@@ -229,7 +282,7 @@ $i: 1;
229
282
  .foo {
230
283
  @while $i != 5 {
231
284
  a: $i;
232
- $i: $i + 1;
285
+ $i: $i + 1 !global;
233
286
  }
234
287
  }
235
288
  SCSS
@@ -262,6 +315,31 @@ c {
262
315
  SCSS
263
316
  end
264
317
 
318
+ def test_destructuring_each_directive
319
+ assert_equal <<CSS, render(<<SCSS)
320
+ a {
321
+ foo: 1px;
322
+ bar: 2px;
323
+ baz: 3px; }
324
+
325
+ c {
326
+ foo: "Value is bar";
327
+ bar: "Value is baz";
328
+ bang: "Value is "; }
329
+ CSS
330
+ a {
331
+ @each $name, $number in (foo: 1px, bar: 2px, baz: 3px) {
332
+ \#{$name}: $number;
333
+ }
334
+ }
335
+ c {
336
+ @each $key, $value in (foo bar) (bar, baz) bang {
337
+ \#{$key}: "Value is \#{$value}";
338
+ }
339
+ }
340
+ SCSS
341
+ end
342
+
265
343
  def test_css_import_directive
266
344
  assert_equal "@import url(foo.css);\n", render('@import "foo.css";')
267
345
  assert_equal "@import url(foo.css);\n", render("@import 'foo.css';")
@@ -379,6 +457,15 @@ foo {a: 1 + // flang }
379
457
  SCSS
380
458
  end
381
459
 
460
+ def test_static_hyphenated_unit
461
+ assert_equal <<CSS, render(<<SCSS)
462
+ foo {
463
+ a: 0px; }
464
+ CSS
465
+ foo {a: 10px-10px }
466
+ SCSS
467
+ end
468
+
382
469
  ## Nested Rules
383
470
 
384
471
  def test_nested_rules
@@ -466,11 +553,17 @@ foo :baz {
466
553
  c: d; }
467
554
  foo bang:bop {
468
555
  e: f; }
556
+ foo ::qux {
557
+ g: h; }
558
+ foo zap::fblthp {
559
+ i: j; }
469
560
  CSS
470
561
  foo {
471
562
  .bar {a: b}
472
563
  :baz {c: d}
473
- bang:bop {e: f}}
564
+ bang:bop {e: f}
565
+ ::qux {g: h}
566
+ zap::fblthp {i: j}}
474
567
  SCSS
475
568
  end
476
569
 
@@ -575,7 +668,7 @@ SCSS
575
668
  end
576
669
 
577
670
  def test_parent_selector_with_subject
578
- assert_equal <<CSS, render(<<SCSS)
671
+ silence_warnings {assert_equal <<CSS, render(<<SCSS)}
579
672
  bar foo.baz! .bip {
580
673
  a: b; }
581
674
 
@@ -590,6 +683,67 @@ foo bar {
590
683
  SCSS
591
684
  end
592
685
 
686
+ def test_parent_selector_with_suffix
687
+ assert_equal <<CSS, render(<<SCSS)
688
+ .foo-bar {
689
+ a: b; }
690
+ .foo_bar {
691
+ c: d; }
692
+ .foobar {
693
+ e: f; }
694
+ .foo123 {
695
+ e: f; }
696
+
697
+ :hover-suffix {
698
+ g: h; }
699
+ CSS
700
+ .foo {
701
+ &-bar {a: b}
702
+ &_bar {c: d}
703
+ &bar {e: f}
704
+ &123 {e: f}
705
+ }
706
+
707
+ :hover {
708
+ &-suffix {g: h}
709
+ }
710
+ SCSS
711
+ end
712
+
713
+ def test_unknown_directive_bubbling
714
+ assert_equal(<<CSS, render(<<SCSS, :style => :nested))
715
+ @fblthp {
716
+ .foo .bar {
717
+ a: b; } }
718
+ CSS
719
+ .foo {
720
+ @fblthp {
721
+ .bar {a: b}
722
+ }
723
+ }
724
+ SCSS
725
+ end
726
+
727
+ def test_keyframe_bubbling
728
+ assert_equal(<<CSS, render(<<SCSS, :style => :nested))
729
+ @keyframes spin {
730
+ 0% {
731
+ transform: rotate(0deg); } }
732
+ @-webkit-keyframes spin {
733
+ 0% {
734
+ transform: rotate(0deg); } }
735
+ CSS
736
+ .foo {
737
+ @keyframes spin {
738
+ 0% {transform: rotate(0deg)}
739
+ }
740
+ @-webkit-keyframes spin {
741
+ 0% {transform: rotate(0deg)}
742
+ }
743
+ }
744
+ SCSS
745
+ end
746
+
593
747
  ## Namespace Properties
594
748
 
595
749
  def test_namespace_properties
@@ -688,18 +842,27 @@ SCSS
688
842
  def test_no_namespace_properties_without_space_even_when_its_unambiguous
689
843
  render(<<SCSS)
690
844
  foo {
691
- bar:1px {
845
+ bar:baz calc(1 + 2) {
692
846
  bip: bop }}
693
847
  SCSS
694
848
  assert(false, "Expected syntax error")
695
849
  rescue Sass::SyntaxError => e
696
- assert_equal <<MESSAGE, e.message
697
- Invalid CSS: a space is required between a property and its definition
698
- when it has other properties nested beneath it.
699
- MESSAGE
850
+ assert_equal 'Invalid CSS after "bar:baz calc": expected selector, was "(1 + 2)"', e.message
700
851
  assert_equal 2, e.sass_line
701
852
  end
702
853
 
854
+ def test_namespace_properties_without_space_allowed_for_non_identifier
855
+ assert_equal <<CSS, render(<<SCSS)
856
+ foo {
857
+ bar: 1px;
858
+ bar-bip: bop; }
859
+ CSS
860
+ foo {
861
+ bar:1px {
862
+ bip: bop }}
863
+ SCSS
864
+ end
865
+
703
866
  ## Mixins
704
867
 
705
868
  def test_basic_mixins
@@ -792,6 +955,33 @@ CSS
792
955
  SCSS
793
956
  end
794
957
 
958
+ def test_keyframes_rules_in_content
959
+ assert_equal <<CSS, render(<<SCSS)
960
+ @keyframes identifier {
961
+ 0% {
962
+ top: 0;
963
+ left: 0; }
964
+ 30% {
965
+ top: 50px; }
966
+ 68%, 72% {
967
+ left: 50px; }
968
+ 100% {
969
+ top: 100px;
970
+ left: 100%; } }
971
+ CSS
972
+ @mixin keyframes {
973
+ @keyframes identifier { @content }
974
+ }
975
+
976
+ @include keyframes {
977
+ 0% {top: 0; left: 0}
978
+ \#{"30%"} {top: 50px}
979
+ 68%, 72% {left: 50px}
980
+ 100% {top: 100px; left: 100%}
981
+ }
982
+ SCSS
983
+ end
984
+
795
985
  ## Functions
796
986
 
797
987
  def test_basic_function
@@ -824,6 +1014,78 @@ bar {
824
1014
  SASS
825
1015
  end
826
1016
 
1017
+ def test_disallowed_function_names
1018
+ Sass::Deprecation.allow_double_warnings do
1019
+ assert_warning(<<WARNING) {render(<<SCSS)}
1020
+ DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1021
+ Naming a function "calc" is disallowed and will be an error in future versions of Sass.
1022
+ This name conflicts with an existing CSS function with special parse rules.
1023
+ WARNING
1024
+ @function calc() {}
1025
+ SCSS
1026
+
1027
+ assert_warning(<<WARNING) {render(<<SCSS)}
1028
+ DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1029
+ Naming a function "-my-calc" is disallowed and will be an error in future versions of Sass.
1030
+ This name conflicts with an existing CSS function with special parse rules.
1031
+ WARNING
1032
+ @function -my-calc() {}
1033
+ SCSS
1034
+
1035
+ assert_warning(<<WARNING) {render(<<SCSS)}
1036
+ DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1037
+ Naming a function "element" is disallowed and will be an error in future versions of Sass.
1038
+ This name conflicts with an existing CSS function with special parse rules.
1039
+ WARNING
1040
+ @function element() {}
1041
+ SCSS
1042
+
1043
+ assert_warning(<<WARNING) {render(<<SCSS)}
1044
+ DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1045
+ Naming a function "-my-element" is disallowed and will be an error in future versions of Sass.
1046
+ This name conflicts with an existing CSS function with special parse rules.
1047
+ WARNING
1048
+ @function -my-element() {}
1049
+ SCSS
1050
+
1051
+ assert_warning(<<WARNING) {render(<<SCSS)}
1052
+ DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1053
+ Naming a function "expression" is disallowed and will be an error in future versions of Sass.
1054
+ This name conflicts with an existing CSS function with special parse rules.
1055
+ WARNING
1056
+ @function expression() {}
1057
+ SCSS
1058
+
1059
+ assert_warning(<<WARNING) {render(<<SCSS)}
1060
+ DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1061
+ Naming a function "url" is disallowed and will be an error in future versions of Sass.
1062
+ This name conflicts with an existing CSS function with special parse rules.
1063
+ WARNING
1064
+ @function url() {}
1065
+ SCSS
1066
+ end
1067
+ end
1068
+
1069
+ def test_allowed_function_names
1070
+ assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
1071
+ .a {
1072
+ b: c; }
1073
+ CSS
1074
+ @function -my-expression() {@return c}
1075
+
1076
+ .a {b: -my-expression()}
1077
+ SCSS
1078
+
1079
+ assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
1080
+ .a {
1081
+ b: c; }
1082
+ CSS
1083
+ @function -my-url() {@return c}
1084
+
1085
+ .a {b: -my-url()}
1086
+ SCSS
1087
+ end
1088
+
827
1089
  ## Var Args
828
1090
 
829
1091
  def test_mixin_var_args
@@ -981,580 +1243,2124 @@ CSS
981
1243
  SCSS
982
1244
  end
983
1245
 
984
- def test_mixin_var_args_with_keyword
985
- assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") {render <<SCSS}
986
- @mixin foo($a, $b...) {
987
- a: $a;
988
- b: $b;
1246
+ def test_mixin_var_keyword_args
1247
+ assert_equal <<CSS, render(<<SCSS)
1248
+ .foo {
1249
+ a: 1;
1250
+ b: 2;
1251
+ c: 3; }
1252
+ CSS
1253
+ @mixin foo($args...) {
1254
+ a: map-get(keywords($args), a);
1255
+ b: map-get(keywords($args), b);
1256
+ c: map-get(keywords($args), c);
989
1257
  }
990
1258
 
991
- .foo {@include foo($a: 1, 2, 3, 4)}
1259
+ .foo {@include foo($a: 1, $b: 2, $c: 3)}
992
1260
  SCSS
993
1261
  end
994
1262
 
995
- def test_mixin_keyword_for_var_arg
996
- assert_raise_message(Sass::SyntaxError, "Argument $b of mixin foo cannot be used as a named argument.") {render <<SCSS}
997
- @mixin foo($a, $b...) {
998
- a: $a;
999
- b: $b;
1263
+ def test_mixin_empty_var_keyword_args
1264
+ assert_equal <<CSS, render(<<SCSS)
1265
+ .foo {
1266
+ length: 0; }
1267
+ CSS
1268
+ @mixin foo($args...) {
1269
+ length: length(keywords($args));
1000
1270
  }
1001
1271
 
1002
- .foo {@include foo(1, $b: 2 3 4)}
1272
+ .foo {@include foo}
1003
1273
  SCSS
1004
1274
  end
1005
1275
 
1006
- def test_mixin_keyword_for_unknown_arg_with_var_args
1007
- assert_raise_message(Sass::SyntaxError, "Mixin foo doesn't have an argument named $c.") {render <<SCSS}
1008
- @mixin foo($a, $b...) {
1276
+ def test_mixin_map_splat
1277
+ assert_equal <<CSS, render(<<SCSS)
1278
+ .foo {
1279
+ a: 1;
1280
+ b: 2;
1281
+ c: 3; }
1282
+ CSS
1283
+ @mixin foo($a, $b, $c) {
1009
1284
  a: $a;
1010
1285
  b: $b;
1286
+ c: $c;
1011
1287
  }
1012
1288
 
1013
- .foo {@include foo(1, $c: 2 3 4)}
1289
+ .foo {
1290
+ $map: (a: 1, b: 2, c: 3);
1291
+ @include foo($map...);
1292
+ }
1014
1293
  SCSS
1015
1294
  end
1016
1295
 
1017
- def test_function_var_args
1296
+ def test_mixin_map_and_list_splat
1018
1297
  assert_equal <<CSS, render(<<SCSS)
1019
1298
  .foo {
1020
- val: "a: 1, b: 2, 3, 4"; }
1021
- CSS
1022
- @function foo($a, $b...) {
1023
- @return "a: \#{$a}, b: \#{$b}";
1299
+ a: x;
1300
+ b: y;
1301
+ c: z;
1302
+ d: 1;
1303
+ e: 2;
1304
+ f: 3; }
1305
+ CSS
1306
+ @mixin foo($a, $b, $c, $d, $e, $f) {
1307
+ a: $a;
1308
+ b: $b;
1309
+ c: $c;
1310
+ d: $d;
1311
+ e: $e;
1312
+ f: $f;
1024
1313
  }
1025
1314
 
1026
- .foo {val: foo(1, 2, 3, 4)}
1315
+ .foo {
1316
+ $list: x y z;
1317
+ $map: (d: 1, e: 2, f: 3);
1318
+ @include foo($list..., $map...);
1319
+ }
1027
1320
  SCSS
1028
1321
  end
1029
1322
 
1030
- def test_function_empty_var_args
1323
+ def test_mixin_map_splat_takes_precedence_over_pass_through
1031
1324
  assert_equal <<CSS, render(<<SCSS)
1032
1325
  .foo {
1033
- val: "a: 1, b: 0"; }
1326
+ a: 1;
1327
+ b: 2;
1328
+ c: z; }
1034
1329
  CSS
1035
- @function foo($a, $b...) {
1036
- @return "a: \#{$a}, b: \#{length($b)}";
1330
+ @mixin foo($args...) {
1331
+ $map: (c: z);
1332
+ @include bar($args..., $map...);
1037
1333
  }
1038
1334
 
1039
- .foo {val: foo(1)}
1040
- SCSS
1041
- end
1335
+ @mixin bar($a, $b, $c) {
1336
+ a: $a;
1337
+ b: $b;
1338
+ c: $c;
1339
+ }
1042
1340
 
1043
- def test_function_var_args_act_like_list
1044
- assert_equal <<CSS, render(<<SCSS)
1045
1341
  .foo {
1046
- val: "a: 3, b: 3"; }
1047
- CSS
1048
- @function foo($a, $b...) {
1049
- @return "a: \#{length($b)}, b: \#{nth($b, 2)}";
1342
+ @include foo(1, $b: 2, $c: 3);
1050
1343
  }
1051
-
1052
- .foo {val: foo(1, 2, 3, 4)}
1053
1344
  SCSS
1054
1345
  end
1055
1346
 
1056
- def test_function_splat_args
1347
+ def test_mixin_list_of_pairs_splat_treated_as_list
1057
1348
  assert_equal <<CSS, render(<<SCSS)
1058
1349
  .foo {
1059
- val: "a: 1, b: 2, c: 3, d: 4"; }
1350
+ a: a 1;
1351
+ b: b 2;
1352
+ c: c 3; }
1060
1353
  CSS
1061
- @function foo($a, $b, $c, $d) {
1062
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}";
1354
+ @mixin foo($a, $b, $c) {
1355
+ a: $a;
1356
+ b: $b;
1357
+ c: $c;
1063
1358
  }
1064
1359
 
1065
- $list: 2, 3, 4;
1066
- .foo {val: foo(1, $list...)}
1360
+ .foo {
1361
+ @include foo((a 1, b 2, c 3)...);
1362
+ }
1067
1363
  SCSS
1068
1364
  end
1069
1365
 
1070
- def test_function_splat_expression
1366
+ def test_mixin_splat_after_keyword_args
1071
1367
  assert_equal <<CSS, render(<<SCSS)
1072
1368
  .foo {
1073
- val: "a: 1, b: 2, c: 3, d: 4"; }
1369
+ a: 1;
1370
+ b: 2;
1371
+ c: 3; }
1074
1372
  CSS
1075
- @function foo($a, $b, $c, $d) {
1076
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}";
1373
+ @mixin foo($a, $b, $c) {
1374
+ a: 1;
1375
+ b: 2;
1376
+ c: 3;
1077
1377
  }
1078
1378
 
1079
- .foo {val: foo(1, (2, 3, 4)...)}
1379
+ .foo {
1380
+ @include foo(1, $c: 3, 2...);
1381
+ }
1080
1382
  SCSS
1081
1383
  end
1082
1384
 
1083
- def test_function_splat_args_with_var_args
1385
+ def test_mixin_keyword_args_after_splat
1084
1386
  assert_equal <<CSS, render(<<SCSS)
1085
1387
  .foo {
1086
- val: "a: 1, b: 2, 3, 4"; }
1388
+ a: 1;
1389
+ b: 2;
1390
+ c: 3; }
1087
1391
  CSS
1088
- @function foo($a, $b...) {
1089
- @return "a: \#{$a}, b: \#{$b}";
1392
+ @mixin foo($a, $b, $c) {
1393
+ a: 1;
1394
+ b: 2;
1395
+ c: 3;
1090
1396
  }
1091
1397
 
1092
- $list: 2, 3, 4;
1093
- .foo {val: foo(1, $list...)}
1398
+ .foo {
1399
+ @include foo(1, 2..., $c: 3);
1400
+ }
1094
1401
  SCSS
1095
1402
  end
1096
1403
 
1097
- def test_function_splat_args_with_var_args_and_normal_args
1404
+ def test_mixin_keyword_splat_after_keyword_args
1098
1405
  assert_equal <<CSS, render(<<SCSS)
1099
1406
  .foo {
1100
- val: "a: 1, b: 2, c: 3, 4"; }
1407
+ a: 1;
1408
+ b: 2;
1409
+ c: 3; }
1101
1410
  CSS
1102
- @function foo($a, $b, $c...) {
1103
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1411
+ @mixin foo($a, $b, $c) {
1412
+ a: 1;
1413
+ b: 2;
1414
+ c: 3;
1104
1415
  }
1105
1416
 
1106
- $list: 2, 3, 4;
1107
- .foo {val: foo(1, $list...)}
1417
+ .foo {
1418
+ @include foo(1, $b: 2, (c: 3)...);
1419
+ }
1108
1420
  SCSS
1109
1421
  end
1110
1422
 
1111
- def test_function_splat_args_with_var_args_preserves_separator
1423
+ def test_mixin_triple_keyword_splat_merge
1112
1424
  assert_equal <<CSS, render(<<SCSS)
1113
1425
  .foo {
1114
- val: "a: 1, b: 2 3 4 5"; }
1426
+ foo: 1;
1427
+ bar: 2;
1428
+ kwarg: 3;
1429
+ a: 3;
1430
+ b: 2;
1431
+ c: 3; }
1115
1432
  CSS
1116
- @function foo($a, $b...) {
1117
- @return "a: \#{$a}, b: \#{$b}";
1433
+ @mixin foo($foo, $bar, $kwarg, $a, $b, $c) {
1434
+ foo: $foo;
1435
+ bar: $bar;
1436
+ kwarg: $kwarg;
1437
+ a: $a;
1438
+ b: $b;
1439
+ c: $c;
1440
+ }
1441
+
1442
+ @mixin bar($args...) {
1443
+ @include foo($args..., $bar: 2, $a: 2, $b: 2, (kwarg: 3, a: 3, c: 3)...);
1444
+ }
1445
+
1446
+ .foo {
1447
+ @include bar($foo: 1, $a: 1, $b: 1, $c: 1);
1448
+ }
1449
+ SCSS
1450
+ end
1451
+
1452
+ def test_mixin_map_splat_converts_hyphens_and_underscores_for_real_args
1453
+ assert_equal <<CSS, render(<<SCSS)
1454
+ .foo {
1455
+ a: 1;
1456
+ b: 2;
1457
+ c: 3;
1458
+ d: 4; }
1459
+ CSS
1460
+ @mixin foo($a-1, $b-2, $c_3, $d_4) {
1461
+ a: $a-1;
1462
+ b: $b-2;
1463
+ c: $c_3;
1464
+ d: $d_4;
1465
+ }
1466
+
1467
+ .foo {
1468
+ $map: (a-1: 1, b_2: 2, c-3: 3, d_4: 4);
1469
+ @include foo($map...);
1470
+ }
1471
+ SCSS
1472
+ end
1473
+
1474
+ def test_mixin_map_splat_doesnt_convert_hyphens_and_underscores_for_var_args
1475
+ assert_equal <<CSS, render(<<SCSS)
1476
+ .foo {
1477
+ a-1: 1;
1478
+ b_2: 2;
1479
+ c-3: 3;
1480
+ d_4: 4; }
1481
+ CSS
1482
+ @mixin foo($args...) {
1483
+ @each $key, $value in keywords($args) {
1484
+ \#{$key}: $value;
1485
+ }
1486
+ }
1487
+
1488
+ .foo {
1489
+ $map: (a-1: 1, b_2: 2, c-3: 3, d_4: 4);
1490
+ @include foo($map...);
1491
+ }
1492
+ SCSS
1493
+ end
1494
+
1495
+ def test_mixin_conflicting_splat_after_keyword_args
1496
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
1497
+ Mixin foo was passed argument $b both by position and by name.
1498
+ MESSAGE
1499
+ @mixin foo($a, $b, $c) {
1500
+ a: 1;
1501
+ b: 2;
1502
+ c: 3;
1503
+ }
1504
+
1505
+ .foo {
1506
+ @include foo(1, $b: 2, 3...);
1507
+ }
1508
+ SCSS
1509
+ end
1510
+
1511
+ def test_mixin_keyword_splat_must_have_string_keys
1512
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
1513
+ Variable keyword argument map must have string keys.
1514
+ 12 is not a string in (12: 1).
1515
+ MESSAGE
1516
+ @mixin foo($a) {
1517
+ a: $a;
1518
+ }
1519
+
1520
+ .foo {@include foo((12: 1)...)}
1521
+ SCSS
1522
+ end
1523
+
1524
+ def test_mixin_positional_arg_after_splat
1525
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
1526
+ Only keyword arguments may follow variable arguments (...).
1527
+ MESSAGE
1528
+ @mixin foo($a, $b, $c) {
1529
+ a: 1;
1530
+ b: 2;
1531
+ c: 3;
1532
+ }
1533
+
1534
+ .foo {
1535
+ @include foo(1, 2..., 3);
1536
+ }
1537
+ SCSS
1538
+ end
1539
+
1540
+ def test_mixin_var_args_with_keyword
1541
+ assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") {render <<SCSS}
1542
+ @mixin foo($a, $b...) {
1543
+ a: $a;
1544
+ b: $b;
1545
+ }
1546
+
1547
+ .foo {@include foo($a: 1, 2, 3, 4)}
1548
+ SCSS
1549
+ end
1550
+
1551
+ def test_mixin_keyword_for_var_arg
1552
+ assert_raise_message(Sass::SyntaxError, "Argument $b of mixin foo cannot be used as a named argument.") {render <<SCSS}
1553
+ @mixin foo($a, $b...) {
1554
+ a: $a;
1555
+ b: $b;
1556
+ }
1557
+
1558
+ .foo {@include foo(1, $b: 2 3 4)}
1559
+ SCSS
1560
+ end
1561
+
1562
+ def test_mixin_keyword_for_unknown_arg_with_var_args
1563
+ assert_raise_message(Sass::SyntaxError, "Mixin foo doesn't have an argument named $c.") {render <<SCSS}
1564
+ @mixin foo($a, $b...) {
1565
+ a: $a;
1566
+ b: $b;
1567
+ }
1568
+
1569
+ .foo {@include foo(1, $c: 2 3 4)}
1570
+ SCSS
1571
+ end
1572
+
1573
+ def test_mixin_map_splat_before_list_splat
1574
+ assert_raise_message(Sass::SyntaxError, "Variable keyword arguments must be a map (was (2 3)).") {render <<SCSS}
1575
+ @mixin foo($a, $b, $c) {
1576
+ a: $a;
1577
+ b: $b;
1578
+ c: $c;
1579
+ }
1580
+
1581
+ .foo {
1582
+ @include foo((a: 1)..., (2 3)...);
1583
+ }
1584
+ SCSS
1585
+ end
1586
+
1587
+ def test_mixin_map_splat_with_unknown_keyword
1588
+ assert_raise_message(Sass::SyntaxError, "Mixin foo doesn't have an argument named $c.") {render <<SCSS}
1589
+ @mixin foo($a, $b) {
1590
+ a: $a;
1591
+ b: $b;
1592
+ }
1593
+
1594
+ .foo {
1595
+ @include foo(1, 2, (c: 1)...);
1596
+ }
1597
+ SCSS
1598
+ end
1599
+
1600
+ def test_mixin_map_splat_with_wrong_type
1601
+ assert_raise_message(Sass::SyntaxError, "Variable keyword arguments must be a map (was 12).") {render <<SCSS}
1602
+ @mixin foo($a, $b) {
1603
+ a: $a;
1604
+ b: $b;
1605
+ }
1606
+
1607
+ .foo {
1608
+ @include foo((1, 2)..., 12...);
1609
+ }
1610
+ SCSS
1611
+ end
1612
+
1613
+ def test_mixin_splat_too_many_args
1614
+ assert_warning(<<WARNING) {render <<SCSS}
1615
+ WARNING: Mixin foo takes 2 arguments but 4 were passed.
1616
+ on line 2 of #{filename_for_test(:scss)}
1617
+ This will be an error in future versions of Sass.
1618
+ WARNING
1619
+ @mixin foo($a, $b) {}
1620
+ @include foo((1, 2, 3, 4)...);
1621
+ SCSS
1622
+ end
1623
+
1624
+ def test_function_var_args
1625
+ assert_equal <<CSS, render(<<SCSS)
1626
+ .foo {
1627
+ val: "a: 1, b: 2, 3, 4"; }
1628
+ CSS
1629
+ @function foo($a, $b...) {
1630
+ @return "a: \#{$a}, b: \#{$b}";
1631
+ }
1632
+
1633
+ .foo {val: foo(1, 2, 3, 4)}
1634
+ SCSS
1635
+ end
1636
+
1637
+ def test_function_empty_var_args
1638
+ assert_equal <<CSS, render(<<SCSS)
1639
+ .foo {
1640
+ val: "a: 1, b: 0"; }
1641
+ CSS
1642
+ @function foo($a, $b...) {
1643
+ @return "a: \#{$a}, b: \#{length($b)}";
1644
+ }
1645
+
1646
+ .foo {val: foo(1)}
1647
+ SCSS
1648
+ end
1649
+
1650
+ def test_function_var_args_act_like_list
1651
+ assert_equal <<CSS, render(<<SCSS)
1652
+ .foo {
1653
+ val: "a: 3, b: 3"; }
1654
+ CSS
1655
+ @function foo($a, $b...) {
1656
+ @return "a: \#{length($b)}, b: \#{nth($b, 2)}";
1657
+ }
1658
+
1659
+ .foo {val: foo(1, 2, 3, 4)}
1660
+ SCSS
1661
+ end
1662
+
1663
+ def test_function_splat_args
1664
+ assert_equal <<CSS, render(<<SCSS)
1665
+ .foo {
1666
+ val: "a: 1, b: 2, c: 3, d: 4"; }
1667
+ CSS
1668
+ @function foo($a, $b, $c, $d) {
1669
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}";
1670
+ }
1671
+
1672
+ $list: 2, 3, 4;
1673
+ .foo {val: foo(1, $list...)}
1674
+ SCSS
1675
+ end
1676
+
1677
+ def test_function_splat_expression
1678
+ assert_equal <<CSS, render(<<SCSS)
1679
+ .foo {
1680
+ val: "a: 1, b: 2, c: 3, d: 4"; }
1681
+ CSS
1682
+ @function foo($a, $b, $c, $d) {
1683
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}";
1684
+ }
1685
+
1686
+ .foo {val: foo(1, (2, 3, 4)...)}
1687
+ SCSS
1688
+ end
1689
+
1690
+ def test_function_splat_args_with_var_args
1691
+ assert_equal <<CSS, render(<<SCSS)
1692
+ .foo {
1693
+ val: "a: 1, b: 2, 3, 4"; }
1694
+ CSS
1695
+ @function foo($a, $b...) {
1696
+ @return "a: \#{$a}, b: \#{$b}";
1697
+ }
1698
+
1699
+ $list: 2, 3, 4;
1700
+ .foo {val: foo(1, $list...)}
1701
+ SCSS
1702
+ end
1703
+
1704
+ def test_function_splat_args_with_var_args_and_normal_args
1705
+ assert_equal <<CSS, render(<<SCSS)
1706
+ .foo {
1707
+ val: "a: 1, b: 2, c: 3, 4"; }
1708
+ CSS
1709
+ @function foo($a, $b, $c...) {
1710
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1711
+ }
1712
+
1713
+ $list: 2, 3, 4;
1714
+ .foo {val: foo(1, $list...)}
1715
+ SCSS
1716
+ end
1717
+
1718
+ def test_function_splat_args_with_var_args_preserves_separator
1719
+ assert_equal <<CSS, render(<<SCSS)
1720
+ .foo {
1721
+ val: "a: 1, b: 2 3 4 5"; }
1722
+ CSS
1723
+ @function foo($a, $b...) {
1724
+ @return "a: \#{$a}, b: \#{$b}";
1725
+ }
1726
+
1727
+ $list: 3 4 5;
1728
+ .foo {val: foo(1, 2, $list...)}
1729
+ SCSS
1730
+ end
1731
+
1732
+ def test_function_var_and_splat_args_pass_through_keywords
1733
+ assert_equal <<CSS, render(<<SCSS)
1734
+ .foo {
1735
+ val: "a: 3, b: 1, c: 2"; }
1736
+ CSS
1737
+ @function foo($a...) {
1738
+ @return bar($a...);
1739
+ }
1740
+
1741
+ @function bar($b, $c, $a) {
1742
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1743
+ }
1744
+
1745
+ .foo {val: foo(1, $c: 2, $a: 3)}
1746
+ SCSS
1747
+ end
1748
+
1749
+ def test_function_var_keyword_args
1750
+ assert_equal <<CSS, render(<<SCSS)
1751
+ .foo {
1752
+ val: "a: 1, b: 2, c: 3"; }
1753
+ CSS
1754
+ @function foo($args...) {
1755
+ @return "a: \#{map-get(keywords($args), a)}, " +
1756
+ "b: \#{map-get(keywords($args), b)}, " +
1757
+ "c: \#{map-get(keywords($args), c)}";
1758
+ }
1759
+
1760
+ .foo {val: foo($a: 1, $b: 2, $c: 3)}
1761
+ SCSS
1762
+ end
1763
+
1764
+ def test_function_empty_var_keyword_args
1765
+ assert_equal <<CSS, render(<<SCSS)
1766
+ .foo {
1767
+ length: 0; }
1768
+ CSS
1769
+ @function foo($args...) {
1770
+ @return length(keywords($args));
1771
+ }
1772
+
1773
+ .foo {length: foo()}
1774
+ SCSS
1775
+ end
1776
+
1777
+ def test_function_map_splat
1778
+ assert_equal <<CSS, render(<<SCSS)
1779
+ .foo {
1780
+ val: "a: 1, b: 2, c: 3"; }
1781
+ CSS
1782
+ @function foo($a, $b, $c) {
1783
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1784
+ }
1785
+
1786
+ .foo {
1787
+ $map: (a: 1, b: 2, c: 3);
1788
+ val: foo($map...);
1789
+ }
1790
+ SCSS
1791
+ end
1792
+
1793
+ def test_function_map_and_list_splat
1794
+ assert_equal <<CSS, render(<<SCSS)
1795
+ .foo {
1796
+ val: "a: x, b: y, c: z, d: 1, e: 2, f: 3"; }
1797
+ CSS
1798
+ @function foo($a, $b, $c, $d, $e, $f) {
1799
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}, e: \#{$e}, f: \#{$f}";
1800
+ }
1801
+
1802
+ .foo {
1803
+ $list: x y z;
1804
+ $map: (d: 1, e: 2, f: 3);
1805
+ val: foo($list..., $map...);
1806
+ }
1807
+ SCSS
1808
+ end
1809
+
1810
+ def test_function_map_splat_takes_precedence_over_pass_through
1811
+ assert_equal <<CSS, render(<<SCSS)
1812
+ .foo {
1813
+ val: "a: 1, b: 2, c: z"; }
1814
+ CSS
1815
+ @function foo($args...) {
1816
+ $map: (c: z);
1817
+ @return bar($args..., $map...);
1818
+ }
1819
+
1820
+ @function bar($a, $b, $c) {
1821
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1822
+ }
1823
+
1824
+ .foo {
1825
+ val: foo(1, $b: 2, $c: 3);
1826
+ }
1827
+ SCSS
1828
+ end
1829
+
1830
+ def test_ruby_function_map_splat_takes_precedence_over_pass_through
1831
+ assert_equal <<CSS, render(<<SCSS)
1832
+ .foo {
1833
+ val: 1 2 3 z; }
1834
+ CSS
1835
+ @function foo($args...) {
1836
+ $map: (val: z);
1837
+ @return append($args..., $map...);
1838
+ }
1839
+
1840
+ .foo {
1841
+ val: foo(1 2 3, $val: 4)
1842
+ }
1843
+ SCSS
1844
+ end
1845
+
1846
+ def test_function_list_of_pairs_splat_treated_as_list
1847
+ assert_equal <<CSS, render(<<SCSS)
1848
+ .foo {
1849
+ val: "a: a 1, b: b 2, c: c 3"; }
1850
+ CSS
1851
+ @function foo($a, $b, $c) {
1852
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1853
+ }
1854
+
1855
+ .foo {
1856
+ val: foo((a 1, b 2, c 3)...);
1857
+ }
1858
+ SCSS
1859
+ end
1860
+
1861
+ def test_function_splat_after_keyword_args
1862
+ assert_equal <<CSS, render(<<SCSS)
1863
+ .foo {
1864
+ val: "a: 1, b: 2, c: 3"; }
1865
+ CSS
1866
+ @function foo($a, $b, $c) {
1867
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1868
+ }
1869
+
1870
+ .foo {
1871
+ val: foo(1, $c: 3, 2...);
1872
+ }
1873
+ SCSS
1874
+ end
1875
+
1876
+ def test_function_keyword_args_after_splat
1877
+ assert_equal <<CSS, render(<<SCSS)
1878
+ .foo {
1879
+ val: "a: 1, b: 2, c: 3"; }
1880
+ CSS
1881
+ @function foo($a, $b, $c) {
1882
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1883
+ }
1884
+
1885
+ .foo {
1886
+ val: foo(1, 2..., $c: 3);
1887
+ }
1888
+ SCSS
1889
+ end
1890
+
1891
+ def test_function_keyword_splat_after_keyword_args
1892
+ assert_equal <<CSS, render(<<SCSS)
1893
+ .foo {
1894
+ val: "a: 1, b: 2, c: 3"; }
1895
+ CSS
1896
+ @function foo($a, $b, $c) {
1897
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1898
+ }
1899
+
1900
+ .foo {
1901
+ val: foo(1, $b: 2, (c: 3)...);
1902
+ }
1903
+ SCSS
1904
+ end
1905
+
1906
+ def test_function_triple_keyword_splat_merge
1907
+ assert_equal <<CSS, render(<<SCSS)
1908
+ .foo {
1909
+ val: "foo: 1, bar: 2, kwarg: 3, a: 3, b: 2, c: 3"; }
1910
+ CSS
1911
+ @function foo($foo, $bar, $kwarg, $a, $b, $c) {
1912
+ @return "foo: \#{$foo}, bar: \#{$bar}, kwarg: \#{$kwarg}, a: \#{$a}, b: \#{$b}, c: \#{$c}";
1913
+ }
1914
+
1915
+ @function bar($args...) {
1916
+ @return foo($args..., $bar: 2, $a: 2, $b: 2, (kwarg: 3, a: 3, c: 3)...);
1917
+ }
1918
+
1919
+ .foo {
1920
+ val: bar($foo: 1, $a: 1, $b: 1, $c: 1);
1921
+ }
1922
+ SCSS
1923
+ end
1924
+
1925
+ def test_function_conflicting_splat_after_keyword_args
1926
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
1927
+ Function foo was passed argument $b both by position and by name.
1928
+ MESSAGE
1929
+ @function foo($a, $b, $c) {
1930
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1931
+ }
1932
+
1933
+ .foo {
1934
+ val: foo(1, $b: 2, 3...);
1935
+ }
1936
+ SCSS
1937
+ end
1938
+
1939
+ def test_function_positional_arg_after_splat
1940
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
1941
+ Only keyword arguments may follow variable arguments (...).
1942
+ MESSAGE
1943
+ @function foo($a, $b, $c) {
1944
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1945
+ }
1946
+
1947
+ .foo {
1948
+ val: foo(1, 2..., 3);
1949
+ }
1950
+ SCSS
1951
+ end
1952
+
1953
+ def test_function_var_args_with_keyword
1954
+ assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") {render <<SCSS}
1955
+ @function foo($a, $b...) {
1956
+ @return "a: \#{$a}, b: \#{$b}";
1957
+ }
1958
+
1959
+ .foo {val: foo($a: 1, 2, 3, 4)}
1960
+ SCSS
1961
+ end
1962
+
1963
+ def test_function_keyword_for_var_arg
1964
+ assert_raise_message(Sass::SyntaxError, "Argument $b of function foo cannot be used as a named argument.") {render <<SCSS}
1965
+ @function foo($a, $b...) {
1966
+ @return "a: \#{$a}, b: \#{$b}";
1967
+ }
1968
+
1969
+ .foo {val: foo(1, $b: 2 3 4)}
1970
+ SCSS
1971
+ end
1972
+
1973
+ def test_function_keyword_for_unknown_arg_with_var_args
1974
+ assert_raise_message(Sass::SyntaxError, "Function foo doesn't have an argument named $c.") {render <<SCSS}
1975
+ @function foo($a, $b...) {
1976
+ @return "a: \#{$a}, b: \#{length($b)}";
1977
+ }
1978
+
1979
+ .foo {val: foo(1, $c: 2 3 4)}
1980
+ SCSS
1981
+ end
1982
+
1983
+ def test_function_var_args_passed_to_native
1984
+ assert_equal <<CSS, render(<<SCSS)
1985
+ .foo {
1986
+ val: #102035; }
1987
+ CSS
1988
+ @function foo($args...) {
1989
+ @return adjust-color($args...);
1990
+ }
1991
+
1992
+ .foo {val: foo(#102030, $blue: 5)}
1993
+ SCSS
1994
+ end
1995
+
1996
+ def test_function_map_splat_before_list_splat
1997
+ assert_raise_message(Sass::SyntaxError, "Variable keyword arguments must be a map (was (2 3)).") {render <<SCSS}
1998
+ @function foo($a, $b, $c) {
1999
+ @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
2000
+ }
2001
+
2002
+ .foo {
2003
+ val: foo((a: 1)..., (2 3)...);
2004
+ }
2005
+ SCSS
2006
+ end
2007
+
2008
+ def test_function_map_splat_with_unknown_keyword
2009
+ assert_raise_message(Sass::SyntaxError, "Function foo doesn't have an argument named $c.") {render <<SCSS}
2010
+ @function foo($a, $b) {
2011
+ @return "a: \#{$a}, b: \#{$b}";
2012
+ }
2013
+
2014
+ .foo {
2015
+ val: foo(1, 2, (c: 1)...);
2016
+ }
2017
+ SCSS
2018
+ end
2019
+
2020
+ def test_function_map_splat_with_wrong_type
2021
+ assert_raise_message(Sass::SyntaxError, "Variable keyword arguments must be a map (was 12).") {render <<SCSS}
2022
+ @function foo($a, $b) {
2023
+ @return "a: \#{$a}, b: \#{$b}";
2024
+ }
2025
+
2026
+ .foo {
2027
+ val: foo((1, 2)..., 12...);
2028
+ }
2029
+ SCSS
2030
+ end
2031
+
2032
+ def test_function_keyword_splat_must_have_string_keys
2033
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
2034
+ Variable keyword argument map must have string keys.
2035
+ 12 is not a string in (12: 1).
2036
+ MESSAGE
2037
+ @function foo($a) {
2038
+ @return $a;
2039
+ }
2040
+
2041
+ .foo {val: foo((12: 1)...)}
2042
+ SCSS
2043
+ end
2044
+
2045
+ def test_function_splat_too_many_args
2046
+ assert_warning(<<WARNING) {render <<SCSS}
2047
+ WARNING: Function foo takes 2 arguments but 4 were passed.
2048
+ on line 2 of #{filename_for_test(:scss)}
2049
+ This will be an error in future versions of Sass.
2050
+ WARNING
2051
+ @function foo($a, $b) {@return null}
2052
+ $var: foo((1, 2, 3, 4)...);
2053
+ SCSS
2054
+ end
2055
+
2056
+ ## Interpolation
2057
+
2058
+ def test_basic_selector_interpolation
2059
+ assert_equal <<CSS, render(<<SCSS)
2060
+ foo ab baz {
2061
+ a: b; }
2062
+ CSS
2063
+ foo \#{'a' + 'b'} baz {a: b}
2064
+ SCSS
2065
+ assert_equal <<CSS, render(<<SCSS)
2066
+ foo.bar baz {
2067
+ a: b; }
2068
+ CSS
2069
+ foo\#{".bar"} baz {a: b}
2070
+ SCSS
2071
+ assert_equal <<CSS, render(<<SCSS)
2072
+ foo.bar baz {
2073
+ a: b; }
2074
+ CSS
2075
+ \#{"foo"}.bar baz {a: b}
2076
+ SCSS
2077
+ end
2078
+
2079
+ def test_selector_only_interpolation
2080
+ assert_equal <<CSS, render(<<SCSS)
2081
+ foo bar {
2082
+ a: b; }
2083
+ CSS
2084
+ \#{"foo" + " bar"} {a: b}
2085
+ SCSS
2086
+ end
2087
+
2088
+ def test_selector_interpolation_before_element_name
2089
+ assert_equal <<CSS, render(<<SCSS)
2090
+ foo barbaz {
2091
+ a: b; }
2092
+ CSS
2093
+ \#{"foo" + " bar"}baz {a: b}
2094
+ SCSS
2095
+ end
2096
+
2097
+ def test_selector_interpolation_in_string
2098
+ assert_equal <<CSS, render(<<SCSS)
2099
+ foo[val="bar foo bar baz"] {
2100
+ a: b; }
2101
+ CSS
2102
+ foo[val="bar \#{"foo" + " bar"} baz"] {a: b}
2103
+ SCSS
2104
+ end
2105
+
2106
+ def test_selector_interpolation_in_pseudoclass
2107
+ assert_equal <<CSS, render(<<SCSS)
2108
+ foo:nth-child(5n) {
2109
+ a: b; }
2110
+ CSS
2111
+ foo:nth-child(\#{5 + "n"}) {a: b}
2112
+ SCSS
2113
+ end
2114
+
2115
+ def test_selector_interpolation_at_class_begininng
2116
+ assert_equal <<CSS, render(<<SCSS)
2117
+ .zzz {
2118
+ a: b; }
2119
+ CSS
2120
+ $zzz: zzz;
2121
+ .\#{$zzz} { a: b; }
2122
+ SCSS
2123
+ end
2124
+
2125
+ def test_selector_interpolation_at_id_begininng
2126
+ assert_equal <<CSS, render(<<SCSS)
2127
+ #zzz {
2128
+ a: b; }
2129
+ CSS
2130
+ $zzz: zzz;
2131
+ #\#{$zzz} { a: b; }
2132
+ SCSS
2133
+ end
2134
+
2135
+ def test_selector_interpolation_at_pseudo_begininng
2136
+ assert_equal <<CSS, render(<<SCSS)
2137
+ :zzz::zzz {
2138
+ a: b; }
2139
+ CSS
2140
+ $zzz: zzz;
2141
+ :\#{$zzz}::\#{$zzz} { a: b; }
2142
+ SCSS
2143
+ end
2144
+
2145
+ def test_selector_interpolation_at_attr_beginning
2146
+ assert_equal <<CSS, render(<<SCSS)
2147
+ [zzz=foo] {
2148
+ a: b; }
2149
+ CSS
2150
+ $zzz: zzz;
2151
+ [\#{$zzz}=foo] { a: b; }
2152
+ SCSS
2153
+ end
2154
+
2155
+ def test_selector_interpolation_at_attr_end
2156
+ assert_equal <<CSS, render(<<SCSS)
2157
+ [foo=zzz] {
2158
+ a: b; }
2159
+ CSS
2160
+ $zzz: zzz;
2161
+ [foo=\#{$zzz}] { a: b; }
2162
+ SCSS
2163
+ end
2164
+
2165
+ def test_selector_interpolation_at_dashes
2166
+ assert_equal <<CSS, render(<<SCSS)
2167
+ div {
2168
+ -foo-a-b-foo: foo; }
2169
+ CSS
2170
+ $a : a;
2171
+ $b : b;
2172
+ div { -foo-\#{$a}-\#{$b}-foo: foo }
2173
+ SCSS
2174
+ end
2175
+
2176
+ def test_selector_interpolation_in_reference_combinator
2177
+ silence_warnings {assert_equal <<CSS, render(<<SCSS)}
2178
+ .foo /a/ .bar /b|c/ .baz {
2179
+ a: b; }
2180
+ CSS
2181
+ $a: a;
2182
+ $b: b;
2183
+ $c: c;
2184
+ .foo /\#{$a}/ .bar /\#{$b}|\#{$c}/ .baz {a: b}
2185
+ SCSS
2186
+ end
2187
+
2188
+ def test_parent_selector_with_parent_and_subject
2189
+ silence_warnings {assert_equal <<CSS, render(<<SCSS)}
2190
+ bar foo.baz! .bip {
2191
+ c: d; }
2192
+ CSS
2193
+ $subject: "!";
2194
+ foo {
2195
+ bar &.baz\#{$subject} .bip {c: d}}
2196
+ SCSS
2197
+ end
2198
+
2199
+ def test_basic_prop_name_interpolation
2200
+ assert_equal <<CSS, render(<<SCSS)
2201
+ foo {
2202
+ barbazbang: blip; }
2203
+ CSS
2204
+ foo {bar\#{"baz" + "bang"}: blip}
2205
+ SCSS
2206
+ assert_equal <<CSS, render(<<SCSS)
2207
+ foo {
2208
+ bar3: blip; }
2209
+ CSS
2210
+ foo {bar\#{1 + 2}: blip}
2211
+ SCSS
2212
+ end
2213
+
2214
+ def test_prop_name_only_interpolation
2215
+ assert_equal <<CSS, render(<<SCSS)
2216
+ foo {
2217
+ bazbang: blip; }
2218
+ CSS
2219
+ foo {\#{"baz" + "bang"}: blip}
2220
+ SCSS
2221
+ end
2222
+
2223
+ def test_directive_interpolation
2224
+ assert_equal <<CSS, render(<<SCSS)
2225
+ @foo bar12 qux {
2226
+ a: b; }
2227
+ CSS
2228
+ $baz: 12;
2229
+ @foo bar\#{$baz} qux {a: b}
2230
+ SCSS
2231
+ end
2232
+
2233
+ def test_media_interpolation
2234
+ assert_equal <<CSS, render(<<SCSS)
2235
+ @media bar12 {
2236
+ a: b; }
2237
+ CSS
2238
+ $baz: 12;
2239
+ @media bar\#{$baz} {a: b}
2240
+ SCSS
2241
+ end
2242
+
2243
+ def test_script_in_media
2244
+ assert_equal <<CSS, render(<<SCSS)
2245
+ @media screen and (-webkit-min-device-pixel-ratio: 20), only print {
2246
+ a: b; }
2247
+ CSS
2248
+ $media1: screen;
2249
+ $media2: print;
2250
+ $var: -webkit-min-device-pixel-ratio;
2251
+ $val: 20;
2252
+ @media \#{$media1} and ($var: $val), only \#{$media2} {a: b}
2253
+ SCSS
2254
+
2255
+ assert_equal <<CSS, render(<<SCSS)
2256
+ @media screen and (-webkit-min-device-pixel-ratio: 13) {
2257
+ a: b; }
2258
+ CSS
2259
+ $vals: 1 2 3;
2260
+ @media screen and (-webkit-min-device-pixel-ratio: 5 + 6 + nth($vals, 2)) {a: b}
2261
+ SCSS
2262
+ end
2263
+
2264
+ def test_media_interpolation_with_reparse
2265
+ assert_equal <<CSS, render(<<SCSS)
2266
+ @media screen and (max-width: 300px) {
2267
+ a: b; }
2268
+ @media screen and (max-width: 300px) {
2269
+ a: b; }
2270
+ @media screen and (max-width: 300px) {
2271
+ a: b; }
2272
+ @media screen and (max-width: 300px), print and (max-width: 300px) {
2273
+ a: b; }
2274
+ CSS
2275
+ $constraint: "(max-width: 300px)";
2276
+ $fragment: "nd \#{$constraint}";
2277
+ $comma: "een, pri";
2278
+ @media screen and \#{$constraint} {a: b}
2279
+ @media screen {
2280
+ @media \#{$constraint} {a: b}
2281
+ }
2282
+ @media screen a\#{$fragment} {a: b}
2283
+ @media scr\#{$comma}nt {
2284
+ @media \#{$constraint} {a: b}
2285
+ }
2286
+ SCSS
2287
+ end
2288
+
2289
+ def test_moz_document_interpolation
2290
+ assert_equal <<CSS, render(<<SCSS)
2291
+ @-moz-document url(http://sass-lang.com/),
2292
+ url-prefix(http://sass-lang.com/docs),
2293
+ domain(sass-lang.com),
2294
+ domain("sass-lang.com") {
2295
+ .foo {
2296
+ a: b; } }
2297
+ CSS
2298
+ $domain: "sass-lang.com";
2299
+ @-moz-document url(http://\#{$domain}/),
2300
+ url-prefix(http://\#{$domain}/docs),
2301
+ domain(\#{$domain}),
2302
+ \#{domain($domain)} {
2303
+ .foo {a: b}
2304
+ }
2305
+ SCSS
2306
+ end
2307
+
2308
+ def test_supports_with_expressions
2309
+ assert_equal <<CSS, render(<<SCSS)
2310
+ @supports ((feature1: val) and (feature2: val)) or (not (feature23: val4)) {
2311
+ foo {
2312
+ a: b; } }
2313
+ CSS
2314
+ $query: "(feature1: val)";
2315
+ $feature: feature2;
2316
+ $val: val;
2317
+ @supports (\#{$query} and ($feature: $val)) or (not ($feature + 3: $val + 4)) {
2318
+ foo {a: b}
2319
+ }
2320
+ SCSS
2321
+ end
2322
+
2323
+ def test_supports_bubbling
2324
+ assert_equal <<CSS, render(<<SCSS)
2325
+ @supports (foo: bar) {
2326
+ a {
2327
+ b: c; }
2328
+ @supports (baz: bang) {
2329
+ a {
2330
+ d: e; } } }
2331
+ CSS
2332
+ a {
2333
+ @supports (foo: bar) {
2334
+ b: c;
2335
+ @supports (baz: bang) {
2336
+ d: e;
2337
+ }
2338
+ }
2339
+ }
2340
+ SCSS
2341
+ end
2342
+
2343
+ def test_random_directive_interpolation
2344
+ assert_equal <<CSS, render(<<SCSS)
2345
+ @foo url(http://sass-lang.com/),
2346
+ domain("sass-lang.com"),
2347
+ "foobarbaz",
2348
+ foobarbaz {
2349
+ .foo {
2350
+ a: b; } }
2351
+ CSS
2352
+ $domain: "sass-lang.com";
2353
+ @foo url(http://\#{$domain}/),
2354
+ \#{domain($domain)},
2355
+ "foo\#{'ba' + 'r'}baz",
2356
+ foo\#{'ba' + 'r'}baz {
2357
+ .foo {a: b}
2358
+ }
2359
+ SCSS
2360
+ end
2361
+
2362
+ def test_color_interpolation_warning_in_selector
2363
+ assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
2364
+ WARNING on line 1, column 4 of #{filename_for_test(:scss)}:
2365
+ You probably don't mean to use the color value `blue' in interpolation here.
2366
+ It may end up represented as #0000ff, which will likely produce invalid CSS.
2367
+ Always quote color names when using them as strings (for example, "blue").
2368
+ If you really want to use the color value here, use `"" + blue'.
2369
+ WARNING
2370
+ fooblue {
2371
+ a: b; }
2372
+ CSS
2373
+ foo\#{blue} {a: b}
2374
+ SCSS
2375
+ end
2376
+
2377
+ def test_color_interpolation_warning_in_directive
2378
+ assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
2379
+ WARNING on line 1, column 12 of #{filename_for_test(:scss)}:
2380
+ You probably don't mean to use the color value `blue' in interpolation here.
2381
+ It may end up represented as #0000ff, which will likely produce invalid CSS.
2382
+ Always quote color names when using them as strings (for example, "blue").
2383
+ If you really want to use the color value here, use `"" + blue'.
2384
+ WARNING
2385
+ @fblthp fooblue {
2386
+ a: b; }
2387
+ CSS
2388
+ @fblthp foo\#{blue} {a: b}
2389
+ SCSS
2390
+ end
2391
+
2392
+ def test_color_interpolation_warning_in_property_name
2393
+ assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
2394
+ WARNING on line 1, column 8 of #{filename_for_test(:scss)}:
2395
+ You probably don't mean to use the color value `blue' in interpolation here.
2396
+ It may end up represented as #0000ff, which will likely produce invalid CSS.
2397
+ Always quote color names when using them as strings (for example, "blue").
2398
+ If you really want to use the color value here, use `"" + blue'.
2399
+ WARNING
2400
+ foo {
2401
+ a-blue: b; }
2402
+ CSS
2403
+ foo {a-\#{blue}: b}
2404
+ SCSS
2405
+ end
2406
+
2407
+ def test_no_color_interpolation_warning_in_property_value
2408
+ assert_no_warning {assert_equal <<CSS, render(<<SCSS)}
2409
+ foo {
2410
+ a: b-blue; }
2411
+ CSS
2412
+ foo {a: b-\#{blue}}
2413
+ SCSS
2414
+ end
2415
+
2416
+ def test_no_color_interpolation_warning_for_nameless_color
2417
+ assert_no_warning {assert_equal <<CSS, render(<<SCSS)}
2418
+ foo-#abcdef {
2419
+ a: b; }
2420
+ CSS
2421
+ foo-\#{#abcdef} {a: b}
2422
+ SCSS
2423
+ end
2424
+
2425
+ def test_nested_mixin_def
2426
+ assert_equal <<CSS, render(<<SCSS)
2427
+ foo {
2428
+ a: b; }
2429
+ CSS
2430
+ foo {
2431
+ @mixin bar {a: b}
2432
+ @include bar; }
2433
+ SCSS
2434
+ end
2435
+
2436
+ def test_nested_mixin_shadow
2437
+ assert_equal <<CSS, render(<<SCSS)
2438
+ foo {
2439
+ c: d; }
2440
+
2441
+ baz {
2442
+ a: b; }
2443
+ CSS
2444
+ @mixin bar {a: b}
2445
+
2446
+ foo {
2447
+ @mixin bar {c: d}
2448
+ @include bar;
2449
+ }
2450
+
2451
+ baz {@include bar}
2452
+ SCSS
2453
+ end
2454
+
2455
+ def test_nested_function_def
2456
+ assert_equal <<CSS, render(<<SCSS)
2457
+ foo {
2458
+ a: 1; }
2459
+
2460
+ bar {
2461
+ b: foo(); }
2462
+ CSS
2463
+ foo {
2464
+ @function foo() {@return 1}
2465
+ a: foo(); }
2466
+
2467
+ bar {b: foo()}
2468
+ SCSS
2469
+ end
2470
+
2471
+ def test_nested_function_shadow
2472
+ assert_equal <<CSS, render(<<SCSS)
2473
+ foo {
2474
+ a: 2; }
2475
+
2476
+ baz {
2477
+ b: 1; }
2478
+ CSS
2479
+ @function foo() {@return 1}
2480
+
2481
+ foo {
2482
+ @function foo() {@return 2}
2483
+ a: foo();
1118
2484
  }
1119
2485
 
1120
- $list: 3 4 5;
1121
- .foo {val: foo(1, 2, $list...)}
2486
+ baz {b: foo()}
1122
2487
  SCSS
1123
2488
  end
1124
2489
 
1125
- def test_function_var_and_splat_args_pass_through_keywords
2490
+ ## @at-root
2491
+
2492
+ def test_simple_at_root
1126
2493
  assert_equal <<CSS, render(<<SCSS)
2494
+ .bar {
2495
+ a: b; }
2496
+ CSS
1127
2497
  .foo {
1128
- val: "a: 3, b: 1, c: 2"; }
2498
+ @at-root {
2499
+ .bar {a: b}
2500
+ }
2501
+ }
2502
+ SCSS
2503
+ end
2504
+
2505
+ def test_at_root_with_selector
2506
+ assert_equal <<CSS, render(<<SCSS)
2507
+ .bar {
2508
+ a: b; }
1129
2509
  CSS
1130
- @function foo($a...) {
1131
- @return bar($a...);
2510
+ .foo {
2511
+ @at-root .bar {a: b}
1132
2512
  }
2513
+ SCSS
2514
+ end
1133
2515
 
1134
- @function bar($b, $c, $a) {
1135
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
2516
+ def test_at_root_in_mixin
2517
+ assert_equal <<CSS, render(<<SCSS)
2518
+ .bar {
2519
+ a: b; }
2520
+ CSS
2521
+ @mixin bar {
2522
+ @at-root .bar {a: b}
1136
2523
  }
1137
2524
 
1138
- .foo {val: foo(1, $c: 2, $a: 3)}
2525
+ .foo {
2526
+ @include bar;
2527
+ }
1139
2528
  SCSS
1140
2529
  end
1141
2530
 
1142
- def test_function_var_args_with_keyword
1143
- assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") {render <<SCSS}
1144
- @function foo($a, $b...) {
1145
- @return "a: \#{$a}, b: $b";
2531
+ def test_at_root_in_media
2532
+ assert_equal <<CSS, render(<<SCSS)
2533
+ @media screen {
2534
+ .bar {
2535
+ a: b; } }
2536
+ CSS
2537
+ @media screen {
2538
+ .foo {
2539
+ @at-root .bar {a: b}
2540
+ }
1146
2541
  }
2542
+ SCSS
2543
+ end
1147
2544
 
1148
- .foo {val: foo($a: 1, 2, 3, 4)}
2545
+ def test_at_root_in_bubbled_media
2546
+ assert_equal <<CSS, render(<<SCSS)
2547
+ @media screen {
2548
+ .bar {
2549
+ a: b; } }
2550
+ CSS
2551
+ .foo {
2552
+ @media screen {
2553
+ @at-root .bar {a: b}
2554
+ }
2555
+ }
1149
2556
  SCSS
1150
2557
  end
1151
2558
 
1152
- def test_function_keyword_for_var_arg
1153
- assert_raise_message(Sass::SyntaxError, "Argument $b of function foo cannot be used as a named argument.") {render <<SCSS}
1154
- @function foo($a, $b...) {
1155
- @return "a: \#{$a}, b: \#{$b}";
2559
+ def test_at_root_in_unknown_directive
2560
+ assert_equal <<CSS, render(<<SCSS)
2561
+ @fblthp {
2562
+ .bar {
2563
+ a: b; } }
2564
+ CSS
2565
+ @fblthp {
2566
+ .foo {
2567
+ @at-root .bar {a: b}
2568
+ }
1156
2569
  }
2570
+ SCSS
2571
+ end
1157
2572
 
1158
- .foo {val: foo(1, $b: 2 3 4)}
2573
+ def test_comments_in_at_root
2574
+ assert_equal <<CSS, render(<<SCSS)
2575
+ /* foo */
2576
+ .bar {
2577
+ a: b; }
2578
+
2579
+ /* baz */
2580
+ CSS
2581
+ .foo {
2582
+ @at-root {
2583
+ /* foo */
2584
+ .bar {a: b}
2585
+ /* baz */
2586
+ }
2587
+ }
1159
2588
  SCSS
1160
2589
  end
1161
2590
 
1162
- def test_function_keyword_for_unknown_arg_with_var_args
1163
- assert_raise_message(Sass::SyntaxError, "Function foo doesn't have an argument named $c.") {render <<SCSS}
1164
- @function foo($a, $b...) {
1165
- @return "a: \#{$a}, b: \#{$b}";
2591
+ def test_comments_in_at_root_in_media
2592
+ assert_equal <<CSS, render(<<SCSS)
2593
+ @media screen {
2594
+ /* foo */
2595
+ .bar {
2596
+ a: b; }
2597
+
2598
+ /* baz */ }
2599
+ CSS
2600
+ @media screen {
2601
+ .foo {
2602
+ @at-root {
2603
+ /* foo */
2604
+ .bar {a: b}
2605
+ /* baz */
2606
+ }
2607
+ }
1166
2608
  }
2609
+ SCSS
2610
+ end
1167
2611
 
1168
- .foo {val: foo(1, $c: 2 3 4)}
2612
+ def test_comments_in_at_root_in_unknown_directive
2613
+ assert_equal <<CSS, render(<<SCSS)
2614
+ @fblthp {
2615
+ /* foo */
2616
+ .bar {
2617
+ a: b; }
2618
+
2619
+ /* baz */ }
2620
+ CSS
2621
+ @fblthp {
2622
+ .foo {
2623
+ @at-root {
2624
+ /* foo */
2625
+ .bar {a: b}
2626
+ /* baz */
2627
+ }
2628
+ }
2629
+ }
1169
2630
  SCSS
1170
2631
  end
1171
2632
 
1172
- def test_function_var_args_passed_to_native
2633
+ def test_media_directive_in_at_root
1173
2634
  assert_equal <<CSS, render(<<SCSS)
2635
+ @media screen {
2636
+ .bar {
2637
+ a: b; } }
2638
+ CSS
1174
2639
  .foo {
1175
- val: #102035; }
2640
+ @at-root {
2641
+ @media screen {.bar {a: b}}
2642
+ }
2643
+ }
2644
+ SCSS
2645
+ end
2646
+
2647
+ def test_bubbled_media_directive_in_at_root
2648
+ assert_equal <<CSS, render(<<SCSS)
2649
+ @media screen {
2650
+ .bar .baz {
2651
+ a: b; } }
1176
2652
  CSS
1177
- @function foo($args...) {
1178
- @return adjust-color($args...);
2653
+ .foo {
2654
+ @at-root {
2655
+ .bar {
2656
+ @media screen {.baz {a: b}}
2657
+ }
2658
+ }
1179
2659
  }
2660
+ SCSS
2661
+ end
1180
2662
 
1181
- .foo {val: foo(#102030, $blue: 5)}
2663
+ def test_unknown_directive_in_at_root
2664
+ assert_equal <<CSS, render(<<SCSS)
2665
+ @fblthp {
2666
+ .bar {
2667
+ a: b; } }
2668
+ CSS
2669
+ .foo {
2670
+ @at-root {
2671
+ @fblthp {.bar {a: b}}
2672
+ }
2673
+ }
1182
2674
  SCSS
1183
2675
  end
1184
2676
 
1185
- ## Interpolation
2677
+ def test_at_root_in_at_root
2678
+ assert_equal <<CSS, render(<<SCSS)
2679
+ .bar {
2680
+ a: b; }
2681
+ CSS
2682
+ .foo {
2683
+ @at-root {
2684
+ @at-root .bar {a: b}
2685
+ }
2686
+ }
2687
+ SCSS
2688
+ end
1186
2689
 
1187
- def test_basic_selector_interpolation
2690
+ def test_at_root_with_parent_ref
1188
2691
  assert_equal <<CSS, render(<<SCSS)
1189
- foo 3 baz {
2692
+ .foo {
1190
2693
  a: b; }
1191
2694
  CSS
1192
- foo \#{1 + 2} baz {a: b}
2695
+ .foo {
2696
+ @at-root & {
2697
+ a: b;
2698
+ }
2699
+ }
1193
2700
  SCSS
2701
+ end
2702
+
2703
+ def test_multi_level_at_root_with_parent_ref
1194
2704
  assert_equal <<CSS, render(<<SCSS)
1195
- foo.bar baz {
2705
+ .foo .bar {
1196
2706
  a: b; }
1197
2707
  CSS
1198
- foo\#{".bar"} baz {a: b}
2708
+ .foo {
2709
+ @at-root & {
2710
+ .bar {
2711
+ @at-root & {
2712
+ a: b;
2713
+ }
2714
+ }
2715
+ }
2716
+ }
1199
2717
  SCSS
2718
+ end
2719
+
2720
+ def test_multi_level_at_root_with_inner_parent_ref
1200
2721
  assert_equal <<CSS, render(<<SCSS)
1201
- foo.bar baz {
2722
+ .bar {
1202
2723
  a: b; }
1203
2724
  CSS
1204
- \#{"foo"}.bar baz {a: b}
2725
+ .foo {
2726
+ @at-root .bar {
2727
+ @at-root & {
2728
+ a: b;
2729
+ }
2730
+ }
2731
+ }
1205
2732
  SCSS
1206
2733
  end
1207
2734
 
1208
- def test_selector_only_interpolation
2735
+ def test_at_root_beneath_comma_selector
2736
+ assert_equal(<<CSS, render(<<SCSS))
2737
+ .baz {
2738
+ a: b; }
2739
+ CSS
2740
+ .foo, .bar {
2741
+ @at-root .baz {
2742
+ a: b;
2743
+ }
2744
+ }
2745
+ SCSS
2746
+ end
2747
+
2748
+ def test_at_root_with_parent_ref_and_class
2749
+ assert_equal(<<CSS, render(<<SCSS))
2750
+ .foo.bar {
2751
+ a: b; }
2752
+ CSS
2753
+ .foo {
2754
+ @at-root &.bar {
2755
+ a: b;
2756
+ }
2757
+ }
2758
+ SCSS
2759
+ end
2760
+
2761
+ def test_at_root_beneath_comma_selector_with_parent_ref
2762
+ assert_equal(<<CSS, render(<<SCSS))
2763
+ .foo.baz, .bar.baz {
2764
+ a: b; }
2765
+ CSS
2766
+ .foo, .bar {
2767
+ @at-root &.baz {
2768
+ a: b;
2769
+ }
2770
+ }
2771
+ SCSS
2772
+ end
2773
+
2774
+ ## @at-root (...)
2775
+
2776
+ def test_at_root_without_media
1209
2777
  assert_equal <<CSS, render(<<SCSS)
1210
- foo bar {
2778
+ .foo .bar {
1211
2779
  a: b; }
1212
2780
  CSS
1213
- \#{"foo" + " bar"} {a: b}
2781
+ .foo {
2782
+ @media screen {
2783
+ @at-root (without: media) {
2784
+ .bar {
2785
+ a: b;
2786
+ }
2787
+ }
2788
+ }
2789
+ }
1214
2790
  SCSS
1215
2791
  end
1216
2792
 
1217
- def test_selector_interpolation_before_element_name
2793
+ def test_at_root_without_supports
1218
2794
  assert_equal <<CSS, render(<<SCSS)
1219
- foo barbaz {
2795
+ .foo .bar {
1220
2796
  a: b; }
1221
2797
  CSS
1222
- \#{"foo" + " bar"}baz {a: b}
2798
+ .foo {
2799
+ @supports (foo: bar) {
2800
+ @at-root (without: supports) {
2801
+ .bar {
2802
+ a: b;
2803
+ }
2804
+ }
2805
+ }
2806
+ }
1223
2807
  SCSS
1224
2808
  end
1225
2809
 
1226
- def test_selector_interpolation_in_string
2810
+ def test_at_root_without_rule
1227
2811
  assert_equal <<CSS, render(<<SCSS)
1228
- foo[val="bar foo bar baz"] {
2812
+ @media screen {
2813
+ .bar {
2814
+ a: b; } }
2815
+ CSS
2816
+ .foo {
2817
+ @media screen {
2818
+ @at-root (without: rule) {
2819
+ .bar {
2820
+ a: b;
2821
+ }
2822
+ }
2823
+ }
2824
+ }
2825
+ SCSS
2826
+ end
2827
+
2828
+ def test_at_root_without_unknown_directive
2829
+ assert_equal <<CSS, render(<<SCSS)
2830
+ @fblthp {}
2831
+ .foo .bar {
1229
2832
  a: b; }
1230
2833
  CSS
1231
- foo[val="bar \#{"foo" + " bar"} baz"] {a: b}
2834
+ .foo {
2835
+ @fblthp {
2836
+ @at-root (without: fblthp) {
2837
+ .bar {
2838
+ a: b;
2839
+ }
2840
+ }
2841
+ }
2842
+ }
1232
2843
  SCSS
1233
2844
  end
1234
2845
 
1235
- def test_selector_interpolation_in_pseudoclass
2846
+ def test_at_root_without_multiple
1236
2847
  assert_equal <<CSS, render(<<SCSS)
1237
- foo:nth-child(5n) {
2848
+ @supports (foo: bar) {
2849
+ .bar {
2850
+ a: b; } }
2851
+ CSS
2852
+ .foo {
2853
+ @media screen {
2854
+ @supports (foo: bar) {
2855
+ @at-root (without: media rule) {
2856
+ .bar {
2857
+ a: b;
2858
+ }
2859
+ }
2860
+ }
2861
+ }
2862
+ }
2863
+ SCSS
2864
+ end
2865
+
2866
+ def test_at_root_without_all
2867
+ assert_equal <<CSS, render(<<SCSS)
2868
+ @supports (foo: bar) {
2869
+ @fblthp {} }
2870
+ .bar {
1238
2871
  a: b; }
1239
2872
  CSS
1240
- foo:nth-child(\#{5 + "n"}) {a: b}
2873
+ .foo {
2874
+ @supports (foo: bar) {
2875
+ @fblthp {
2876
+ @at-root (without: all) {
2877
+ .bar {
2878
+ a: b;
2879
+ }
2880
+ }
2881
+ }
2882
+ }
2883
+ }
2884
+ SCSS
2885
+ end
2886
+
2887
+ def test_at_root_with_media
2888
+ assert_equal <<CSS, render(<<SCSS)
2889
+ @media screen {
2890
+ @fblthp {}
2891
+ .bar {
2892
+ a: b; } }
2893
+ CSS
2894
+ .foo {
2895
+ @media screen {
2896
+ @fblthp {
2897
+ @supports (foo: bar) {
2898
+ @at-root (with: media) {
2899
+ .bar {
2900
+ a: b;
2901
+ }
2902
+ }
2903
+ }
2904
+ }
2905
+ }
2906
+ }
1241
2907
  SCSS
1242
2908
  end
1243
2909
 
1244
- def test_selector_interpolation_at_class_begininng
2910
+ def test_at_root_with_rule
1245
2911
  assert_equal <<CSS, render(<<SCSS)
1246
- .zzz {
2912
+ @media screen {
2913
+ @fblthp {} }
2914
+ .foo .bar {
1247
2915
  a: b; }
1248
2916
  CSS
1249
- $zzz: zzz;
1250
- .\#{$zzz} { a: b; }
2917
+ .foo {
2918
+ @media screen {
2919
+ @fblthp {
2920
+ @supports (foo: bar) {
2921
+ @at-root (with: rule) {
2922
+ .bar {
2923
+ a: b;
2924
+ }
2925
+ }
2926
+ }
2927
+ }
2928
+ }
2929
+ }
1251
2930
  SCSS
1252
2931
  end
1253
2932
 
1254
- def test_selector_interpolation_at_id_begininng
2933
+ def test_at_root_with_supports
1255
2934
  assert_equal <<CSS, render(<<SCSS)
1256
- #zzz {
1257
- a: b; }
2935
+ @media screen {
2936
+ @fblthp {} }
2937
+ @supports (foo: bar) {
2938
+ .bar {
2939
+ a: b; } }
1258
2940
  CSS
1259
- $zzz: zzz;
1260
- #\#{$zzz} { a: b; }
2941
+ .foo {
2942
+ @media screen {
2943
+ @fblthp {
2944
+ @supports (foo: bar) {
2945
+ @at-root (with: supports) {
2946
+ .bar {
2947
+ a: b;
2948
+ }
2949
+ }
2950
+ }
2951
+ }
2952
+ }
2953
+ }
1261
2954
  SCSS
1262
2955
  end
1263
2956
 
1264
- def test_selector_interpolation_at_pseudo_begininng
2957
+ def test_at_root_with_unknown_directive
1265
2958
  assert_equal <<CSS, render(<<SCSS)
1266
- :zzz::zzz {
1267
- a: b; }
2959
+ @media screen {
2960
+ @fblthp {} }
2961
+ @fblthp {
2962
+ .bar {
2963
+ a: b; } }
1268
2964
  CSS
1269
- $zzz: zzz;
1270
- :\#{$zzz}::\#{$zzz} { a: b; }
2965
+ .foo {
2966
+ @media screen {
2967
+ @fblthp {
2968
+ @supports (foo: bar) {
2969
+ @at-root (with: fblthp) {
2970
+ .bar {
2971
+ a: b;
2972
+ }
2973
+ }
2974
+ }
2975
+ }
2976
+ }
2977
+ }
1271
2978
  SCSS
1272
2979
  end
1273
2980
 
1274
- def test_selector_interpolation_at_attr_beginning
2981
+ def test_at_root_with_multiple
1275
2982
  assert_equal <<CSS, render(<<SCSS)
1276
- [zzz=foo] {
1277
- a: b; }
2983
+ @media screen {
2984
+ @fblthp {}
2985
+ .foo .bar {
2986
+ a: b; } }
1278
2987
  CSS
1279
- $zzz: zzz;
1280
- [\#{$zzz}=foo] { a: b; }
2988
+ .foo {
2989
+ @media screen {
2990
+ @fblthp {
2991
+ @supports (foo: bar) {
2992
+ @at-root (with: media rule) {
2993
+ .bar {
2994
+ a: b;
2995
+ }
2996
+ }
2997
+ }
2998
+ }
2999
+ }
3000
+ }
1281
3001
  SCSS
1282
3002
  end
1283
3003
 
1284
- def test_selector_interpolation_at_attr_end
3004
+ def test_at_root_with_all
1285
3005
  assert_equal <<CSS, render(<<SCSS)
1286
- [foo=zzz] {
1287
- a: b; }
3006
+ @media screen {
3007
+ @fblthp {
3008
+ @supports (foo: bar) {
3009
+ .foo .bar {
3010
+ a: b; } } } }
1288
3011
  CSS
1289
- $zzz: zzz;
1290
- [foo=\#{$zzz}] { a: b; }
3012
+ .foo {
3013
+ @media screen {
3014
+ @fblthp {
3015
+ @supports (foo: bar) {
3016
+ @at-root (with: all) {
3017
+ .bar {
3018
+ a: b;
3019
+ }
3020
+ }
3021
+ }
3022
+ }
3023
+ }
3024
+ }
1291
3025
  SCSS
1292
3026
  end
1293
3027
 
1294
- def test_selector_interpolation_at_dashes
3028
+ def test_at_root_dynamic_values
1295
3029
  assert_equal <<CSS, render(<<SCSS)
1296
- div {
1297
- -foo-a-b-foo: foo; }
3030
+ @media screen {
3031
+ .bar {
3032
+ a: b; } }
1298
3033
  CSS
1299
- $a : a;
1300
- $b : b;
1301
- div { -foo-\#{$a}-\#{$b}-foo: foo }
3034
+ $key: with;
3035
+ $value: media;
3036
+ .foo {
3037
+ @media screen {
3038
+ @at-root ($key: $value) {
3039
+ .bar {
3040
+ a: b;
3041
+ }
3042
+ }
3043
+ }
3044
+ }
1302
3045
  SCSS
1303
3046
  end
1304
3047
 
1305
- def test_selector_interpolation_in_reference_combinator
3048
+ def test_at_root_interpolated_query
1306
3049
  assert_equal <<CSS, render(<<SCSS)
1307
- .foo /a/ .bar /b|c/ .baz {
1308
- a: b; }
3050
+ @media screen {
3051
+ .bar {
3052
+ a: b; } }
1309
3053
  CSS
1310
- $a: a;
1311
- $b: b;
1312
- $c: c;
1313
- .foo /\#{$a}/ .bar /\#{$b}|\#{$c}/ .baz {a: b}
3054
+ .foo {
3055
+ @media screen {
3056
+ @at-root (\#{"with: media"}) {
3057
+ .bar {
3058
+ a: b;
3059
+ }
3060
+ }
3061
+ }
3062
+ }
1314
3063
  SCSS
1315
3064
  end
1316
3065
 
1317
- def test_parent_selector_with_parent_and_subject
3066
+ def test_at_root_plus_extend
1318
3067
  assert_equal <<CSS, render(<<SCSS)
1319
- bar foo.baz! .bip {
1320
- c: d; }
3068
+ .foo .bar {
3069
+ a: b; }
1321
3070
  CSS
1322
- $subject: "!";
1323
- foo {
1324
- bar &.baz\#{$subject} .bip {c: d}}
3071
+ %base {
3072
+ a: b;
3073
+ }
3074
+
3075
+ .foo {
3076
+ @media screen {
3077
+ @at-root (without: media) {
3078
+ .bar {
3079
+ @extend %base;
3080
+ }
3081
+ }
3082
+ }
3083
+ }
1325
3084
  SCSS
1326
3085
  end
1327
3086
 
1328
- def test_basic_prop_name_interpolation
1329
- assert_equal <<CSS, render(<<SCSS)
1330
- foo {
1331
- barbazbang: blip; }
1332
- CSS
1333
- foo {bar\#{"baz" + "bang"}: blip}
1334
- SCSS
3087
+ def test_at_root_without_keyframes_in_keyframe_rule
1335
3088
  assert_equal <<CSS, render(<<SCSS)
1336
- foo {
1337
- bar3: blip; }
3089
+ .foo {
3090
+ a: b; }
1338
3091
  CSS
1339
- foo {bar\#{1 + 2}: blip}
3092
+ @keyframes identifier {
3093
+ 0% {
3094
+ @at-root (without: keyframes) {
3095
+ .foo {a: b}
3096
+ }
3097
+ }
3098
+ }
1340
3099
  SCSS
1341
3100
  end
1342
3101
 
1343
- def test_prop_name_only_interpolation
3102
+ def test_at_root_without_rule_in_keyframe_rule
1344
3103
  assert_equal <<CSS, render(<<SCSS)
1345
- foo {
1346
- bazbang: blip; }
3104
+ @keyframes identifier {
3105
+ 0% {
3106
+ a: b; } }
1347
3107
  CSS
1348
- foo {\#{"baz" + "bang"}: blip}
3108
+ @keyframes identifier {
3109
+ 0% {
3110
+ @at-root (without: rule) {a: b}
3111
+ }
3112
+ }
1349
3113
  SCSS
1350
3114
  end
1351
3115
 
1352
- def test_directive_interpolation
1353
- assert_equal <<CSS, render(<<SCSS)
1354
- @foo bar12 qux {
1355
- a: b; }
3116
+ ## Selector Script
3117
+
3118
+ def test_selector_script
3119
+ assert_equal(<<CSS, render(<<SCSS))
3120
+ .foo .bar {
3121
+ content: ".foo .bar"; }
1356
3122
  CSS
1357
- $baz: 12;
1358
- @foo bar\#{$baz} qux {a: b}
3123
+ .foo .bar {
3124
+ content: "\#{&}";
3125
+ }
1359
3126
  SCSS
1360
3127
  end
1361
3128
 
1362
- def test_media_interpolation
1363
- assert_equal <<CSS, render(<<SCSS)
1364
- @media bar12 {
1365
- a: b; }
3129
+ def test_nested_selector_script
3130
+ assert_equal(<<CSS, render(<<SCSS))
3131
+ .foo .bar {
3132
+ content: ".foo .bar"; }
1366
3133
  CSS
1367
- $baz: 12;
1368
- @media bar\#{$baz} {a: b}
3134
+ .foo {
3135
+ .bar {
3136
+ content: "\#{&}";
3137
+ }
3138
+ }
1369
3139
  SCSS
1370
3140
  end
1371
3141
 
1372
- def test_script_in_media
1373
- assert_equal <<CSS, render(<<SCSS)
1374
- @media screen and (-webkit-min-device-pixel-ratio: 20), only print {
1375
- a: b; }
3142
+ def test_nested_selector_script_with_outer_comma_selector
3143
+ assert_equal(<<CSS, render(<<SCSS))
3144
+ .foo .baz, .bar .baz {
3145
+ content: ".foo .baz, .bar .baz"; }
1376
3146
  CSS
1377
- $media1: screen;
1378
- $media2: print;
1379
- $var: -webkit-min-device-pixel-ratio;
1380
- $val: 20;
1381
- @media \#{$media1} and ($var: $val), only \#{$media2} {a: b}
3147
+ .foo, .bar {
3148
+ .baz {
3149
+ content: "\#{&}";
3150
+ }
3151
+ }
1382
3152
  SCSS
3153
+ end
1383
3154
 
1384
- assert_equal <<CSS, render(<<SCSS)
1385
- @media screen and (-webkit-min-device-pixel-ratio: 13) {
1386
- a: b; }
3155
+ def test_nested_selector_script_with_inner_comma_selector
3156
+ assert_equal(<<CSS, render(<<SCSS))
3157
+ .foo .bar, .foo .baz {
3158
+ content: ".foo .bar, .foo .baz"; }
1387
3159
  CSS
1388
- $vals: 1 2 3;
1389
- @media screen and (-webkit-min-device-pixel-ratio: 5 + 6 + nth($vals, 2)) {a: b}
3160
+ .foo {
3161
+ .bar, .baz {
3162
+ content: "\#{&}";
3163
+ }
3164
+ }
1390
3165
  SCSS
1391
3166
  end
1392
3167
 
1393
- def test_media_interpolation_with_reparse
1394
- assert_equal <<CSS, render(<<SCSS)
1395
- @media screen and (max-width: 300px) {
1396
- a: b; }
1397
- @media screen and (max-width: 300px) {
1398
- a: b; }
1399
- @media screen and (max-width: 300px) {
1400
- a: b; }
1401
- @media screen and (max-width: 300px), print and (max-width: 300px) {
1402
- a: b; }
3168
+ def test_selector_script_through_mixin
3169
+ assert_equal(<<CSS, render(<<SCSS))
3170
+ .foo {
3171
+ content: ".foo"; }
1403
3172
  CSS
1404
- $constraint: "(max-width: 300px)";
1405
- $fragment: "nd \#{$constraint}";
1406
- $comma: "een, pri";
1407
- @media screen and \#{$constraint} {a: b}
1408
- @media screen {
1409
- @media \#{$constraint} {a: b}
3173
+ @mixin mixin {
3174
+ content: "\#{&}";
1410
3175
  }
1411
- @media screen a\#{$fragment} {a: b}
1412
- @media scr\#{$comma}nt {
1413
- @media \#{$constraint} {a: b}
3176
+
3177
+ .foo {
3178
+ @include mixin;
1414
3179
  }
1415
3180
  SCSS
1416
3181
  end
1417
3182
 
1418
- def test_moz_document_interpolation
1419
- assert_equal <<CSS, render(<<SCSS)
1420
- @-moz-document url(http://sass-lang.com/),
1421
- url-prefix(http://sass-lang.com/docs),
1422
- domain(sass-lang.com),
1423
- domain("sass-lang.com") {
1424
- .foo {
1425
- a: b; } }
3183
+ def test_selector_script_through_content
3184
+ assert_equal(<<CSS, render(<<SCSS))
3185
+ .foo {
3186
+ content: ".foo"; }
1426
3187
  CSS
1427
- $domain: "sass-lang.com";
1428
- @-moz-document url(http://\#{$domain}/),
1429
- url-prefix(http://\#{$domain}/docs),
1430
- domain(\#{$domain}),
1431
- \#{domain($domain)} {
1432
- .foo {a: b}
3188
+ @mixin mixin {
3189
+ @content;
3190
+ }
3191
+
3192
+ .foo {
3193
+ @include mixin {
3194
+ content: "\#{&}";
3195
+ }
1433
3196
  }
1434
3197
  SCSS
1435
3198
  end
1436
3199
 
1437
- def test_supports_with_expressions
1438
- assert_equal <<CSS, render(<<SCSS)
1439
- @supports (feature1: val) and (feature2: val) or (not (feature23: val4)) {
1440
- foo {
1441
- a: b; } }
3200
+ def test_selector_script_through_function
3201
+ assert_equal(<<CSS, render(<<SCSS))
3202
+ .foo {
3203
+ content: ".foo"; }
1442
3204
  CSS
1443
- $query: "(feature1: val)";
1444
- $feature: feature2;
1445
- $val: val;
1446
- @supports \#{$query} and ($feature: $val) or (not ($feature + 3: $val + 4)) {
1447
- foo {a: b}
3205
+ @function fn() {
3206
+ @return "\#{&}";
3207
+ }
3208
+
3209
+ .foo {
3210
+ content: fn();
1448
3211
  }
1449
3212
  SCSS
1450
3213
  end
1451
3214
 
1452
- def test_supports_bubbling
1453
- assert_equal <<CSS, render(<<SCSS)
1454
- @supports (foo: bar) {
1455
- a {
1456
- b: c; }
1457
- @supports (baz: bang) {
1458
- a {
1459
- d: e; } } }
3215
+ def test_selector_script_through_media
3216
+ assert_equal(<<CSS, render(<<SCSS))
3217
+ .foo {
3218
+ content: "outer"; }
3219
+ @media screen {
3220
+ .foo .bar {
3221
+ content: ".foo .bar"; } }
1460
3222
  CSS
1461
- a {
1462
- @supports (foo: bar) {
1463
- b: c;
1464
- @supports (baz: bang) {
1465
- d: e;
3223
+ .foo {
3224
+ content: "outer";
3225
+ @media screen {
3226
+ .bar {
3227
+ content: "\#{&}";
1466
3228
  }
1467
3229
  }
1468
3230
  }
1469
3231
  SCSS
1470
3232
  end
1471
3233
 
1472
- def test_random_directive_interpolation
1473
- assert_equal <<CSS, render(<<SCSS)
1474
- @foo url(http://sass-lang.com/),
1475
- domain("sass-lang.com"),
1476
- "foobarbaz",
1477
- foobarbaz {
1478
- .foo {
1479
- a: b; } }
1480
- CSS
1481
- $domain: "sass-lang.com";
1482
- @foo url(http://\#{$domain}/),
1483
- \#{domain($domain)},
1484
- "foo\#{'ba' + 'r'}baz",
1485
- foo\#{'ba' + 'r'}baz {
1486
- .foo {a: b}
3234
+ def test_selector_script_save_and_reuse
3235
+ assert_equal(<<CSS, render(<<SCSS))
3236
+ .bar {
3237
+ content: ".foo"; }
3238
+ CSS
3239
+ $var: null;
3240
+ .foo {
3241
+ $var: & !global;
3242
+ }
3243
+
3244
+ .bar {
3245
+ content: "\#{$var}";
1487
3246
  }
1488
3247
  SCSS
1489
3248
  end
1490
3249
 
1491
- def test_nested_mixin_def
1492
- assert_equal <<CSS, render(<<SCSS)
1493
- foo {
3250
+ def test_selector_script_with_at_root
3251
+ assert_equal(<<CSS, render(<<SCSS))
3252
+ .foo-bar {
1494
3253
  a: b; }
1495
3254
  CSS
1496
- foo {
1497
- @mixin bar {a: b}
1498
- @include bar; }
3255
+ .foo {
3256
+ @at-root \#{&}-bar {
3257
+ a: b;
3258
+ }
3259
+ }
1499
3260
  SCSS
1500
3261
  end
1501
3262
 
1502
- def test_nested_mixin_shadow
3263
+ def test_multi_level_at_root_with_inner_selector_script
1503
3264
  assert_equal <<CSS, render(<<SCSS)
1504
- foo {
1505
- c: d; }
1506
-
1507
- baz {
3265
+ .bar {
1508
3266
  a: b; }
1509
3267
  CSS
1510
- @mixin bar {a: b}
1511
-
1512
- foo {
1513
- @mixin bar {c: d}
1514
- @include bar;
3268
+ .foo {
3269
+ @at-root .bar {
3270
+ @at-root \#{&} {
3271
+ a: b;
3272
+ }
3273
+ }
1515
3274
  }
1516
-
1517
- baz {@include bar}
1518
3275
  SCSS
1519
3276
  end
1520
3277
 
1521
- def test_nested_function_def
1522
- assert_equal <<CSS, render(<<SCSS)
1523
- foo {
1524
- a: 1; }
1525
-
1526
- bar {
1527
- b: foo(); }
3278
+ def test_at_root_with_at_root_through_mixin
3279
+ assert_equal(<<CSS, render(<<SCSS))
3280
+ .bar-baz {
3281
+ a: b; }
1528
3282
  CSS
1529
- foo {
1530
- @function foo() {@return 1}
1531
- a: foo(); }
3283
+ @mixin foo {
3284
+ .bar {
3285
+ @at-root \#{&}-baz {
3286
+ a: b;
3287
+ }
3288
+ }
3289
+ }
1532
3290
 
1533
- bar {b: foo()}
3291
+ @include foo;
1534
3292
  SCSS
1535
3293
  end
1536
3294
 
1537
- def test_nested_function_shadow
3295
+ # See https://github.com/sass/sass/issues/1294
3296
+ def test_extend_top_leveled_by_at_root
3297
+ render(<<SCSS)
3298
+ .span-10 {
3299
+ @at-root (without: all) {
3300
+ @extend %column;
3301
+ }
3302
+ }
3303
+ SCSS
3304
+
3305
+ assert(false, "Expected syntax error")
3306
+ rescue Sass::SyntaxError => e
3307
+ assert_equal "Extend directives may only be used within rules.", e.message
3308
+ assert_equal 3, e.sass_line
3309
+ end
3310
+
3311
+ def test_at_root_doesnt_always_break_blocks
1538
3312
  assert_equal <<CSS, render(<<SCSS)
1539
- foo {
1540
- a: 2; }
3313
+ .foo {
3314
+ a: b; }
1541
3315
 
1542
- baz {
1543
- b: 1; }
3316
+ @media screen {
3317
+ .foo {
3318
+ c: d; }
3319
+ .bar {
3320
+ e: f; } }
1544
3321
  CSS
1545
- @function foo() {@return 1}
1546
-
1547
- foo {
1548
- @function foo() {@return 2}
1549
- a: foo();
3322
+ %base {
3323
+ a: b;
1550
3324
  }
1551
3325
 
1552
- baz {b: foo()}
3326
+ @media screen {
3327
+ .foo {
3328
+ c: d;
3329
+ @at-root (without: media) {
3330
+ @extend %base;
3331
+ }
3332
+ }
3333
+
3334
+ .bar {e: f}
3335
+ }
1553
3336
  SCSS
1554
3337
  end
1555
3338
 
1556
3339
  ## Errors
1557
3340
 
3341
+ def test_keyframes_rule_outside_of_keyframes
3342
+ render <<SCSS
3343
+ 0% {
3344
+ top: 0; }
3345
+ SCSS
3346
+ assert(false, "Expected syntax error")
3347
+ rescue Sass::SyntaxError => e
3348
+ assert_equal 'Invalid CSS after "": expected selector, was "0%"', e.message
3349
+ assert_equal 1, e.sass_line
3350
+ end
3351
+
3352
+ def test_selector_rule_in_keyframes
3353
+ render <<SCSS
3354
+ @keyframes identifier {
3355
+ .foo {
3356
+ top: 0; } }
3357
+ SCSS
3358
+ assert(false, "Expected syntax error")
3359
+ rescue Sass::SyntaxError => e
3360
+ assert_equal 'Invalid CSS after "": expected keyframes selector (e.g. 10%), was ".foo"', e.message
3361
+ assert_equal 2, e.sass_line
3362
+ end
3363
+
1558
3364
  def test_nested_mixin_def_is_scoped
1559
3365
  render <<SCSS
1560
3366
  foo {
@@ -1609,7 +3415,7 @@ foo {
1609
3415
  SCSS
1610
3416
  assert(false, "Expected syntax error")
1611
3417
  rescue Sass::SyntaxError => e
1612
- assert_equal 'Invalid CSS after " .bar:baz ": expected "{", was "<fail>; }"', e.message
3418
+ assert_equal 'Invalid CSS after " .bar:baz <fail>": expected expression (e.g. 1px, bold), was "; }"', e.message
1613
3419
  assert_equal 2, e.sass_line
1614
3420
  end
1615
3421
 
@@ -1719,7 +3525,7 @@ SCSS
1719
3525
 
1720
3526
  def test_parent_in_mid_selector_error
1721
3527
  assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
1722
- Invalid CSS after " .foo": expected "{", was "&.bar {a: b}"
3528
+ Invalid CSS after ".foo": expected "{", was "&.bar"
1723
3529
 
1724
3530
  "&.bar" may only be used at the beginning of a compound selector.
1725
3531
  MESSAGE
@@ -1731,7 +3537,7 @@ SCSS
1731
3537
 
1732
3538
  def test_parent_after_selector_error
1733
3539
  assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
1734
- Invalid CSS after " .foo.bar": expected "{", was "& {a: b}"
3540
+ Invalid CSS after ".foo.bar": expected "{", was "&"
1735
3541
 
1736
3542
  "&" may only be used at the beginning of a compound selector.
1737
3543
  MESSAGE
@@ -1743,7 +3549,7 @@ SCSS
1743
3549
 
1744
3550
  def test_double_parent_selector_error
1745
3551
  assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
1746
- Invalid CSS after " &": expected "{", was "& {a: b}"
3552
+ Invalid CSS after "&": expected "{", was "&"
1747
3553
 
1748
3554
  "&" may only be used at the beginning of a compound selector.
1749
3555
  MESSAGE
@@ -1761,8 +3567,226 @@ MESSAGE
1761
3567
  SCSS
1762
3568
  end
1763
3569
 
3570
+ def test_failed_parent_selector_with_suffix
3571
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3572
+ Invalid parent selector for "&-bar": "*"
3573
+ MESSAGE
3574
+ * {
3575
+ &-bar {a: b}
3576
+ }
3577
+ SCSS
3578
+
3579
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3580
+ Invalid parent selector for "&-bar": "[foo=bar]"
3581
+ MESSAGE
3582
+ [foo=bar] {
3583
+ &-bar {a: b}
3584
+ }
3585
+ SCSS
3586
+
3587
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3588
+ Invalid parent selector for "&-bar": "::nth-child(2n+1)"
3589
+ MESSAGE
3590
+ ::nth-child(2n+1) {
3591
+ &-bar {a: b}
3592
+ }
3593
+ SCSS
3594
+
3595
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3596
+ Invalid parent selector for "&-bar": ":not(.foo)"
3597
+ MESSAGE
3598
+ :not(.foo) {
3599
+ &-bar {a: b}
3600
+ }
3601
+ SCSS
3602
+
3603
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3604
+ Invalid parent selector for "&-bar": ".foo +"
3605
+ MESSAGE
3606
+ .foo + {
3607
+ &-bar {a: b}
3608
+ }
3609
+ SCSS
3610
+ end
3611
+
3612
+ def test_empty_media_query_error
3613
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3614
+ Invalid CSS after "": expected media query list, was ""
3615
+ MESSAGE
3616
+ @media \#{""} {
3617
+ foo {a: b}
3618
+ }
3619
+ SCSS
3620
+ end
3621
+
3622
+ def test_newline_in_property_value
3623
+ assert_equal(<<CSS, render(<<SCSS))
3624
+ .foo {
3625
+ bar: "bazbang"; }
3626
+ CSS
3627
+ .foo {
3628
+ $var: "baz\\
3629
+ bang";
3630
+ bar: $var;
3631
+ }
3632
+ SCSS
3633
+ end
3634
+
3635
+ def test_raw_newline_warning
3636
+ assert_warning(<<MESSAGE.rstrip) {assert_equal(<<CSS, render(<<SCSS))}
3637
+ DEPRECATION WARNING on line 2, column 9 of #{filename_for_test :scss}:
3638
+ Unescaped multiline strings are deprecated and will be removed in a future version of Sass.
3639
+ To include a newline in a string, use "\\a" or "\\a " as in CSS.
3640
+ MESSAGE
3641
+ .foo {
3642
+ bar: "baz\\a bang"; }
3643
+ CSS
3644
+ .foo {
3645
+ $var: "baz
3646
+ bang";
3647
+ bar: $var;
3648
+ }
3649
+ SCSS
3650
+ end
3651
+
1764
3652
  # Regression
1765
-
3653
+
3654
+ # Regression test for #2031.
3655
+ def test_no_interpolation_warning_in_nested_selector
3656
+ assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
3657
+ z a:b(n+1) {
3658
+ x: y; }
3659
+ CSS
3660
+ z {
3661
+ a:b(n+\#{1}) {
3662
+ x: y;
3663
+ }
3664
+ }
3665
+ SCSS
3666
+ end
3667
+
3668
+ # Ensures that the fix for #2031 doesn't hide legitimate warnings.
3669
+ def test_interpolation_warning_in_selector_like_property
3670
+ assert_warning(<<WARNING) {assert_equal(<<CSS, render(<<SCSS))}
3671
+ DEPRECATION WARNING on line 2 of #{filename_for_test :scss}:
3672
+ \#{} interpolation near operators will be simplified in a future version of Sass.
3673
+ To preserve the current behavior, use quotes:
3674
+
3675
+ unquote("n+1")
3676
+
3677
+ You can use the sass-convert command to automatically fix most cases.
3678
+ WARNING
3679
+ z {
3680
+ a: b(n+1); }
3681
+ CSS
3682
+ z {
3683
+ a:b(n+\#{1});
3684
+ }
3685
+ SCSS
3686
+ end
3687
+
3688
+ def test_escape_in_selector
3689
+ assert_equal(<<CSS, render(".\\!foo {a: b}"))
3690
+ .\\!foo {
3691
+ a: b; }
3692
+ CSS
3693
+ end
3694
+
3695
+ def test_for_directive_with_float_bounds
3696
+ assert_equal(<<CSS, render(<<SCSS))
3697
+ .a {
3698
+ b: 0;
3699
+ b: 1;
3700
+ b: 2;
3701
+ b: 3;
3702
+ b: 4;
3703
+ b: 5; }
3704
+ CSS
3705
+ .a {
3706
+ @for $i from 0.0 through 5.0 {b: $i}
3707
+ }
3708
+ SCSS
3709
+
3710
+ assert_raise_message(Sass::SyntaxError, "0.5 is not an integer.") {render(<<SCSS)}
3711
+ .a {
3712
+ @for $i from 0.5 through 5.0 {b: $i}
3713
+ }
3714
+ SCSS
3715
+
3716
+ assert_raise_message(Sass::SyntaxError, "5.5 is not an integer.") {render(<<SCSS)}
3717
+ .a {
3718
+ @for $i from 0.0 through 5.5 {b: $i}
3719
+ }
3720
+ SCSS
3721
+ end
3722
+
3723
+ def test_parent_selector_in_function_pseudo_selector
3724
+ assert_equal <<CSS, render(<<SCSS)
3725
+ .bar:not(.foo) {
3726
+ a: b; }
3727
+
3728
+ .qux:nth-child(2n of .baz .bang) {
3729
+ c: d; }
3730
+ CSS
3731
+ .foo {
3732
+ .bar:not(&) {a: b}
3733
+ }
3734
+
3735
+ .baz .bang {
3736
+ .qux:nth-child(2n of &) {c: d}
3737
+ }
3738
+ SCSS
3739
+ end
3740
+
3741
+ def test_parent_selector_in_and_out_of_function_pseudo_selector
3742
+ # Regression test for https://github.com/sass/sass/issues/1464#issuecomment-70352288
3743
+ assert_equal(<<CSS, render(<<SCSS))
3744
+ .a:not(.a-b) {
3745
+ x: y; }
3746
+ CSS
3747
+ .a {
3748
+ &:not(&-b) {
3749
+ x: y;
3750
+ }
3751
+ }
3752
+ SCSS
3753
+
3754
+ assert_equal(<<CSS, render(<<SCSS))
3755
+ .a:nth-child(2n of .a-b) {
3756
+ x: y; }
3757
+ CSS
3758
+ .a {
3759
+ &:nth-child(2n of &-b) {
3760
+ x: y;
3761
+ }
3762
+ }
3763
+ SCSS
3764
+ end
3765
+
3766
+ def test_attribute_selector_in_selector_pseudoclass
3767
+ # Even though this is plain CSS, it only failed when given to the SCSS
3768
+ # parser.
3769
+ assert_equal(<<CSS, render(<<SCSS))
3770
+ [href^='http://'] {
3771
+ color: red; }
3772
+ CSS
3773
+ [href^='http://'] {
3774
+ color: red;
3775
+ }
3776
+ SCSS
3777
+ end
3778
+
3779
+ def test_top_level_unknown_directive_in_at_root
3780
+ assert_equal(<<CSS, render(<<SCSS))
3781
+ @fblthp {
3782
+ a: b; }
3783
+ CSS
3784
+ @at-root {
3785
+ @fblthp {a: b}
3786
+ }
3787
+ SCSS
3788
+ end
3789
+
1766
3790
  def test_parent_ref_with_newline
1767
3791
  assert_equal(<<CSS, render(<<SCSS))
1768
3792
  a.c
@@ -1774,6 +3798,24 @@ a
1774
3798
  SCSS
1775
3799
  end
1776
3800
 
3801
+ def test_parent_ref_in_nested_at_root
3802
+ assert_equal(<<CSS, render(<<SCSS))
3803
+ #test {
3804
+ border: 0; }
3805
+ #test:hover {
3806
+ display: none; }
3807
+ CSS
3808
+ a {
3809
+ @at-root #test {
3810
+ border: 0;
3811
+ &:hover{
3812
+ display: none;
3813
+ }
3814
+ }
3815
+ }
3816
+ SCSS
3817
+ end
3818
+
1777
3819
  def test_loud_comment_in_compressed_mode
1778
3820
  assert_equal(<<CSS, render(<<SCSS))
1779
3821
  /*! foo */
@@ -1818,7 +3860,19 @@ SCSS
1818
3860
  end
1819
3861
 
1820
3862
  def test_reference_combinator_with_parent_ref
1821
- assert_equal <<CSS, render(<<SCSS)
3863
+ silence_warnings {assert_equal <<CSS, render(<<SCSS)}
3864
+ a /foo/ b {
3865
+ c: d; }
3866
+ CSS
3867
+ a {& /foo/ b {c: d}}
3868
+ SCSS
3869
+ end
3870
+
3871
+ def test_reference_combinator_warning
3872
+ assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
3873
+ DEPRECATION WARNING on line 1, column 8 of test_reference_combinator_warning_inline.scss:
3874
+ The reference combinator /foo/ is deprecated and will be removed in a future release.
3875
+ WARNING
1822
3876
  a /foo/ b {
1823
3877
  c: d; }
1824
3878
  CSS
@@ -1928,6 +3982,22 @@ CSS
1928
3982
  SCSS
1929
3983
  end
1930
3984
 
3985
+ def test_keyword_arg_scope
3986
+ assert_equal <<CSS, render(<<SCSS)
3987
+ .mixed {
3988
+ arg1: default;
3989
+ arg2: non-default; }
3990
+ CSS
3991
+ $arg1: default;
3992
+ $arg2: default;
3993
+ @mixin a-mixin($arg1: $arg1, $arg2: $arg2) {
3994
+ arg1: $arg1;
3995
+ arg2: $arg2;
3996
+ }
3997
+ .mixed { @include a-mixin($arg2: non-default); }
3998
+ SCSS
3999
+ end
4000
+
1931
4001
  def test_passing_required_args_as_a_keyword_arg
1932
4002
  assert_equal <<CSS, render(<<SCSS)
1933
4003
  .mixed {
@@ -2067,10 +4137,10 @@ SCSS
2067
4137
  }
2068
4138
  .aaa .aaa .aaa {
2069
4139
  background-color: black;
2070
- }
4140
+ }
2071
4141
  .bbb {
2072
4142
  @extend .aaa;
2073
- }
4143
+ }
2074
4144
  .xxx {
2075
4145
  @extend .bbb;
2076
4146
  }
@@ -2081,7 +4151,7 @@ SCSS
2081
4151
  @extend .bbb;
2082
4152
  }
2083
4153
  SCSS
2084
- Sass::SCSS::Parser.new(template, "test.scss").parse
4154
+ Sass::SCSS::Parser.new(template, "test.scss", nil).parse
2085
4155
  end
2086
4156
 
2087
4157
  def test_extend_in_media_in_rule
@@ -2103,4 +4173,33 @@ CSS
2103
4173
  }
2104
4174
  SCSS
2105
4175
  end
4176
+
4177
+ def test_import_with_supports_clause_interp
4178
+ assert_equal(<<CSS, render(<<'SASS', :style => :compressed))
4179
+ @import url("fallback-layout.css") supports(not (display: flex))
4180
+ CSS
4181
+ $display-type: flex;
4182
+ @import url("fallback-layout.css") supports(not (display: #{$display-type}));
4183
+ SASS
4184
+ end
4185
+
4186
+ def test_import_with_supports_clause
4187
+ assert_equal(<<CSS, render(<<SASS, :style => :compressed))
4188
+ @import url("fallback-layout.css") supports(not (display: flex));.foo{bar:baz}
4189
+ CSS
4190
+ @import url("fallback-layout.css") supports(not (display: flex));
4191
+ .foo { bar: baz; }
4192
+ SASS
4193
+ end
4194
+
4195
+ def test_crlf
4196
+ # Attempt to reproduce https://github.com/sass/sass/issues/1985
4197
+ assert_equal(<<CSS, render(<<SCSS))
4198
+ p {
4199
+ margin: 0; }
4200
+ CSS
4201
+ p {\r\n margin: 0;\r\n}
4202
+ SCSS
4203
+ end
4204
+
2106
4205
  end