sass 3.5.2 → 3.7.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (163) hide show
  1. checksums.yaml +4 -4
  2. data/CODE_OF_CONDUCT.md +1 -1
  3. data/CONTRIBUTING.md +3 -3
  4. data/README.md +17 -9
  5. data/VERSION +1 -1
  6. data/VERSION_DATE +1 -1
  7. data/extra/sass-spec-ref.sh +9 -1
  8. data/lib/sass/engine.rb +1 -9
  9. data/lib/sass/exec/base.rb +0 -2
  10. data/lib/sass/exec/sass_scss.rb +1 -5
  11. data/lib/sass/importers/filesystem.rb +4 -2
  12. data/lib/sass/logger/base.rb +11 -0
  13. data/lib/sass/script/css_parser.rb +4 -1
  14. data/lib/sass/script/functions.rb +76 -41
  15. data/lib/sass/script/lexer.rb +62 -19
  16. data/lib/sass/script/parser.rb +260 -93
  17. data/lib/sass/script/tree/funcall.rb +0 -4
  18. data/lib/sass/script/tree/interpolation.rb +0 -3
  19. data/lib/sass/script/tree/operation.rb +1 -1
  20. data/lib/sass/script/value/color.rb +3 -2
  21. data/lib/sass/script/value/helpers.rb +8 -2
  22. data/lib/sass/script/value/number.rb +2 -1
  23. data/lib/sass/scss/css_parser.rb +6 -1
  24. data/lib/sass/scss/parser.rb +48 -18
  25. data/lib/sass/scss/rx.rb +1 -1
  26. data/lib/sass/scss/static_parser.rb +15 -18
  27. data/lib/sass/selector/comma_sequence.rb +2 -1
  28. data/lib/sass/selector/pseudo.rb +1 -1
  29. data/lib/sass/selector/sequence.rb +0 -4
  30. data/lib/sass/source/map.rb +0 -4
  31. data/lib/sass/tree/rule_node.rb +3 -6
  32. data/lib/sass/tree/visitors/perform.rb +2 -6
  33. data/lib/sass/tree/visitors/to_css.rb +4 -11
  34. data/lib/sass/util.rb +60 -20
  35. data/lib/sass/version.rb +0 -2
  36. metadata +38 -162
  37. data/Rakefile +0 -338
  38. data/lib/test.css +0 -4
  39. data/lib/test.css.map +0 -7
  40. data/test/sass-spec.yml +0 -3
  41. data/test/sass/cache_test.rb +0 -130
  42. data/test/sass/callbacks_test.rb +0 -60
  43. data/test/sass/compiler_test.rb +0 -225
  44. data/test/sass/conversion_test.rb +0 -2138
  45. data/test/sass/css2sass_test.rb +0 -523
  46. data/test/sass/css_variable_test.rb +0 -237
  47. data/test/sass/data/hsl-rgb.txt +0 -319
  48. data/test/sass/encoding_test.rb +0 -188
  49. data/test/sass/engine_test.rb +0 -3499
  50. data/test/sass/exec_test.rb +0 -95
  51. data/test/sass/extend_test.rb +0 -1678
  52. data/test/sass/fixtures/test_staleness_check_across_importers.css +0 -1
  53. data/test/sass/fixtures/test_staleness_check_across_importers.scss +0 -1
  54. data/test/sass/functions_test.rb +0 -2021
  55. data/test/sass/importer_test.rb +0 -420
  56. data/test/sass/logger_test.rb +0 -57
  57. data/test/sass/mock_importer.rb +0 -49
  58. data/test/sass/more_results/more1.css +0 -9
  59. data/test/sass/more_results/more1_with_line_comments.css +0 -26
  60. data/test/sass/more_results/more_import.css +0 -29
  61. data/test/sass/more_templates/_more_partial.sass +0 -2
  62. data/test/sass/more_templates/more1.sass +0 -23
  63. data/test/sass/more_templates/more_import.sass +0 -11
  64. data/test/sass/plugin_test.rb +0 -552
  65. data/test/sass/results/alt.css +0 -4
  66. data/test/sass/results/basic.css +0 -9
  67. data/test/sass/results/cached_import_option.css +0 -3
  68. data/test/sass/results/compact.css +0 -5
  69. data/test/sass/results/complex.css +0 -86
  70. data/test/sass/results/compressed.css +0 -1
  71. data/test/sass/results/expanded.css +0 -19
  72. data/test/sass/results/filename_fn.css +0 -3
  73. data/test/sass/results/if.css +0 -3
  74. data/test/sass/results/import.css +0 -31
  75. data/test/sass/results/import_charset.css +0 -5
  76. data/test/sass/results/import_charset_ibm866.css +0 -5
  77. data/test/sass/results/import_content.css +0 -1
  78. data/test/sass/results/line_numbers.css +0 -49
  79. data/test/sass/results/mixins.css +0 -95
  80. data/test/sass/results/multiline.css +0 -24
  81. data/test/sass/results/nested.css +0 -22
  82. data/test/sass/results/options.css +0 -1
  83. data/test/sass/results/parent_ref.css +0 -13
  84. data/test/sass/results/script.css +0 -16
  85. data/test/sass/results/scss_import.css +0 -31
  86. data/test/sass/results/scss_importee.css +0 -2
  87. data/test/sass/results/subdir/nested_subdir/nested_subdir.css +0 -1
  88. data/test/sass/results/subdir/subdir.css +0 -3
  89. data/test/sass/results/units.css +0 -11
  90. data/test/sass/results/warn.css +0 -0
  91. data/test/sass/results/warn_imported.css +0 -0
  92. data/test/sass/script_conversion_test.rb +0 -365
  93. data/test/sass/script_test.rb +0 -1429
  94. data/test/sass/scss/css_test.rb +0 -1266
  95. data/test/sass/scss/rx_test.rb +0 -159
  96. data/test/sass/scss/scss_test.rb +0 -4238
  97. data/test/sass/scss/test_helper.rb +0 -37
  98. data/test/sass/source_map_test.rb +0 -1052
  99. data/test/sass/superselector_test.rb +0 -209
  100. data/test/sass/templates/_cached_import_option_partial.scss +0 -1
  101. data/test/sass/templates/_double_import_loop2.sass +0 -1
  102. data/test/sass/templates/_filename_fn_import.scss +0 -11
  103. data/test/sass/templates/_imported_charset_ibm866.sass +0 -4
  104. data/test/sass/templates/_imported_charset_utf8.sass +0 -4
  105. data/test/sass/templates/_imported_content.sass +0 -3
  106. data/test/sass/templates/_partial.sass +0 -2
  107. data/test/sass/templates/_same_name_different_partiality.scss +0 -1
  108. data/test/sass/templates/alt.sass +0 -16
  109. data/test/sass/templates/basic.sass +0 -23
  110. data/test/sass/templates/bork1.sass +0 -2
  111. data/test/sass/templates/bork2.sass +0 -2
  112. data/test/sass/templates/bork3.sass +0 -2
  113. data/test/sass/templates/bork4.sass +0 -2
  114. data/test/sass/templates/bork5.sass +0 -3
  115. data/test/sass/templates/cached_import_option.scss +0 -3
  116. data/test/sass/templates/compact.sass +0 -17
  117. data/test/sass/templates/complex.sass +0 -305
  118. data/test/sass/templates/compressed.sass +0 -15
  119. data/test/sass/templates/double_import_loop1.sass +0 -1
  120. data/test/sass/templates/expanded.sass +0 -17
  121. data/test/sass/templates/filename_fn.scss +0 -18
  122. data/test/sass/templates/if.sass +0 -11
  123. data/test/sass/templates/import.sass +0 -12
  124. data/test/sass/templates/import_charset.sass +0 -9
  125. data/test/sass/templates/import_charset_ibm866.sass +0 -11
  126. data/test/sass/templates/import_content.sass +0 -4
  127. data/test/sass/templates/importee.less +0 -2
  128. data/test/sass/templates/importee.sass +0 -19
  129. data/test/sass/templates/line_numbers.sass +0 -13
  130. data/test/sass/templates/mixin_bork.sass +0 -5
  131. data/test/sass/templates/mixins.sass +0 -76
  132. data/test/sass/templates/multiline.sass +0 -20
  133. data/test/sass/templates/nested.sass +0 -25
  134. data/test/sass/templates/nested_bork1.sass +0 -2
  135. data/test/sass/templates/nested_bork2.sass +0 -2
  136. data/test/sass/templates/nested_bork3.sass +0 -2
  137. data/test/sass/templates/nested_bork4.sass +0 -2
  138. data/test/sass/templates/nested_import.sass +0 -2
  139. data/test/sass/templates/nested_mixin_bork.sass +0 -6
  140. data/test/sass/templates/options.sass +0 -2
  141. data/test/sass/templates/parent_ref.sass +0 -25
  142. data/test/sass/templates/same_name_different_ext.sass +0 -2
  143. data/test/sass/templates/same_name_different_ext.scss +0 -1
  144. data/test/sass/templates/same_name_different_partiality.scss +0 -1
  145. data/test/sass/templates/script.sass +0 -101
  146. data/test/sass/templates/scss_import.scss +0 -12
  147. data/test/sass/templates/scss_importee.scss +0 -1
  148. data/test/sass/templates/single_import_loop.sass +0 -1
  149. data/test/sass/templates/subdir/import_up1.scss +0 -1
  150. data/test/sass/templates/subdir/import_up2.scss +0 -1
  151. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +0 -2
  152. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +0 -3
  153. data/test/sass/templates/subdir/subdir.sass +0 -6
  154. data/test/sass/templates/units.sass +0 -11
  155. data/test/sass/templates/warn.sass +0 -3
  156. data/test/sass/templates/warn_imported.sass +0 -4
  157. data/test/sass/test_helper.rb +0 -8
  158. data/test/sass/util/multibyte_string_scanner_test.rb +0 -152
  159. data/test/sass/util/normalized_map_test.rb +0 -50
  160. data/test/sass/util/subset_map_test.rb +0 -90
  161. data/test/sass/util_test.rb +0 -403
  162. data/test/sass/value_helpers_test.rb +0 -178
  163. data/test/test_helper.rb +0 -149
