haml 3.1.0.alpha.14 → 3.1.0.alpha.17

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of haml might be problematic. Click here for more details.

Files changed (222) hide show
  1. data/EDGE_GEM_VERSION +1 -1
  2. data/VERSION +1 -1
  3. data/lib/haml.rb +3 -2
  4. data/lib/haml/exec.rb +0 -226
  5. data/lib/sass.rb +8 -0
  6. data/lib/sass/plugin.rb +8 -0
  7. data/lib/sass/rails2_shim.rb +9 -0
  8. data/lib/sass/rails3_shim.rb +16 -0
  9. data/vendor/sass/CONTRIBUTING +3 -0
  10. data/vendor/sass/MIT-LICENSE +20 -0
  11. data/vendor/sass/README.md +201 -0
  12. data/vendor/sass/Rakefile +363 -0
  13. data/vendor/sass/TODO +39 -0
  14. data/vendor/sass/VERSION +1 -0
  15. data/vendor/sass/VERSION_NAME +1 -0
  16. data/vendor/sass/bin/css2sass +13 -0
  17. data/vendor/sass/bin/sass +8 -0
  18. data/vendor/sass/bin/sass-convert +7 -0
  19. data/vendor/sass/doc-src/FAQ.md +35 -0
  20. data/vendor/sass/doc-src/INDENTED_SYNTAX.md +210 -0
  21. data/vendor/sass/doc-src/SASS_CHANGELOG.md +1878 -0
  22. data/vendor/sass/doc-src/SASS_REFERENCE.md +1713 -0
  23. data/vendor/sass/doc-src/SCSS_FOR_SASS_USERS.md +155 -0
  24. data/vendor/sass/ext/extconf.rb +10 -0
  25. data/vendor/sass/extra/update_watch.rb +13 -0
  26. data/vendor/sass/init.rb +18 -0
  27. data/vendor/sass/lib/sass.rb +71 -0
  28. data/vendor/sass/lib/sass/cache_store.rb +208 -0
  29. data/vendor/sass/lib/sass/callbacks.rb +66 -0
  30. data/vendor/sass/lib/sass/css.rb +294 -0
  31. data/vendor/sass/lib/sass/engine.rb +792 -0
  32. data/vendor/sass/lib/sass/environment.rb +143 -0
  33. data/vendor/sass/lib/sass/error.rb +201 -0
  34. data/vendor/sass/lib/sass/exec.rb +619 -0
  35. data/vendor/sass/lib/sass/importers.rb +22 -0
  36. data/vendor/sass/lib/sass/importers/base.rb +138 -0
  37. data/vendor/sass/lib/sass/importers/filesystem.rb +121 -0
  38. data/vendor/sass/lib/sass/less.rb +363 -0
  39. data/vendor/sass/lib/sass/plugin.rb +126 -0
  40. data/vendor/sass/lib/sass/plugin/compiler.rb +346 -0
  41. data/vendor/sass/lib/sass/plugin/configuration.rb +123 -0
  42. data/vendor/sass/lib/sass/plugin/generic.rb +15 -0
  43. data/vendor/sass/lib/sass/plugin/merb.rb +48 -0
  44. data/vendor/sass/lib/sass/plugin/rack.rb +47 -0
  45. data/vendor/sass/lib/sass/plugin/rails.rb +41 -0
  46. data/vendor/sass/lib/sass/plugin/staleness_checker.rb +145 -0
  47. data/vendor/sass/lib/sass/railtie.rb +8 -0
  48. data/vendor/sass/lib/sass/repl.rb +58 -0
  49. data/vendor/sass/lib/sass/root.rb +7 -0
  50. data/vendor/sass/lib/sass/script.rb +63 -0
  51. data/vendor/sass/lib/sass/script/bool.rb +18 -0
  52. data/vendor/sass/lib/sass/script/color.rb +491 -0
  53. data/vendor/sass/lib/sass/script/css_lexer.rb +29 -0
  54. data/vendor/sass/lib/sass/script/css_parser.rb +31 -0
  55. data/vendor/sass/lib/sass/script/funcall.rb +76 -0
  56. data/vendor/sass/lib/sass/script/functions.rb +852 -0
  57. data/vendor/sass/lib/sass/script/interpolation.rb +70 -0
  58. data/vendor/sass/lib/sass/script/lexer.rb +337 -0
  59. data/vendor/sass/lib/sass/script/literal.rb +236 -0
  60. data/vendor/sass/lib/sass/script/node.rb +112 -0
  61. data/vendor/sass/lib/sass/script/number.rb +423 -0
  62. data/vendor/sass/lib/sass/script/operation.rb +90 -0
  63. data/vendor/sass/lib/sass/script/parser.rb +392 -0
  64. data/vendor/sass/lib/sass/script/string.rb +67 -0
  65. data/vendor/sass/lib/sass/script/string_interpolation.rb +93 -0
  66. data/vendor/sass/lib/sass/script/unary_operation.rb +57 -0
  67. data/vendor/sass/lib/sass/script/variable.rb +48 -0
  68. data/vendor/sass/lib/sass/scss.rb +17 -0
  69. data/vendor/sass/lib/sass/scss/css_parser.rb +51 -0
  70. data/vendor/sass/lib/sass/scss/parser.rb +838 -0
  71. data/vendor/sass/lib/sass/scss/rx.rb +126 -0
  72. data/vendor/sass/lib/sass/scss/sass_parser.rb +11 -0
  73. data/vendor/sass/lib/sass/scss/script_lexer.rb +15 -0
  74. data/vendor/sass/lib/sass/scss/script_parser.rb +25 -0
  75. data/vendor/sass/lib/sass/scss/static_parser.rb +40 -0
  76. data/vendor/sass/lib/sass/selector.rb +361 -0
  77. data/vendor/sass/lib/sass/selector/abstract_sequence.rb +62 -0
  78. data/vendor/sass/lib/sass/selector/comma_sequence.rb +82 -0
  79. data/vendor/sass/lib/sass/selector/sequence.rb +236 -0
  80. data/vendor/sass/lib/sass/selector/simple.rb +113 -0
  81. data/vendor/sass/lib/sass/selector/simple_sequence.rb +135 -0
  82. data/vendor/sass/lib/sass/shared.rb +78 -0
  83. data/vendor/sass/lib/sass/tree/comment_node.rb +128 -0
  84. data/vendor/sass/lib/sass/tree/debug_node.rb +36 -0
  85. data/vendor/sass/lib/sass/tree/directive_node.rb +75 -0
  86. data/vendor/sass/lib/sass/tree/extend_node.rb +65 -0
  87. data/vendor/sass/lib/sass/tree/for_node.rb +67 -0
  88. data/vendor/sass/lib/sass/tree/if_node.rb +81 -0
  89. data/vendor/sass/lib/sass/tree/import_node.rb +124 -0
  90. data/vendor/sass/lib/sass/tree/mixin_def_node.rb +60 -0
  91. data/vendor/sass/lib/sass/tree/mixin_node.rb +123 -0
  92. data/vendor/sass/lib/sass/tree/node.rb +490 -0
  93. data/vendor/sass/lib/sass/tree/prop_node.rb +220 -0
  94. data/vendor/sass/lib/sass/tree/root_node.rb +125 -0
  95. data/vendor/sass/lib/sass/tree/rule_node.rb +273 -0
  96. data/vendor/sass/lib/sass/tree/variable_node.rb +39 -0
  97. data/vendor/sass/lib/sass/tree/warn_node.rb +42 -0
  98. data/vendor/sass/lib/sass/tree/while_node.rb +48 -0
  99. data/vendor/sass/lib/sass/util.rb +700 -0
  100. data/vendor/sass/lib/sass/util/subset_map.rb +101 -0
  101. data/vendor/sass/lib/sass/version.rb +109 -0
  102. data/vendor/sass/rails/init.rb +1 -0
  103. data/vendor/sass/sass.gemspec +32 -0
  104. data/vendor/sass/test/sass/cache_test.rb +74 -0
  105. data/vendor/sass/test/sass/callbacks_test.rb +61 -0
  106. data/vendor/sass/test/sass/conversion_test.rb +1210 -0
  107. data/vendor/sass/test/sass/css2sass_test.rb +364 -0
  108. data/vendor/sass/test/sass/data/hsl-rgb.txt +319 -0
  109. data/vendor/sass/test/sass/engine_test.rb +2305 -0
  110. data/vendor/sass/test/sass/extend_test.rb +1348 -0
  111. data/vendor/sass/test/sass/functions_test.rb +565 -0
  112. data/vendor/sass/test/sass/importer_test.rb +104 -0
  113. data/vendor/sass/test/sass/less_conversion_test.rb +632 -0
  114. data/vendor/sass/test/sass/mock_importer.rb +49 -0
  115. data/vendor/sass/test/sass/more_results/more1.css +9 -0
  116. data/vendor/sass/test/sass/more_results/more1_with_line_comments.css +26 -0
  117. data/vendor/sass/test/sass/more_results/more_import.css +29 -0
  118. data/vendor/sass/test/sass/more_templates/_more_partial.sass +2 -0
  119. data/vendor/sass/test/sass/more_templates/more1.sass +23 -0
  120. data/vendor/sass/test/sass/more_templates/more_import.sass +11 -0
  121. data/vendor/sass/test/sass/plugin_test.rb +430 -0
  122. data/vendor/sass/test/sass/results/alt.css +4 -0
  123. data/vendor/sass/test/sass/results/basic.css +9 -0
  124. data/vendor/sass/test/sass/results/compact.css +5 -0
  125. data/vendor/sass/test/sass/results/complex.css +86 -0
  126. data/vendor/sass/test/sass/results/compressed.css +1 -0
  127. data/vendor/sass/test/sass/results/expanded.css +19 -0
  128. data/vendor/sass/test/sass/results/import.css +31 -0
  129. data/vendor/sass/test/sass/results/line_numbers.css +49 -0
  130. data/vendor/sass/test/sass/results/mixins.css +95 -0
  131. data/vendor/sass/test/sass/results/multiline.css +24 -0
  132. data/vendor/sass/test/sass/results/nested.css +22 -0
  133. data/vendor/sass/test/sass/results/options.css +1 -0
  134. data/vendor/sass/test/sass/results/parent_ref.css +13 -0
  135. data/vendor/sass/test/sass/results/script.css +16 -0
  136. data/vendor/sass/test/sass/results/scss_import.css +31 -0
  137. data/vendor/sass/test/sass/results/scss_importee.css +2 -0
  138. data/vendor/sass/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
  139. data/vendor/sass/test/sass/results/subdir/subdir.css +3 -0
  140. data/vendor/sass/test/sass/results/units.css +11 -0
  141. data/vendor/sass/test/sass/results/warn.css +0 -0
  142. data/vendor/sass/test/sass/results/warn_imported.css +0 -0
  143. data/vendor/sass/test/sass/script_conversion_test.rb +254 -0
  144. data/vendor/sass/test/sass/script_test.rb +470 -0
  145. data/vendor/sass/test/sass/scss/css_test.rb +897 -0
  146. data/vendor/sass/test/sass/scss/rx_test.rb +156 -0
  147. data/vendor/sass/test/sass/scss/scss_test.rb +1088 -0
  148. data/vendor/sass/test/sass/scss/test_helper.rb +37 -0
  149. data/vendor/sass/test/sass/templates/_partial.sass +2 -0
  150. data/vendor/sass/test/sass/templates/alt.sass +16 -0
  151. data/vendor/sass/test/sass/templates/basic.sass +23 -0
  152. data/vendor/sass/test/sass/templates/bork1.sass +2 -0
  153. data/vendor/sass/test/sass/templates/bork2.sass +2 -0
  154. data/vendor/sass/test/sass/templates/bork3.sass +2 -0
  155. data/vendor/sass/test/sass/templates/bork4.sass +2 -0
  156. data/vendor/sass/test/sass/templates/compact.sass +17 -0
  157. data/vendor/sass/test/sass/templates/complex.sass +305 -0
  158. data/vendor/sass/test/sass/templates/compressed.sass +15 -0
  159. data/vendor/sass/test/sass/templates/expanded.sass +17 -0
  160. data/vendor/sass/test/sass/templates/import.sass +12 -0
  161. data/vendor/sass/test/sass/templates/importee.less +2 -0
  162. data/vendor/sass/test/sass/templates/importee.sass +19 -0
  163. data/vendor/sass/test/sass/templates/line_numbers.sass +13 -0
  164. data/vendor/sass/test/sass/templates/mixin_bork.sass +5 -0
  165. data/vendor/sass/test/sass/templates/mixins.sass +76 -0
  166. data/vendor/sass/test/sass/templates/multiline.sass +20 -0
  167. data/vendor/sass/test/sass/templates/nested.sass +25 -0
  168. data/vendor/sass/test/sass/templates/nested_bork1.sass +2 -0
  169. data/vendor/sass/test/sass/templates/nested_bork2.sass +2 -0
  170. data/vendor/sass/test/sass/templates/nested_bork3.sass +2 -0
  171. data/vendor/sass/test/sass/templates/nested_bork4.sass +2 -0
  172. data/vendor/sass/test/sass/templates/nested_mixin_bork.sass +6 -0
  173. data/vendor/sass/test/sass/templates/options.sass +2 -0
  174. data/vendor/sass/test/sass/templates/parent_ref.sass +25 -0
  175. data/vendor/sass/test/sass/templates/script.sass +101 -0
  176. data/vendor/sass/test/sass/templates/scss_import.scss +11 -0
  177. data/vendor/sass/test/sass/templates/scss_importee.scss +1 -0
  178. data/vendor/sass/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
  179. data/vendor/sass/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
  180. data/vendor/sass/test/sass/templates/subdir/subdir.sass +6 -0
  181. data/vendor/sass/test/sass/templates/units.sass +11 -0
  182. data/vendor/sass/test/sass/templates/warn.sass +3 -0
  183. data/vendor/sass/test/sass/templates/warn_imported.sass +4 -0
  184. data/vendor/sass/test/sass/test_helper.rb +8 -0
  185. data/vendor/sass/test/sass/util/subset_map_test.rb +91 -0
  186. data/vendor/sass/test/sass/util_test.rb +275 -0
  187. data/vendor/sass/test/test_helper.rb +64 -0
  188. data/vendor/sass/vendor/fssm/LICENSE +20 -0
  189. data/vendor/sass/vendor/fssm/README.markdown +55 -0
  190. data/vendor/sass/vendor/fssm/Rakefile +59 -0
  191. data/vendor/sass/vendor/fssm/VERSION.yml +5 -0
  192. data/vendor/sass/vendor/fssm/example.rb +9 -0
  193. data/vendor/sass/vendor/fssm/fssm.gemspec +77 -0
  194. data/vendor/sass/vendor/fssm/lib/fssm.rb +33 -0
  195. data/vendor/sass/vendor/fssm/lib/fssm/backends/fsevents.rb +36 -0
  196. data/vendor/sass/vendor/fssm/lib/fssm/backends/inotify.rb +26 -0
  197. data/vendor/sass/vendor/fssm/lib/fssm/backends/polling.rb +25 -0
  198. data/vendor/sass/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +131 -0
  199. data/vendor/sass/vendor/fssm/lib/fssm/monitor.rb +26 -0
  200. data/vendor/sass/vendor/fssm/lib/fssm/path.rb +91 -0
  201. data/vendor/sass/vendor/fssm/lib/fssm/pathname.rb +502 -0
  202. data/vendor/sass/vendor/fssm/lib/fssm/state/directory.rb +57 -0
  203. data/vendor/sass/vendor/fssm/lib/fssm/state/file.rb +24 -0
  204. data/vendor/sass/vendor/fssm/lib/fssm/support.rb +63 -0
  205. data/vendor/sass/vendor/fssm/lib/fssm/tree.rb +176 -0
  206. data/vendor/sass/vendor/fssm/profile/prof-cache.rb +40 -0
  207. data/vendor/sass/vendor/fssm/profile/prof-fssm-pathname.html +1231 -0
  208. data/vendor/sass/vendor/fssm/profile/prof-pathname.rb +68 -0
  209. data/vendor/sass/vendor/fssm/profile/prof-plain-pathname.html +988 -0
  210. data/vendor/sass/vendor/fssm/profile/prof.html +2379 -0
  211. data/vendor/sass/vendor/fssm/spec/path_spec.rb +75 -0
  212. data/vendor/sass/vendor/fssm/spec/root/duck/quack.txt +0 -0
  213. data/vendor/sass/vendor/fssm/spec/root/file.css +0 -0
  214. data/vendor/sass/vendor/fssm/spec/root/file.rb +0 -0
  215. data/vendor/sass/vendor/fssm/spec/root/file.yml +0 -0
  216. data/vendor/sass/vendor/fssm/spec/root/moo/cow.txt +0 -0
  217. data/vendor/sass/vendor/fssm/spec/spec_helper.rb +14 -0
  218. data/vendor/sass/yard/callbacks.rb +29 -0
  219. data/vendor/sass/yard/default/fulldoc/html/css/common.sass +26 -0
  220. data/vendor/sass/yard/default/layout/html/footer.erb +12 -0
  221. data/vendor/sass/yard/inherited_hash.rb +41 -0
  222. metadata +219 -2
@@ -0,0 +1,2305 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require File.dirname(__FILE__) + '/../test_helper'
4
+ require File.dirname(__FILE__) + '/test_helper'
5
+ require 'sass/engine'
6
+ require 'stringio'
7
+ require 'mock_importer'
8
+
9
+ module Sass::Script::Functions::UserFunctions
10
+ def option(name)
11
+ Sass::Script::String.new(@options[name.value.to_sym].to_s)
12
+ end
13
+ end
14
+
15
+ class SassEngineTest < Test::Unit::TestCase
16
+ FAKE_FILE_NAME = __FILE__.gsub(/rb$/,"sass")
17
+ # A map of erroneous Sass documents to the error messages they should produce.
18
+ # The error messages may be arrays;
19
+ # if so, the second element should be the line number that should be reported for the error.
20
+ # If this isn't provided, the tests will assume the line number should be the last line of the document.
21
+ EXCEPTION_MAP = {
22
+ "$a: 1 + " => 'Invalid CSS after "1 +": expected expression (e.g. 1px, bold), was ""',
23
+ "$a: 1 + 2 +" => 'Invalid CSS after "1 + 2 +": expected expression (e.g. 1px, bold), was ""',
24
+ "$a: 1 + 2 + %" => 'Invalid CSS after "1 + 2 + ": expected expression (e.g. 1px, bold), was "%"',
25
+ "$a: foo(\"bar\"" => 'Invalid CSS after "foo("bar"": expected ")", was ""',
26
+ "$a: 1 }" => 'Invalid CSS after "1 ": expected expression (e.g. 1px, bold), was "}"',
27
+ "$a: 1 }foo\"" => 'Invalid CSS after "1 ": expected expression (e.g. 1px, bold), was "}foo""',
28
+ ":" => 'Invalid property: ":".',
29
+ ": a" => 'Invalid property: ": a".',
30
+ "a\n :b" => <<MSG,
31
+ Invalid property: ":b" (no value).
32
+ If ":b" should be a selector, use "\\:b" instead.
33
+ MSG
34
+ "a\n b:" => 'Invalid property: "b:" (no value).',
35
+ "a\n :b: c" => 'Invalid property: ":b: c".',
36
+ "a\n :b:c d" => 'Invalid property: ":b:c d".',
37
+ "a\n :b c;" => 'Invalid CSS after "c": expected expression (e.g. 1px, bold), was ";"',
38
+ "a\n b: c;" => 'Invalid CSS after "c": expected expression (e.g. 1px, bold), was ";"',
39
+ ".foo ^bar\n a: b" => ['Invalid CSS after ".foo ": expected selector, was "^bar"', 1],
40
+ "a\n @extend .foo ^bar" => 'Invalid CSS after ".foo ": expected selector, was "^bar"',
41
+ "a: b" => 'Properties aren\'t allowed at the root of a document.',
42
+ ":a b" => 'Properties aren\'t allowed at the root of a document.',
43
+ "!" => 'Invalid variable: "!".',
44
+ "$a" => 'Invalid variable: "$a".',
45
+ "! a" => 'Invalid variable: "! a".',
46
+ "$a b" => 'Invalid variable: "$a b".',
47
+ "$a: 1b + 2c" => "Incompatible units: 'c' and 'b'.",
48
+ "$a: 1b < 2c" => "Incompatible units: 'c' and 'b'.",
49
+ "$a: 1b > 2c" => "Incompatible units: 'c' and 'b'.",
50
+ "$a: 1b <= 2c" => "Incompatible units: 'c' and 'b'.",
51
+ "$a: 1b >= 2c" => "Incompatible units: 'c' and 'b'.",
52
+ "a\n b: 1b * 2c" => "2b*c isn't a valid CSS value.",
53
+ "a\n b: 1b % 2c" => "Cannot modulo by a number with units: 2c.",
54
+ "$a: 2px + #ccc" => "Cannot add a number with units (2px) to a color (#cccccc).",
55
+ "$a: #ccc + 2px" => "Cannot add a number with units (2px) to a color (#cccccc).",
56
+ "& a\n :b c" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 1],
57
+ "a\n :b\n c" => "Illegal nesting: Only properties may be nested beneath properties.",
58
+ "a,\n :b c" => ["Rules can\'t end in commas.", 1],
59
+ "a," => "Rules can\'t end in commas.",
60
+ "a,\n$b: 1" => ["Rules can\'t end in commas.", 1],
61
+ "$a: b\n :c d\n" => "Illegal nesting: Nothing may be nested beneath variable declarations.",
62
+ "@import foo.sass" => "File to import not found or unreadable: foo.sass.",
63
+ "a,\n$b: 1" => ["Rules can\'t end in commas.", 1],
64
+ "$a: b\n :c d\n" => "Illegal nesting: Nothing may be nested beneath variable declarations.",
65
+ "@import foo.sass" => <<MSG,
66
+ File to import not found or unreadable: foo.sass.
67
+ Load path: .
68
+ MSG
69
+ "@import templates/basic\n foo" => "Illegal nesting: Nothing may be nested beneath import directives.",
70
+ "foo\n @import templates/basic" => "Import directives may only be used at the root of a document.",
71
+ "foo\n @import #{File.dirname(__FILE__)}/templates/basic" => "Import directives may only be used at the root of a document.",
72
+ '$foo: "bar" "baz" !' => %Q{Invalid CSS after ""bar" "baz" ": expected expression (e.g. 1px, bold), was "!"},
73
+ "=foo\n :color red\n.bar\n +bang" => "Undefined mixin 'bang'.",
74
+ "=foo\n :color red\n.bar\n +bang_bop" => "Undefined mixin 'bang_bop'.",
75
+ "=foo\n :color red\n.bar\n +bang-bop" => "Undefined mixin 'bang-bop'.",
76
+ ".bar\n =foo\n :color red\n" => ["Mixins may only be defined at the root of a document.", 2],
77
+ "=foo\n :color red\n.bar\n +foo\n :color red" => "Illegal nesting: Nothing may be nested beneath mixin directives.",
78
+ " a\n b: c" => ["Indenting at the beginning of the document is illegal.", 1],
79
+ " \n \n\t\n a\n b: c" => ["Indenting at the beginning of the document is illegal.", 4],
80
+ "a\n b: c\n b: c" => ["Inconsistent indentation: 1 space was used for indentation, but the rest of the document was indented using 2 spaces.", 3],
81
+ "a\n b: c\na\n b: c" => ["Inconsistent indentation: 1 space was used for indentation, but the rest of the document was indented using 2 spaces.", 4],
82
+ "a\n\t\tb: c\n\tb: c" => ["Inconsistent indentation: 1 tab was used for indentation, but the rest of the document was indented using 2 tabs.", 3],
83
+ "a\n b: c\n b: c" => ["Inconsistent indentation: 3 spaces were used for indentation, but the rest of the document was indented using 2 spaces.", 3],
84
+ "a\n b: c\n a\n d: e" => ["Inconsistent indentation: 3 spaces were used for indentation, but the rest of the document was indented using 2 spaces.", 4],
85
+ "a\n b: c\na\n d: e" => ["The line was indented 2 levels deeper than the previous line.", 4],
86
+ "a\n b: c\n a\n d: e" => ["The line was indented 3 levels deeper than the previous line.", 4],
87
+ "a\n \tb: c" => ["Indentation can't use both tabs and spaces.", 2],
88
+ "=a(" => 'Invalid CSS after "(": expected variable (e.g. $foo), was ""',
89
+ "=a(b)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was "b)"',
90
+ "=a(,)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was ",)"',
91
+ "=a($)" => 'Invalid CSS after "(": expected variable (e.g. $foo), was "$)"',
92
+ "=a($foo bar)" => 'Invalid CSS after "($foo ": expected ")", was "bar)"',
93
+ "=foo\n bar: baz\n+foo" => ["Properties aren't allowed at the root of a document.", 2],
94
+ "a-\#{$b\n c: d" => ['Invalid CSS after "a-#{$b": expected "}", was ""', 1],
95
+ "=a($b = 1, $c)" => "Required argument $c must come before any optional arguments.",
96
+ "=a($b = 1)\n a: $b\ndiv\n +a(1,2)" => "Mixin a takes 1 argument but 2 were passed.",
97
+ "=a($b)\n a: $b\ndiv\n +a" => "Mixin a is missing parameter $b.",
98
+ "@else\n a\n b: c" => ["@else must come after @if.", 1],
99
+ "@if false\n@else foo" => "Invalid else directive '@else foo': expected 'if <expr>'.",
100
+ "@if false\n@else if " => "Invalid else directive '@else if': expected 'if <expr>'.",
101
+ "a\n !b: 12\nc\n d: !b" => 'Undefined variable: "$b".',
102
+ "a\n $b: 12\nc\n d: $b" => 'Undefined variable: "$b".',
103
+ "=foo\n $b: 12\nc\n +foo\n d: $b" => 'Undefined variable: "$b".',
104
+ "c\n d: $b-foo" => 'Undefined variable: "$b-foo".',
105
+ "c\n d: $b_foo" => 'Undefined variable: "$b_foo".',
106
+ '@for $a from "foo" to 1' => '"foo" is not an integer.',
107
+ '@for $a from 1 to "2"' => '"2" is not an integer.',
108
+ '@for $a from 1 to "foo"' => '"foo" is not an integer.',
109
+ '@for $a from 1 to 1.232323' => '1.232 is not an integer.',
110
+ '@for $a from 1px to 3em' => "Incompatible units: 'em' and 'px'.",
111
+ '@if' => "Invalid if directive '@if': expected expression.",
112
+ '@while' => "Invalid while directive '@while': expected expression.",
113
+ '@debug' => "Invalid debug directive '@debug': expected expression.",
114
+ %Q{@debug "a message"\n "nested message"} => "Illegal nesting: Nothing may be nested beneath debug directives.",
115
+ '@warn' => "Invalid warn directive '@warn': expected expression.",
116
+ %Q{@warn "a message"\n "nested message"} => "Illegal nesting: Nothing may be nested beneath warn directives.",
117
+ "/* foo\n bar\n baz" => "Inconsistent indentation: previous line was indented by 4 spaces, but this line was indented by 2 spaces.",
118
+
119
+ # Regression tests
120
+ "a\n b:\n c\n d" => ["Illegal nesting: Only properties may be nested beneath properties.", 3],
121
+ "& foo\n bar: baz\n blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 1],
122
+ "a\n b: c\n& foo\n bar: baz\n blat: bang" => ["Base-level rules cannot contain the parent-selector-referencing character '&'.", 3],
123
+ }
124
+
125
+ def teardown
126
+ clean_up_sassc
127
+ end
128
+
129
+ def test_basic_render
130
+ renders_correctly "basic", { :style => :compact }
131
+ end
132
+
133
+ def test_empty_render
134
+ assert_equal "", render("")
135
+ end
136
+
137
+ def test_multiple_calls_to_render
138
+ sass = Sass::Engine.new("a\n b: c")
139
+ assert_equal sass.render, sass.render
140
+ end
141
+
142
+ def test_alternate_styles
143
+ renders_correctly "expanded", { :style => :expanded }
144
+ renders_correctly "compact", { :style => :compact }
145
+ renders_correctly "nested", { :style => :nested }
146
+ renders_correctly "compressed", { :style => :compressed }
147
+ end
148
+
149
+ def test_compile
150
+ assert_equal "div { hello: world; }\n", Sass.compile("$who: world\ndiv\n hello: $who", :syntax => :sass, :style => :compact)
151
+ assert_equal "div { hello: world; }\n", Sass.compile("$who: world; div { hello: $who }", :style => :compact)
152
+ end
153
+
154
+ def test_compile_file
155
+ FileUtils.mkdir_p(absolutize("tmp"))
156
+ open(absolutize("tmp/test_compile_file.sass"), "w") {|f| f.write("$who: world\ndiv\n hello: $who")}
157
+ open(absolutize("tmp/test_compile_file.scss"), "w") {|f| f.write("$who: world; div { hello: $who }")}
158
+ assert_equal "div { hello: world; }\n", Sass.compile_file(absolutize("tmp/test_compile_file.sass"), :style => :compact)
159
+ assert_equal "div { hello: world; }\n", Sass.compile_file(absolutize("tmp/test_compile_file.scss"), :style => :compact)
160
+ ensure
161
+ FileUtils.rm_rf(absolutize("tmp"))
162
+ end
163
+
164
+ def test_compile_file_to_css_file
165
+ FileUtils.mkdir_p(absolutize("tmp"))
166
+ open(absolutize("tmp/test_compile_file.sass"), "w") {|f| f.write("$who: world\ndiv\n hello: $who")}
167
+ open(absolutize("tmp/test_compile_file.scss"), "w") {|f| f.write("$who: world; div { hello: $who }")}
168
+ Sass.compile_file(absolutize("tmp/test_compile_file.sass"), absolutize("tmp/test_compile_file_sass.css"), :style => :compact)
169
+ Sass.compile_file(absolutize("tmp/test_compile_file.scss"), absolutize("tmp/test_compile_file_scss.css"), :style => :compact)
170
+ assert_equal "div { hello: world; }\n", File.read(absolutize("tmp/test_compile_file_sass.css"))
171
+ assert_equal "div { hello: world; }\n", File.read(absolutize("tmp/test_compile_file_scss.css"))
172
+ ensure
173
+ FileUtils.rm_rf(absolutize("tmp"))
174
+ end
175
+
176
+ def test_flexible_tabulation
177
+ assert_equal("p {\n a: b; }\n p q {\n c: d; }\n",
178
+ render("p\n a: b\n q\n c: d\n"))
179
+ assert_equal("p {\n a: b; }\n p q {\n c: d; }\n",
180
+ render("p\n\ta: b\n\tq\n\t\tc: d\n"))
181
+ end
182
+
183
+ EXCEPTION_MAP.each do |key, value|
184
+ define_method("test_exception (#{key.inspect})") do
185
+ line = 10
186
+ begin
187
+ silence_warnings {Sass::Engine.new(key, :filename => FAKE_FILE_NAME, :line => line).render}
188
+ rescue Sass::SyntaxError => err
189
+ value = [value] unless value.is_a?(Array)
190
+
191
+ assert_equal(value.first.rstrip, err.message, "Line: #{key}")
192
+ assert_equal(FAKE_FILE_NAME, err.sass_filename)
193
+ assert_equal((value[1] || key.split("\n").length) + line - 1, err.sass_line, "Line: #{key}")
194
+ assert_match(/#{Regexp.escape(FAKE_FILE_NAME)}:[0-9]+/, err.backtrace[0], "Line: #{key}")
195
+ else
196
+ assert(false, "Exception not raised for\n#{key}")
197
+ end
198
+ end
199
+ end
200
+
201
+ def test_exception_line
202
+ to_render = <<SASS
203
+ rule
204
+ :prop val
205
+ // comment!
206
+
207
+ :broken
208
+ SASS
209
+ begin
210
+ Sass::Engine.new(to_render).render
211
+ rescue Sass::SyntaxError => err
212
+ assert_equal(5, err.sass_line)
213
+ else
214
+ assert(false, "Exception not raised for '#{to_render}'!")
215
+ end
216
+ end
217
+
218
+ def test_exception_location
219
+ to_render = <<SASS
220
+ rule
221
+ :prop val
222
+ // comment!
223
+
224
+ :broken
225
+ SASS
226
+ begin
227
+ Sass::Engine.new(to_render, :filename => FAKE_FILE_NAME, :line => (__LINE__-7)).render
228
+ rescue Sass::SyntaxError => err
229
+ assert_equal(FAKE_FILE_NAME, err.sass_filename)
230
+ assert_equal((__LINE__-6), err.sass_line)
231
+ else
232
+ assert(false, "Exception not raised for '#{to_render}'!")
233
+ end
234
+ end
235
+
236
+ def test_imported_exception
237
+ [1, 2, 3, 4].each do |i|
238
+ begin
239
+ Sass::Engine.new("@import bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
240
+ rescue Sass::SyntaxError => err
241
+ assert_equal(2, err.sass_line)
242
+ assert_match(/(\/|^)bork#{i}\.sass$/, err.sass_filename)
243
+
244
+ assert_hash_has(err.sass_backtrace.first,
245
+ :filename => err.sass_filename, :line => err.sass_line)
246
+
247
+ assert_nil(err.sass_backtrace[1][:filename])
248
+ assert_equal(1, err.sass_backtrace[1][:line])
249
+
250
+ assert_match(/(\/|^)bork#{i}\.sass:2$/, err.backtrace.first)
251
+ assert_equal("(sass):1", err.backtrace[1])
252
+ else
253
+ assert(false, "Exception not raised for imported template: bork#{i}")
254
+ end
255
+ end
256
+ end
257
+
258
+ def test_double_imported_exception
259
+ [1, 2, 3, 4].each do |i|
260
+ begin
261
+ Sass::Engine.new("@import nested_bork#{i}", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
262
+ rescue Sass::SyntaxError => err
263
+ assert_equal(2, err.sass_line)
264
+ assert_match(/(\/|^)bork#{i}\.sass$/, err.sass_filename)
265
+
266
+ assert_hash_has(err.sass_backtrace.first,
267
+ :filename => err.sass_filename, :line => err.sass_line)
268
+
269
+ assert_match(/(\/|^)nested_bork#{i}\.sass$/, err.sass_backtrace[1][:filename])
270
+ assert_equal(2, err.sass_backtrace[1][:line])
271
+
272
+ assert_nil(err.sass_backtrace[2][:filename])
273
+ assert_equal(1, err.sass_backtrace[2][:line])
274
+
275
+ assert_match(/(\/|^)bork#{i}\.sass:2$/, err.backtrace.first)
276
+ assert_match(/(\/|^)nested_bork#{i}\.sass:2$/, err.backtrace[1])
277
+ assert_equal("(sass):1", err.backtrace[2])
278
+ else
279
+ assert(false, "Exception not raised for imported template: bork#{i}")
280
+ end
281
+ end
282
+ end
283
+
284
+ def test_mixin_exception
285
+ render(<<SASS)
286
+ =error-mixin($a)
287
+ color: $a * 1em * 1px
288
+
289
+ =outer-mixin($a)
290
+ +error-mixin($a)
291
+
292
+ .error
293
+ +outer-mixin(12)
294
+ SASS
295
+ assert(false, "Exception not raised")
296
+ rescue Sass::SyntaxError => err
297
+ assert_equal(2, err.sass_line)
298
+ assert_equal(filename_for_test, err.sass_filename)
299
+ assert_equal("error-mixin", err.sass_mixin)
300
+
301
+ assert_hash_has(err.sass_backtrace.first, :line => err.sass_line,
302
+ :filename => err.sass_filename, :mixin => err.sass_mixin)
303
+ assert_hash_has(err.sass_backtrace[1], :line => 5,
304
+ :filename => filename_for_test, :mixin => "outer-mixin")
305
+ assert_hash_has(err.sass_backtrace[2], :line => 8,
306
+ :filename => filename_for_test, :mixin => nil)
307
+
308
+ assert_equal("#{filename_for_test}:2:in `error-mixin'", err.backtrace.first)
309
+ assert_equal("#{filename_for_test}:5:in `outer-mixin'", err.backtrace[1])
310
+ assert_equal("#{filename_for_test}:8", err.backtrace[2])
311
+ end
312
+
313
+ def test_mixin_callsite_exception
314
+ render(<<SASS)
315
+ =one-arg-mixin($a)
316
+ color: $a
317
+
318
+ =outer-mixin($a)
319
+ +one-arg-mixin($a, 12)
320
+
321
+ .error
322
+ +outer-mixin(12)
323
+ SASS
324
+ assert(false, "Exception not raised")
325
+ rescue Sass::SyntaxError => err
326
+ assert_hash_has(err.sass_backtrace.first, :line => 5,
327
+ :filename => filename_for_test, :mixin => "one-arg-mixin")
328
+ assert_hash_has(err.sass_backtrace[1], :line => 5,
329
+ :filename => filename_for_test, :mixin => "outer-mixin")
330
+ assert_hash_has(err.sass_backtrace[2], :line => 8,
331
+ :filename => filename_for_test, :mixin => nil)
332
+ end
333
+
334
+ def test_mixin_exception_cssize
335
+ render(<<SASS)
336
+ =parent-ref-mixin
337
+ & foo
338
+ a: b
339
+
340
+ =outer-mixin
341
+ +parent-ref-mixin
342
+
343
+ +outer-mixin
344
+ SASS
345
+ assert(false, "Exception not raised")
346
+ rescue Sass::SyntaxError => err
347
+ assert_hash_has(err.sass_backtrace.first, :line => 2,
348
+ :filename => filename_for_test, :mixin => "parent-ref-mixin")
349
+ assert_hash_has(err.sass_backtrace[1], :line => 6,
350
+ :filename => filename_for_test, :mixin => "outer-mixin")
351
+ assert_hash_has(err.sass_backtrace[2], :line => 8,
352
+ :filename => filename_for_test, :mixin => nil)
353
+ end
354
+
355
+ def test_mixin_and_import_exception
356
+ Sass::Engine.new("@import nested_mixin_bork", :load_paths => [File.dirname(__FILE__) + '/templates/']).render
357
+ assert(false, "Exception not raised")
358
+ rescue Sass::SyntaxError => err
359
+ assert_match(/(\/|^)nested_mixin_bork\.sass$/, err.sass_backtrace.first[:filename])
360
+ assert_hash_has(err.sass_backtrace.first, :mixin => "error-mixin", :line => 4)
361
+
362
+ assert_match(/(\/|^)mixin_bork\.sass$/, err.sass_backtrace[1][:filename])
363
+ assert_hash_has(err.sass_backtrace[1], :mixin => "outer-mixin", :line => 2)
364
+
365
+ assert_match(/(\/|^)mixin_bork\.sass$/, err.sass_backtrace[2][:filename])
366
+ assert_hash_has(err.sass_backtrace[2], :mixin => nil, :line => 5)
367
+
368
+ assert_match(/(\/|^)nested_mixin_bork\.sass$/, err.sass_backtrace[3][:filename])
369
+ assert_hash_has(err.sass_backtrace[3], :mixin => nil, :line => 6)
370
+
371
+ assert_hash_has(err.sass_backtrace[4], :filename => nil, :mixin => nil, :line => 1)
372
+ end
373
+
374
+ def test_basic_mixin_loop_exception
375
+ render <<SASS
376
+ @mixin foo
377
+ @include foo
378
+ @include foo
379
+ SASS
380
+ assert(false, "Exception not raised")
381
+ rescue Sass::SyntaxError => err
382
+ assert_equal("An @include loop has been found: foo includes itself", err.message)
383
+ assert_hash_has(err.sass_backtrace[0], :mixin => "foo", :line => 2)
384
+ end
385
+
386
+ def test_double_mixin_loop_exception
387
+ render <<SASS
388
+ @mixin foo
389
+ @include bar
390
+ @mixin bar
391
+ @include foo
392
+ @include foo
393
+ SASS
394
+ assert(false, "Exception not raised")
395
+ rescue Sass::SyntaxError => err
396
+ assert_equal(<<MESSAGE.rstrip, err.message)
397
+ An @include loop has been found:
398
+ foo includes bar
399
+ bar includes foo
400
+ MESSAGE
401
+ assert_hash_has(err.sass_backtrace[0], :mixin => "bar", :line => 4)
402
+ assert_hash_has(err.sass_backtrace[1], :mixin => "foo", :line => 2)
403
+ end
404
+
405
+ def test_deep_mixin_loop_exception
406
+ render <<SASS
407
+ @mixin foo
408
+ @include bar
409
+
410
+ @mixin bar
411
+ @include baz
412
+
413
+ @mixin baz
414
+ @include foo
415
+
416
+ @include foo
417
+ SASS
418
+ assert(false, "Exception not raised")
419
+ rescue Sass::SyntaxError => err
420
+ assert_equal(<<MESSAGE.rstrip, err.message)
421
+ An @include loop has been found:
422
+ foo includes bar
423
+ bar includes baz
424
+ baz includes foo
425
+ MESSAGE
426
+ assert_hash_has(err.sass_backtrace[0], :mixin => "baz", :line => 8)
427
+ assert_hash_has(err.sass_backtrace[1], :mixin => "bar", :line => 5)
428
+ assert_hash_has(err.sass_backtrace[2], :mixin => "foo", :line => 2)
429
+ end
430
+
431
+ def test_exception_css_with_offset
432
+ opts = {:full_exception => true, :line => 362}
433
+ render(("a\n b: c\n" * 10) + "d\n e:\n" + ("f\n g: h\n" * 10), opts)
434
+ rescue Sass::SyntaxError => e
435
+ assert_equal(<<CSS, Sass::SyntaxError.exception_to_css(e, opts).split("\n")[0..15].join("\n"))
436
+ /*
437
+ Syntax error: Invalid property: "e:" (no value).
438
+ on line 383 of test_exception_css_with_offset_inline.sass
439
+
440
+ 378: a
441
+ 379: b: c
442
+ 380: a
443
+ 381: b: c
444
+ 382: d
445
+ 383: e:
446
+ 384: f
447
+ 385: g: h
448
+ 386: f
449
+ 387: g: h
450
+ 388: f
451
+ CSS
452
+ else
453
+ assert(false, "Exception not raised for test_exception_css_with_offset")
454
+ end
455
+
456
+ def test_exception_css_with_mixins
457
+ opts = {:full_exception => true}
458
+ render(<<SASS, opts)
459
+ =error-mixin($a)
460
+ color: $a * 1em * 1px
461
+
462
+ =outer-mixin($a)
463
+ +error-mixin($a)
464
+
465
+ .error
466
+ +outer-mixin(12)
467
+ SASS
468
+ rescue Sass::SyntaxError => e
469
+ assert_equal(<<CSS, Sass::SyntaxError.exception_to_css(e, opts).split("\n")[0..13].join("\n"))
470
+ /*
471
+ Syntax error: 12em*px isn't a valid CSS value.
472
+ on line 2 of test_exception_css_with_mixins_inline.sass, in `error-mixin'
473
+ from line 5 of test_exception_css_with_mixins_inline.sass, in `outer-mixin'
474
+ from line 8 of test_exception_css_with_mixins_inline.sass
475
+
476
+ 1: =error-mixin($a)
477
+ 2: color: $a * 1em * 1px
478
+ 3:
479
+ 4: =outer-mixin($a)
480
+ 5: +error-mixin($a)
481
+ 6:
482
+ 7: .error
483
+ CSS
484
+ else
485
+ assert(false, "Exception not raised")
486
+ end
487
+
488
+ def test_cssize_exception_css
489
+ opts = {:full_exception => true}
490
+ render(<<SASS, opts)
491
+ .filler
492
+ stuff: "stuff!"
493
+
494
+ a: b
495
+
496
+ .more.filler
497
+ a: b
498
+ SASS
499
+ rescue Sass::SyntaxError => e
500
+ assert_equal(<<CSS, Sass::SyntaxError.exception_to_css(e, opts).split("\n")[0..11].join("\n"))
501
+ /*
502
+ Syntax error: Properties aren't allowed at the root of a document.
503
+ on line 4 of test_cssize_exception_css_inline.sass
504
+
505
+ 1: .filler
506
+ 2: stuff: "stuff!"
507
+ 3:
508
+ 4: a: b
509
+ 5:
510
+ 6: .more.filler
511
+ 7: a: b
512
+ CSS
513
+ else
514
+ assert(false, "Exception not raised")
515
+ end
516
+
517
+ def test_css_import
518
+ assert_equal("@import url(./fonts.css);\n", render("@import \"./fonts.css\""))
519
+ end
520
+
521
+ def test_http_import
522
+ assert_equal("@import url(http://fonts.googleapis.com/css?family=Droid+Sans);\n",
523
+ render("@import \"http://fonts.googleapis.com/css?family=Droid+Sans\""))
524
+ end
525
+
526
+ def test_url_import
527
+ assert_equal("@import url(fonts.sass);\n", render("@import url(fonts.sass)"))
528
+ end
529
+
530
+ def test_sass_import
531
+ sassc_file = sassc_path("importee")
532
+ assert !File.exists?(sassc_file)
533
+ renders_correctly "import", { :style => :compact, :load_paths => [File.dirname(__FILE__) + "/templates"] }
534
+ assert File.exists?(sassc_file)
535
+ end
536
+
537
+ def test_nonexistent_extensionless_import
538
+ assert_raise_message(Sass::SyntaxError, <<ERR.rstrip) do
539
+ File to import not found or unreadable: nonexistent.
540
+ Load path: .
541
+ ERR
542
+ assert_equal("@import url(nonexistent.css);\n", render("@import nonexistent"))
543
+ end
544
+ end
545
+
546
+ def test_no_cache
547
+ assert !File.exists?(sassc_path("importee"))
548
+ renders_correctly("import", {
549
+ :style => :compact, :cache => false,
550
+ :load_paths => [File.dirname(__FILE__) + "/templates"],
551
+ })
552
+ assert !File.exists?(sassc_path("importee"))
553
+ end
554
+
555
+ def test_units
556
+ renders_correctly "units"
557
+ end
558
+
559
+ def test_default_function
560
+ assert_equal(<<CSS, render(<<SASS))
561
+ foo {
562
+ bar: url("foo.png"); }
563
+ CSS
564
+ foo
565
+ bar: url("foo.png")
566
+ SASS
567
+ assert_equal("foo {\n bar: url(); }\n", render("foo\n bar: url()\n"));
568
+ end
569
+
570
+ def test_string_minus
571
+ assert_equal("foo {\n bar: baz-boom-bat; }\n", render(%Q{foo\n bar: baz-boom-bat}))
572
+ assert_equal("foo {\n bar: -baz-boom; }\n", render(%Q{foo\n bar: -baz-boom}))
573
+ end
574
+
575
+ def test_string_div
576
+ assert_equal("foo {\n bar: baz/boom/bat; }\n", render(%Q{foo\n bar: baz/boom/bat}))
577
+ assert_equal("foo {\n bar: /baz/boom; }\n", render(%Q{foo\n bar: /baz/boom}))
578
+ end
579
+
580
+ def test_basic_multiline_selector
581
+ assert_equal("#foo #bar,\n#baz #boom {\n foo: bar; }\n",
582
+ render("#foo #bar,\n#baz #boom\n :foo bar"))
583
+ assert_equal("#foo #bar,\n#foo #baz {\n foo: bar; }\n",
584
+ render("#foo\n #bar,\n #baz\n :foo bar"))
585
+ assert_equal("#foo,\n#bar {\n foo: bar; }\n #foo #baz,\n #bar #baz {\n foo: bar; }\n",
586
+ render("#foo,\n#bar\n :foo bar\n #baz\n :foo bar"))
587
+ assert_equal("#foo #bar, #baz #boom { foo: bar; }\n",
588
+ render("#foo #bar,\n#baz #boom\n :foo bar", :style => :compact))
589
+
590
+ assert_equal("#foo #bar,#baz #boom{foo:bar}\n",
591
+ render("#foo #bar,\n#baz #boom\n :foo bar", :style => :compressed))
592
+ end
593
+
594
+ def test_complex_multiline_selector
595
+ renders_correctly "multiline"
596
+ end
597
+
598
+ def test_colon_only
599
+ begin
600
+ render("a\n b: c", :property_syntax => :old)
601
+ rescue Sass::SyntaxError => e
602
+ assert_equal("Illegal property syntax: can't use new syntax when :property_syntax => :old is set.",
603
+ e.message)
604
+ assert_equal(2, e.sass_line)
605
+ else
606
+ assert(false, "SyntaxError not raised for :property_syntax => :old")
607
+ end
608
+
609
+ begin
610
+ render("a\n :b c", :property_syntax => :new)
611
+ assert_equal(2, e.sass_line)
612
+ rescue Sass::SyntaxError => e
613
+ assert_equal("Illegal property syntax: can't use old syntax when :property_syntax => :new is set.",
614
+ e.message)
615
+ else
616
+ assert(false, "SyntaxError not raised for :property_syntax => :new")
617
+ end
618
+ end
619
+
620
+ def test_pseudo_elements
621
+ assert_equal(<<CSS, render(<<SASS))
622
+ ::first-line {
623
+ size: 10em; }
624
+ CSS
625
+ ::first-line
626
+ size: 10em
627
+ SASS
628
+ end
629
+
630
+ def test_directive
631
+ assert_equal("@a b;\n", render("@a b"))
632
+
633
+ assert_equal("@a {\n b: c; }\n", render("@a\n :b c"))
634
+ assert_equal("@a { b: c; }\n", render("@a\n :b c", :style => :compact))
635
+ assert_equal("@a {\n b: c;\n}\n", render("@a\n :b c", :style => :expanded))
636
+ assert_equal("@a{b:c}\n", render("@a\n :b c", :style => :compressed))
637
+
638
+ assert_equal("@a {\n b: c;\n d: e; }\n",
639
+ render("@a\n :b c\n :d e"))
640
+ assert_equal("@a { b: c; d: e; }\n",
641
+ render("@a\n :b c\n :d e", :style => :compact))
642
+ assert_equal("@a {\n b: c;\n d: e;\n}\n",
643
+ render("@a\n :b c\n :d e", :style => :expanded))
644
+ assert_equal("@a{b:c;d:e}\n",
645
+ render("@a\n :b c\n :d e", :style => :compressed))
646
+
647
+ assert_equal("@a {\n #b {\n c: d; } }\n",
648
+ render("@a\n #b\n :c d"))
649
+ assert_equal("@a { #b { c: d; } }\n",
650
+ render("@a\n #b\n :c d", :style => :compact))
651
+ assert_equal("@a {\n #b {\n c: d;\n }\n}\n",
652
+ render("@a\n #b\n :c d", :style => :expanded))
653
+ assert_equal("@a{#b{c:d}}\n",
654
+ render("@a\n #b\n :c d", :style => :compressed))
655
+
656
+ assert_equal("@a {\n #b {\n a: b; }\n #b #c {\n d: e; } }\n",
657
+ render("@a\n #b\n :a b\n #c\n :d e"))
658
+ assert_equal("@a { #b { a: b; }\n #b #c { d: e; } }\n",
659
+ render("@a\n #b\n :a b\n #c\n :d e", :style => :compact))
660
+ assert_equal("@a {\n #b {\n a: b;\n }\n #b #c {\n d: e;\n }\n}\n",
661
+ render("@a\n #b\n :a b\n #c\n :d e", :style => :expanded))
662
+ assert_equal("@a{#b{a:b}#b #c{d:e}}\n",
663
+ render("@a\n #b\n :a b\n #c\n :d e", :style => :compressed))
664
+
665
+ assert_equal("@a {\n #foo,\n #bar {\n b: c; } }\n",
666
+ render("@a\n #foo, \n #bar\n :b c"))
667
+ assert_equal("@a { #foo, #bar { b: c; } }\n",
668
+ render("@a\n #foo, \n #bar\n :b c", :style => :compact))
669
+ assert_equal("@a {\n #foo,\n #bar {\n b: c;\n }\n}\n",
670
+ render("@a\n #foo, \n #bar\n :b c", :style => :expanded))
671
+ assert_equal("@a{#foo,#bar{b:c}}\n",
672
+ render("@a\n #foo, \n #bar\n :b c", :style => :compressed))
673
+
674
+ to_render = <<END
675
+ @a
676
+ :b c
677
+ #d
678
+ :e f
679
+ :g h
680
+ END
681
+ rendered = <<END
682
+ @a { b: c;
683
+ #d { e: f; }
684
+ g: h; }
685
+ END
686
+ assert_equal(rendered, render(to_render, :style => :compact))
687
+
688
+ assert_equal("@a{b:c;#d{e:f}g:h}\n", render(to_render, :style => :compressed))
689
+ end
690
+
691
+ def test_property_hacks
692
+ assert_equal(<<CSS, render(<<SASS))
693
+ foo {
694
+ _name: val;
695
+ *name: val;
696
+ #name: val;
697
+ .name: val;
698
+ name/**/: val;
699
+ name/*\\**/: val;
700
+ name: val; }
701
+ CSS
702
+ foo
703
+ _name: val
704
+ *name: val
705
+ #name: val
706
+ .name: val
707
+ name/**/: val
708
+ name/*\\**/: val
709
+ name: val
710
+ SASS
711
+ end
712
+
713
+ def test_properties_with_space_after_colon
714
+ assert_equal <<CSS, render(<<SASS)
715
+ foo {
716
+ bar: baz;
717
+ bizz: bap; }
718
+ CSS
719
+ foo
720
+ bar : baz
721
+ bizz : bap
722
+ SASS
723
+ end
724
+
725
+ def test_line_annotations
726
+ assert_equal(<<CSS, render(<<SASS, :line_comments => true, :style => :compact))
727
+ /* line 2, test_line_annotations_inline.sass */
728
+ foo bar { foo: bar; }
729
+ /* line 5, test_line_annotations_inline.sass */
730
+ foo baz { blip: blop; }
731
+
732
+ /* line 9, test_line_annotations_inline.sass */
733
+ floodle { flop: blop; }
734
+
735
+ /* line 18, test_line_annotations_inline.sass */
736
+ bup { mix: on; }
737
+ /* line 15, test_line_annotations_inline.sass */
738
+ bup mixin { moop: mup; }
739
+
740
+ /* line 22, test_line_annotations_inline.sass */
741
+ bip hop, skip hop { a: b; }
742
+ CSS
743
+ foo
744
+ bar
745
+ foo: bar
746
+
747
+ baz
748
+ blip: blop
749
+
750
+
751
+ floodle
752
+
753
+ flop: blop
754
+
755
+ =mxn
756
+ mix: on
757
+ mixin
758
+ moop: mup
759
+
760
+ bup
761
+ +mxn
762
+
763
+ bip, skip
764
+ hop
765
+ a: b
766
+ SASS
767
+ end
768
+
769
+ def test_line_annotations_with_filename
770
+ renders_correctly "line_numbers", :line_comments => true, :load_paths => [File.dirname(__FILE__) + "/templates"]
771
+ end
772
+
773
+ def test_debug_info
774
+ esc_file_name = Sass::SCSS::RX.escape_ident(Sass::Util.scope("test_debug_info_inline.sass"))
775
+
776
+ assert_equal(<<CSS, render(<<SASS, :debug_info => true, :style => :compact))
777
+ @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000032}}
778
+ foo bar { foo: bar; }
779
+ @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000035}}
780
+ foo baz { blip: blop; }
781
+
782
+ @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000039}}
783
+ floodle { flop: blop; }
784
+
785
+ @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000318}}
786
+ bup { mix: on; }
787
+ @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000315}}
788
+ bup mixin { moop: mup; }
789
+
790
+ @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\0000322}}
791
+ bip hop, skip hop { a: b; }
792
+ CSS
793
+ foo
794
+ bar
795
+ foo: bar
796
+
797
+ baz
798
+ blip: blop
799
+
800
+
801
+ floodle
802
+
803
+ flop: blop
804
+
805
+ =mxn
806
+ mix: on
807
+ mixin
808
+ moop: mup
809
+
810
+ bup
811
+ +mxn
812
+
813
+ bip, skip
814
+ hop
815
+ a: b
816
+ SASS
817
+ end
818
+
819
+ def test_debug_info_without_filename
820
+ assert_equal(<<CSS, Sass::Engine.new(<<SASS, :debug_info => true).render)
821
+ @media -sass-debug-info{filename{font-family:}line{font-family:\\000031}}
822
+ foo {
823
+ a: b; }
824
+ CSS
825
+ foo
826
+ a: b
827
+ SASS
828
+ end
829
+
830
+ def test_debug_info_with_compressed
831
+ assert_equal(<<CSS, render(<<SASS, :debug_info => true, :style => :compressed))
832
+ foo{a:b}
833
+ CSS
834
+ foo
835
+ a: b
836
+ SASS
837
+ end
838
+
839
+ def test_debug_info_with_line_annotations
840
+ esc_file_name = Sass::SCSS::RX.escape_ident(Sass::Util.scope("test_debug_info_with_line_annotations_inline.sass"))
841
+
842
+ assert_equal(<<CSS, render(<<SASS, :debug_info => true, :line_comments => true))
843
+ @media -sass-debug-info{filename{font-family:file\\:\\/\\/#{esc_file_name}}line{font-family:\\000031}}
844
+ foo {
845
+ a: b; }
846
+ CSS
847
+ foo
848
+ a: b
849
+ SASS
850
+ end
851
+
852
+ def test_empty_first_line
853
+ assert_equal("#a {\n b: c; }\n", render("#a\n\n b: c"))
854
+ end
855
+
856
+ def test_escaped_rule
857
+ assert_equal(":focus {\n a: b; }\n", render("\\:focus\n a: b"))
858
+ assert_equal("a {\n b: c; }\n a :focus {\n d: e; }\n", render("\\a\n b: c\n \\:focus\n d: e"))
859
+ end
860
+
861
+ def test_cr_newline
862
+ assert_equal("foo {\n a: b;\n c: d;\n e: f; }\n", render("foo\r a: b\r\n c: d\n\r e: f"))
863
+ end
864
+
865
+ def test_property_with_content_and_nested_props
866
+ assert_equal(<<CSS, render(<<SASS))
867
+ foo {
868
+ a: b;
869
+ a-c: d;
870
+ a-c-e: f; }
871
+ CSS
872
+ foo
873
+ a: b
874
+ c: d
875
+ e: f
876
+ SASS
877
+
878
+ assert_equal(<<CSS, render(<<SASS))
879
+ foo {
880
+ a: b;
881
+ a-c-e: f; }
882
+ CSS
883
+ foo
884
+ a: b
885
+ c:
886
+ e: f
887
+ SASS
888
+ end
889
+
890
+ def test_equals_warning_for_properties
891
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SASS))}
892
+ DEPRECATION WARNING:
893
+ On line 3, character 3 of 'test_equals_warning_for_properties_inline.sass'
894
+ Setting properties with = has been deprecated and will be removed in version 3.2.
895
+ Use "a: $var" instead.
896
+
897
+ You can use `sass-convert --in-place --from sass2 file.sass' to convert files automatically.
898
+ WARN
899
+ foo {
900
+ a: 2px 3px; }
901
+ CSS
902
+ $var: 2px 3px
903
+ foo
904
+ a = $var
905
+ SASS
906
+ end
907
+
908
+ def test_equals_warning_for_dynamic_properties
909
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SASS))}
910
+ DEPRECATION WARNING:
911
+ On line 4, character 3 of 'test_equals_warning_for_dynamic_properties_inline.sass'
912
+ Setting properties with = has been deprecated and will be removed in version 3.2.
913
+ Use "a-\#{$i}: $var" instead.
914
+
915
+ You can use `sass-convert --in-place --from sass2 file.sass' to convert files automatically.
916
+ WARN
917
+ foo {
918
+ a-12: 2px 3px; }
919
+ CSS
920
+ $var: 2px 3px
921
+ $i: 12
922
+ foo
923
+ a-\#{$i} = $var
924
+ SASS
925
+ end
926
+
927
+ def test_equals_warning_for_property_with_string
928
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SASS))}
929
+ DEPRECATION WARNING:
930
+ On line 2, character 3 of 'test_equals_warning_for_property_with_string_inline.sass'
931
+ Setting properties with = has been deprecated and will be removed in version 3.2.
932
+ Use "a: foo" instead.
933
+
934
+ You can use `sass-convert --in-place --from sass2 file.sass' to convert files automatically.
935
+ WARN
936
+ foo {
937
+ a: foo; }
938
+ CSS
939
+ foo
940
+ a = "foo"
941
+ SASS
942
+ end
943
+
944
+ def test_equals_warning_for_property_with_division
945
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SASS))}
946
+ DEPRECATION WARNING:
947
+ On line 2, character 3 of 'test_equals_warning_for_property_with_division_inline.sass'
948
+ Setting properties with = has been deprecated and will be removed in version 3.2.
949
+ Use "a: (1px / 2px)" instead.
950
+
951
+ You can use `sass-convert --in-place --from sass2 file.sass' to convert files automatically.
952
+ WARN
953
+ foo {
954
+ a: 0.5; }
955
+ CSS
956
+ foo
957
+ a = 1px/2px
958
+ SASS
959
+ end
960
+
961
+ def test_guarded_assign
962
+ assert_equal("foo {\n a: b; }\n", render(%Q{$foo: b\n$foo: c !default\nfoo\n a: $foo}))
963
+ assert_equal("foo {\n a: b; }\n", render(%Q{$foo: b !default\nfoo\n a: $foo}))
964
+ end
965
+
966
+ def test_mixins
967
+ renders_correctly "mixins", { :style => :expanded }
968
+ end
969
+
970
+ def test_directive_style_mixins
971
+ assert_equal <<CSS, render(<<SASS)
972
+ bar {
973
+ prop: baz; }
974
+ CSS
975
+ @mixin foo($arg)
976
+ prop: $arg
977
+
978
+ bar
979
+ @include foo(baz)
980
+ SASS
981
+ end
982
+
983
+ def test_mixins_dont_interfere_with_sibling_combinator
984
+ assert_equal("foo + bar {\n a: b; }\nfoo + baz {\n c: d; }\n",
985
+ render("foo\n +\n bar\n a: b\n baz\n c: d"))
986
+ end
987
+
988
+ def test_mixin_args
989
+ assert_equal("blat {\n baz: hi; }\n", render(<<SASS))
990
+ =foo($bar)
991
+ baz: $bar
992
+ blat
993
+ +foo(hi)
994
+ SASS
995
+ assert_equal("blat {\n baz: 3; }\n", render(<<SASS))
996
+ =foo($a, $b)
997
+ baz: $a + $b
998
+ blat
999
+ +foo(1, 2)
1000
+ SASS
1001
+ assert_equal("blat {\n baz: 4;\n baz: 3;\n baz: 5;\n bang: 3; }\n", render(<<SASS))
1002
+ =foo($c: (6 + 4) / 2)
1003
+ baz: $c
1004
+ $c: 3
1005
+ blat
1006
+ +foo($c + 1)
1007
+ +foo(($c + 3)/2)
1008
+ +foo
1009
+ bang: $c
1010
+ SASS
1011
+ end
1012
+
1013
+ def test_default_values_for_mixin_arguments
1014
+ assert_equal("white {\n color: white; }\n\nblack {\n color: black; }\n", render(<<SASS))
1015
+ =foo($a: #FFF)
1016
+ :color $a
1017
+ white
1018
+ +foo
1019
+ black
1020
+ +foo(#000)
1021
+ SASS
1022
+ assert_equal(<<CSS, render(<<SASS))
1023
+ one {
1024
+ color: white;
1025
+ padding: 1px;
1026
+ margin: 4px; }
1027
+
1028
+ two {
1029
+ color: white;
1030
+ padding: 2px;
1031
+ margin: 5px; }
1032
+
1033
+ three {
1034
+ color: white;
1035
+ padding: 2px;
1036
+ margin: 3px; }
1037
+ CSS
1038
+ $a: 5px
1039
+ =foo($a, $b: 1px, $c: 3px + $b)
1040
+ :color $a
1041
+ :padding $b
1042
+ :margin $c
1043
+ one
1044
+ +foo(#fff)
1045
+ two
1046
+ +foo(#fff, 2px)
1047
+ three
1048
+ +foo(#fff, 2px, 3px)
1049
+ SASS
1050
+ end
1051
+
1052
+ def test_hyphen_underscore_insensitive_mixins
1053
+ assert_equal(<<CSS, render(<<SASS))
1054
+ a {
1055
+ b: 12;
1056
+ c: foo; }
1057
+ CSS
1058
+ =mixin-hyphen
1059
+ b: 12
1060
+
1061
+ =mixin_under
1062
+ c: foo
1063
+
1064
+ a
1065
+ +mixin_hyphen
1066
+ +mixin-under
1067
+ SASS
1068
+ end
1069
+
1070
+ def test_equals_warning_for_mixin_args
1071
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SASS))}
1072
+ DEPRECATION WARNING:
1073
+ On line 1, character 10 of 'test_equals_warning_for_mixin_args_inline.sass'
1074
+ Setting mixin argument defaults with = has been deprecated and will be removed in version 3.2.
1075
+ Use "$arg: 1px" instead.
1076
+
1077
+ You can use `sass-convert --in-place --from sass2 file.sass' to convert files automatically.
1078
+ WARN
1079
+ bar {
1080
+ a: 1px; }
1081
+ CSS
1082
+ =foo($arg = 1px)
1083
+ a: $arg
1084
+
1085
+ bar
1086
+ +foo
1087
+ SASS
1088
+ end
1089
+
1090
+ def test_css_identifier_mixin
1091
+ assert_equal(<<CSS, render(<<SASS))
1092
+ a {
1093
+ foo: 12; }
1094
+ CSS
1095
+ =\\{foo\\(12\\)($a)
1096
+ foo: $a
1097
+
1098
+ a
1099
+ +\\{foo\\(12\\)(12)
1100
+ SASS
1101
+ end
1102
+
1103
+ def test_interpolation
1104
+ assert_equal("a-1 {\n b-2-3: c-3; }\n", render(<<SASS))
1105
+ $a: 1
1106
+ $b: 2
1107
+ $c: 3
1108
+ a-\#{$a}
1109
+ b-\#{$b}-\#{$c}: c-\#{$a + $b}
1110
+ SASS
1111
+ end
1112
+
1113
+ def test_complex_property_interpolation
1114
+ assert_equal(<<CSS, render(<<SASS))
1115
+ a-1 {
1116
+ b-2 3-fizzap18: c-3; }
1117
+ CSS
1118
+ $a: 1
1119
+ $b: 2
1120
+ $c: 3
1121
+ a-\#{$a}
1122
+ b-\#{$b $c}-\#{fizzap + ($c + 15)}: c-\#{$a + $b}
1123
+ SASS
1124
+ end
1125
+
1126
+ def test_if_directive
1127
+ assert_equal("a {\n b: 1; }\n", render(<<SASS))
1128
+ $var: true
1129
+ a
1130
+ @if $var
1131
+ b: 1
1132
+ @if not $var
1133
+ b: 2
1134
+ SASS
1135
+ end
1136
+
1137
+ def test_for
1138
+ assert_equal(<<CSS, render(<<SASS))
1139
+ a-0 {
1140
+ two-i: 0; }
1141
+
1142
+ a-1 {
1143
+ two-i: 2; }
1144
+
1145
+ a-2 {
1146
+ two-i: 4; }
1147
+
1148
+ a-3 {
1149
+ two-i: 6; }
1150
+
1151
+ b-1 {
1152
+ j-1: 0; }
1153
+
1154
+ b-2 {
1155
+ j-1: 1; }
1156
+
1157
+ b-3 {
1158
+ j-1: 2; }
1159
+
1160
+ b-4 {
1161
+ j-1: 3; }
1162
+ CSS
1163
+ $a: 3
1164
+ @for $i from 0 to $a + 1
1165
+ a-\#{$i}
1166
+ two-i: 2 * $i
1167
+
1168
+ @for $j from 1 through 4
1169
+ b-\#{$j}
1170
+ j-1: $j - 1
1171
+ SASS
1172
+ end
1173
+
1174
+ def test_for_with_bang_var
1175
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SASS))}
1176
+ DEPRECATION WARNING:
1177
+ On line 1, character 6 of 'test_for_with_bang_var_inline.sass'
1178
+ Variables with ! have been deprecated and will be removed in version 3.2.
1179
+ Use "$bar" instead.
1180
+
1181
+ You can use `sass-convert --in-place --from sass2 file.sass' to convert files automatically.
1182
+ WARN
1183
+ a-0 {
1184
+ b: c; }
1185
+
1186
+ a-1 {
1187
+ b: c; }
1188
+
1189
+ a-2 {
1190
+ b: c; }
1191
+ CSS
1192
+ @for !bar from 0 to 3
1193
+ a-\#{$bar}
1194
+ b: c
1195
+ SASS
1196
+ end
1197
+
1198
+ def test_while
1199
+ assert_equal(<<CSS, render(<<SASS))
1200
+ a-5 {
1201
+ blooble: gloop; }
1202
+
1203
+ a-4 {
1204
+ blooble: gloop; }
1205
+
1206
+ a-3 {
1207
+ blooble: gloop; }
1208
+
1209
+ a-2 {
1210
+ blooble: gloop; }
1211
+
1212
+ a-1 {
1213
+ blooble: gloop; }
1214
+ CSS
1215
+ $a: 5
1216
+ @while $a != 0
1217
+ a-\#{$a}
1218
+ blooble: gloop
1219
+ $a: $a - 1
1220
+ SASS
1221
+ end
1222
+
1223
+ def test_else
1224
+ assert_equal(<<CSS, render(<<SASS))
1225
+ a {
1226
+ t1: t;
1227
+ t2: t;
1228
+ t3: t;
1229
+ t4: t; }
1230
+ CSS
1231
+ a
1232
+ @if true
1233
+ t1: t
1234
+ @else
1235
+ f1: f
1236
+
1237
+ @if false
1238
+ f2: f
1239
+ @else
1240
+ t2: t
1241
+
1242
+ @if false
1243
+ f3: f1
1244
+ @else if 1 + 1 == 3
1245
+ f3: f2
1246
+ @else
1247
+ t3: t
1248
+
1249
+ @if false
1250
+ f4: f1
1251
+ @else if 1 + 1 == 2
1252
+ t4: t
1253
+ @else
1254
+ f4: f2
1255
+
1256
+ @if false
1257
+ f5: f1
1258
+ @else if false
1259
+ f5: f2
1260
+ SASS
1261
+ end
1262
+
1263
+ def test_variable_reassignment
1264
+ assert_equal(<<CSS, render(<<SASS))
1265
+ a {
1266
+ b: 1;
1267
+ c: 2; }
1268
+ CSS
1269
+ $a: 1
1270
+ a
1271
+ b: $a
1272
+ $a: 2
1273
+ c: $a
1274
+ SASS
1275
+ end
1276
+
1277
+ def test_bang_variables
1278
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SASS))}
1279
+ DEPRECATION WARNING:
1280
+ On line 1, character 1 of 'test_bang_variables_inline.sass'
1281
+ Variables with ! have been deprecated and will be removed in version 3.2.
1282
+ Use "$bang-var" instead.
1283
+
1284
+ You can use `sass-convert --in-place --from sass2 file.sass' to convert files automatically.
1285
+ WARN
1286
+ foo {
1287
+ a: 1px; }
1288
+ CSS
1289
+ !bang-var: 1px
1290
+ foo
1291
+ a: $bang-var
1292
+ SASS
1293
+
1294
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SASS))}
1295
+ DEPRECATION WARNING:
1296
+ On line 3, character 6 of 'test_bang_variables_inline.sass'
1297
+ Variables with ! have been deprecated and will be removed in version 3.2.
1298
+ Use "$dollar-var" instead.
1299
+
1300
+ You can use `sass-convert --in-place --from sass2 file.sass' to convert files automatically.
1301
+ WARN
1302
+ foo {
1303
+ a: 1px; }
1304
+ CSS
1305
+ $dollar-var: 1px
1306
+ foo
1307
+ a: !dollar-var
1308
+ SASS
1309
+ end
1310
+
1311
+ def test_equals_warning_for_variables
1312
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SASS))}
1313
+ DEPRECATION WARNING:
1314
+ On line 2, character 1 of 'test_equals_warning_for_variables_inline.sass'
1315
+ Setting variables with = has been deprecated and will be removed in version 3.2.
1316
+ Use "$equals-var: 2px 3px" instead.
1317
+
1318
+ You can use `sass-convert --in-place --from sass2 file.sass' to convert files automatically.
1319
+ WARN
1320
+ foo {
1321
+ a: 2px 3px; }
1322
+ CSS
1323
+
1324
+ $equals-var = 2px 3px
1325
+ foo
1326
+ a: $equals-var
1327
+ SASS
1328
+ end
1329
+
1330
+ def test_equals_warning_for_guarded_variables
1331
+ assert_warning(<<WARN) {assert_equal(<<CSS, render(<<SASS))}
1332
+ DEPRECATION WARNING:
1333
+ On line 2, character 1 of 'test_equals_warning_for_guarded_variables_inline.sass'
1334
+ Setting variable defaults with ||= has been deprecated and will be removed in version 3.2.
1335
+ Use "$equals-var: 2px 3px !default" instead.
1336
+
1337
+ You can use `sass-convert --in-place --from sass2 file.sass' to convert files automatically.
1338
+ WARN
1339
+ foo {
1340
+ a: 2px 3px; }
1341
+ CSS
1342
+
1343
+ $equals-var ||= 2px 3px
1344
+ foo
1345
+ a: $equals-var
1346
+ SASS
1347
+ end
1348
+
1349
+ def test_variable_scope
1350
+ assert_equal(<<CSS, render(<<SASS))
1351
+ a {
1352
+ b-1: c;
1353
+ b-2: c;
1354
+ d: 12; }
1355
+
1356
+ b {
1357
+ d: 17; }
1358
+ CSS
1359
+ $i: 12
1360
+ a
1361
+ @for $i from 1 through 2
1362
+ b-\#{$i}: c
1363
+ d: $i
1364
+
1365
+ =foo
1366
+ $i: 17
1367
+
1368
+ b
1369
+ +foo
1370
+ d: $i
1371
+ SASS
1372
+ end
1373
+
1374
+ def test_hyphen_underscore_insensitive_variables
1375
+ assert_equal(<<CSS, render(<<SASS))
1376
+ a {
1377
+ b: c; }
1378
+
1379
+ d {
1380
+ e: 13;
1381
+ f: foobar; }
1382
+ CSS
1383
+ $var-hyphen: 12
1384
+ $var_under: foo
1385
+
1386
+ a
1387
+ $var_hyphen: 1 + $var_hyphen
1388
+ $var-under: $var-under + bar
1389
+ b: c
1390
+
1391
+ d
1392
+ e: $var-hyphen
1393
+ f: $var_under
1394
+ SASS
1395
+ end
1396
+
1397
+ def test_css_identifier_variable
1398
+ assert_equal(<<CSS, render(<<SASS))
1399
+ a {
1400
+ b: 12; }
1401
+ CSS
1402
+ $\\{foo\\(12\\): 12
1403
+
1404
+ a
1405
+ b: $\\{foo\\(12\\)
1406
+ SASS
1407
+ end
1408
+
1409
+ def test_important
1410
+ assert_equal(<<CSS, render(<<SASS))
1411
+ a {
1412
+ b: 12px !important; }
1413
+ CSS
1414
+ $foo: 12px
1415
+ a
1416
+ b: $foo !important
1417
+ SASS
1418
+ end
1419
+
1420
+ def test_argument_error
1421
+ assert_raise(Sass::SyntaxError) { render("a\n b: hsl(1)") }
1422
+ end
1423
+
1424
+ def test_comments_at_the_top_of_a_document
1425
+ render(<<SASS)
1426
+ //
1427
+ This is a comment that
1428
+ continues to the second line.
1429
+ foo
1430
+ bar: baz
1431
+ SASS
1432
+ end
1433
+
1434
+ def test_loud_comments_containing_a_comment_close
1435
+ actual_css = render(<<SASS)
1436
+ /*
1437
+ This is a comment that
1438
+ continues to the second line. */
1439
+ foo
1440
+ bar: baz
1441
+ SASS
1442
+ assert_equal(<<CSS, actual_css)
1443
+ /* This is a comment that
1444
+ * continues to the second line. */
1445
+ foo {
1446
+ bar: baz; }
1447
+ CSS
1448
+ end
1449
+
1450
+ def test_loud_comments_with_starred_lines
1451
+ assert_equal(<<CSS, render(<<SASS))
1452
+ /* This is a comment that
1453
+ * continues to the second line.
1454
+ * And even to the third! */
1455
+ CSS
1456
+ /* This is a comment that
1457
+ * continues to the second line.
1458
+ * And even to the third!
1459
+ SASS
1460
+ end
1461
+
1462
+ def test_loud_comments_with_no_space_after_starred_lines
1463
+ assert_equal(<<CSS, render(<<SASS))
1464
+ /*bip bop
1465
+ *beep boop
1466
+ *bap blimp */
1467
+ CSS
1468
+ /*bip bop
1469
+ *beep boop
1470
+ *bap blimp
1471
+ SASS
1472
+ end
1473
+
1474
+ def test_comment_indentation_at_beginning_of_doc
1475
+ assert_equal <<CSS, render(<<SASS)
1476
+ /* foo
1477
+ * bar
1478
+ * baz */
1479
+ foo {
1480
+ a: b; }
1481
+ CSS
1482
+ /* foo
1483
+ bar
1484
+ baz
1485
+ foo
1486
+ a: b
1487
+ SASS
1488
+ end
1489
+
1490
+ def test_unusual_comment_indentation
1491
+ assert_equal <<CSS, render(<<SASS)
1492
+ foo {
1493
+ /* foo
1494
+ * bar
1495
+ * baz */ }
1496
+ CSS
1497
+ foo
1498
+ /* foo
1499
+ bar
1500
+ baz
1501
+ SASS
1502
+ end
1503
+
1504
+ def test_loud_comment_with_close
1505
+ assert_equal <<CSS, render(<<SASS)
1506
+ foo {
1507
+ /* foo
1508
+ * bar */ }
1509
+ CSS
1510
+ foo
1511
+ /* foo
1512
+ bar */
1513
+ SASS
1514
+ end
1515
+
1516
+ def test_loud_comment_with_separate_line_close
1517
+ assert_equal <<CSS, render(<<SASS)
1518
+ foo {
1519
+ /* foo
1520
+ * bar
1521
+ */ }
1522
+ CSS
1523
+ foo
1524
+ /* foo
1525
+ * bar
1526
+ */
1527
+ SASS
1528
+ end
1529
+
1530
+ def test_attribute_selector_with_spaces
1531
+ assert_equal(<<CSS, render(<<SASS))
1532
+ a b[foo=bar] {
1533
+ c: d; }
1534
+ CSS
1535
+ a
1536
+ b[foo = bar]
1537
+ c: d
1538
+ SASS
1539
+ end
1540
+
1541
+ def test_quoted_colon
1542
+ assert_equal(<<CSS, render(<<SASS))
1543
+ a b[foo="bar: baz"] {
1544
+ c: d; }
1545
+ CSS
1546
+ a
1547
+ b[foo="bar: baz"]
1548
+ c: d
1549
+ SASS
1550
+ end
1551
+
1552
+ def test_quoted_comma
1553
+ assert_equal(<<CSS, render(<<SASS))
1554
+ a b[foo="bar, baz"] {
1555
+ c: d; }
1556
+ CSS
1557
+ a
1558
+ b[foo="bar, baz"]
1559
+ c: d
1560
+ SASS
1561
+ end
1562
+
1563
+ def test_quoted_ampersand
1564
+ assert_equal(<<CSS, render(<<SASS))
1565
+ a b[foo="bar & baz"] {
1566
+ c: d; }
1567
+ CSS
1568
+ a
1569
+ b[foo="bar & baz"]
1570
+ c: d
1571
+ SASS
1572
+ end
1573
+
1574
+ def test_empty_selector_warning
1575
+ assert_warning(<<END) {render("foo bar")}
1576
+ WARNING on line 1 of test_empty_selector_warning_inline.sass:
1577
+ This selector doesn't have any properties and will not be rendered.
1578
+ END
1579
+ end
1580
+
1581
+ def test_root_level_pseudo_class_with_new_properties
1582
+ assert_equal(<<CSS, render(<<SASS, :property_syntax => :new))
1583
+ :focus {
1584
+ outline: 0; }
1585
+ CSS
1586
+ :focus
1587
+ outline: 0
1588
+ SASS
1589
+ end
1590
+
1591
+ def test_pseudo_class_with_new_properties
1592
+ assert_equal(<<CSS, render(<<SASS, :property_syntax => :new))
1593
+ p :focus {
1594
+ outline: 0; }
1595
+ CSS
1596
+ p
1597
+ :focus
1598
+ outline: 0
1599
+ SASS
1600
+ end
1601
+
1602
+ def test_nil_option
1603
+ assert_equal(<<CSS, render(<<SASS, :format => nil))
1604
+ foo {
1605
+ a: b; }
1606
+ CSS
1607
+ foo
1608
+ a: b
1609
+ SASS
1610
+ end
1611
+
1612
+ def test_interpolation_in_raw_functions
1613
+ assert_equal(<<CSS, render(<<SASS))
1614
+ foo {
1615
+ filter: progid:Microsoft.foo.bar.Baz(flip=foobar, bang=#00ff00cc); }
1616
+ CSS
1617
+ foo
1618
+ filter: progid:Microsoft.foo.bar.Baz(flip=\#{foo + bar}, bang=#00ff00cc)
1619
+ SASS
1620
+ end
1621
+
1622
+ # SassScript string behavior
1623
+
1624
+ def test_plus_preserves_quotedness
1625
+ assert_equal(<<CSS, render(<<SASS))
1626
+ foo {
1627
+ a: "foo1";
1628
+ b: "1foo";
1629
+ c: foo1;
1630
+ d: 1foo;
1631
+ e: "foobar";
1632
+ f: foobar; }
1633
+ CSS
1634
+ foo
1635
+ a: "foo" + 1
1636
+ b: 1 + "foo"
1637
+ c: foo + 1
1638
+ d: 1 + foo
1639
+ e: "foo" + bar
1640
+ f: foo + "bar"
1641
+ SASS
1642
+ end
1643
+
1644
+ def test_colon_properties_preserve_quotedness
1645
+ assert_equal(<<CSS, render(<<SASS))
1646
+ foo {
1647
+ a: "foo";
1648
+ b: bar;
1649
+ c: "foo" bar;
1650
+ d: foo, "bar"; }
1651
+ CSS
1652
+ foo
1653
+ a: "foo"
1654
+ b: bar
1655
+ c: "foo" bar
1656
+ d: foo, "bar"
1657
+ SASS
1658
+ end
1659
+
1660
+ def test_colon_variables_preserve_quotedness
1661
+ assert_equal(<<CSS, render(<<SASS))
1662
+ foo {
1663
+ a: "foo";
1664
+ b: bar; }
1665
+ CSS
1666
+ $a: "foo"
1667
+ $b: bar
1668
+
1669
+ foo
1670
+ a: $a
1671
+ b: $b
1672
+ SASS
1673
+ end
1674
+
1675
+ def test_colon_args_preserve_quotedness
1676
+ assert_equal(<<CSS, render(<<SASS))
1677
+ foo {
1678
+ a: "foo";
1679
+ b: bar;
1680
+ c: "foo" bar;
1681
+ d: foo, "bar"; }
1682
+ CSS
1683
+ =foo($a: "foo", $b: bar, $c: "foo" bar, $d: (foo, "bar"))
1684
+ foo
1685
+ a: $a
1686
+ b: $b
1687
+ c: $c
1688
+ d: $d
1689
+
1690
+ +foo
1691
+ SASS
1692
+ end
1693
+
1694
+ def test_interpolation_unquotes_strings
1695
+ assert_equal(<<CSS, render(<<SASS))
1696
+ .foo-bar {
1697
+ a: b; }
1698
+ CSS
1699
+ .foo-\#{"bar"}
1700
+ a: b
1701
+ SASS
1702
+
1703
+ assert_equal(<<CSS, render(<<SASS))
1704
+ .foo {
1705
+ a: b c; }
1706
+ CSS
1707
+ .foo
1708
+ a: b \#{"c"}
1709
+ SASS
1710
+ end
1711
+
1712
+ def test_interpolation_unquotes_strings_in_vars
1713
+ assert_equal(<<CSS, render(<<SASS))
1714
+ .foo-bar {
1715
+ a: b; }
1716
+ CSS
1717
+ $var: "bar"
1718
+
1719
+ .foo-\#{$var}
1720
+ a: b
1721
+ SASS
1722
+ end
1723
+
1724
+ def test_interpolation_doesnt_deep_unquote_strings
1725
+ assert_equal(<<CSS, render(<<SASS))
1726
+ .foo- "bar" "baz" {
1727
+ a: b; }
1728
+ CSS
1729
+ .foo-\#{"bar" "baz"}
1730
+ a: b
1731
+ SASS
1732
+ end
1733
+
1734
+ # Deprecated equals behavior
1735
+
1736
+ def test_equals_properties_unquote_strings
1737
+ silence_warnings do
1738
+ assert_equal(<<CSS, render(<<SASS))
1739
+ foo {
1740
+ a: foo;
1741
+ b: bar;
1742
+ c: foo bar;
1743
+ d: foo, bar baz;
1744
+ e: foo bar, bar; }
1745
+ CSS
1746
+ foo
1747
+ a= "foo"
1748
+ b= bar
1749
+ c= "foo" bar
1750
+ d= foo, "bar baz"
1751
+ e= "foo bar", bar
1752
+ SASS
1753
+ end
1754
+ end
1755
+
1756
+ def test_equals_properties_unquote_value
1757
+ silence_warnings do
1758
+ assert_equal(<<CSS, render(<<SASS))
1759
+ foo {
1760
+ a: foo; }
1761
+ CSS
1762
+ $var: "foo"
1763
+
1764
+ foo
1765
+ a= $var
1766
+ SASS
1767
+ end
1768
+ end
1769
+
1770
+ def test_equals_properties_deep_unquote_vars
1771
+ silence_warnings do
1772
+ assert_equal(<<CSS, render(<<SASS))
1773
+ foo {
1774
+ a: foo bar;
1775
+ b: bar foo; }
1776
+ CSS
1777
+ $var: "foo"
1778
+
1779
+ foo
1780
+ a= $var "bar"
1781
+ b= "bar" $var
1782
+ SASS
1783
+ end
1784
+ end
1785
+
1786
+ def test_equals_vars_unquote_strings
1787
+ silence_warnings do
1788
+ assert_equal(<<CSS, render(<<SASS))
1789
+ foo {
1790
+ a: foo;
1791
+ b: bar;
1792
+ c: foo bar;
1793
+ d: foo, bar; }
1794
+ CSS
1795
+ $a = "foo"
1796
+ $b = bar
1797
+ $c = "foo" bar
1798
+ $d = foo, "bar"
1799
+
1800
+ foo
1801
+ a: $a
1802
+ b: $b
1803
+ c: $c
1804
+ d: $d
1805
+ SASS
1806
+ end
1807
+ end
1808
+
1809
+ def test_equals_vars_unquote_value
1810
+ silence_warnings do
1811
+ assert_equal(<<CSS, render(<<SASS))
1812
+ foo {
1813
+ a: foo; }
1814
+ CSS
1815
+ $var1: "foo"
1816
+ $var2 = $var1
1817
+
1818
+ foo
1819
+ a: $var2
1820
+ SASS
1821
+ end
1822
+ end
1823
+
1824
+ def test_equals_vars_deep_unquote_vars
1825
+ silence_warnings do
1826
+ assert_equal(<<CSS, render(<<SASS))
1827
+ foo {
1828
+ a: foo bar;
1829
+ b: bar foo; }
1830
+ CSS
1831
+ $var: "foo"
1832
+ $a = $var "bar"
1833
+ $b = "bar" $var
1834
+
1835
+ foo
1836
+ a: $a
1837
+ b: $b
1838
+ SASS
1839
+ end
1840
+ end
1841
+
1842
+ def test_equals_args_unquote_strings
1843
+ silence_warnings do
1844
+ assert_equal(<<CSS, render(<<SASS))
1845
+ foo {
1846
+ a: foo;
1847
+ b: bar;
1848
+ c: foo bar;
1849
+ d: foo, bar; }
1850
+ CSS
1851
+ =foo($a = "foo", $b = bar, $c = "foo" bar, $d = (foo, "bar"))
1852
+ foo
1853
+ a: $a
1854
+ b: $b
1855
+ c: $c
1856
+ d: $d
1857
+
1858
+ +foo
1859
+ SASS
1860
+ end
1861
+ end
1862
+
1863
+ def test_equals_args_unquote_value
1864
+ silence_warnings do
1865
+ assert_equal(<<CSS, render(<<SASS))
1866
+ foo {
1867
+ a: foo; }
1868
+ CSS
1869
+ $var1: "foo"
1870
+
1871
+ =foo($var2 = $var1)
1872
+ foo
1873
+ a: $var2
1874
+
1875
+ +foo
1876
+ SASS
1877
+ end
1878
+ end
1879
+
1880
+ def test_equals_args_deep_unquote_vars
1881
+ silence_warnings do
1882
+ assert_equal(<<CSS, render(<<SASS))
1883
+ foo {
1884
+ a: foo bar;
1885
+ b: bar foo; }
1886
+ CSS
1887
+ $var: "foo"
1888
+ =foo($a = $var "bar", $b = "bar" $var)
1889
+ foo
1890
+ a: $a
1891
+ b: $b
1892
+
1893
+ +foo
1894
+ SASS
1895
+ end
1896
+ end
1897
+
1898
+ def test_equals_properties_force_division
1899
+ silence_warnings do
1900
+ assert_equal(<<CSS, render(<<SASS))
1901
+ foo {
1902
+ a: 0.5; }
1903
+ CSS
1904
+ foo
1905
+ a = 1px/2px
1906
+ SASS
1907
+ end
1908
+ end
1909
+
1910
+ def test_warn_directive
1911
+ expected_warning = <<EXPECTATION
1912
+ WARNING: this is a warning
1913
+ on line 4 of test_warn_directive_inline.sass
1914
+
1915
+ WARNING: this is a mixin warning
1916
+ on line 2 of test_warn_directive_inline.sass, in `foo'
1917
+ from line 7 of test_warn_directive_inline.sass
1918
+ EXPECTATION
1919
+ assert_warning expected_warning do
1920
+ assert_equal <<CSS, render(<<SASS)
1921
+ bar {
1922
+ c: d; }
1923
+ CSS
1924
+ =foo
1925
+ @warn "this is a mixin warning"
1926
+
1927
+ @warn "this is a warning"
1928
+ bar
1929
+ c: d
1930
+ +foo
1931
+ SASS
1932
+ end
1933
+ end
1934
+
1935
+ def test_warn_directive_when_quiet
1936
+ assert_warning "" do
1937
+ assert_equal <<CSS, render(<<SASS, :quiet => true)
1938
+ CSS
1939
+ @warn "this is a warning"
1940
+ SASS
1941
+ end
1942
+ end
1943
+
1944
+ def test_warn_with_imports
1945
+ expected_warning = <<WARN
1946
+ WARNING: In the main file
1947
+ on line 1 of #{File.dirname(__FILE__)}/templates/warn.sass
1948
+
1949
+ WARNING: Imported
1950
+ on line 1 of #{File.dirname(__FILE__)}/templates/warn_imported.sass
1951
+ from line 2 of #{File.dirname(__FILE__)}/templates/warn.sass
1952
+
1953
+ WARNING: In an imported mixin
1954
+ on line 4 of #{File.dirname(__FILE__)}/templates/warn_imported.sass, in `emits-a-warning'
1955
+ from line 3 of #{File.dirname(__FILE__)}/templates/warn.sass
1956
+ WARN
1957
+ assert_warning expected_warning do
1958
+ renders_correctly "warn", :style => :compact, :load_paths => [File.dirname(__FILE__) + "/templates"]
1959
+ end
1960
+ end
1961
+
1962
+ # Regression tests
1963
+
1964
+ def test_parens_in_mixins
1965
+ assert_equal(<<CSS, render(<<SASS))
1966
+ .foo {
1967
+ color: #01ff7f;
1968
+ background-color: #000102; }
1969
+ CSS
1970
+ =foo($c1, $c2: rgb(0, 1, 2))
1971
+ color: $c1
1972
+ background-color: $c2
1973
+
1974
+ .foo
1975
+ +foo(rgb(1,255,127))
1976
+ SASS
1977
+ end
1978
+
1979
+ def test_comment_beneath_prop
1980
+ assert_equal(<<RESULT, render(<<SOURCE))
1981
+ .box {
1982
+ border-style: solid; }
1983
+ RESULT
1984
+ .box
1985
+ :border
1986
+ //:color black
1987
+ :style solid
1988
+ SOURCE
1989
+
1990
+ assert_equal(<<RESULT, render(<<SOURCE))
1991
+ .box {
1992
+ /* :color black */
1993
+ border-style: solid; }
1994
+ RESULT
1995
+ .box
1996
+ :border
1997
+ /* :color black
1998
+ :style solid
1999
+ SOURCE
2000
+
2001
+ assert_equal(<<RESULT, render(<<SOURCE, :style => :compressed))
2002
+ .box{border-style:solid}
2003
+ RESULT
2004
+ .box
2005
+ :border
2006
+ /*:color black
2007
+ :style solid
2008
+ SOURCE
2009
+ end
2010
+
2011
+ def test_compressed_comment_beneath_directive
2012
+ assert_equal(<<RESULT, render(<<SOURCE, :style => :compressed))
2013
+ @foo{a:b}
2014
+ RESULT
2015
+ @foo
2016
+ a: b
2017
+ /*b: c
2018
+ SOURCE
2019
+ end
2020
+
2021
+ def test_comment_with_crazy_indentation
2022
+ assert_equal(<<CSS, render(<<SASS))
2023
+ /* This is a loud comment:
2024
+ * Where the indentation is wonky. */
2025
+ .comment {
2026
+ width: 1px; }
2027
+ CSS
2028
+ /*
2029
+ This is a loud comment:
2030
+ Where the indentation is wonky.
2031
+ //
2032
+ This is a silent comment:
2033
+ Where the indentation is wonky.
2034
+ .comment
2035
+ width: 1px
2036
+ SASS
2037
+ end
2038
+
2039
+ def test_plus_with_space
2040
+ assert_equal(<<CSS, render(<<SASS))
2041
+ a + b {
2042
+ color: green; }
2043
+ CSS
2044
+ a
2045
+ + b
2046
+ color: green
2047
+ SASS
2048
+ end
2049
+
2050
+ def test_empty_line_comment
2051
+ assert_equal(<<CSS, render(<<SASS))
2052
+ /* Foo
2053
+ *
2054
+ * Bar */
2055
+ CSS
2056
+ /*
2057
+ Foo
2058
+
2059
+ Bar
2060
+ SASS
2061
+ end
2062
+
2063
+ def test_empty_comment
2064
+ assert_equal(<<CSS, render(<<SASS))
2065
+ /* */
2066
+ a {
2067
+ /* */
2068
+ b: c; }
2069
+ CSS
2070
+ /*
2071
+ a
2072
+ /*
2073
+ b: c
2074
+ SASS
2075
+ end
2076
+
2077
+ def test_options_available_in_environment
2078
+ assert_equal(<<CSS, render(<<SASS))
2079
+ a {
2080
+ b: nested; }
2081
+ CSS
2082
+ a
2083
+ b: option("style")
2084
+ SASS
2085
+ end
2086
+
2087
+ def test_mixin_no_arg_error
2088
+ assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "($bar,": expected variable (e.g. $foo), was ")"') do
2089
+ render(<<SASS)
2090
+ =foo($bar,)
2091
+ bip: bap
2092
+ SASS
2093
+ end
2094
+ end
2095
+
2096
+ def test_import_with_commas_in_url
2097
+ assert_equal <<CSS, render(<<SASS)
2098
+ @import url(foo.css?bar,baz);
2099
+ CSS
2100
+ @import url(foo.css?bar,baz)
2101
+ SASS
2102
+ end
2103
+
2104
+ def test_function_output_with_comma
2105
+ assert_equal <<CSS, render(<<SASS)
2106
+ foo {
2107
+ a: b(c), d(e); }
2108
+ CSS
2109
+ foo
2110
+ a: b(c), d(e)
2111
+ SASS
2112
+ end
2113
+
2114
+ def test_interpolation_with_comma
2115
+ assert_equal <<CSS, render(<<SASS)
2116
+ foo {
2117
+ a: foo, bar; }
2118
+ CSS
2119
+ $foo: foo
2120
+ foo
2121
+ a: \#{$foo}, bar
2122
+ SASS
2123
+ end
2124
+
2125
+ def test_string_interpolation_with_comma
2126
+ assert_equal <<CSS, render(<<SASS)
2127
+ foo {
2128
+ a: "bip foo bap", bar; }
2129
+ CSS
2130
+ $foo: foo
2131
+ foo
2132
+ a: "bip \#{$foo} bap", bar
2133
+ SASS
2134
+ end
2135
+
2136
+ # Encodings
2137
+
2138
+ unless Sass::Util.ruby1_8?
2139
+ def test_encoding_error
2140
+ render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
2141
+ assert(false, "Expected exception")
2142
+ rescue Sass::SyntaxError => e
2143
+ assert_equal(3, e.sass_line)
2144
+ assert_equal('Invalid UTF-8 character "\xFE"', e.message)
2145
+ end
2146
+
2147
+ def test_ascii_incompatible_encoding_error
2148
+ template = "foo\nbar\nb_z".encode("utf-16le")
2149
+ template[9] = "\xFE".force_encoding("utf-16le")
2150
+ render(template)
2151
+ assert(false, "Expected exception")
2152
+ rescue Sass::SyntaxError => e
2153
+ assert_equal(3, e.sass_line)
2154
+ assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
2155
+ end
2156
+
2157
+ def test_same_charset_as_encoding
2158
+ assert_renders_encoded(<<CSS, <<SASS)
2159
+ @charset "utf-8";
2160
+ fóó {
2161
+ a: b; }
2162
+ CSS
2163
+ @charset "utf-8"
2164
+ fóó
2165
+ a: b
2166
+ SASS
2167
+ end
2168
+
2169
+ def test_different_charset_than_encoding
2170
+ assert_renders_encoded(<<CSS.force_encoding("IBM866"), <<SASS)
2171
+ @charset "ibm866";
2172
+ fóó {
2173
+ a: b; }
2174
+ CSS
2175
+ @charset "ibm866"
2176
+ fóó
2177
+ a: b
2178
+ SASS
2179
+ end
2180
+
2181
+ def test_different_encoding_than_system
2182
+ assert_renders_encoded(<<CSS.encode("IBM866"), <<SASS.encode("IBM866"))
2183
+ тАЬ {
2184
+ a: b; }
2185
+ CSS
2186
+ тАЬ
2187
+ a: b
2188
+ SASS
2189
+ end
2190
+
2191
+ def test_multibyte_charset
2192
+ assert_renders_encoded(<<CSS.encode("UTF-16BE"), <<SASS.encode("UTF-16BE").force_encoding("UTF-8"))
2193
+ @charset "utf-16be";
2194
+ fóó {
2195
+ a: b; }
2196
+ CSS
2197
+ @charset "utf-16be"
2198
+ fóó
2199
+ a: b
2200
+ SASS
2201
+ end
2202
+
2203
+ def test_multibyte_charset_without_endian_specifier
2204
+ assert_renders_encoded(<<CSS.encode("UTF-32LE"), <<SASS.encode("UTF-32LE").force_encoding("UTF-8"))
2205
+ @charset "utf-32";
2206
+ fóó {
2207
+ a: b; }
2208
+ CSS
2209
+ @charset "utf-32"
2210
+ fóó
2211
+ a: b
2212
+ SASS
2213
+ end
2214
+
2215
+ def test_utf8_bom
2216
+ assert_renders_encoded(<<CSS, <<SASS.force_encoding("BINARY"))
2217
+ fóó {
2218
+ a: b; }
2219
+ CSS
2220
+ \uFEFFfóó
2221
+ a: b
2222
+ SASS
2223
+ end
2224
+
2225
+ def test_utf16le_bom
2226
+ assert_renders_encoded(<<CSS.encode("UTF-16LE"), <<SASS.encode("UTF-16LE").force_encoding("BINARY"))
2227
+ fóó {
2228
+ a: b; }
2229
+ CSS
2230
+ \uFEFFfóó
2231
+ a: b
2232
+ SASS
2233
+ end
2234
+
2235
+ def test_utf32be_bom
2236
+ assert_renders_encoded(<<CSS.encode("UTF-32BE"), <<SASS.encode("UTF-32BE").force_encoding("BINARY"))
2237
+ fóó {
2238
+ a: b; }
2239
+ CSS
2240
+ \uFEFFfóó
2241
+ a: b
2242
+ SASS
2243
+ end
2244
+ end
2245
+
2246
+ def test_original_filename_set
2247
+ importer = MockImporter.new
2248
+ importer.add_import("imported", "div{color:red}")
2249
+
2250
+ original_filename = filename_for_test
2251
+ engine = Sass::Engine.new('@import "imported"; div{color:blue}',
2252
+ :filename => original_filename, :load_paths => [importer], :syntax => :scss)
2253
+ engine.render
2254
+
2255
+ assert_equal original_filename, engine.options[:original_filename]
2256
+ assert_equal original_filename, importer.engine("imported").options[:original_filename]
2257
+ end
2258
+
2259
+
2260
+ private
2261
+
2262
+ def assert_hash_has(hash, expected)
2263
+ expected.each {|k, v| assert_equal(v, hash[k])}
2264
+ end
2265
+
2266
+ def assert_renders_encoded(css, sass)
2267
+ result = render(sass)
2268
+ assert_equal css.encoding, result.encoding
2269
+ assert_equal css, result
2270
+ end
2271
+
2272
+ def render(sass, options = {})
2273
+ munge_filename options
2274
+ Sass::Engine.new(sass, options).render
2275
+ end
2276
+
2277
+ def renders_correctly(name, options={})
2278
+ sass_file = load_file(name, "sass")
2279
+ css_file = load_file(name, "css")
2280
+ options[:filename] ||= filename(name, "sass")
2281
+ options[:syntax] ||= :sass
2282
+ options[:css_filename] ||= filename(name, "css")
2283
+ css_result = Sass::Engine.new(sass_file, options).render
2284
+ assert_equal css_file, css_result
2285
+ end
2286
+
2287
+ def load_file(name, type = "sass")
2288
+ @result = ''
2289
+ File.new(filename(name, type)).each_line { |l| @result += l }
2290
+ @result
2291
+ end
2292
+
2293
+ def filename(name, type)
2294
+ File.dirname(__FILE__) + "/#{type == 'sass' ? 'templates' : 'results'}/#{name}.#{type}"
2295
+ end
2296
+
2297
+ def sassc_path(template)
2298
+ sassc_path = File.join(File.dirname(__FILE__) + "/templates/#{template}.sass")
2299
+ engine = Sass::Engine.new("", :filename => sassc_path,
2300
+ :importer => Sass::Importers::Filesystem.new("."))
2301
+ key = engine.send(:sassc_key)
2302
+ File.join(engine.options[:cache_location], key)
2303
+ end
2304
+ end
2305
+