@@ -1,159 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require File.dirname(__FILE__) + '/../../test_helper'
3
- require 'sass/engine'
4
-
5
- class ScssRxTest < MiniTest::Test
6
- include Sass::SCSS::RX
7
-
8
- def test_identifiers
9
- assert_match IDENT, "foo"
10
- assert_match IDENT, "\xC3\xBFoo" # Initial char can be nonascii
11
- assert_match IDENT, "\\123abcoo" # Initial char can be unicode escape
12
- assert_match IDENT, "\\f oo" # Unicode escapes can be followed by whitespace
13
- assert_match IDENT, "\\fa\too"
14
- assert_match IDENT, "\\ff2\roo"
15
- assert_match IDENT, "\\f13a\foo"
16
- assert_match IDENT, "\\f13abcoo"
17
- assert_match IDENT, "\\ oo" # Initial char can be a plain escape as well
18
- assert_match IDENT, "\\~oo"
19
- assert_match IDENT, "\\\\oo"
20
- assert_match IDENT, "\\{oo"
21
- assert_match IDENT, "\\\xC3\xBFoo"
22
- assert_match IDENT, "-foo" # Can put a - before anything
23
- assert_match IDENT, "-\xC3\xBFoo"
24
- assert_match IDENT, "-\\f oo"
25
- assert_match IDENT, "_foo" # Can put a _ before anything
26
- assert_match IDENT, "_\xC3\xBFoo"
27
- assert_match IDENT, "_\\f oo"
28
- assert_match IDENT, "--foo" # "Custom" identifier
29
-
30
- assert_match IDENT, "foo-bar"
31
- assert_match IDENT, "f012-23"
32
- assert_match IDENT, "foo_-_bar"
33
- assert_match IDENT, "f012_23"
34
-
35
- # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-003.xht
36
- assert_match IDENT, "c\\lass"
37
- # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-004.xht
38
- assert_match IDENT, "c\\00006Cas\\000073"
39
- # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-001.xht
40
- assert_match IDENT, "IdE6n-3t0_6"
41
- # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-006.xht
42
- assert_match IDENT, "\\6000ident"
43
- # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-007.xht
44
- assert_match IDENT, "iden\\6000t\\6000"
45
- # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/ident-013.xht
46
- assert_match IDENT, "\\-ident"
47
- end
48
-
49
- def test_underscores_in_identifiers
50
- assert_match IDENT, "foo_bar"
51
- assert_match IDENT, "_\xC3\xBFfoo"
52
- assert_match IDENT, "__foo"
53
- assert_match IDENT, "_1foo"
54
- assert_match IDENT, "-_foo"
55
- assert_match IDENT, "_-foo"
56
- end
57
-
58
- def test_invalid_identifiers
59
- assert_no_match IDENT, ""
60
- assert_no_match IDENT, "1foo"
61
- assert_no_match IDENT, "-1foo"
62
- assert_no_match IDENT, "foo bar"
63
- assert_no_match IDENT, "foo~bar"
64
-
65
- # http://www.w3.org/Style/CSS/Test/CSS2.1/current/xhtml1/escapes-008.xht
66
- assert_no_match IDENT, "c\\06C ass"
67
- assert_no_match IDENT, "back\\67\n round"
68
- end
69
-
70
- def test_double_quote_strings
71
- assert_match STRING, '"foo bar"'
72
- assert_match STRING, '"foo\\\nbar"'
73
- assert_match STRING, "\"\\\"\""
74
- assert_match STRING, '"\t !#$%&(-~()*+,-./0123456789~"'
75
- end
76
-
77
- def test_single_quote_strings
78
- assert_match STRING, "'foo bar'"
79
- assert_match STRING, "'foo\\\nbar'"
80
- assert_match STRING, "'\\''"
81
- assert_match STRING, "'\t !#\$%&(-~()*+,-./0123456789~'"
82
- end
83
-
84
- def test_invalid_strings
85
- assert_no_match STRING, "\"foo\nbar\""
86
- assert_no_match STRING, "\"foo\"bar\""
87
- assert_no_match STRING, "'foo\nbar'"
88
- assert_no_match STRING, "'foo'bar'"
89
- end
90
-
91
- def test_uri
92
- assert_match URI, 'url("foo bar)")'
93
- assert_match URI, "url('foo bar)')"
94
- assert_match URI, 'url( "foo bar)" )'
95
- assert_match URI, "url(#\\%&**+,-./0123456789~)"
96
- end
97
-
98
- def test_invalid_uri
99
- assert_no_match URI, 'url(foo)bar)'
100
- end
101
-
102
- def test_unicode_range
103
- assert_match UNICODERANGE, 'U+00-Ff'
104
- assert_match UNICODERANGE, 'u+980-9FF'
105
- assert_match UNICODERANGE, 'U+9aF??'
106
- assert_match UNICODERANGE, 'U+??'
107
- end
108
-
109
- def test_escape_empty_ident
110
- assert_equal "", Sass::SCSS::RX.escape_ident("")
111
- end
112
-
113
- def test_escape_just_prefix_ident
114
- assert_equal "\\-", Sass::SCSS::RX.escape_ident("-")
115
- assert_equal "\\_", Sass::SCSS::RX.escape_ident("_")
116
- end
117
-
118
- def test_escape_plain_ident
119
- assert_equal "foo", Sass::SCSS::RX.escape_ident("foo")
120
- assert_equal "foo-1bar", Sass::SCSS::RX.escape_ident("foo-1bar")
121
- assert_equal "-foo-bar", Sass::SCSS::RX.escape_ident("-foo-bar")
122
- assert_equal "f2oo_bar", Sass::SCSS::RX.escape_ident("f2oo_bar")
123
- assert_equal "_foo_bar", Sass::SCSS::RX.escape_ident("_foo_bar")
124
- end
125
-
126
- def test_escape_initial_funky_ident
127
- assert_equal "\\000035foo", Sass::SCSS::RX.escape_ident("5foo")
128
- assert_equal "-\\000035foo", Sass::SCSS::RX.escape_ident("-5foo")
129
- assert_equal "_\\000035foo", Sass::SCSS::RX.escape_ident("_5foo")
130
-
131
- assert_equal "\\&foo", Sass::SCSS::RX.escape_ident("&foo")
132
- assert_equal "-\\&foo", Sass::SCSS::RX.escape_ident("-&foo")
133
-
134
- assert_equal "-\\ foo", Sass::SCSS::RX.escape_ident("- foo")
135
- end
136
-
137
- def test_escape_mid_funky_ident
138
- assert_equal "foo\\&bar", Sass::SCSS::RX.escape_ident("foo&bar")
139
- assert_equal "foo\\ \\ bar", Sass::SCSS::RX.escape_ident("foo bar")
140
- assert_equal "foo\\00007fbar", Sass::SCSS::RX.escape_ident("foo\177bar")
141
- end
142
-
143
- def test_no_static_hyphenated_units
144
- assert_no_match STATIC_VALUE, "20px-20px"
145
- end
146
-
147
- private
148
-
149
- def assert_match(rx, str)
150
- refute_nil(match = rx.match(str))
151
- assert_equal str.size, match[0].size
152
- end
153
-
154
- def assert_no_match(rx, str)
155
- match = rx.match(str)
156
- refute_equal str.size, match && match[0].size
157
- end
158
-
159
- end
@@ -1,4238 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require File.dirname(__FILE__) + '/test_helper'
3
-
4
- class ScssTest < MiniTest::Test
5
- include ScssTestHelper
6
-
7
- ## One-Line Comments
8
-
9
- def test_one_line_comments
10
- assert_equal <<CSS, render(<<SCSS)
11
- .foo {
12
- baz: bang; }
13
- CSS
14
- .foo {// bar: baz;}
15
- baz: bang; //}
16
- }
17
- SCSS
18
- assert_equal <<CSS, render(<<SCSS)
19
- .foo bar[val="//"] {
20
- baz: bang; }
21
- CSS
22
- .foo bar[val="//"] {
23
- baz: bang; //}
24
- }
25
- SCSS
26
- end
27
-
28
- ## Script
29
-
30
- def test_variables
31
- assert_equal <<CSS, render(<<SCSS)
32
- blat {
33
- a: foo; }
34
- CSS
35
- $var: foo;
36
-
37
- blat {a: $var}
38
- SCSS
39
-
40
- assert_equal <<CSS, render(<<SCSS)
41
- foo {
42
- a: 2;
43
- b: 6; }
44
- CSS
45
- foo {
46
- $var: 2;
47
- $another-var: 4;
48
- a: $var;
49
- b: $var + $another-var;}
50
- SCSS
51
- end
52
-
53
- def test_unicode_variables
54
- assert_equal <<CSS, render(<<SCSS)
55
- blat {
56
- a: foo; }
57
- CSS
58
- $vär: foo;
59
-
60
- blat {a: $vär}
61
- SCSS
62
- end
63
-
64
- def test_guard_assign
65
- assert_equal <<CSS, render(<<SCSS)
66
- foo {
67
- a: 1; }
68
- CSS
69
- $var: 1;
70
- $var: 2 !default;
71
-
72
- foo {a: $var}
73
- SCSS
74
-
75
- assert_equal <<CSS, render(<<SCSS)
76
- foo {
77
- a: 2; }
78
- CSS
79
- $var: 2 !default;
80
-
81
- foo {a: $var}
82
- SCSS
83
- end
84
-
85
- def test_sass_script
86
- assert_equal <<CSS, render(<<SCSS)
87
- foo {
88
- a: 3;
89
- b: -1;
90
- c: foobar;
91
- d: 12px; }
92
- CSS
93
- foo {
94
- a: 1 + 2;
95
- b: 1 - 2;
96
- c: foo + bar;
97
- d: floor(12.3px); }
98
- SCSS
99
- end
100
-
101
- def test_debug_directive
102
- assert_warning "test_debug_directive_inline.scss:2 DEBUG: hello world!" do
103
- assert_equal <<CSS, render(<<SCSS)
104
- foo {
105
- a: b; }
106
-
107
- bar {
108
- c: d; }
109
- CSS
110
- foo {a: b}
111
- @debug "hello world!";
112
- bar {c: d}
113
- SCSS
114
- end
115
- end
116
-
117
- def test_error_directive
118
- assert_raise_message(Sass::SyntaxError, "hello world!") {render(<<SCSS)}
119
- foo {a: b}
120
- @error "hello world!";
121
- bar {c: d}
122
- SCSS
123
- end
124
-
125
- def test_warn_directive
126
- expected_warning = <<EXPECTATION
127
- WARNING: this is a warning
128
- on line 2 of test_warn_directive_inline.scss
129
-
130
- WARNING: this is a mixin
131
- on line 1 of test_warn_directive_inline.scss, in `foo'
132
- from line 3 of test_warn_directive_inline.scss
133
- EXPECTATION
134
- assert_warning expected_warning do
135
- assert_equal <<CSS, render(<<SCSS)
136
- bar {
137
- c: d; }
138
- CSS
139
- @mixin foo { @warn "this is a mixin";}
140
- @warn "this is a warning";
141
- bar {c: d; @include foo;}
142
- SCSS
143
- end
144
- end
145
-
146
- def test_for_directive
147
- assert_equal <<CSS, render(<<SCSS)
148
- .foo {
149
- a: 1;
150
- a: 2;
151
- a: 3;
152
- a: 4; }
153
- CSS
154
- .foo {
155
- @for $var from 1 to 5 {a: $var;}
156
- }
157
- SCSS
158
-
159
- assert_equal <<CSS, render(<<SCSS)
160
- .foo {
161
- a: 1;
162
- a: 2;
163
- a: 3;
164
- a: 4;
165
- a: 5; }
166
- CSS
167
- .foo {
168
- @for $var from 1 through 5 {a: $var;}
169
- }
170
- SCSS
171
- end
172
-
173
- def test_for_directive_with_same_start_and_end
174
- assert_equal <<CSS, render(<<SCSS)
175
- CSS
176
- .foo {
177
- @for $var from 1 to 1 {a: $var;}
178
- }
179
- SCSS
180
-
181
- assert_equal <<CSS, render(<<SCSS)
182
- .foo {
183
- a: 1; }
184
- CSS
185
- .foo {
186
- @for $var from 1 through 1 {a: $var;}
187
- }
188
- SCSS
189
- end
190
-
191
- def test_decrementing_estfor_directive
192
- assert_equal <<CSS, render(<<SCSS)
193
- .foo {
194
- a: 5;
195
- a: 4;
196
- a: 3;
197
- a: 2;
198
- a: 1; }
199
- CSS
200
- .foo {
201
- @for $var from 5 through 1 {a: $var;}
202
- }
203
- SCSS
204
-
205
- assert_equal <<CSS, render(<<SCSS)
206
- .foo {
207
- a: 5;
208
- a: 4;
209
- a: 3;
210
- a: 2; }
211
- CSS
212
- .foo {
213
- @for $var from 5 to 1 {a: $var;}
214
- }
215
- SCSS
216
- end
217
-
218
- def test_if_directive
219
- assert_equal <<CSS, render(<<SCSS)
220
- foo {
221
- a: b; }
222
- CSS
223
- @if "foo" == "foo" {foo {a: b}}
224
- @if "foo" != "foo" {bar {a: b}}
225
- SCSS
226
-
227
- assert_equal <<CSS, render(<<SCSS)
228
- bar {
229
- a: b; }
230
- CSS
231
- @if "foo" != "foo" {foo {a: b}}
232
- @else if "foo" == "foo" {bar {a: b}}
233
- @else if true {baz {a: b}}
234
- SCSS
235
-
236
- assert_equal <<CSS, render(<<SCSS)
237
- bar {
238
- a: b; }
239
- CSS
240
- @if "foo" != "foo" {foo {a: b}}
241
- @else {bar {a: b}}
242
- SCSS
243
- end
244
-
245
- def test_comment_after_if_directive
246
- assert_equal <<CSS, render(<<SCSS)
247
- foo {
248
- a: b;
249
- /* This is a comment */
250
- c: d; }
251
- CSS
252
- foo {
253
- @if true {a: b}
254
- /* This is a comment */
255
- c: d }
256
- SCSS
257
- assert_equal <<CSS, render(<<SCSS)
258
- foo {
259
- a: b;
260
- /* This is a comment */
261
- c: d; }
262
- CSS
263
- foo {
264
- @if true {a: b}
265
- @else {x: y}
266
- /* This is a comment */
267
- c: d }
268
- SCSS
269
- end
270
-
271
- def test_while_directive
272
- assert_equal <<CSS, render(<<SCSS)
273
- .foo {
274
- a: 1;
275
- a: 2;
276
- a: 3;
277
- a: 4; }
278
- CSS
279
- $i: 1;
280
-
281
- .foo {
282
- @while $i != 5 {
283
- a: $i;
284
- $i: $i + 1 !global;
285
- }
286
- }
287
- SCSS
288
- end
289
-
290
- def test_each_directive
291
- assert_equal <<CSS, render(<<SCSS)
292
- a {
293
- b: 1px;
294
- b: 2px;
295
- b: 3px;
296
- b: 4px; }
297
-
298
- c {
299
- d: foo;
300
- d: bar;
301
- d: baz;
302
- d: bang; }
303
- CSS
304
- a {
305
- @each $number in 1px 2px 3px 4px {
306
- b: $number;
307
- }
308
- }
309
- c {
310
- @each $str in foo, bar, baz, bang {
311
- d: $str;
312
- }
313
- }
314
- SCSS
315
- end
316
-
317
- def test_destructuring_each_directive
318
- assert_equal <<CSS, render(<<SCSS)
319
- a {
320
- foo: 1px;
321
- bar: 2px;
322
- baz: 3px; }
323
-
324
- c {
325
- foo: "Value is bar";
326
- bar: "Value is baz";
327
- bang: "Value is "; }
328
- CSS
329
- a {
330
- @each $name, $number in (foo: 1px, bar: 2px, baz: 3px) {
331
- \#{$name}: $number;
332
- }
333
- }
334
- c {
335
- @each $key, $value in (foo bar) (bar, baz) bang {
336
- \#{$key}: "Value is \#{$value}";
337
- }
338
- }
339
- SCSS
340
- end
341
-
342
- def test_css_import_directive
343
- assert_equal "@import url(foo.css);\n", render('@import "foo.css";')
344
- assert_equal "@import url(foo.css);\n", render("@import 'foo.css';")
345
- assert_equal "@import url(\"foo.css\");\n", render('@import url("foo.css");')
346
- assert_equal "@import url(\"foo.css\");\n", render('@import url("foo.css");')
347
- assert_equal "@import url(foo.css);\n", render('@import url(foo.css);')
348
- end
349
-
350
- def test_css_string_import_directive_with_media
351
- assert_parses '@import "foo.css" screen;'
352
- assert_parses '@import "foo.css" screen, print;'
353
- assert_parses '@import "foo.css" screen, print and (foo: 0);'
354
- assert_parses '@import "foo.css" screen, only print, screen and (foo: 0);'
355
- end
356
-
357
- def test_css_url_import_directive_with_media
358
- assert_parses '@import url("foo.css") screen;'
359
- assert_parses '@import url("foo.css") screen, print;'
360
- assert_parses '@import url("foo.css") screen, print and (foo: 0);'
361
- assert_parses '@import url("foo.css") screen, only print, screen and (foo: 0);'
362
- end
363
-
364
- def test_media_import
365
- assert_equal("@import \"./fonts.sass\" all;\n", render("@import \"./fonts.sass\" all;"))
366
- end
367
-
368
- def test_dynamic_media_import
369
- assert_equal(<<CSS, render(<<SCSS))
370
- @import "foo" print and (-webkit-min-device-pixel-ratio-foo: 25);
371
- CSS
372
- $media: print;
373
- $key: -webkit-min-device-pixel-ratio;
374
- $value: 20;
375
- @import "foo" \#{$media} and ($key + "-foo": $value + 5);
376
- SCSS
377
- end
378
-
379
- def test_http_import
380
- assert_equal("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\";\n",
381
- render("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\";"))
382
- end
383
-
384
- def test_protocol_relative_import
385
- assert_equal("@import \"//fonts.googleapis.com/css?family=Droid+Sans\";\n",
386
- render("@import \"//fonts.googleapis.com/css?family=Droid+Sans\";"))
387
- end
388
-
389
- def test_import_with_interpolation
390
- assert_equal <<CSS, render(<<SCSS)
391
- @import url("http://fonts.googleapis.com/css?family=Droid+Sans");
392
- CSS
393
- $family: unquote("Droid+Sans");
394
- @import url("http://fonts.googleapis.com/css?family=\#{$family}");
395
- SCSS
396
- end
397
-
398
- def test_url_import
399
- assert_equal("@import url(fonts.sass);\n", render("@import url(fonts.sass);"))
400
- end
401
-
402
- def test_css_import_doesnt_move_through_comments
403
- assert_equal <<CSS, render(<<SCSS)
404
- /* Comment 1 */
405
- @import url("foo.css");
406
- /* Comment 2 */
407
- @import url("bar.css");
408
- CSS
409
- /* Comment 1 */
410
- @import url("foo.css");
411
-
412
- /* Comment 2 */
413
- @import url("bar.css");
414
- SCSS
415
- end
416
-
417
- def test_css_import_movement_stops_at_comments
418
- assert_equal <<CSS, render(<<SCSS)
419
- /* Comment 1 */
420
- @import url("foo.css");
421
- /* Comment 2 */
422
- @import url("bar.css");
423
- .foo {
424
- a: b; }
425
-
426
- /* Comment 3 */
427
- CSS
428
- /* Comment 1 */
429
- @import url("foo.css");
430
-
431
- /* Comment 2 */
432
-
433
- .foo {a: b}
434
-
435
- /* Comment 3 */
436
- @import url("bar.css");
437
- SCSS
438
- end
439
-
440
- def test_block_comment_in_script
441
- assert_equal <<CSS, render(<<SCSS)
442
- foo {
443
- a: 1bar; }
444
- CSS
445
- foo {a: 1 + /* flang */ bar}
446
- SCSS
447
- end
448
-
449
- def test_line_comment_in_script
450
- assert_equal <<CSS, render(<<SCSS)
451
- foo {
452
- a: 1blang; }
453
- CSS
454
- foo {a: 1 + // flang }
455
- blang }
456
- SCSS
457
- end
458
-
459
- def test_static_hyphenated_unit
460
- assert_equal <<CSS, render(<<SCSS)
461
- foo {
462
- a: 0px; }
463
- CSS
464
- foo {a: 10px-10px }
465
- SCSS
466
- end
467
-
468
- ## Nested Rules
469
-
470
- def test_nested_rules
471
- assert_equal <<CSS, render(<<SCSS)
472
- foo bar {
473
- a: b; }
474
- CSS
475
- foo {bar {a: b}}
476
- SCSS
477
- assert_equal <<CSS, render(<<SCSS)
478
- foo bar {
479
- a: b; }
480
- foo baz {
481
- b: c; }
482
- CSS
483
- foo {
484
- bar {a: b}
485
- baz {b: c}}
486
- SCSS
487
- assert_equal <<CSS, render(<<SCSS)
488
- foo bar baz {
489
- a: b; }
490
- foo bang bip {
491
- a: b; }
492
- CSS
493
- foo {
494
- bar {baz {a: b}}
495
- bang {bip {a: b}}}
496
- SCSS
497
- end
498
-
499
- def test_nested_rules_with_declarations
500
- assert_equal <<CSS, render(<<SCSS)
501
- foo {
502
- a: b; }
503
- foo bar {
504
- c: d; }
505
- CSS
506
- foo {
507
- a: b;
508
- bar {c: d}}
509
- SCSS
510
- assert_equal <<CSS, render(<<SCSS)
511
- foo {
512
- a: b; }
513
- foo bar {
514
- c: d; }
515
- CSS
516
- foo {
517
- bar {c: d}
518
- a: b}
519
- SCSS
520
- assert_equal <<CSS, render(<<SCSS)
521
- foo {
522
- ump: nump;
523
- grump: clump; }
524
- foo bar {
525
- blat: bang;
526
- habit: rabbit; }
527
- foo bar baz {
528
- a: b; }
529
- foo bar bip {
530
- c: d; }
531
- foo bibble bap {
532
- e: f; }
533
- CSS
534
- foo {
535
- ump: nump;
536
- grump: clump;
537
- bar {
538
- blat: bang;
539
- habit: rabbit;
540
- baz {a: b}
541
- bip {c: d}}
542
- bibble {
543
- bap {e: f}}}
544
- SCSS
545
- end
546
-
547
- def test_nested_rules_with_fancy_selectors
548
- assert_equal <<CSS, render(<<SCSS)
549
- foo .bar {
550
- a: b; }
551
- foo :baz {
552
- c: d; }
553
- foo bang:bop {
554
- e: f; }
555
- foo ::qux {
556
- g: h; }
557
- foo zap::fblthp {
558
- i: j; }
559
- CSS
560
- foo {
561
- .bar {a: b}
562
- :baz {c: d}
563
- bang:bop {e: f}
564
- ::qux {g: h}
565
- zap::fblthp {i: j}}
566
- SCSS
567
- end
568
-
569
- def test_almost_ambiguous_nested_rules_and_declarations
570
- assert_equal <<CSS, render(<<SCSS)
571
- foo {
572
- bar: baz bang bop biddle woo look at all these elems; }
573
- foo bar:baz:bang:bop:biddle:woo:look:at:all:these:pseudoclasses {
574
- a: b; }
575
- foo bar:baz bang bop biddle woo look at all these elems {
576
- a: b; }
577
- CSS
578
- foo {
579
- bar:baz:bang:bop:biddle:woo:look:at:all:these:pseudoclasses {a: b};
580
- bar:baz bang bop biddle woo look at all these elems {a: b};
581
- bar:baz bang bop biddle woo look at all these elems; }
582
- SCSS
583
- end
584
-
585
- def test_newlines_in_selectors
586
- assert_equal <<CSS, render(<<SCSS)
587
- foo
588
- bar {
589
- a: b; }
590
- CSS
591
- foo
592
- bar {a: b}
593
- SCSS
594
-
595
- assert_equal <<CSS, render(<<SCSS)
596
- foo baz,
597
- foo bang,
598
- bar baz,
599
- bar bang {
600
- a: b; }
601
- CSS
602
- foo,
603
- bar {
604
- baz,
605
- bang {a: b}}
606
- SCSS
607
-
608
- assert_equal <<CSS, render(<<SCSS)
609
- foo
610
- bar baz
611
- bang {
612
- a: b; }
613
- foo
614
- bar bip bop {
615
- c: d; }
616
- CSS
617
- foo
618
- bar {
619
- baz
620
- bang {a: b}
621
-
622
- bip bop {c: d}}
623
- SCSS
624
-
625
- assert_equal <<CSS, render(<<SCSS)
626
- foo bang, foo bip
627
- bop, bar
628
- baz bang, bar
629
- baz bip
630
- bop {
631
- a: b; }
632
- CSS
633
- foo, bar
634
- baz {
635
- bang, bip
636
- bop {a: b}}
637
- SCSS
638
- end
639
-
640
- def test_trailing_comma_in_selector
641
- assert_equal <<CSS, render(<<SCSS)
642
- #foo #bar,
643
- #baz #boom {
644
- a: b; }
645
-
646
- #bip #bop {
647
- c: d; }
648
- CSS
649
- #foo #bar,,
650
- ,#baz #boom, {a: b}
651
-
652
- #bip #bop, ,, {c: d}
653
- SCSS
654
- end
655
-
656
- def test_parent_selectors
657
- assert_equal <<CSS, render(<<SCSS)
658
- foo:hover {
659
- a: b; }
660
- bar foo.baz {
661
- c: d; }
662
- CSS
663
- foo {
664
- &:hover {a: b}
665
- bar &.baz {c: d}}
666
- SCSS
667
- end
668
-
669
- def test_parent_selector_with_subject
670
- silence_warnings {assert_equal <<CSS, render(<<SCSS)}
671
- bar foo.baz! .bip {
672
- a: b; }
673
-
674
- bar foo bar.baz! .bip {
675
- c: d; }
676
- CSS
677
- foo {
678
- bar &.baz! .bip {a: b}}
679
-
680
- foo bar {
681
- bar &.baz! .bip {c: d}}
682
- SCSS
683
- end
684
-
685
- def test_parent_selector_with_suffix
686
- assert_equal <<CSS, render(<<SCSS)
687
- .foo-bar {
688
- a: b; }
689
- .foo_bar {
690
- c: d; }
691
- .foobar {
692
- e: f; }
693
- .foo123 {
694
- e: f; }
695
-
696
- :hover-suffix {
697
- g: h; }
698
- CSS
699
- .foo {
700
- &-bar {a: b}
701
- &_bar {c: d}
702
- &bar {e: f}
703
- &123 {e: f}
704
- }
705
-
706
- :hover {
707
- &-suffix {g: h}
708
- }
709
- SCSS
710
- end
711
-
712
- def test_unknown_directive_bubbling
713
- assert_equal(<<CSS, render(<<SCSS, :style => :nested))
714
- @fblthp {
715
- .foo .bar {
716
- a: b; } }
717
- CSS
718
- .foo {
719
- @fblthp {
720
- .bar {a: b}
721
- }
722
- }
723
- SCSS
724
- end
725
-
726
- def test_keyframe_bubbling
727
- assert_equal(<<CSS, render(<<SCSS, :style => :nested))
728
- @keyframes spin {
729
- 0% {
730
- transform: rotate(0deg); } }
731
- @-webkit-keyframes spin {
732
- 0% {
733
- transform: rotate(0deg); } }
734
- CSS
735
- .foo {
736
- @keyframes spin {
737
- 0% {transform: rotate(0deg)}
738
- }
739
- @-webkit-keyframes spin {
740
- 0% {transform: rotate(0deg)}
741
- }
742
- }
743
- SCSS
744
- end
745
-
746
- ## Namespace Properties
747
-
748
- def test_namespace_properties
749
- assert_equal <<CSS, render(<<SCSS)
750
- foo {
751
- bar: baz;
752
- bang-bip: 1px;
753
- bang-bop: bar; }
754
- CSS
755
- foo {
756
- bar: baz;
757
- bang: {
758
- bip: 1px;
759
- bop: bar;}}
760
- SCSS
761
- end
762
-
763
- def test_several_namespace_properties
764
- assert_equal <<CSS, render(<<SCSS)
765
- foo {
766
- bar: baz;
767
- bang-bip: 1px;
768
- bang-bop: bar;
769
- buzz-fram: "foo";
770
- buzz-frum: moo; }
771
- CSS
772
- foo {
773
- bar: baz;
774
- bang: {
775
- bip: 1px;
776
- bop: bar;}
777
- buzz: {
778
- fram: "foo";
779
- frum: moo;
780
- }
781
- }
782
- SCSS
783
- end
784
-
785
- def test_nested_namespace_properties
786
- assert_equal <<CSS, render(<<SCSS)
787
- foo {
788
- bar: baz;
789
- bang-bip: 1px;
790
- bang-bop: bar;
791
- bang-blat-baf: bort; }
792
- CSS
793
- foo {
794
- bar: baz;
795
- bang: {
796
- bip: 1px;
797
- bop: bar;
798
- blat:{baf:bort}}}
799
- SCSS
800
- end
801
-
802
- def test_namespace_properties_with_value
803
- assert_equal <<CSS, render(<<SCSS)
804
- foo {
805
- bar: baz;
806
- bar-bip: bop;
807
- bar-bing: bop; }
808
- CSS
809
- foo {
810
- bar: baz {
811
- bip: bop;
812
- bing: bop; }}
813
- SCSS
814
- end
815
-
816
- def test_namespace_properties_with_script_value
817
- assert_equal <<CSS, render(<<SCSS)
818
- foo {
819
- bar: bazbang;
820
- bar-bip: bop;
821
- bar-bing: bop; }
822
- CSS
823
- foo {
824
- bar: baz + bang {
825
- bip: bop;
826
- bing: bop; }}
827
- SCSS
828
- end
829
-
830
- def test_no_namespace_properties_without_space
831
- assert_equal <<CSS, render(<<SCSS)
832
- foo bar:baz {
833
- bip: bop; }
834
- CSS
835
- foo {
836
- bar:baz {
837
- bip: bop }}
838
- SCSS
839
- end
840
-
841
- def test_no_namespace_properties_without_space_even_when_its_unambiguous
842
- render(<<SCSS)
843
- foo {
844
- bar:baz calc(1 + 2) {
845
- bip: bop }}
846
- SCSS
847
- assert(false, "Expected syntax error")
848
- rescue Sass::SyntaxError => e
849
- assert_equal 'Invalid CSS after "bar:baz calc": expected selector, was "(1 + 2)"', e.message
850
- assert_equal 2, e.sass_line
851
- end
852
-
853
- def test_namespace_properties_without_space_allowed_for_non_identifier
854
- assert_equal <<CSS, render(<<SCSS)
855
- foo {
856
- bar: 1px;
857
- bar-bip: bop; }
858
- CSS
859
- foo {
860
- bar:1px {
861
- bip: bop }}
862
- SCSS
863
- end
864
-
865
- ## Mixins
866
-
867
- def test_basic_mixins
868
- assert_equal <<CSS, render(<<SCSS)
869
- .foo {
870
- a: b; }
871
- CSS
872
- @mixin foo {
873
- .foo {a: b}}
874
-
875
- @include foo;
876
- SCSS
877
-
878
- assert_equal <<CSS, render(<<SCSS)
879
- bar {
880
- c: d; }
881
- bar .foo {
882
- a: b; }
883
- CSS
884
- @mixin foo {
885
- .foo {a: b}}
886
-
887
- bar {
888
- @include foo;
889
- c: d; }
890
- SCSS
891
-
892
- assert_equal <<CSS, render(<<SCSS)
893
- bar {
894
- a: b;
895
- c: d; }
896
- CSS
897
- @mixin foo {a: b}
898
-
899
- bar {
900
- @include foo;
901
- c: d; }
902
- SCSS
903
- end
904
-
905
- def test_mixins_with_empty_args
906
- assert_equal <<CSS, render(<<SCSS)
907
- .foo {
908
- a: b; }
909
- CSS
910
- @mixin foo() {a: b}
911
-
912
- .foo {@include foo();}
913
- SCSS
914
-
915
- assert_equal <<CSS, render(<<SCSS)
916
- .foo {
917
- a: b; }
918
- CSS
919
- @mixin foo() {a: b}
920
-
921
- .foo {@include foo;}
922
- SCSS
923
-
924
- assert_equal <<CSS, render(<<SCSS)
925
- .foo {
926
- a: b; }
927
- CSS
928
- @mixin foo {a: b}
929
-
930
- .foo {@include foo();}
931
- SCSS
932
- end
933
-
934
- def test_mixins_with_args
935
- assert_equal <<CSS, render(<<SCSS)
936
- .foo {
937
- a: bar; }
938
- CSS
939
- @mixin foo($a) {a: $a}
940
-
941
- .foo {@include foo(bar)}
942
- SCSS
943
-
944
- assert_equal <<CSS, render(<<SCSS)
945
- .foo {
946
- a: bar;
947
- b: 12px; }
948
- CSS
949
- @mixin foo($a, $b) {
950
- a: $a;
951
- b: $b; }
952
-
953
- .foo {@include foo(bar, 12px)}
954
- SCSS
955
- end
956
-
957
- def test_keyframes_rules_in_content
958
- assert_equal <<CSS, render(<<SCSS)
959
- @keyframes identifier {
960
- 0% {
961
- top: 0;
962
- left: 0; }
963
- 30% {
964
- top: 50px; }
965
- 68%, 72% {
966
- left: 50px; }
967
- 100% {
968
- top: 100px;
969
- left: 100%; } }
970
- CSS
971
- @mixin keyframes {
972
- @keyframes identifier { @content }
973
- }
974
-
975
- @include keyframes {
976
- 0% {top: 0; left: 0}
977
- \#{"30%"} {top: 50px}
978
- 68%, 72% {left: 50px}
979
- 100% {top: 100px; left: 100%}
980
- }
981
- SCSS
982
- end
983
-
984
- ## Functions
985
-
986
- def test_basic_function
987
- assert_equal(<<CSS, render(<<SASS))
988
- bar {
989
- a: 3; }
990
- CSS
991
- @function foo() {
992
- @return 1 + 2;
993
- }
994
-
995
- bar {
996
- a: foo();
997
- }
998
- SASS
999
- end
1000
-
1001
- def test_function_args
1002
- assert_equal(<<CSS, render(<<SASS))
1003
- bar {
1004
- a: 3; }
1005
- CSS
1006
- @function plus($var1, $var2) {
1007
- @return $var1 + $var2;
1008
- }
1009
-
1010
- bar {
1011
- a: plus(1, 2);
1012
- }
1013
- SASS
1014
- end
1015
-
1016
- def test_disallowed_function_names
1017
- Sass::Deprecation.allow_double_warnings do
1018
- assert_warning(<<WARNING) {render(<<SCSS)}
1019
- DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1020
- Naming a function "calc" is disallowed and will be an error in future versions of Sass.
1021
- This name conflicts with an existing CSS function with special parse rules.
1022
- WARNING
1023
- @function calc() {}
1024
- SCSS
1025
-
1026
- assert_warning(<<WARNING) {render(<<SCSS)}
1027
- DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1028
- Naming a function "-my-calc" is disallowed and will be an error in future versions of Sass.
1029
- This name conflicts with an existing CSS function with special parse rules.
1030
- WARNING
1031
- @function -my-calc() {}
1032
- SCSS
1033
-
1034
- assert_warning(<<WARNING) {render(<<SCSS)}
1035
- DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1036
- Naming a function "element" is disallowed and will be an error in future versions of Sass.
1037
- This name conflicts with an existing CSS function with special parse rules.
1038
- WARNING
1039
- @function element() {}
1040
- SCSS
1041
-
1042
- assert_warning(<<WARNING) {render(<<SCSS)}
1043
- DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1044
- Naming a function "-my-element" is disallowed and will be an error in future versions of Sass.
1045
- This name conflicts with an existing CSS function with special parse rules.
1046
- WARNING
1047
- @function -my-element() {}
1048
- SCSS
1049
-
1050
- assert_warning(<<WARNING) {render(<<SCSS)}
1051
- DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1052
- Naming a function "expression" is disallowed and will be an error in future versions of Sass.
1053
- This name conflicts with an existing CSS function with special parse rules.
1054
- WARNING
1055
- @function expression() {}
1056
- SCSS
1057
-
1058
- assert_warning(<<WARNING) {render(<<SCSS)}
1059
- DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1060
- Naming a function "url" is disallowed and will be an error in future versions of Sass.
1061
- This name conflicts with an existing CSS function with special parse rules.
1062
- WARNING
1063
- @function url() {}
1064
- SCSS
1065
- end
1066
- end
1067
-
1068
- def test_allowed_function_names
1069
- assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
1070
- .a {
1071
- b: c; }
1072
- CSS
1073
- @function -my-expression() {@return c}
1074
-
1075
- .a {b: -my-expression()}
1076
- SCSS
1077
-
1078
- assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
1079
- .a {
1080
- b: c; }
1081
- CSS
1082
- @function -my-url() {@return c}
1083
-
1084
- .a {b: -my-url()}
1085
- SCSS
1086
- end
1087
-
1088
- ## Var Args
1089
-
1090
- def test_mixin_var_args
1091
- assert_equal <<CSS, render(<<SCSS)
1092
- .foo {
1093
- a: 1;
1094
- b: 2, 3, 4; }
1095
- CSS
1096
- @mixin foo($a, $b...) {
1097
- a: $a;
1098
- b: $b;
1099
- }
1100
-
1101
- .foo {@include foo(1, 2, 3, 4)}
1102
- SCSS
1103
- end
1104
-
1105
- def test_mixin_empty_var_args
1106
- assert_equal <<CSS, render(<<SCSS)
1107
- .foo {
1108
- a: 1;
1109
- b: 0; }
1110
- CSS
1111
- @mixin foo($a, $b...) {
1112
- a: $a;
1113
- b: length($b);
1114
- }
1115
-
1116
- .foo {@include foo(1)}
1117
- SCSS
1118
- end
1119
-
1120
- def test_mixin_var_args_act_like_list
1121
- assert_equal <<CSS, render(<<SCSS)
1122
- .foo {
1123
- a: 3;
1124
- b: 3; }
1125
- CSS
1126
- @mixin foo($a, $b...) {
1127
- a: length($b);
1128
- b: nth($b, 2);
1129
- }
1130
-
1131
- .foo {@include foo(1, 2, 3, 4)}
1132
- SCSS
1133
- end
1134
-
1135
- def test_mixin_splat_args
1136
- assert_equal <<CSS, render(<<SCSS)
1137
- .foo {
1138
- a: 1;
1139
- b: 2;
1140
- c: 3;
1141
- d: 4; }
1142
- CSS
1143
- @mixin foo($a, $b, $c, $d) {
1144
- a: $a;
1145
- b: $b;
1146
- c: $c;
1147
- d: $d;
1148
- }
1149
-
1150
- $list: 2, 3, 4;
1151
- .foo {@include foo(1, $list...)}
1152
- SCSS
1153
- end
1154
-
1155
- def test_mixin_splat_expression
1156
- assert_equal <<CSS, render(<<SCSS)
1157
- .foo {
1158
- a: 1;
1159
- b: 2;
1160
- c: 3;
1161
- d: 4; }
1162
- CSS
1163
- @mixin foo($a, $b, $c, $d) {
1164
- a: $a;
1165
- b: $b;
1166
- c: $c;
1167
- d: $d;
1168
- }
1169
-
1170
- .foo {@include foo(1, (2, 3, 4)...)}
1171
- SCSS
1172
- end
1173
-
1174
- def test_mixin_splat_args_with_var_args
1175
- assert_equal <<CSS, render(<<SCSS)
1176
- .foo {
1177
- a: 1;
1178
- b: 2, 3, 4; }
1179
- CSS
1180
- @mixin foo($a, $b...) {
1181
- a: $a;
1182
- b: $b;
1183
- }
1184
-
1185
- $list: 2, 3, 4;
1186
- .foo {@include foo(1, $list...)}
1187
- SCSS
1188
- end
1189
-
1190
- def test_mixin_splat_args_with_var_args_and_normal_args
1191
- assert_equal <<CSS, render(<<SCSS)
1192
- .foo {
1193
- a: 1;
1194
- b: 2;
1195
- c: 3, 4; }
1196
- CSS
1197
- @mixin foo($a, $b, $c...) {
1198
- a: $a;
1199
- b: $b;
1200
- c: $c;
1201
- }
1202
-
1203
- $list: 2, 3, 4;
1204
- .foo {@include foo(1, $list...)}
1205
- SCSS
1206
- end
1207
-
1208
- def test_mixin_splat_args_with_var_args_preserves_separator
1209
- assert_equal <<CSS, render(<<SCSS)
1210
- .foo {
1211
- a: 1;
1212
- b: 2 3 4 5; }
1213
- CSS
1214
- @mixin foo($a, $b...) {
1215
- a: $a;
1216
- b: $b;
1217
- }
1218
-
1219
- $list: 3 4 5;
1220
- .foo {@include foo(1, 2, $list...)}
1221
- SCSS
1222
- end
1223
-
1224
- def test_mixin_var_and_splat_args_pass_through_keywords
1225
- assert_equal <<CSS, render(<<SCSS)
1226
- .foo {
1227
- a: 3;
1228
- b: 1;
1229
- c: 2; }
1230
- CSS
1231
- @mixin foo($a...) {
1232
- @include bar($a...);
1233
- }
1234
-
1235
- @mixin bar($b, $c, $a) {
1236
- a: $a;
1237
- b: $b;
1238
- c: $c;
1239
- }
1240
-
1241
- .foo {@include foo(1, $c: 2, $a: 3)}
1242
- SCSS
1243
- end
1244
-
1245
- def test_mixin_var_keyword_args
1246
- assert_equal <<CSS, render(<<SCSS)
1247
- .foo {
1248
- a: 1;
1249
- b: 2;
1250
- c: 3; }
1251
- CSS
1252
- @mixin foo($args...) {
1253
- a: map-get(keywords($args), a);
1254
- b: map-get(keywords($args), b);
1255
- c: map-get(keywords($args), c);
1256
- }
1257
-
1258
- .foo {@include foo($a: 1, $b: 2, $c: 3)}
1259
- SCSS
1260
- end
1261
-
1262
- def test_mixin_empty_var_keyword_args
1263
- assert_equal <<CSS, render(<<SCSS)
1264
- .foo {
1265
- length: 0; }
1266
- CSS
1267
- @mixin foo($args...) {
1268
- length: length(keywords($args));
1269
- }
1270
-
1271
- .foo {@include foo}
1272
- SCSS
1273
- end
1274
-
1275
- def test_mixin_map_splat
1276
- assert_equal <<CSS, render(<<SCSS)
1277
- .foo {
1278
- a: 1;
1279
- b: 2;
1280
- c: 3; }
1281
- CSS
1282
- @mixin foo($a, $b, $c) {
1283
- a: $a;
1284
- b: $b;
1285
- c: $c;
1286
- }
1287
-
1288
- .foo {
1289
- $map: (a: 1, b: 2, c: 3);
1290
- @include foo($map...);
1291
- }
1292
- SCSS
1293
- end
1294
-
1295
- def test_mixin_map_and_list_splat
1296
- assert_equal <<CSS, render(<<SCSS)
1297
- .foo {
1298
- a: x;
1299
- b: y;
1300
- c: z;
1301
- d: 1;
1302
- e: 2;
1303
- f: 3; }
1304
- CSS
1305
- @mixin foo($a, $b, $c, $d, $e, $f) {
1306
- a: $a;
1307
- b: $b;
1308
- c: $c;
1309
- d: $d;
1310
- e: $e;
1311
- f: $f;
1312
- }
1313
-
1314
- .foo {
1315
- $list: x y z;
1316
- $map: (d: 1, e: 2, f: 3);
1317
- @include foo($list..., $map...);
1318
- }
1319
- SCSS
1320
- end
1321
-
1322
- def test_mixin_map_splat_takes_precedence_over_pass_through
1323
- assert_equal <<CSS, render(<<SCSS)
1324
- .foo {
1325
- a: 1;
1326
- b: 2;
1327
- c: z; }
1328
- CSS
1329
- @mixin foo($args...) {
1330
- $map: (c: z);
1331
- @include bar($args..., $map...);
1332
- }
1333
-
1334
- @mixin bar($a, $b, $c) {
1335
- a: $a;
1336
- b: $b;
1337
- c: $c;
1338
- }
1339
-
1340
- .foo {
1341
- @include foo(1, $b: 2, $c: 3);
1342
- }
1343
- SCSS
1344
- end
1345
-
1346
- def test_mixin_list_of_pairs_splat_treated_as_list
1347
- assert_equal <<CSS, render(<<SCSS)
1348
- .foo {
1349
- a: a 1;
1350
- b: b 2;
1351
- c: c 3; }
1352
- CSS
1353
- @mixin foo($a, $b, $c) {
1354
- a: $a;
1355
- b: $b;
1356
- c: $c;
1357
- }
1358
-
1359
- .foo {
1360
- @include foo((a 1, b 2, c 3)...);
1361
- }
1362
- SCSS
1363
- end
1364
-
1365
- def test_mixin_splat_after_keyword_args
1366
- assert_equal <<CSS, render(<<SCSS)
1367
- .foo {
1368
- a: 1;
1369
- b: 2;
1370
- c: 3; }
1371
- CSS
1372
- @mixin foo($a, $b, $c) {
1373
- a: 1;
1374
- b: 2;
1375
- c: 3;
1376
- }
1377
-
1378
- .foo {
1379
- @include foo(1, $c: 3, 2...);
1380
- }
1381
- SCSS
1382
- end
1383
-
1384
- def test_mixin_keyword_args_after_splat
1385
- assert_equal <<CSS, render(<<SCSS)
1386
- .foo {
1387
- a: 1;
1388
- b: 2;
1389
- c: 3; }
1390
- CSS
1391
- @mixin foo($a, $b, $c) {
1392
- a: 1;
1393
- b: 2;
1394
- c: 3;
1395
- }
1396
-
1397
- .foo {
1398
- @include foo(1, 2..., $c: 3);
1399
- }
1400
- SCSS
1401
- end
1402
-
1403
- def test_mixin_keyword_splat_after_keyword_args
1404
- assert_equal <<CSS, render(<<SCSS)
1405
- .foo {
1406
- a: 1;
1407
- b: 2;
1408
- c: 3; }
1409
- CSS
1410
- @mixin foo($a, $b, $c) {
1411
- a: 1;
1412
- b: 2;
1413
- c: 3;
1414
- }
1415
-
1416
- .foo {
1417
- @include foo(1, $b: 2, (c: 3)...);
1418
- }
1419
- SCSS
1420
- end
1421
-
1422
- def test_mixin_triple_keyword_splat_merge
1423
- assert_equal <<CSS, render(<<SCSS)
1424
- .foo {
1425
- foo: 1;
1426
- bar: 2;
1427
- kwarg: 3;
1428
- a: 3;
1429
- b: 2;
1430
- c: 3; }
1431
- CSS
1432
- @mixin foo($foo, $bar, $kwarg, $a, $b, $c) {
1433
- foo: $foo;
1434
- bar: $bar;
1435
- kwarg: $kwarg;
1436
- a: $a;
1437
- b: $b;
1438
- c: $c;
1439
- }
1440
-
1441
- @mixin bar($args...) {
1442
- @include foo($args..., $bar: 2, $a: 2, $b: 2, (kwarg: 3, a: 3, c: 3)...);
1443
- }
1444
-
1445
- .foo {
1446
- @include bar($foo: 1, $a: 1, $b: 1, $c: 1);
1447
- }
1448
- SCSS
1449
- end
1450
-
1451
- def test_mixin_map_splat_converts_hyphens_and_underscores_for_real_args
1452
- assert_equal <<CSS, render(<<SCSS)
1453
- .foo {
1454
- a: 1;
1455
- b: 2;
1456
- c: 3;
1457
- d: 4; }
1458
- CSS
1459
- @mixin foo($a-1, $b-2, $c_3, $d_4) {
1460
- a: $a-1;
1461
- b: $b-2;
1462
- c: $c_3;
1463
- d: $d_4;
1464
- }
1465
-
1466
- .foo {
1467
- $map: (a-1: 1, b_2: 2, c-3: 3, d_4: 4);
1468
- @include foo($map...);
1469
- }
1470
- SCSS
1471
- end
1472
-
1473
- def test_mixin_map_splat_doesnt_convert_hyphens_and_underscores_for_var_args
1474
- assert_equal <<CSS, render(<<SCSS)
1475
- .foo {
1476
- a-1: 1;
1477
- b_2: 2;
1478
- c-3: 3;
1479
- d_4: 4; }
1480
- CSS
1481
- @mixin foo($args...) {
1482
- @each $key, $value in keywords($args) {
1483
- \#{$key}: $value;
1484
- }
1485
- }
1486
-
1487
- .foo {
1488
- $map: (a-1: 1, b_2: 2, c-3: 3, d_4: 4);
1489
- @include foo($map...);
1490
- }
1491
- SCSS
1492
- end
1493
-
1494
- def test_mixin_conflicting_splat_after_keyword_args
1495
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
1496
- Mixin foo was passed argument $b both by position and by name.
1497
- MESSAGE
1498
- @mixin foo($a, $b, $c) {
1499
- a: 1;
1500
- b: 2;
1501
- c: 3;
1502
- }
1503
-
1504
- .foo {
1505
- @include foo(1, $b: 2, 3...);
1506
- }
1507
- SCSS
1508
- end
1509
-
1510
- def test_mixin_keyword_splat_must_have_string_keys
1511
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
1512
- Variable keyword argument map must have string keys.
1513
- 12 is not a string in (12: 1).
1514
- MESSAGE
1515
- @mixin foo($a) {
1516
- a: $a;
1517
- }
1518
-
1519
- .foo {@include foo((12: 1)...)}
1520
- SCSS
1521
- end
1522
-
1523
- def test_mixin_positional_arg_after_splat
1524
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
1525
- Only keyword arguments may follow variable arguments (...).
1526
- MESSAGE
1527
- @mixin foo($a, $b, $c) {
1528
- a: 1;
1529
- b: 2;
1530
- c: 3;
1531
- }
1532
-
1533
- .foo {
1534
- @include foo(1, 2..., 3);
1535
- }
1536
- SCSS
1537
- end
1538
-
1539
- def test_mixin_var_args_with_keyword
1540
- assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") {render <<SCSS}
1541
- @mixin foo($a, $b...) {
1542
- a: $a;
1543
- b: $b;
1544
- }
1545
-
1546
- .foo {@include foo($a: 1, 2, 3, 4)}
1547
- SCSS
1548
- end
1549
-
1550
- def test_mixin_keyword_for_var_arg
1551
- assert_raise_message(Sass::SyntaxError, "Argument $b of mixin foo cannot be used as a named argument.") {render <<SCSS}
1552
- @mixin foo($a, $b...) {
1553
- a: $a;
1554
- b: $b;
1555
- }
1556
-
1557
- .foo {@include foo(1, $b: 2 3 4)}
1558
- SCSS
1559
- end
1560
-
1561
- def test_mixin_keyword_for_unknown_arg_with_var_args
1562
- assert_raise_message(Sass::SyntaxError, "Mixin foo doesn't have an argument named $c.") {render <<SCSS}
1563
- @mixin foo($a, $b...) {
1564
- a: $a;
1565
- b: $b;
1566
- }
1567
-
1568
- .foo {@include foo(1, $c: 2 3 4)}
1569
- SCSS
1570
- end
1571
-
1572
- def test_mixin_map_splat_before_list_splat
1573
- assert_raise_message(Sass::SyntaxError, "Variable keyword arguments must be a map (was (2 3)).") {render <<SCSS}
1574
- @mixin foo($a, $b, $c) {
1575
- a: $a;
1576
- b: $b;
1577
- c: $c;
1578
- }
1579
-
1580
- .foo {
1581
- @include foo((a: 1)..., (2 3)...);
1582
- }
1583
- SCSS
1584
- end
1585
-
1586
- def test_mixin_map_splat_with_unknown_keyword
1587
- assert_raise_message(Sass::SyntaxError, "Mixin foo doesn't have an argument named $c.") {render <<SCSS}
1588
- @mixin foo($a, $b) {
1589
- a: $a;
1590
- b: $b;
1591
- }
1592
-
1593
- .foo {
1594
- @include foo(1, 2, (c: 1)...);
1595
- }
1596
- SCSS
1597
- end
1598
-
1599
- def test_mixin_map_splat_with_wrong_type
1600
- assert_raise_message(Sass::SyntaxError, "Variable keyword arguments must be a map (was 12).") {render <<SCSS}
1601
- @mixin foo($a, $b) {
1602
- a: $a;
1603
- b: $b;
1604
- }
1605
-
1606
- .foo {
1607
- @include foo((1, 2)..., 12...);
1608
- }
1609
- SCSS
1610
- end
1611
-
1612
- def test_mixin_splat_too_many_args
1613
- assert_warning(<<WARNING) {render <<SCSS}
1614
- WARNING: Mixin foo takes 2 arguments but 4 were passed.
1615
- on line 2 of #{filename_for_test(:scss)}
1616
- This will be an error in future versions of Sass.
1617
- WARNING
1618
- @mixin foo($a, $b) {}
1619
- @include foo((1, 2, 3, 4)...);
1620
- SCSS
1621
- end
1622
-
1623
- def test_function_var_args
1624
- assert_equal <<CSS, render(<<SCSS)
1625
- .foo {
1626
- val: "a: 1, b: 2, 3, 4"; }
1627
- CSS
1628
- @function foo($a, $b...) {
1629
- @return "a: \#{$a}, b: \#{$b}";
1630
- }
1631
-
1632
- .foo {val: foo(1, 2, 3, 4)}
1633
- SCSS
1634
- end
1635
-
1636
- def test_function_empty_var_args
1637
- assert_equal <<CSS, render(<<SCSS)
1638
- .foo {
1639
- val: "a: 1, b: 0"; }
1640
- CSS
1641
- @function foo($a, $b...) {
1642
- @return "a: \#{$a}, b: \#{length($b)}";
1643
- }
1644
-
1645
- .foo {val: foo(1)}
1646
- SCSS
1647
- end
1648
-
1649
- def test_function_var_args_act_like_list
1650
- assert_equal <<CSS, render(<<SCSS)
1651
- .foo {
1652
- val: "a: 3, b: 3"; }
1653
- CSS
1654
- @function foo($a, $b...) {
1655
- @return "a: \#{length($b)}, b: \#{nth($b, 2)}";
1656
- }
1657
-
1658
- .foo {val: foo(1, 2, 3, 4)}
1659
- SCSS
1660
- end
1661
-
1662
- def test_function_splat_args
1663
- assert_equal <<CSS, render(<<SCSS)
1664
- .foo {
1665
- val: "a: 1, b: 2, c: 3, d: 4"; }
1666
- CSS
1667
- @function foo($a, $b, $c, $d) {
1668
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}";
1669
- }
1670
-
1671
- $list: 2, 3, 4;
1672
- .foo {val: foo(1, $list...)}
1673
- SCSS
1674
- end
1675
-
1676
- def test_function_splat_expression
1677
- assert_equal <<CSS, render(<<SCSS)
1678
- .foo {
1679
- val: "a: 1, b: 2, c: 3, d: 4"; }
1680
- CSS
1681
- @function foo($a, $b, $c, $d) {
1682
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}";
1683
- }
1684
-
1685
- .foo {val: foo(1, (2, 3, 4)...)}
1686
- SCSS
1687
- end
1688
-
1689
- def test_function_splat_args_with_var_args
1690
- assert_equal <<CSS, render(<<SCSS)
1691
- .foo {
1692
- val: "a: 1, b: 2, 3, 4"; }
1693
- CSS
1694
- @function foo($a, $b...) {
1695
- @return "a: \#{$a}, b: \#{$b}";
1696
- }
1697
-
1698
- $list: 2, 3, 4;
1699
- .foo {val: foo(1, $list...)}
1700
- SCSS
1701
- end
1702
-
1703
- def test_function_splat_args_with_var_args_and_normal_args
1704
- assert_equal <<CSS, render(<<SCSS)
1705
- .foo {
1706
- val: "a: 1, b: 2, c: 3, 4"; }
1707
- CSS
1708
- @function foo($a, $b, $c...) {
1709
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1710
- }
1711
-
1712
- $list: 2, 3, 4;
1713
- .foo {val: foo(1, $list...)}
1714
- SCSS
1715
- end
1716
-
1717
- def test_function_splat_args_with_var_args_preserves_separator
1718
- assert_equal <<CSS, render(<<SCSS)
1719
- .foo {
1720
- val: "a: 1, b: 2 3 4 5"; }
1721
- CSS
1722
- @function foo($a, $b...) {
1723
- @return "a: \#{$a}, b: \#{$b}";
1724
- }
1725
-
1726
- $list: 3 4 5;
1727
- .foo {val: foo(1, 2, $list...)}
1728
- SCSS
1729
- end
1730
-
1731
- def test_function_var_and_splat_args_pass_through_keywords
1732
- assert_equal <<CSS, render(<<SCSS)
1733
- .foo {
1734
- val: "a: 3, b: 1, c: 2"; }
1735
- CSS
1736
- @function foo($a...) {
1737
- @return bar($a...);
1738
- }
1739
-
1740
- @function bar($b, $c, $a) {
1741
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1742
- }
1743
-
1744
- .foo {val: foo(1, $c: 2, $a: 3)}
1745
- SCSS
1746
- end
1747
-
1748
- def test_function_var_keyword_args
1749
- assert_equal <<CSS, render(<<SCSS)
1750
- .foo {
1751
- val: "a: 1, b: 2, c: 3"; }
1752
- CSS
1753
- @function foo($args...) {
1754
- @return "a: \#{map-get(keywords($args), a)}, " +
1755
- "b: \#{map-get(keywords($args), b)}, " +
1756
- "c: \#{map-get(keywords($args), c)}";
1757
- }
1758
-
1759
- .foo {val: foo($a: 1, $b: 2, $c: 3)}
1760
- SCSS
1761
- end
1762
-
1763
- def test_function_empty_var_keyword_args
1764
- assert_equal <<CSS, render(<<SCSS)
1765
- .foo {
1766
- length: 0; }
1767
- CSS
1768
- @function foo($args...) {
1769
- @return length(keywords($args));
1770
- }
1771
-
1772
- .foo {length: foo()}
1773
- SCSS
1774
- end
1775
-
1776
- def test_function_map_splat
1777
- assert_equal <<CSS, render(<<SCSS)
1778
- .foo {
1779
- val: "a: 1, b: 2, c: 3"; }
1780
- CSS
1781
- @function foo($a, $b, $c) {
1782
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1783
- }
1784
-
1785
- .foo {
1786
- $map: (a: 1, b: 2, c: 3);
1787
- val: foo($map...);
1788
- }
1789
- SCSS
1790
- end
1791
-
1792
- def test_function_map_and_list_splat
1793
- assert_equal <<CSS, render(<<SCSS)
1794
- .foo {
1795
- val: "a: x, b: y, c: z, d: 1, e: 2, f: 3"; }
1796
- CSS
1797
- @function foo($a, $b, $c, $d, $e, $f) {
1798
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}, d: \#{$d}, e: \#{$e}, f: \#{$f}";
1799
- }
1800
-
1801
- .foo {
1802
- $list: x y z;
1803
- $map: (d: 1, e: 2, f: 3);
1804
- val: foo($list..., $map...);
1805
- }
1806
- SCSS
1807
- end
1808
-
1809
- def test_function_map_splat_takes_precedence_over_pass_through
1810
- assert_equal <<CSS, render(<<SCSS)
1811
- .foo {
1812
- val: "a: 1, b: 2, c: z"; }
1813
- CSS
1814
- @function foo($args...) {
1815
- $map: (c: z);
1816
- @return bar($args..., $map...);
1817
- }
1818
-
1819
- @function bar($a, $b, $c) {
1820
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1821
- }
1822
-
1823
- .foo {
1824
- val: foo(1, $b: 2, $c: 3);
1825
- }
1826
- SCSS
1827
- end
1828
-
1829
- def test_ruby_function_map_splat_takes_precedence_over_pass_through
1830
- assert_equal <<CSS, render(<<SCSS)
1831
- .foo {
1832
- val: 1 2 3 z; }
1833
- CSS
1834
- @function foo($args...) {
1835
- $map: (val: z);
1836
- @return append($args..., $map...);
1837
- }
1838
-
1839
- .foo {
1840
- val: foo(1 2 3, $val: 4)
1841
- }
1842
- SCSS
1843
- end
1844
-
1845
- def test_function_list_of_pairs_splat_treated_as_list
1846
- assert_equal <<CSS, render(<<SCSS)
1847
- .foo {
1848
- val: "a: a 1, b: b 2, c: c 3"; }
1849
- CSS
1850
- @function foo($a, $b, $c) {
1851
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1852
- }
1853
-
1854
- .foo {
1855
- val: foo((a 1, b 2, c 3)...);
1856
- }
1857
- SCSS
1858
- end
1859
-
1860
- def test_function_splat_after_keyword_args
1861
- assert_equal <<CSS, render(<<SCSS)
1862
- .foo {
1863
- val: "a: 1, b: 2, c: 3"; }
1864
- CSS
1865
- @function foo($a, $b, $c) {
1866
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1867
- }
1868
-
1869
- .foo {
1870
- val: foo(1, $c: 3, 2...);
1871
- }
1872
- SCSS
1873
- end
1874
-
1875
- def test_function_keyword_args_after_splat
1876
- assert_equal <<CSS, render(<<SCSS)
1877
- .foo {
1878
- val: "a: 1, b: 2, c: 3"; }
1879
- CSS
1880
- @function foo($a, $b, $c) {
1881
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1882
- }
1883
-
1884
- .foo {
1885
- val: foo(1, 2..., $c: 3);
1886
- }
1887
- SCSS
1888
- end
1889
-
1890
- def test_function_keyword_splat_after_keyword_args
1891
- assert_equal <<CSS, render(<<SCSS)
1892
- .foo {
1893
- val: "a: 1, b: 2, c: 3"; }
1894
- CSS
1895
- @function foo($a, $b, $c) {
1896
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1897
- }
1898
-
1899
- .foo {
1900
- val: foo(1, $b: 2, (c: 3)...);
1901
- }
1902
- SCSS
1903
- end
1904
-
1905
- def test_function_triple_keyword_splat_merge
1906
- assert_equal <<CSS, render(<<SCSS)
1907
- .foo {
1908
- val: "foo: 1, bar: 2, kwarg: 3, a: 3, b: 2, c: 3"; }
1909
- CSS
1910
- @function foo($foo, $bar, $kwarg, $a, $b, $c) {
1911
- @return "foo: \#{$foo}, bar: \#{$bar}, kwarg: \#{$kwarg}, a: \#{$a}, b: \#{$b}, c: \#{$c}";
1912
- }
1913
-
1914
- @function bar($args...) {
1915
- @return foo($args..., $bar: 2, $a: 2, $b: 2, (kwarg: 3, a: 3, c: 3)...);
1916
- }
1917
-
1918
- .foo {
1919
- val: bar($foo: 1, $a: 1, $b: 1, $c: 1);
1920
- }
1921
- SCSS
1922
- end
1923
-
1924
- def test_function_conflicting_splat_after_keyword_args
1925
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
1926
- Function foo was passed argument $b both by position and by name.
1927
- MESSAGE
1928
- @function foo($a, $b, $c) {
1929
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1930
- }
1931
-
1932
- .foo {
1933
- val: foo(1, $b: 2, 3...);
1934
- }
1935
- SCSS
1936
- end
1937
-
1938
- def test_function_positional_arg_after_splat
1939
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
1940
- Only keyword arguments may follow variable arguments (...).
1941
- MESSAGE
1942
- @function foo($a, $b, $c) {
1943
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1944
- }
1945
-
1946
- .foo {
1947
- val: foo(1, 2..., 3);
1948
- }
1949
- SCSS
1950
- end
1951
-
1952
- def test_function_var_args_with_keyword
1953
- assert_raise_message(Sass::SyntaxError, "Positional arguments must come before keyword arguments.") {render <<SCSS}
1954
- @function foo($a, $b...) {
1955
- @return "a: \#{$a}, b: \#{$b}";
1956
- }
1957
-
1958
- .foo {val: foo($a: 1, 2, 3, 4)}
1959
- SCSS
1960
- end
1961
-
1962
- def test_function_keyword_for_var_arg
1963
- assert_raise_message(Sass::SyntaxError, "Argument $b of function foo cannot be used as a named argument.") {render <<SCSS}
1964
- @function foo($a, $b...) {
1965
- @return "a: \#{$a}, b: \#{$b}";
1966
- }
1967
-
1968
- .foo {val: foo(1, $b: 2 3 4)}
1969
- SCSS
1970
- end
1971
-
1972
- def test_function_keyword_for_unknown_arg_with_var_args
1973
- assert_raise_message(Sass::SyntaxError, "Function foo doesn't have an argument named $c.") {render <<SCSS}
1974
- @function foo($a, $b...) {
1975
- @return "a: \#{$a}, b: \#{length($b)}";
1976
- }
1977
-
1978
- .foo {val: foo(1, $c: 2 3 4)}
1979
- SCSS
1980
- end
1981
-
1982
- def test_function_var_args_passed_to_native
1983
- assert_equal <<CSS, render(<<SCSS)
1984
- .foo {
1985
- val: #102035; }
1986
- CSS
1987
- @function foo($args...) {
1988
- @return adjust-color($args...);
1989
- }
1990
-
1991
- .foo {val: foo(#102030, $blue: 5)}
1992
- SCSS
1993
- end
1994
-
1995
- def test_function_map_splat_before_list_splat
1996
- assert_raise_message(Sass::SyntaxError, "Variable keyword arguments must be a map (was (2 3)).") {render <<SCSS}
1997
- @function foo($a, $b, $c) {
1998
- @return "a: \#{$a}, b: \#{$b}, c: \#{$c}";
1999
- }
2000
-
2001
- .foo {
2002
- val: foo((a: 1)..., (2 3)...);
2003
- }
2004
- SCSS
2005
- end
2006
-
2007
- def test_function_map_splat_with_unknown_keyword
2008
- assert_raise_message(Sass::SyntaxError, "Function foo doesn't have an argument named $c.") {render <<SCSS}
2009
- @function foo($a, $b) {
2010
- @return "a: \#{$a}, b: \#{$b}";
2011
- }
2012
-
2013
- .foo {
2014
- val: foo(1, 2, (c: 1)...);
2015
- }
2016
- SCSS
2017
- end
2018
-
2019
- def test_function_map_splat_with_wrong_type
2020
- assert_raise_message(Sass::SyntaxError, "Variable keyword arguments must be a map (was 12).") {render <<SCSS}
2021
- @function foo($a, $b) {
2022
- @return "a: \#{$a}, b: \#{$b}";
2023
- }
2024
-
2025
- .foo {
2026
- val: foo((1, 2)..., 12...);
2027
- }
2028
- SCSS
2029
- end
2030
-
2031
- def test_function_keyword_splat_must_have_string_keys
2032
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
2033
- Variable keyword argument map must have string keys.
2034
- 12 is not a string in (12: 1).
2035
- MESSAGE
2036
- @function foo($a) {
2037
- @return $a;
2038
- }
2039
-
2040
- .foo {val: foo((12: 1)...)}
2041
- SCSS
2042
- end
2043
-
2044
- def test_function_splat_too_many_args
2045
- assert_warning(<<WARNING) {render <<SCSS}
2046
- WARNING: Function foo takes 2 arguments but 4 were passed.
2047
- on line 2 of #{filename_for_test(:scss)}
2048
- This will be an error in future versions of Sass.
2049
- WARNING
2050
- @function foo($a, $b) {@return null}
2051
- $var: foo((1, 2, 3, 4)...);
2052
- SCSS
2053
- end
2054
-
2055
- ## Interpolation
2056
-
2057
- def test_basic_selector_interpolation
2058
- assert_equal <<CSS, render(<<SCSS)
2059
- foo ab baz {
2060
- a: b; }
2061
- CSS
2062
- foo \#{'a' + 'b'} baz {a: b}
2063
- SCSS
2064
- assert_equal <<CSS, render(<<SCSS)
2065
- foo.bar baz {
2066
- a: b; }
2067
- CSS
2068
- foo\#{".bar"} baz {a: b}
2069
- SCSS
2070
- assert_equal <<CSS, render(<<SCSS)
2071
- foo.bar baz {
2072
- a: b; }
2073
- CSS
2074
- \#{"foo"}.bar baz {a: b}
2075
- SCSS
2076
- end
2077
-
2078
- def test_selector_only_interpolation
2079
- assert_equal <<CSS, render(<<SCSS)
2080
- foo bar {
2081
- a: b; }
2082
- CSS
2083
- \#{"foo" + " bar"} {a: b}
2084
- SCSS
2085
- end
2086
-
2087
- def test_selector_interpolation_before_element_name
2088
- assert_equal <<CSS, render(<<SCSS)
2089
- foo barbaz {
2090
- a: b; }
2091
- CSS
2092
- \#{"foo" + " bar"}baz {a: b}
2093
- SCSS
2094
- end
2095
-
2096
- def test_selector_interpolation_in_string
2097
- assert_equal <<CSS, render(<<SCSS)
2098
- foo[val="bar foo bar baz"] {
2099
- a: b; }
2100
- CSS
2101
- foo[val="bar \#{"foo" + " bar"} baz"] {a: b}
2102
- SCSS
2103
- end
2104
-
2105
- def test_selector_interpolation_in_pseudoclass
2106
- assert_equal <<CSS, render(<<SCSS)
2107
- foo:nth-child(5n) {
2108
- a: b; }
2109
- CSS
2110
- foo:nth-child(\#{5 + "n"}) {a: b}
2111
- SCSS
2112
- end
2113
-
2114
- def test_selector_interpolation_at_class_begininng
2115
- assert_equal <<CSS, render(<<SCSS)
2116
- .zzz {
2117
- a: b; }
2118
- CSS
2119
- $zzz: zzz;
2120
- .\#{$zzz} { a: b; }
2121
- SCSS
2122
- end
2123
-
2124
- def test_selector_interpolation_at_id_begininng
2125
- assert_equal <<CSS, render(<<SCSS)
2126
- #zzz {
2127
- a: b; }
2128
- CSS
2129
- $zzz: zzz;
2130
- #\#{$zzz} { a: b; }
2131
- SCSS
2132
- end
2133
-
2134
- def test_selector_interpolation_at_pseudo_begininng
2135
- assert_equal <<CSS, render(<<SCSS)
2136
- :zzz::zzz {
2137
- a: b; }
2138
- CSS
2139
- $zzz: zzz;
2140
- :\#{$zzz}::\#{$zzz} { a: b; }
2141
- SCSS
2142
- end
2143
-
2144
- def test_selector_interpolation_at_attr_beginning
2145
- assert_equal <<CSS, render(<<SCSS)
2146
- [zzz=foo] {
2147
- a: b; }
2148
- CSS
2149
- $zzz: zzz;
2150
- [\#{$zzz}=foo] { a: b; }
2151
- SCSS
2152
- end
2153
-
2154
- def test_selector_interpolation_at_attr_end
2155
- assert_equal <<CSS, render(<<SCSS)
2156
- [foo=zzz] {
2157
- a: b; }
2158
- CSS
2159
- $zzz: zzz;
2160
- [foo=\#{$zzz}] { a: b; }
2161
- SCSS
2162
- end
2163
-
2164
- def test_selector_interpolation_at_dashes
2165
- assert_equal <<CSS, render(<<SCSS)
2166
- div {
2167
- -foo-a-b-foo: foo; }
2168
- CSS
2169
- $a : a;
2170
- $b : b;
2171
- div { -foo-\#{$a}-\#{$b}-foo: foo }
2172
- SCSS
2173
- end
2174
-
2175
- def test_selector_interpolation_in_reference_combinator
2176
- silence_warnings {assert_equal <<CSS, render(<<SCSS)}
2177
- .foo /a/ .bar /b|c/ .baz {
2178
- a: b; }
2179
- CSS
2180
- $a: a;
2181
- $b: b;
2182
- $c: c;
2183
- .foo /\#{$a}/ .bar /\#{$b}|\#{$c}/ .baz {a: b}
2184
- SCSS
2185
- end
2186
-
2187
- def test_parent_selector_with_parent_and_subject
2188
- silence_warnings {assert_equal <<CSS, render(<<SCSS)}
2189
- bar foo.baz! .bip {
2190
- c: d; }
2191
- CSS
2192
- $subject: "!";
2193
- foo {
2194
- bar &.baz\#{$subject} .bip {c: d}}
2195
- SCSS
2196
- end
2197
-
2198
- def test_basic_prop_name_interpolation
2199
- assert_equal <<CSS, render(<<SCSS)
2200
- foo {
2201
- barbazbang: blip; }
2202
- CSS
2203
- foo {bar\#{"baz" + "bang"}: blip}
2204
- SCSS
2205
- assert_equal <<CSS, render(<<SCSS)
2206
- foo {
2207
- bar3: blip; }
2208
- CSS
2209
- foo {bar\#{1 + 2}: blip}
2210
- SCSS
2211
- end
2212
-
2213
- def test_prop_name_only_interpolation
2214
- assert_equal <<CSS, render(<<SCSS)
2215
- foo {
2216
- bazbang: blip; }
2217
- CSS
2218
- foo {\#{"baz" + "bang"}: blip}
2219
- SCSS
2220
- end
2221
-
2222
- def test_directive_interpolation
2223
- assert_equal <<CSS, render(<<SCSS)
2224
- @foo bar12 qux {
2225
- a: b; }
2226
- CSS
2227
- $baz: 12;
2228
- @foo bar\#{$baz} qux {a: b}
2229
- SCSS
2230
- end
2231
-
2232
- def test_media_interpolation
2233
- assert_equal <<CSS, render(<<SCSS)
2234
- @media bar12 {
2235
- a: b; }
2236
- CSS
2237
- $baz: 12;
2238
- @media bar\#{$baz} {a: b}
2239
- SCSS
2240
- end
2241
-
2242
- def test_script_in_media
2243
- assert_equal <<CSS, render(<<SCSS)
2244
- @media screen and (-webkit-min-device-pixel-ratio: 20), only print {
2245
- a: b; }
2246
- CSS
2247
- $media1: screen;
2248
- $media2: print;
2249
- $var: -webkit-min-device-pixel-ratio;
2250
- $val: 20;
2251
- @media \#{$media1} and ($var: $val), only \#{$media2} {a: b}
2252
- SCSS
2253
-
2254
- assert_equal <<CSS, render(<<SCSS)
2255
- @media screen and (-webkit-min-device-pixel-ratio: 13) {
2256
- a: b; }
2257
- CSS
2258
- $vals: 1 2 3;
2259
- @media screen and (-webkit-min-device-pixel-ratio: 5 + 6 + nth($vals, 2)) {a: b}
2260
- SCSS
2261
- end
2262
-
2263
- def test_media_interpolation_with_reparse
2264
- assert_equal <<CSS, render(<<SCSS)
2265
- @media screen and (max-width: 300px) {
2266
- a: b; }
2267
- @media screen and (max-width: 300px) {
2268
- a: b; }
2269
- @media screen and (max-width: 300px) {
2270
- a: b; }
2271
- @media screen and (max-width: 300px), print and (max-width: 300px) {
2272
- a: b; }
2273
- CSS
2274
- $constraint: "(max-width: 300px)";
2275
- $fragment: "nd \#{$constraint}";
2276
- $comma: "een, pri";
2277
- @media screen and \#{$constraint} {a: b}
2278
- @media screen {
2279
- @media \#{$constraint} {a: b}
2280
- }
2281
- @media screen a\#{$fragment} {a: b}
2282
- @media scr\#{$comma}nt {
2283
- @media \#{$constraint} {a: b}
2284
- }
2285
- SCSS
2286
- end
2287
-
2288
- def test_moz_document_interpolation
2289
- assert_equal <<CSS, render(<<SCSS)
2290
- @-moz-document url(http://sass-lang.com/),
2291
- url-prefix(http://sass-lang.com/docs),
2292
- domain(sass-lang.com),
2293
- domain("sass-lang.com") {
2294
- .foo {
2295
- a: b; } }
2296
- CSS
2297
- $domain: "sass-lang.com";
2298
- @-moz-document url(http://\#{$domain}/),
2299
- url-prefix(http://\#{$domain}/docs),
2300
- domain(\#{$domain}),
2301
- \#{domain($domain)} {
2302
- .foo {a: b}
2303
- }
2304
- SCSS
2305
- end
2306
-
2307
- def test_supports_with_expressions
2308
- assert_equal <<CSS, render(<<SCSS)
2309
- @supports ((feature1: val) and (feature2: val)) or (not (feature23: val4)) {
2310
- foo {
2311
- a: b; } }
2312
- CSS
2313
- $query: "(feature1: val)";
2314
- $feature: feature2;
2315
- $val: val;
2316
- @supports (\#{$query} and ($feature: $val)) or (not ($feature + 3: $val + 4)) {
2317
- foo {a: b}
2318
- }
2319
- SCSS
2320
- end
2321
-
2322
- def test_supports_bubbling
2323
- assert_equal <<CSS, render(<<SCSS)
2324
- @supports (foo: bar) {
2325
- a {
2326
- b: c; }
2327
- @supports (baz: bang) {
2328
- a {
2329
- d: e; } } }
2330
- CSS
2331
- a {
2332
- @supports (foo: bar) {
2333
- b: c;
2334
- @supports (baz: bang) {
2335
- d: e;
2336
- }
2337
- }
2338
- }
2339
- SCSS
2340
- end
2341
-
2342
- def test_random_directive_interpolation
2343
- assert_equal <<CSS, render(<<SCSS)
2344
- @foo url(http://sass-lang.com/),
2345
- domain("sass-lang.com"),
2346
- "foobarbaz",
2347
- foobarbaz {
2348
- .foo {
2349
- a: b; } }
2350
- CSS
2351
- $domain: "sass-lang.com";
2352
- @foo url(http://\#{$domain}/),
2353
- \#{domain($domain)},
2354
- "foo\#{'ba' + 'r'}baz",
2355
- foo\#{'ba' + 'r'}baz {
2356
- .foo {a: b}
2357
- }
2358
- SCSS
2359
- end
2360
-
2361
- def test_color_interpolation_warning_in_selector
2362
- assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
2363
- WARNING on line 1, column 4 of #{filename_for_test(:scss)}:
2364
- You probably don't mean to use the color value `blue' in interpolation here.
2365
- It may end up represented as #0000ff, which will likely produce invalid CSS.
2366
- Always quote color names when using them as strings (for example, "blue").
2367
- If you really want to use the color value here, use `"" + blue'.
2368
- WARNING
2369
- fooblue {
2370
- a: b; }
2371
- CSS
2372
- foo\#{blue} {a: b}
2373
- SCSS
2374
- end
2375
-
2376
- def test_color_interpolation_warning_in_directive
2377
- assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
2378
- WARNING on line 1, column 12 of #{filename_for_test(:scss)}:
2379
- You probably don't mean to use the color value `blue' in interpolation here.
2380
- It may end up represented as #0000ff, which will likely produce invalid CSS.
2381
- Always quote color names when using them as strings (for example, "blue").
2382
- If you really want to use the color value here, use `"" + blue'.
2383
- WARNING
2384
- @fblthp fooblue {
2385
- a: b; }
2386
- CSS
2387
- @fblthp foo\#{blue} {a: b}
2388
- SCSS
2389
- end
2390
-
2391
- def test_color_interpolation_warning_in_property_name
2392
- assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
2393
- WARNING on line 1, column 8 of #{filename_for_test(:scss)}:
2394
- You probably don't mean to use the color value `blue' in interpolation here.
2395
- It may end up represented as #0000ff, which will likely produce invalid CSS.
2396
- Always quote color names when using them as strings (for example, "blue").
2397
- If you really want to use the color value here, use `"" + blue'.
2398
- WARNING
2399
- foo {
2400
- a-blue: b; }
2401
- CSS
2402
- foo {a-\#{blue}: b}
2403
- SCSS
2404
- end
2405
-
2406
- def test_no_color_interpolation_warning_in_property_value
2407
- assert_no_warning {assert_equal <<CSS, render(<<SCSS)}
2408
- foo {
2409
- a: b-blue; }
2410
- CSS
2411
- foo {a: b-\#{blue}}
2412
- SCSS
2413
- end
2414
-
2415
- def test_no_color_interpolation_warning_for_nameless_color
2416
- assert_no_warning {assert_equal <<CSS, render(<<SCSS)}
2417
- foo-#abcdef {
2418
- a: b; }
2419
- CSS
2420
- foo-\#{#abcdef} {a: b}
2421
- SCSS
2422
- end
2423
-
2424
- def test_nested_mixin_def
2425
- assert_equal <<CSS, render(<<SCSS)
2426
- foo {
2427
- a: b; }
2428
- CSS
2429
- foo {
2430
- @mixin bar {a: b}
2431
- @include bar; }
2432
- SCSS
2433
- end
2434
-
2435
- def test_nested_mixin_shadow
2436
- assert_equal <<CSS, render(<<SCSS)
2437
- foo {
2438
- c: d; }
2439
-
2440
- baz {
2441
- a: b; }
2442
- CSS
2443
- @mixin bar {a: b}
2444
-
2445
- foo {
2446
- @mixin bar {c: d}
2447
- @include bar;
2448
- }
2449
-
2450
- baz {@include bar}
2451
- SCSS
2452
- end
2453
-
2454
- def test_nested_function_def
2455
- assert_equal <<CSS, render(<<SCSS)
2456
- foo {
2457
- a: 1; }
2458
-
2459
- bar {
2460
- b: foo(); }
2461
- CSS
2462
- foo {
2463
- @function foo() {@return 1}
2464
- a: foo(); }
2465
-
2466
- bar {b: foo()}
2467
- SCSS
2468
- end
2469
-
2470
- def test_nested_function_shadow
2471
- assert_equal <<CSS, render(<<SCSS)
2472
- foo {
2473
- a: 2; }
2474
-
2475
- baz {
2476
- b: 1; }
2477
- CSS
2478
- @function foo() {@return 1}
2479
-
2480
- foo {
2481
- @function foo() {@return 2}
2482
- a: foo();
2483
- }
2484
-
2485
- baz {b: foo()}
2486
- SCSS
2487
- end
2488
-
2489
- ## @at-root
2490
-
2491
- def test_simple_at_root
2492
- assert_equal <<CSS, render(<<SCSS)
2493
- .bar {
2494
- a: b; }
2495
- CSS
2496
- .foo {
2497
- @at-root {
2498
- .bar {a: b}
2499
- }
2500
- }
2501
- SCSS
2502
- end
2503
-
2504
- def test_at_root_with_selector
2505
- assert_equal <<CSS, render(<<SCSS)
2506
- .bar {
2507
- a: b; }
2508
- CSS
2509
- .foo {
2510
- @at-root .bar {a: b}
2511
- }
2512
- SCSS
2513
- end
2514
-
2515
- def test_at_root_in_mixin
2516
- assert_equal <<CSS, render(<<SCSS)
2517
- .bar {
2518
- a: b; }
2519
- CSS
2520
- @mixin bar {
2521
- @at-root .bar {a: b}
2522
- }
2523
-
2524
- .foo {
2525
- @include bar;
2526
- }
2527
- SCSS
2528
- end
2529
-
2530
- def test_at_root_in_media
2531
- assert_equal <<CSS, render(<<SCSS)
2532
- @media screen {
2533
- .bar {
2534
- a: b; } }
2535
- CSS
2536
- @media screen {
2537
- .foo {
2538
- @at-root .bar {a: b}
2539
- }
2540
- }
2541
- SCSS
2542
- end
2543
-
2544
- def test_at_root_in_bubbled_media
2545
- assert_equal <<CSS, render(<<SCSS)
2546
- @media screen {
2547
- .bar {
2548
- a: b; } }
2549
- CSS
2550
- .foo {
2551
- @media screen {
2552
- @at-root .bar {a: b}
2553
- }
2554
- }
2555
- SCSS
2556
- end
2557
-
2558
- def test_at_root_in_unknown_directive
2559
- assert_equal <<CSS, render(<<SCSS)
2560
- @fblthp {
2561
- .bar {
2562
- a: b; } }
2563
- CSS
2564
- @fblthp {
2565
- .foo {
2566
- @at-root .bar {a: b}
2567
- }
2568
- }
2569
- SCSS
2570
- end
2571
-
2572
- def test_comments_in_at_root
2573
- assert_equal <<CSS, render(<<SCSS)
2574
- /* foo */
2575
- .bar {
2576
- a: b; }
2577
-
2578
- /* baz */
2579
- CSS
2580
- .foo {
2581
- @at-root {
2582
- /* foo */
2583
- .bar {a: b}
2584
- /* baz */
2585
- }
2586
- }
2587
- SCSS
2588
- end
2589
-
2590
- def test_comments_in_at_root_in_media
2591
- assert_equal <<CSS, render(<<SCSS)
2592
- @media screen {
2593
- /* foo */
2594
- .bar {
2595
- a: b; }
2596
-
2597
- /* baz */ }
2598
- CSS
2599
- @media screen {
2600
- .foo {
2601
- @at-root {
2602
- /* foo */
2603
- .bar {a: b}
2604
- /* baz */
2605
- }
2606
- }
2607
- }
2608
- SCSS
2609
- end
2610
-
2611
- def test_comments_in_at_root_in_unknown_directive
2612
- assert_equal <<CSS, render(<<SCSS)
2613
- @fblthp {
2614
- /* foo */
2615
- .bar {
2616
- a: b; }
2617
-
2618
- /* baz */ }
2619
- CSS
2620
- @fblthp {
2621
- .foo {
2622
- @at-root {
2623
- /* foo */
2624
- .bar {a: b}
2625
- /* baz */
2626
- }
2627
- }
2628
- }
2629
- SCSS
2630
- end
2631
-
2632
- def test_media_directive_in_at_root
2633
- assert_equal <<CSS, render(<<SCSS)
2634
- @media screen {
2635
- .bar {
2636
- a: b; } }
2637
- CSS
2638
- .foo {
2639
- @at-root {
2640
- @media screen {.bar {a: b}}
2641
- }
2642
- }
2643
- SCSS
2644
- end
2645
-
2646
- def test_bubbled_media_directive_in_at_root
2647
- assert_equal <<CSS, render(<<SCSS)
2648
- @media screen {
2649
- .bar .baz {
2650
- a: b; } }
2651
- CSS
2652
- .foo {
2653
- @at-root {
2654
- .bar {
2655
- @media screen {.baz {a: b}}
2656
- }
2657
- }
2658
- }
2659
- SCSS
2660
- end
2661
-
2662
- def test_unknown_directive_in_at_root
2663
- assert_equal <<CSS, render(<<SCSS)
2664
- @fblthp {
2665
- .bar {
2666
- a: b; } }
2667
- CSS
2668
- .foo {
2669
- @at-root {
2670
- @fblthp {.bar {a: b}}
2671
- }
2672
- }
2673
- SCSS
2674
- end
2675
-
2676
- def test_at_root_in_at_root
2677
- assert_equal <<CSS, render(<<SCSS)
2678
- .bar {
2679
- a: b; }
2680
- CSS
2681
- .foo {
2682
- @at-root {
2683
- @at-root .bar {a: b}
2684
- }
2685
- }
2686
- SCSS
2687
- end
2688
-
2689
- def test_at_root_with_parent_ref
2690
- assert_equal <<CSS, render(<<SCSS)
2691
- .foo {
2692
- a: b; }
2693
- CSS
2694
- .foo {
2695
- @at-root & {
2696
- a: b;
2697
- }
2698
- }
2699
- SCSS
2700
- end
2701
-
2702
- def test_multi_level_at_root_with_parent_ref
2703
- assert_equal <<CSS, render(<<SCSS)
2704
- .foo .bar {
2705
- a: b; }
2706
- CSS
2707
- .foo {
2708
- @at-root & {
2709
- .bar {
2710
- @at-root & {
2711
- a: b;
2712
- }
2713
- }
2714
- }
2715
- }
2716
- SCSS
2717
- end
2718
-
2719
- def test_multi_level_at_root_with_inner_parent_ref
2720
- assert_equal <<CSS, render(<<SCSS)
2721
- .bar {
2722
- a: b; }
2723
- CSS
2724
- .foo {
2725
- @at-root .bar {
2726
- @at-root & {
2727
- a: b;
2728
- }
2729
- }
2730
- }
2731
- SCSS
2732
- end
2733
-
2734
- def test_at_root_beneath_comma_selector
2735
- assert_equal(<<CSS, render(<<SCSS))
2736
- .baz {
2737
- a: b; }
2738
- CSS
2739
- .foo, .bar {
2740
- @at-root .baz {
2741
- a: b;
2742
- }
2743
- }
2744
- SCSS
2745
- end
2746
-
2747
- def test_at_root_with_parent_ref_and_class
2748
- assert_equal(<<CSS, render(<<SCSS))
2749
- .foo.bar {
2750
- a: b; }
2751
- CSS
2752
- .foo {
2753
- @at-root &.bar {
2754
- a: b;
2755
- }
2756
- }
2757
- SCSS
2758
- end
2759
-
2760
- def test_at_root_beneath_comma_selector_with_parent_ref
2761
- assert_equal(<<CSS, render(<<SCSS))
2762
- .foo.baz, .bar.baz {
2763
- a: b; }
2764
- CSS
2765
- .foo, .bar {
2766
- @at-root &.baz {
2767
- a: b;
2768
- }
2769
- }
2770
- SCSS
2771
- end
2772
-
2773
- ## @at-root (...)
2774
-
2775
- def test_at_root_without_media
2776
- assert_equal <<CSS, render(<<SCSS)
2777
- .foo .bar {
2778
- a: b; }
2779
- CSS
2780
- .foo {
2781
- @media screen {
2782
- @at-root (without: media) {
2783
- .bar {
2784
- a: b;
2785
- }
2786
- }
2787
- }
2788
- }
2789
- SCSS
2790
- end
2791
-
2792
- def test_at_root_without_supports
2793
- assert_equal <<CSS, render(<<SCSS)
2794
- .foo .bar {
2795
- a: b; }
2796
- CSS
2797
- .foo {
2798
- @supports (foo: bar) {
2799
- @at-root (without: supports) {
2800
- .bar {
2801
- a: b;
2802
- }
2803
- }
2804
- }
2805
- }
2806
- SCSS
2807
- end
2808
-
2809
- def test_at_root_without_rule
2810
- assert_equal <<CSS, render(<<SCSS)
2811
- @media screen {
2812
- .bar {
2813
- a: b; } }
2814
- CSS
2815
- .foo {
2816
- @media screen {
2817
- @at-root (without: rule) {
2818
- .bar {
2819
- a: b;
2820
- }
2821
- }
2822
- }
2823
- }
2824
- SCSS
2825
- end
2826
-
2827
- def test_at_root_without_unknown_directive
2828
- assert_equal <<CSS, render(<<SCSS)
2829
- @fblthp {}
2830
- .foo .bar {
2831
- a: b; }
2832
- CSS
2833
- .foo {
2834
- @fblthp {
2835
- @at-root (without: fblthp) {
2836
- .bar {
2837
- a: b;
2838
- }
2839
- }
2840
- }
2841
- }
2842
- SCSS
2843
- end
2844
-
2845
- def test_at_root_without_multiple
2846
- assert_equal <<CSS, render(<<SCSS)
2847
- @supports (foo: bar) {
2848
- .bar {
2849
- a: b; } }
2850
- CSS
2851
- .foo {
2852
- @media screen {
2853
- @supports (foo: bar) {
2854
- @at-root (without: media rule) {
2855
- .bar {
2856
- a: b;
2857
- }
2858
- }
2859
- }
2860
- }
2861
- }
2862
- SCSS
2863
- end
2864
-
2865
- def test_at_root_without_all
2866
- assert_equal <<CSS, render(<<SCSS)
2867
- @supports (foo: bar) {
2868
- @fblthp {} }
2869
- .bar {
2870
- a: b; }
2871
- CSS
2872
- .foo {
2873
- @supports (foo: bar) {
2874
- @fblthp {
2875
- @at-root (without: all) {
2876
- .bar {
2877
- a: b;
2878
- }
2879
- }
2880
- }
2881
- }
2882
- }
2883
- SCSS
2884
- end
2885
-
2886
- def test_at_root_with_media
2887
- assert_equal <<CSS, render(<<SCSS)
2888
- @media screen {
2889
- @fblthp {}
2890
- .bar {
2891
- a: b; } }
2892
- CSS
2893
- .foo {
2894
- @media screen {
2895
- @fblthp {
2896
- @supports (foo: bar) {
2897
- @at-root (with: media) {
2898
- .bar {
2899
- a: b;
2900
- }
2901
- }
2902
- }
2903
- }
2904
- }
2905
- }
2906
- SCSS
2907
- end
2908
-
2909
- def test_at_root_with_rule
2910
- assert_equal <<CSS, render(<<SCSS)
2911
- @media screen {
2912
- @fblthp {} }
2913
- .foo .bar {
2914
- a: b; }
2915
- CSS
2916
- .foo {
2917
- @media screen {
2918
- @fblthp {
2919
- @supports (foo: bar) {
2920
- @at-root (with: rule) {
2921
- .bar {
2922
- a: b;
2923
- }
2924
- }
2925
- }
2926
- }
2927
- }
2928
- }
2929
- SCSS
2930
- end
2931
-
2932
- def test_at_root_with_supports
2933
- assert_equal <<CSS, render(<<SCSS)
2934
- @media screen {
2935
- @fblthp {} }
2936
- @supports (foo: bar) {
2937
- .bar {
2938
- a: b; } }
2939
- CSS
2940
- .foo {
2941
- @media screen {
2942
- @fblthp {
2943
- @supports (foo: bar) {
2944
- @at-root (with: supports) {
2945
- .bar {
2946
- a: b;
2947
- }
2948
- }
2949
- }
2950
- }
2951
- }
2952
- }
2953
- SCSS
2954
- end
2955
-
2956
- def test_at_root_with_unknown_directive
2957
- assert_equal <<CSS, render(<<SCSS)
2958
- @media screen {
2959
- @fblthp {} }
2960
- @fblthp {
2961
- .bar {
2962
- a: b; } }
2963
- CSS
2964
- .foo {
2965
- @media screen {
2966
- @fblthp {
2967
- @supports (foo: bar) {
2968
- @at-root (with: fblthp) {
2969
- .bar {
2970
- a: b;
2971
- }
2972
- }
2973
- }
2974
- }
2975
- }
2976
- }
2977
- SCSS
2978
- end
2979
-
2980
- def test_at_root_with_multiple
2981
- assert_equal <<CSS, render(<<SCSS)
2982
- @media screen {
2983
- @fblthp {}
2984
- .foo .bar {
2985
- a: b; } }
2986
- CSS
2987
- .foo {
2988
- @media screen {
2989
- @fblthp {
2990
- @supports (foo: bar) {
2991
- @at-root (with: media rule) {
2992
- .bar {
2993
- a: b;
2994
- }
2995
- }
2996
- }
2997
- }
2998
- }
2999
- }
3000
- SCSS
3001
- end
3002
-
3003
- def test_at_root_with_all
3004
- assert_equal <<CSS, render(<<SCSS)
3005
- @media screen {
3006
- @fblthp {
3007
- @supports (foo: bar) {
3008
- .foo .bar {
3009
- a: b; } } } }
3010
- CSS
3011
- .foo {
3012
- @media screen {
3013
- @fblthp {
3014
- @supports (foo: bar) {
3015
- @at-root (with: all) {
3016
- .bar {
3017
- a: b;
3018
- }
3019
- }
3020
- }
3021
- }
3022
- }
3023
- }
3024
- SCSS
3025
- end
3026
-
3027
- def test_at_root_dynamic_values
3028
- assert_equal <<CSS, render(<<SCSS)
3029
- @media screen {
3030
- .bar {
3031
- a: b; } }
3032
- CSS
3033
- $key: with;
3034
- $value: media;
3035
- .foo {
3036
- @media screen {
3037
- @at-root ($key: $value) {
3038
- .bar {
3039
- a: b;
3040
- }
3041
- }
3042
- }
3043
- }
3044
- SCSS
3045
- end
3046
-
3047
- def test_at_root_interpolated_query
3048
- assert_equal <<CSS, render(<<SCSS)
3049
- @media screen {
3050
- .bar {
3051
- a: b; } }
3052
- CSS
3053
- .foo {
3054
- @media screen {
3055
- @at-root (\#{"with: media"}) {
3056
- .bar {
3057
- a: b;
3058
- }
3059
- }
3060
- }
3061
- }
3062
- SCSS
3063
- end
3064
-
3065
- def test_at_root_plus_extend
3066
- assert_equal <<CSS, render(<<SCSS)
3067
- .foo .bar {
3068
- a: b; }
3069
- CSS
3070
- %base {
3071
- a: b;
3072
- }
3073
-
3074
- .foo {
3075
- @media screen {
3076
- @at-root (without: media) {
3077
- .bar {
3078
- @extend %base;
3079
- }
3080
- }
3081
- }
3082
- }
3083
- SCSS
3084
- end
3085
-
3086
- def test_at_root_without_keyframes_in_keyframe_rule
3087
- assert_equal <<CSS, render(<<SCSS)
3088
- .foo {
3089
- a: b; }
3090
- CSS
3091
- @keyframes identifier {
3092
- 0% {
3093
- @at-root (without: keyframes) {
3094
- .foo {a: b}
3095
- }
3096
- }
3097
- }
3098
- SCSS
3099
- end
3100
-
3101
- def test_at_root_without_rule_in_keyframe_rule
3102
- assert_equal <<CSS, render(<<SCSS)
3103
- @keyframes identifier {
3104
- 0% {
3105
- a: b; } }
3106
- CSS
3107
- @keyframes identifier {
3108
- 0% {
3109
- @at-root (without: rule) {a: b}
3110
- }
3111
- }
3112
- SCSS
3113
- end
3114
-
3115
- ## Selector Script
3116
-
3117
- def test_selector_script
3118
- assert_equal(<<CSS, render(<<SCSS))
3119
- .foo .bar {
3120
- content: ".foo .bar"; }
3121
- CSS
3122
- .foo .bar {
3123
- content: "\#{&}";
3124
- }
3125
- SCSS
3126
- end
3127
-
3128
- def test_nested_selector_script
3129
- assert_equal(<<CSS, render(<<SCSS))
3130
- .foo .bar {
3131
- content: ".foo .bar"; }
3132
- CSS
3133
- .foo {
3134
- .bar {
3135
- content: "\#{&}";
3136
- }
3137
- }
3138
- SCSS
3139
- end
3140
-
3141
- def test_nested_selector_script_with_outer_comma_selector
3142
- assert_equal(<<CSS, render(<<SCSS))
3143
- .foo .baz, .bar .baz {
3144
- content: ".foo .baz, .bar .baz"; }
3145
- CSS
3146
- .foo, .bar {
3147
- .baz {
3148
- content: "\#{&}";
3149
- }
3150
- }
3151
- SCSS
3152
- end
3153
-
3154
- def test_nested_selector_script_with_inner_comma_selector
3155
- assert_equal(<<CSS, render(<<SCSS))
3156
- .foo .bar, .foo .baz {
3157
- content: ".foo .bar, .foo .baz"; }
3158
- CSS
3159
- .foo {
3160
- .bar, .baz {
3161
- content: "\#{&}";
3162
- }
3163
- }
3164
- SCSS
3165
- end
3166
-
3167
- def test_selector_script_through_mixin
3168
- assert_equal(<<CSS, render(<<SCSS))
3169
- .foo {
3170
- content: ".foo"; }
3171
- CSS
3172
- @mixin mixin {
3173
- content: "\#{&}";
3174
- }
3175
-
3176
- .foo {
3177
- @include mixin;
3178
- }
3179
- SCSS
3180
- end
3181
-
3182
- def test_selector_script_through_content
3183
- assert_equal(<<CSS, render(<<SCSS))
3184
- .foo {
3185
- content: ".foo"; }
3186
- CSS
3187
- @mixin mixin {
3188
- @content;
3189
- }
3190
-
3191
- .foo {
3192
- @include mixin {
3193
- content: "\#{&}";
3194
- }
3195
- }
3196
- SCSS
3197
- end
3198
-
3199
- def test_selector_script_through_function
3200
- assert_equal(<<CSS, render(<<SCSS))
3201
- .foo {
3202
- content: ".foo"; }
3203
- CSS
3204
- @function fn() {
3205
- @return "\#{&}";
3206
- }
3207
-
3208
- .foo {
3209
- content: fn();
3210
- }
3211
- SCSS
3212
- end
3213
-
3214
- def test_selector_script_through_media
3215
- assert_equal(<<CSS, render(<<SCSS))
3216
- .foo {
3217
- content: "outer"; }
3218
- @media screen {
3219
- .foo .bar {
3220
- content: ".foo .bar"; } }
3221
- CSS
3222
- .foo {
3223
- content: "outer";
3224
- @media screen {
3225
- .bar {
3226
- content: "\#{&}";
3227
- }
3228
- }
3229
- }
3230
- SCSS
3231
- end
3232
-
3233
- def test_selector_script_save_and_reuse
3234
- assert_equal(<<CSS, render(<<SCSS))
3235
- .bar {
3236
- content: ".foo"; }
3237
- CSS
3238
- $var: null;
3239
- .foo {
3240
- $var: & !global;
3241
- }
3242
-
3243
- .bar {
3244
- content: "\#{$var}";
3245
- }
3246
- SCSS
3247
- end
3248
-
3249
- def test_selector_script_with_at_root
3250
- assert_equal(<<CSS, render(<<SCSS))
3251
- .foo-bar {
3252
- a: b; }
3253
- CSS
3254
- .foo {
3255
- @at-root \#{&}-bar {
3256
- a: b;
3257
- }
3258
- }
3259
- SCSS
3260
- end
3261
-
3262
- def test_multi_level_at_root_with_inner_selector_script
3263
- assert_equal <<CSS, render(<<SCSS)
3264
- .bar {
3265
- a: b; }
3266
- CSS
3267
- .foo {
3268
- @at-root .bar {
3269
- @at-root \#{&} {
3270
- a: b;
3271
- }
3272
- }
3273
- }
3274
- SCSS
3275
- end
3276
-
3277
- def test_at_root_with_at_root_through_mixin
3278
- assert_equal(<<CSS, render(<<SCSS))
3279
- .bar-baz {
3280
- a: b; }
3281
- CSS
3282
- @mixin foo {
3283
- .bar {
3284
- @at-root \#{&}-baz {
3285
- a: b;
3286
- }
3287
- }
3288
- }
3289
-
3290
- @include foo;
3291
- SCSS
3292
- end
3293
-
3294
- # See https://github.com/sass/sass/issues/1294
3295
- def test_extend_top_leveled_by_at_root
3296
- render(<<SCSS)
3297
- .span-10 {
3298
- @at-root (without: all) {
3299
- @extend %column;
3300
- }
3301
- }
3302
- SCSS
3303
-
3304
- assert(false, "Expected syntax error")
3305
- rescue Sass::SyntaxError => e
3306
- assert_equal "Extend directives may only be used within rules.", e.message
3307
- assert_equal 3, e.sass_line
3308
- end
3309
-
3310
- def test_at_root_doesnt_always_break_blocks
3311
- assert_equal <<CSS, render(<<SCSS)
3312
- .foo {
3313
- a: b; }
3314
-
3315
- @media screen {
3316
- .foo {
3317
- c: d; }
3318
- .bar {
3319
- e: f; } }
3320
- CSS
3321
- %base {
3322
- a: b;
3323
- }
3324
-
3325
- @media screen {
3326
- .foo {
3327
- c: d;
3328
- @at-root (without: media) {
3329
- @extend %base;
3330
- }
3331
- }
3332
-
3333
- .bar {e: f}
3334
- }
3335
- SCSS
3336
- end
3337
-
3338
- ## Errors
3339
-
3340
- def test_keyframes_rule_outside_of_keyframes
3341
- render <<SCSS
3342
- 0% {
3343
- top: 0; }
3344
- SCSS
3345
- assert(false, "Expected syntax error")
3346
- rescue Sass::SyntaxError => e
3347
- assert_equal 'Invalid CSS after "": expected selector, was "0%"', e.message
3348
- assert_equal 1, e.sass_line
3349
- end
3350
-
3351
- def test_selector_rule_in_keyframes
3352
- render <<SCSS
3353
- @keyframes identifier {
3354
- .foo {
3355
- top: 0; } }
3356
- SCSS
3357
- assert(false, "Expected syntax error")
3358
- rescue Sass::SyntaxError => e
3359
- assert_equal 'Invalid CSS after "": expected keyframes selector (e.g. 10%), was ".foo"', e.message
3360
- assert_equal 2, e.sass_line
3361
- end
3362
-
3363
- def test_nested_mixin_def_is_scoped
3364
- render <<SCSS
3365
- foo {
3366
- @mixin bar {a: b}}
3367
- bar {@include bar}
3368
- SCSS
3369
- assert(false, "Expected syntax error")
3370
- rescue Sass::SyntaxError => e
3371
- assert_equal "Undefined mixin 'bar'.", e.message
3372
- assert_equal 3, e.sass_line
3373
- end
3374
-
3375
- def test_rules_beneath_properties
3376
- render <<SCSS
3377
- foo {
3378
- bar: {
3379
- baz {
3380
- bang: bop }}}
3381
- SCSS
3382
- assert(false, "Expected syntax error")
3383
- rescue Sass::SyntaxError => e
3384
- assert_equal 'Illegal nesting: Only properties may be nested beneath properties.', e.message
3385
- assert_equal 3, e.sass_line
3386
- end
3387
-
3388
- def test_uses_property_exception_with_star_hack
3389
- render <<SCSS
3390
- foo {
3391
- *bar:baz <fail>; }
3392
- SCSS
3393
- assert(false, "Expected syntax error")
3394
- rescue Sass::SyntaxError => e
3395
- assert_equal 'Invalid CSS after " *bar:baz <fail>": expected expression (e.g. 1px, bold), was "; }"', e.message
3396
- assert_equal 2, e.sass_line
3397
- end
3398
-
3399
- def test_uses_property_exception_with_colon_hack
3400
- render <<SCSS
3401
- foo {
3402
- :bar:baz <fail>; }
3403
- SCSS
3404
- assert(false, "Expected syntax error")
3405
- rescue Sass::SyntaxError => e
3406
- assert_equal 'Invalid CSS after " :bar:baz <fail>": expected expression (e.g. 1px, bold), was "; }"', e.message
3407
- assert_equal 2, e.sass_line
3408
- end
3409
-
3410
- def test_uses_rule_exception_with_dot_hack
3411
- render <<SCSS
3412
- foo {
3413
- .bar:baz <fail>; }
3414
- SCSS
3415
- assert(false, "Expected syntax error")
3416
- rescue Sass::SyntaxError => e
3417
- assert_equal 'Invalid CSS after " .bar:baz <fail>": expected expression (e.g. 1px, bold), was "; }"', e.message
3418
- assert_equal 2, e.sass_line
3419
- end
3420
-
3421
- def test_uses_property_exception_with_space_after_name
3422
- render <<SCSS
3423
- foo {
3424
- bar: baz <fail>; }
3425
- SCSS
3426
- assert(false, "Expected syntax error")
3427
- rescue Sass::SyntaxError => e
3428
- assert_equal 'Invalid CSS after " bar: baz <fail>": expected expression (e.g. 1px, bold), was "; }"', e.message
3429
- assert_equal 2, e.sass_line
3430
- end
3431
-
3432
- def test_uses_property_exception_with_non_identifier_after_name
3433
- render <<SCSS
3434
- foo {
3435
- bar:1px <fail>; }
3436
- SCSS
3437
- assert(false, "Expected syntax error")
3438
- rescue Sass::SyntaxError => e
3439
- assert_equal 'Invalid CSS after " bar:1px <fail>": expected expression (e.g. 1px, bold), was "; }"', e.message
3440
- assert_equal 2, e.sass_line
3441
- end
3442
-
3443
- def test_uses_property_exception_when_followed_by_open_bracket
3444
- render <<SCSS
3445
- foo {
3446
- bar:{baz: .fail} }
3447
- SCSS
3448
- assert(false, "Expected syntax error")
3449
- rescue Sass::SyntaxError => e
3450
- assert_equal 'Invalid CSS after " bar:{baz: ": expected expression (e.g. 1px, bold), was ".fail} }"', e.message
3451
- assert_equal 2, e.sass_line
3452
- end
3453
-
3454
- def test_script_error
3455
- render <<SCSS
3456
- foo {
3457
- bar: "baz" * * }
3458
- SCSS
3459
- assert(false, "Expected syntax error")
3460
- rescue Sass::SyntaxError => e
3461
- assert_equal 'Invalid CSS after " bar: "baz" * ": expected expression (e.g. 1px, bold), was "* }"', e.message
3462
- assert_equal 2, e.sass_line
3463
- end
3464
-
3465
- def test_multiline_script_syntax_error
3466
- render <<SCSS
3467
- foo {
3468
- bar:
3469
- "baz" * * }
3470
- SCSS
3471
- assert(false, "Expected syntax error")
3472
- rescue Sass::SyntaxError => e
3473
- assert_equal 'Invalid CSS after " "baz" * ": expected expression (e.g. 1px, bold), was "* }"', e.message
3474
- assert_equal 3, e.sass_line
3475
- end
3476
-
3477
- def test_multiline_script_runtime_error
3478
- render <<SCSS
3479
- foo {
3480
- bar: "baz" +
3481
- "bar" +
3482
- $bang }
3483
- SCSS
3484
- assert(false, "Expected syntax error")
3485
- rescue Sass::SyntaxError => e
3486
- assert_equal "Undefined variable: \"$bang\".", e.message
3487
- assert_equal 4, e.sass_line
3488
- end
3489
-
3490
- def test_post_multiline_script_runtime_error
3491
- render <<SCSS
3492
- foo {
3493
- bar: "baz" +
3494
- "bar" +
3495
- "baz";
3496
- bip: $bop; }
3497
- SCSS
3498
- assert(false, "Expected syntax error")
3499
- rescue Sass::SyntaxError => e
3500
- assert_equal "Undefined variable: \"$bop\".", e.message
3501
- assert_equal 5, e.sass_line
3502
- end
3503
-
3504
- def test_multiline_property_runtime_error
3505
- render <<SCSS
3506
- foo {
3507
- bar: baz
3508
- bar
3509
- \#{$bang} }
3510
- SCSS
3511
- assert(false, "Expected syntax error")
3512
- rescue Sass::SyntaxError => e
3513
- assert_equal "Undefined variable: \"$bang\".", e.message
3514
- assert_equal 4, e.sass_line
3515
- end
3516
-
3517
- def test_post_resolution_selector_error
3518
- render "\n\nfoo \#{\") bar\"} {a: b}"
3519
- assert(false, "Expected syntax error")
3520
- rescue Sass::SyntaxError => e
3521
- assert_equal 'Invalid CSS after "foo ": expected selector, was ") bar"', e.message
3522
- assert_equal 3, e.sass_line
3523
- end
3524
-
3525
- def test_parent_in_mid_selector_error
3526
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
3527
- Invalid CSS after ".foo": expected "{", was "&.bar"
3528
-
3529
- "&.bar" may only be used at the beginning of a compound selector.
3530
- MESSAGE
3531
- flim {
3532
- .foo&.bar {a: b}
3533
- }
3534
- SCSS
3535
- end
3536
-
3537
- def test_parent_after_selector_error
3538
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
3539
- Invalid CSS after ".foo.bar": expected "{", was "&"
3540
-
3541
- "&" may only be used at the beginning of a compound selector.
3542
- MESSAGE
3543
- flim {
3544
- .foo.bar& {a: b}
3545
- }
3546
- SCSS
3547
- end
3548
-
3549
- def test_double_parent_selector_error
3550
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
3551
- Invalid CSS after "&": expected "{", was "&"
3552
-
3553
- "&" may only be used at the beginning of a compound selector.
3554
- MESSAGE
3555
- flim {
3556
- && {a: b}
3557
- }
3558
- SCSS
3559
- end
3560
-
3561
- def test_no_lonely_else
3562
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
3563
- Invalid CSS: @else must come after @if
3564
- MESSAGE
3565
- @else {foo: bar}
3566
- SCSS
3567
- end
3568
-
3569
- def test_failed_parent_selector_with_suffix
3570
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3571
- Invalid parent selector for "&-bar": "*"
3572
- MESSAGE
3573
- * {
3574
- &-bar {a: b}
3575
- }
3576
- SCSS
3577
-
3578
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3579
- Invalid parent selector for "&-bar": "[foo=bar]"
3580
- MESSAGE
3581
- [foo=bar] {
3582
- &-bar {a: b}
3583
- }
3584
- SCSS
3585
-
3586
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3587
- Invalid parent selector for "&-bar": "::nth-child(2n+1)"
3588
- MESSAGE
3589
- ::nth-child(2n+1) {
3590
- &-bar {a: b}
3591
- }
3592
- SCSS
3593
-
3594
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3595
- Invalid parent selector for "&-bar": ":not(.foo)"
3596
- MESSAGE
3597
- :not(.foo) {
3598
- &-bar {a: b}
3599
- }
3600
- SCSS
3601
-
3602
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3603
- Invalid parent selector for "&-bar": ".foo +"
3604
- MESSAGE
3605
- .foo + {
3606
- &-bar {a: b}
3607
- }
3608
- SCSS
3609
- end
3610
-
3611
- def test_empty_media_query_error
3612
- assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3613
- Invalid CSS after "": expected media query list, was ""
3614
- MESSAGE
3615
- @media \#{""} {
3616
- foo {a: b}
3617
- }
3618
- SCSS
3619
- end
3620
-
3621
- def test_newline_in_property_value
3622
- assert_equal(<<CSS, render(<<SCSS))
3623
- .foo {
3624
- bar: "bazbang"; }
3625
- CSS
3626
- .foo {
3627
- $var: "baz\\
3628
- bang";
3629
- bar: $var;
3630
- }
3631
- SCSS
3632
- end
3633
-
3634
- def test_raw_newline_warning
3635
- assert_warning(<<MESSAGE.rstrip) {assert_equal(<<CSS, render(<<SCSS))}
3636
- DEPRECATION WARNING on line 2, column 9 of #{filename_for_test :scss}:
3637
- Unescaped multiline strings are deprecated and will be removed in a future version of Sass.
3638
- To include a newline in a string, use "\\a" or "\\a " as in CSS.
3639
- MESSAGE
3640
- .foo {
3641
- bar: "baz\\a bang"; }
3642
- CSS
3643
- .foo {
3644
- $var: "baz
3645
- bang";
3646
- bar: $var;
3647
- }
3648
- SCSS
3649
- end
3650
-
3651
- # Regression
3652
-
3653
- # Regression test for #2031.
3654
- def test_no_interpolation_warning_in_nested_selector
3655
- assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
3656
- z a:b(n+1) {
3657
- x: y; }
3658
- CSS
3659
- z {
3660
- a:b(n+\#{1}) {
3661
- x: y;
3662
- }
3663
- }
3664
- SCSS
3665
- end
3666
-
3667
- # Ensures that the fix for #2031 doesn't hide legitimate warnings.
3668
- def test_interpolation_warning_in_selector_like_property
3669
- assert_warning(<<WARNING) {assert_equal(<<CSS, render(<<SCSS))}
3670
- DEPRECATION WARNING on line 2 of #{filename_for_test :scss}:
3671
- \#{} interpolation near operators will be simplified in a future version of Sass.
3672
- To preserve the current behavior, use quotes:
3673
-
3674
- unquote("n+1")
3675
-
3676
- You can use the sass-convert command to automatically fix most cases.
3677
- WARNING
3678
- z {
3679
- a: b(n+1); }
3680
- CSS
3681
- z {
3682
- a:b(n+\#{1});
3683
- }
3684
- SCSS
3685
- end
3686
-
3687
- def test_escape_in_selector
3688
- assert_equal(<<CSS, render(".\\!foo {a: b}"))
3689
- .\\!foo {
3690
- a: b; }
3691
- CSS
3692
- end
3693
-
3694
- def test_for_directive_with_float_bounds
3695
- assert_equal(<<CSS, render(<<SCSS))
3696
- .a {
3697
- b: 0;
3698
- b: 1;
3699
- b: 2;
3700
- b: 3;
3701
- b: 4;
3702
- b: 5; }
3703
- CSS
3704
- .a {
3705
- @for $i from 0.0 through 5.0 {b: $i}
3706
- }
3707
- SCSS
3708
-
3709
- assert_raise_message(Sass::SyntaxError, "0.5 is not an integer.") {render(<<SCSS)}
3710
- .a {
3711
- @for $i from 0.5 through 5.0 {b: $i}
3712
- }
3713
- SCSS
3714
-
3715
- assert_raise_message(Sass::SyntaxError, "5.5 is not an integer.") {render(<<SCSS)}
3716
- .a {
3717
- @for $i from 0.0 through 5.5 {b: $i}
3718
- }
3719
- SCSS
3720
- end
3721
-
3722
- def test_parent_selector_in_function_pseudo_selector
3723
- assert_equal <<CSS, render(<<SCSS)
3724
- .bar:not(.foo) {
3725
- a: b; }
3726
-
3727
- .qux:nth-child(2n of .baz .bang) {
3728
- c: d; }
3729
- CSS
3730
- .foo {
3731
- .bar:not(&) {a: b}
3732
- }
3733
-
3734
- .baz .bang {
3735
- .qux:nth-child(2n of &) {c: d}
3736
- }
3737
- SCSS
3738
- end
3739
-
3740
- def test_parent_selector_in_and_out_of_function_pseudo_selector
3741
- # Regression test for https://github.com/sass/sass/issues/1464#issuecomment-70352288
3742
- assert_equal(<<CSS, render(<<SCSS))
3743
- .a:not(.a-b) {
3744
- x: y; }
3745
- CSS
3746
- .a {
3747
- &:not(&-b) {
3748
- x: y;
3749
- }
3750
- }
3751
- SCSS
3752
-
3753
- assert_equal(<<CSS, render(<<SCSS))
3754
- .a:nth-child(2n of .a-b) {
3755
- x: y; }
3756
- CSS
3757
- .a {
3758
- &:nth-child(2n of &-b) {
3759
- x: y;
3760
- }
3761
- }
3762
- SCSS
3763
- end
3764
-
3765
- def test_attribute_selector_in_selector_pseudoclass
3766
- # Even though this is plain CSS, it only failed when given to the SCSS
3767
- # parser.
3768
- assert_equal(<<CSS, render(<<SCSS))
3769
- [href^='http://'] {
3770
- color: red; }
3771
- CSS
3772
- [href^='http://'] {
3773
- color: red;
3774
- }
3775
- SCSS
3776
- end
3777
-
3778
- def test_top_level_unknown_directive_in_at_root
3779
- assert_equal(<<CSS, render(<<SCSS))
3780
- @fblthp {
3781
- a: b; }
3782
- CSS
3783
- @at-root {
3784
- @fblthp {a: b}
3785
- }
3786
- SCSS
3787
- end
3788
-
3789
- def test_parent_ref_with_newline
3790
- assert_equal(<<CSS, render(<<SCSS))
3791
- a.c
3792
- , b.c {
3793
- x: y; }
3794
- CSS
3795
- a
3796
- , b {&.c {x: y}}
3797
- SCSS
3798
- end
3799
-
3800
- def test_parent_ref_in_nested_at_root
3801
- assert_equal(<<CSS, render(<<SCSS))
3802
- #test {
3803
- border: 0; }
3804
- #test:hover {
3805
- display: none; }
3806
- CSS
3807
- a {
3808
- @at-root #test {
3809
- border: 0;
3810
- &:hover{
3811
- display: none;
3812
- }
3813
- }
3814
- }
3815
- SCSS
3816
- end
3817
-
3818
- def test_loud_comment_in_compressed_mode
3819
- assert_equal(<<CSS, render(<<SCSS))
3820
- /*! foo */
3821
- CSS
3822
- /*! foo */
3823
- SCSS
3824
- end
3825
-
3826
- def test_parsing_decimals_followed_by_comments_doesnt_take_forever
3827
- assert_equal(<<CSS, render(<<SCSS))
3828
- .foo {
3829
- padding: 4.2105263158% 4.2105263158% 5.6315789474%; }
3830
- CSS
3831
- .foo {
3832
- padding: 4.21052631578947% 4.21052631578947% 5.631578947368421% /**/
3833
- }
3834
- SCSS
3835
- end
3836
-
3837
- def test_parsing_many_numbers_doesnt_take_forever
3838
- values = ["80% 90%"] * 1000
3839
- assert_equal(<<CSS, render(<<SCSS))
3840
- .foo {
3841
- padding: #{values.join(', ')}; }
3842
- CSS
3843
- .foo {
3844
- padding: #{values.join(', ')};
3845
- }
3846
- SCSS
3847
- end
3848
-
3849
- def test_import_comments_in_imports
3850
- assert_equal(<<CSS, render(<<SCSS))
3851
- @import url(foo.css);
3852
- @import url(bar.css);
3853
- @import url(baz.css);
3854
- CSS
3855
- @import "foo.css", // this is a comment
3856
- "bar.css", /* this is another comment */
3857
- "baz.css"; // this is a third comment
3858
- SCSS
3859
- end
3860
-
3861
- def test_reference_combinator_with_parent_ref
3862
- silence_warnings {assert_equal <<CSS, render(<<SCSS)}
3863
- a /foo/ b {
3864
- c: d; }
3865
- CSS
3866
- a {& /foo/ b {c: d}}
3867
- SCSS
3868
- end
3869
-
3870
- def test_reference_combinator_warning
3871
- assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
3872
- DEPRECATION WARNING on line 1, column 8 of test_reference_combinator_warning_inline.scss:
3873
- The reference combinator /foo/ is deprecated and will be removed in a future release.
3874
- WARNING
3875
- a /foo/ b {
3876
- c: d; }
3877
- CSS
3878
- a {& /foo/ b {c: d}}
3879
- SCSS
3880
- end
3881
-
3882
- def test_newline_selector_rendered_multiple_times
3883
- assert_equal <<CSS, render(<<SCSS)
3884
- form input,
3885
- form select {
3886
- color: white; }
3887
-
3888
- form input,
3889
- form select {
3890
- color: white; }
3891
- CSS
3892
- @for $i from 1 through 2 {
3893
- form {
3894
- input,
3895
- select {
3896
- color: white;
3897
- }
3898
- }
3899
- }
3900
- SCSS
3901
- end
3902
-
3903
- def test_prop_name_interpolation_after_hyphen
3904
- assert_equal <<CSS, render(<<SCSS)
3905
- a {
3906
- -foo-bar: b; }
3907
- CSS
3908
- a { -\#{"foo"}-bar: b; }
3909
- SCSS
3910
- end
3911
-
3912
- def test_star_plus_and_parent
3913
- assert_equal <<CSS, render(<<SCSS)
3914
- * + html foo {
3915
- a: b; }
3916
- CSS
3917
- foo {*+html & {a: b}}
3918
- SCSS
3919
- end
3920
-
3921
- def test_weird_added_space
3922
- assert_equal <<CSS, render(<<SCSS)
3923
- foo {
3924
- bar: -moz-bip; }
3925
- CSS
3926
- $value : bip;
3927
-
3928
- foo {
3929
- bar: -moz-\#{$value};
3930
- }
3931
- SCSS
3932
- end
3933
-
3934
- def test_interpolation_with_bracket_on_next_line
3935
- assert_equal <<CSS, render(<<SCSS)
3936
- a.foo b {
3937
- color: red; }
3938
- CSS
3939
- a.\#{"foo"} b
3940
- {color: red}
3941
- SCSS
3942
- end
3943
-
3944
- def test_extra_comma_in_mixin_arglist
3945
- assert_equal <<CSS, render(<<SCSS)
3946
- .bar {
3947
- baz: bar; }
3948
- CSS
3949
- @mixin foo($a1,) {
3950
- baz: $a1;
3951
- }
3952
-
3953
- .bar {
3954
- @include foo(bar, );
3955
- }
3956
- SCSS
3957
- end
3958
-
3959
-
3960
- def test_extra_comma_between_parameters_in_mixin_arglist
3961
- assert_raise_message(Sass::SyntaxError, "Invalid CSS after \"...nclude foo(bar,\": expected \")\", was \", baz );\"") {render <<SCSS}
3962
- @mixin foo($a1, $a2) {
3963
- baz: $a1;
3964
- bef: $a2;
3965
- }
3966
-
3967
- .bar {
3968
- @include foo(bar,, baz );
3969
- }
3970
- SCSS
3971
- end
3972
-
3973
-
3974
- def test_extra_comma_in_mixin_arglist_ending_needs_have_parentheses_after
3975
- assert_raise_message(Sass::SyntaxError, "Invalid CSS after \" bri,\": expected \")\", was \"};\"") {render <<SCSS}
3976
- @mixin foo($a1, $a2) {
3977
- baz: $a1;
3978
- bal: $a2;
3979
- }
3980
-
3981
- .bar {
3982
- @include foo(
3983
- bar,
3984
- bri,
3985
- };
3986
- }
3987
- SCSS
3988
- end
3989
-
3990
-
3991
-
3992
- def test_interpolation
3993
- assert_equal <<CSS, render(<<SCSS)
3994
- ul li#foo a span.label {
3995
- foo: bar; }
3996
- CSS
3997
- $bar : "#foo";
3998
- ul li\#{$bar} a span.label { foo: bar; }
3999
- SCSS
4000
- end
4001
-
4002
- def test_mixin_with_keyword_args
4003
- assert_equal <<CSS, render(<<SCSS)
4004
- .mixed {
4005
- required: foo;
4006
- arg1: default-val1;
4007
- arg2: non-default-val2; }
4008
- CSS
4009
- @mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
4010
- required: $required;
4011
- arg1: $arg1;
4012
- arg2: $arg2;
4013
- }
4014
- .mixed { @include a-mixin(foo, $arg2: non-default-val2); }
4015
- SCSS
4016
- end
4017
-
4018
- def test_keyword_arg_scope
4019
- assert_equal <<CSS, render(<<SCSS)
4020
- .mixed {
4021
- arg1: default;
4022
- arg2: non-default; }
4023
- CSS
4024
- $arg1: default;
4025
- $arg2: default;
4026
- @mixin a-mixin($arg1: $arg1, $arg2: $arg2) {
4027
- arg1: $arg1;
4028
- arg2: $arg2;
4029
- }
4030
- .mixed { @include a-mixin($arg2: non-default); }
4031
- SCSS
4032
- end
4033
-
4034
- def test_passing_required_args_as_a_keyword_arg
4035
- assert_equal <<CSS, render(<<SCSS)
4036
- .mixed {
4037
- required: foo;
4038
- arg1: default-val1;
4039
- arg2: default-val2; }
4040
- CSS
4041
- @mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
4042
- required: $required;
4043
- arg1: $arg1;
4044
- arg2: $arg2; }
4045
- .mixed { @include a-mixin($required: foo); }
4046
- SCSS
4047
- end
4048
-
4049
- def test_passing_all_as_keyword_args_in_opposite_order
4050
- assert_equal <<CSS, render(<<SCSS)
4051
- .mixed {
4052
- required: foo;
4053
- arg1: non-default-val1;
4054
- arg2: non-default-val2; }
4055
- CSS
4056
- @mixin a-mixin($required, $arg1: default-val1, $arg2: default-val2) {
4057
- required: $required;
4058
- arg1: $arg1;
4059
- arg2: $arg2; }
4060
- .mixed { @include a-mixin($arg2: non-default-val2, $arg1: non-default-val1, $required: foo); }
4061
- SCSS
4062
- end
4063
-
4064
- def test_keyword_args_in_functions
4065
- assert_equal <<CSS, render(<<SCSS)
4066
- .keyed {
4067
- color: rgba(170, 119, 204, 0.4); }
4068
- CSS
4069
- .keyed { color: rgba($color: #a7c, $alpha: 0.4) }
4070
- SCSS
4071
- end
4072
-
4073
- def test_unknown_keyword_arg_raises_error
4074
- assert_raise_message(Sass::SyntaxError, "Mixin a doesn't have an argument named $c.") {render <<SCSS}
4075
- @mixin a($b: 1) { a: $b; }
4076
- div { @include a(1, $c: 3); }
4077
- SCSS
4078
- end
4079
-
4080
-
4081
- def test_newlines_removed_from_selectors_when_compressed
4082
- assert_equal <<CSS, render(<<SCSS, :style => :compressed)
4083
- z a,z b{display:block}
4084
- CSS
4085
- a
4086
- , b {
4087
- z & {
4088
- display: block;
4089
- }
4090
- }
4091
- SCSS
4092
- end
4093
-
4094
- def test_if_error_line
4095
- assert_raise_line(2) {render(<<SCSS)}
4096
- @if true {foo: bar}
4097
- }
4098
- SCSS
4099
- end
4100
-
4101
- def test_multiline_var
4102
- assert_equal <<CSS, render(<<SCSS)
4103
- foo {
4104
- a: 3;
4105
- b: false;
4106
- c: a b c; }
4107
- CSS
4108
- foo {
4109
- $var1: 1 +
4110
- 2;
4111
- $var2: true and
4112
- false;
4113
- $var3: a b
4114
- c;
4115
- a: $var1;
4116
- b: $var2;
4117
- c: $var3; }
4118
- SCSS
4119
- end
4120
-
4121
- def test_mixin_content
4122
- assert_equal <<CSS, render(<<SASS)
4123
- .parent {
4124
- background-color: red;
4125
- border-color: red; }
4126
- .parent .child {
4127
- background-color: yellow;
4128
- color: blue;
4129
- border-color: yellow; }
4130
- CSS
4131
- $color: blue;
4132
- @mixin context($class, $color: red) {
4133
- .\#{$class} {
4134
- background-color: $color;
4135
- @content;
4136
- border-color: $color;
4137
- }
4138
- }
4139
- @include context(parent) {
4140
- @include context(child, $color: yellow) {
4141
- color: $color;
4142
- }
4143
- }
4144
- SASS
4145
- end
4146
-
4147
- def test_empty_content
4148
- assert_equal <<CSS, render(<<SCSS)
4149
- a {
4150
- b: c; }
4151
- CSS
4152
- @mixin foo { @content }
4153
- a { b: c; @include foo {} }
4154
- SCSS
4155
- end
4156
-
4157
- def test_options_passed_to_script
4158
- assert_equal <<CSS, render(<<SCSS, :style => :compressed)
4159
- foo{color:#000}
4160
- CSS
4161
- foo {color: darken(black, 10%)}
4162
- SCSS
4163
- end
4164
-
4165
- # ref: https://github.com/nex3/sass/issues/104
4166
- def test_no_buffer_overflow
4167
- template = render <<SCSS
4168
- .aaa {
4169
- background-color: white;
4170
- }
4171
- .aaa .aaa .aaa {
4172
- background-color: black;
4173
- }
4174
- .bbb {
4175
- @extend .aaa;
4176
- }
4177
- .xxx {
4178
- @extend .bbb;
4179
- }
4180
- .yyy {
4181
- @extend .bbb;
4182
- }
4183
- .zzz {
4184
- @extend .bbb;
4185
- }
4186
- SCSS
4187
- Sass::SCSS::Parser.new(template, "test.scss", nil).parse
4188
- end
4189
-
4190
- def test_extend_in_media_in_rule
4191
- assert_equal(<<CSS, render(<<SCSS))
4192
- @media screen {
4193
- .foo {
4194
- a: b; } }
4195
- CSS
4196
- .foo {
4197
- @media screen {
4198
- @extend %bar;
4199
- }
4200
- }
4201
-
4202
- @media screen {
4203
- %bar {
4204
- a: b;
4205
- }
4206
- }
4207
- SCSS
4208
- end
4209
-
4210
- def test_import_with_supports_clause_interp
4211
- assert_equal(<<CSS, render(<<'SASS', :style => :compressed))
4212
- @import url("fallback-layout.css") supports(not (display: flex))
4213
- CSS
4214
- $display-type: flex;
4215
- @import url("fallback-layout.css") supports(not (display: #{$display-type}));
4216
- SASS
4217
- end
4218
-
4219
- def test_import_with_supports_clause
4220
- assert_equal(<<CSS, render(<<SASS, :style => :compressed))
4221
- @import url("fallback-layout.css") supports(not (display: flex));.foo{bar:baz}
4222
- CSS
4223
- @import url("fallback-layout.css") supports(not (display: flex));
4224
- .foo { bar: baz; }
4225
- SASS
4226
- end
4227
-
4228
- def test_crlf
4229
- # Attempt to reproduce https://github.com/sass/sass/issues/1985
4230
- assert_equal(<<CSS, render(<<SCSS))
4231
- p {
4232
- margin: 0; }
4233
- CSS
4234
- p {\r\n margin: 0;\r\n}
4235
- SCSS
4236
- end
4237
-
4238
- end