aliddle-sass 1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.yardopts +11 -0
- data/CONTRIBUTING +3 -0
- data/MIT-LICENSE +20 -0
- data/README.md +201 -0
- data/Rakefile +347 -0
- data/VERSION +1 -0
- data/VERSION_NAME +1 -0
- data/bin/sass +9 -0
- data/bin/sass-convert +8 -0
- data/bin/scss +9 -0
- data/extra/update_watch.rb +13 -0
- data/init.rb +18 -0
- data/lib/sass.rb +95 -0
- data/lib/sass/cache_stores.rb +15 -0
- data/lib/sass/cache_stores/base.rb +88 -0
- data/lib/sass/cache_stores/chain.rb +33 -0
- data/lib/sass/cache_stores/filesystem.rb +60 -0
- data/lib/sass/cache_stores/memory.rb +47 -0
- data/lib/sass/cache_stores/null.rb +25 -0
- data/lib/sass/callbacks.rb +66 -0
- data/lib/sass/css.rb +409 -0
- data/lib/sass/engine.rb +928 -0
- data/lib/sass/environment.rb +101 -0
- data/lib/sass/error.rb +201 -0
- data/lib/sass/exec.rb +707 -0
- data/lib/sass/importers.rb +22 -0
- data/lib/sass/importers/base.rb +139 -0
- data/lib/sass/importers/filesystem.rb +190 -0
- data/lib/sass/logger.rb +15 -0
- data/lib/sass/logger/base.rb +32 -0
- data/lib/sass/logger/log_level.rb +49 -0
- data/lib/sass/media.rb +213 -0
- data/lib/sass/plugin.rb +132 -0
- data/lib/sass/plugin/compiler.rb +406 -0
- data/lib/sass/plugin/configuration.rb +123 -0
- data/lib/sass/plugin/generic.rb +15 -0
- data/lib/sass/plugin/merb.rb +48 -0
- data/lib/sass/plugin/rack.rb +60 -0
- data/lib/sass/plugin/rails.rb +47 -0
- data/lib/sass/plugin/staleness_checker.rb +183 -0
- data/lib/sass/railtie.rb +9 -0
- data/lib/sass/repl.rb +57 -0
- data/lib/sass/root.rb +7 -0
- data/lib/sass/script.rb +39 -0
- data/lib/sass/script/arg_list.rb +52 -0
- data/lib/sass/script/bool.rb +18 -0
- data/lib/sass/script/color.rb +606 -0
- data/lib/sass/script/css_lexer.rb +29 -0
- data/lib/sass/script/css_parser.rb +31 -0
- data/lib/sass/script/funcall.rb +237 -0
- data/lib/sass/script/functions.rb +1543 -0
- data/lib/sass/script/interpolation.rb +79 -0
- data/lib/sass/script/lexer.rb +348 -0
- data/lib/sass/script/list.rb +85 -0
- data/lib/sass/script/literal.rb +221 -0
- data/lib/sass/script/node.rb +99 -0
- data/lib/sass/script/null.rb +37 -0
- data/lib/sass/script/number.rb +453 -0
- data/lib/sass/script/operation.rb +110 -0
- data/lib/sass/script/parser.rb +495 -0
- data/lib/sass/script/string.rb +51 -0
- data/lib/sass/script/string_interpolation.rb +103 -0
- data/lib/sass/script/unary_operation.rb +69 -0
- data/lib/sass/script/variable.rb +58 -0
- data/lib/sass/scss.rb +16 -0
- data/lib/sass/scss/css_parser.rb +36 -0
- data/lib/sass/scss/parser.rb +1179 -0
- data/lib/sass/scss/rx.rb +133 -0
- data/lib/sass/scss/script_lexer.rb +15 -0
- data/lib/sass/scss/script_parser.rb +25 -0
- data/lib/sass/scss/static_parser.rb +54 -0
- data/lib/sass/selector.rb +452 -0
- data/lib/sass/selector/abstract_sequence.rb +94 -0
- data/lib/sass/selector/comma_sequence.rb +92 -0
- data/lib/sass/selector/sequence.rb +507 -0
- data/lib/sass/selector/simple.rb +119 -0
- data/lib/sass/selector/simple_sequence.rb +212 -0
- data/lib/sass/shared.rb +76 -0
- data/lib/sass/supports.rb +229 -0
- data/lib/sass/tree/charset_node.rb +22 -0
- data/lib/sass/tree/comment_node.rb +82 -0
- data/lib/sass/tree/content_node.rb +9 -0
- data/lib/sass/tree/css_import_node.rb +60 -0
- data/lib/sass/tree/debug_node.rb +18 -0
- data/lib/sass/tree/directive_node.rb +42 -0
- data/lib/sass/tree/each_node.rb +24 -0
- data/lib/sass/tree/extend_node.rb +36 -0
- data/lib/sass/tree/for_node.rb +36 -0
- data/lib/sass/tree/function_node.rb +34 -0
- data/lib/sass/tree/if_node.rb +52 -0
- data/lib/sass/tree/import_node.rb +75 -0
- data/lib/sass/tree/media_node.rb +58 -0
- data/lib/sass/tree/mixin_def_node.rb +38 -0
- data/lib/sass/tree/mixin_node.rb +39 -0
- data/lib/sass/tree/node.rb +196 -0
- data/lib/sass/tree/prop_node.rb +152 -0
- data/lib/sass/tree/return_node.rb +18 -0
- data/lib/sass/tree/root_node.rb +28 -0
- data/lib/sass/tree/rule_node.rb +132 -0
- data/lib/sass/tree/supports_node.rb +51 -0
- data/lib/sass/tree/trace_node.rb +32 -0
- data/lib/sass/tree/variable_node.rb +30 -0
- data/lib/sass/tree/visitors/base.rb +75 -0
- data/lib/sass/tree/visitors/check_nesting.rb +147 -0
- data/lib/sass/tree/visitors/convert.rb +316 -0
- data/lib/sass/tree/visitors/cssize.rb +229 -0
- data/lib/sass/tree/visitors/deep_copy.rb +102 -0
- data/lib/sass/tree/visitors/extend.rb +68 -0
- data/lib/sass/tree/visitors/perform.rb +446 -0
- data/lib/sass/tree/visitors/set_options.rb +125 -0
- data/lib/sass/tree/visitors/to_css.rb +230 -0
- data/lib/sass/tree/warn_node.rb +18 -0
- data/lib/sass/tree/while_node.rb +18 -0
- data/lib/sass/util.rb +906 -0
- data/lib/sass/util/multibyte_string_scanner.rb +155 -0
- data/lib/sass/util/subset_map.rb +109 -0
- data/lib/sass/util/test.rb +10 -0
- data/lib/sass/version.rb +126 -0
- data/rails/init.rb +1 -0
- data/test/Gemfile +3 -0
- data/test/Gemfile.lock +10 -0
- data/test/sass/cache_test.rb +89 -0
- data/test/sass/callbacks_test.rb +61 -0
- data/test/sass/conversion_test.rb +1760 -0
- data/test/sass/css2sass_test.rb +439 -0
- data/test/sass/data/hsl-rgb.txt +319 -0
- data/test/sass/engine_test.rb +3243 -0
- data/test/sass/exec_test.rb +86 -0
- data/test/sass/extend_test.rb +1461 -0
- data/test/sass/fixtures/test_staleness_check_across_importers.css +1 -0
- data/test/sass/fixtures/test_staleness_check_across_importers.scss +1 -0
- data/test/sass/functions_test.rb +1139 -0
- data/test/sass/importer_test.rb +192 -0
- data/test/sass/logger_test.rb +58 -0
- data/test/sass/mock_importer.rb +49 -0
- data/test/sass/more_results/more1.css +9 -0
- data/test/sass/more_results/more1_with_line_comments.css +26 -0
- data/test/sass/more_results/more_import.css +29 -0
- data/test/sass/more_templates/_more_partial.sass +2 -0
- data/test/sass/more_templates/more1.sass +23 -0
- data/test/sass/more_templates/more_import.sass +11 -0
- data/test/sass/plugin_test.rb +550 -0
- data/test/sass/results/alt.css +4 -0
- data/test/sass/results/basic.css +9 -0
- data/test/sass/results/cached_import_option.css +3 -0
- data/test/sass/results/compact.css +5 -0
- data/test/sass/results/complex.css +86 -0
- data/test/sass/results/compressed.css +1 -0
- data/test/sass/results/expanded.css +19 -0
- data/test/sass/results/filename_fn.css +3 -0
- data/test/sass/results/if.css +3 -0
- data/test/sass/results/import.css +31 -0
- data/test/sass/results/import_charset.css +5 -0
- data/test/sass/results/import_charset_1_8.css +5 -0
- data/test/sass/results/import_charset_ibm866.css +5 -0
- data/test/sass/results/import_content.css +1 -0
- data/test/sass/results/line_numbers.css +49 -0
- data/test/sass/results/mixins.css +95 -0
- data/test/sass/results/multiline.css +24 -0
- data/test/sass/results/nested.css +22 -0
- data/test/sass/results/options.css +1 -0
- data/test/sass/results/parent_ref.css +13 -0
- data/test/sass/results/script.css +16 -0
- data/test/sass/results/scss_import.css +31 -0
- data/test/sass/results/scss_importee.css +2 -0
- data/test/sass/results/subdir/nested_subdir/nested_subdir.css +1 -0
- data/test/sass/results/subdir/subdir.css +3 -0
- data/test/sass/results/units.css +11 -0
- data/test/sass/results/warn.css +0 -0
- data/test/sass/results/warn_imported.css +0 -0
- data/test/sass/script_conversion_test.rb +299 -0
- data/test/sass/script_test.rb +591 -0
- data/test/sass/scss/css_test.rb +1093 -0
- data/test/sass/scss/rx_test.rb +156 -0
- data/test/sass/scss/scss_test.rb +2043 -0
- data/test/sass/scss/test_helper.rb +37 -0
- data/test/sass/templates/_cached_import_option_partial.scss +1 -0
- data/test/sass/templates/_double_import_loop2.sass +1 -0
- data/test/sass/templates/_filename_fn_import.scss +11 -0
- data/test/sass/templates/_imported_charset_ibm866.sass +4 -0
- data/test/sass/templates/_imported_charset_utf8.sass +4 -0
- data/test/sass/templates/_imported_content.sass +3 -0
- data/test/sass/templates/_partial.sass +2 -0
- data/test/sass/templates/_same_name_different_partiality.scss +1 -0
- data/test/sass/templates/alt.sass +16 -0
- data/test/sass/templates/basic.sass +23 -0
- data/test/sass/templates/bork1.sass +2 -0
- data/test/sass/templates/bork2.sass +2 -0
- data/test/sass/templates/bork3.sass +2 -0
- data/test/sass/templates/bork4.sass +2 -0
- data/test/sass/templates/bork5.sass +3 -0
- data/test/sass/templates/cached_import_option.scss +3 -0
- data/test/sass/templates/compact.sass +17 -0
- data/test/sass/templates/complex.sass +305 -0
- data/test/sass/templates/compressed.sass +15 -0
- data/test/sass/templates/double_import_loop1.sass +1 -0
- data/test/sass/templates/expanded.sass +17 -0
- data/test/sass/templates/filename_fn.scss +18 -0
- data/test/sass/templates/if.sass +11 -0
- data/test/sass/templates/import.sass +12 -0
- data/test/sass/templates/import_charset.sass +9 -0
- data/test/sass/templates/import_charset_1_8.sass +6 -0
- data/test/sass/templates/import_charset_ibm866.sass +11 -0
- data/test/sass/templates/import_content.sass +4 -0
- data/test/sass/templates/importee.less +2 -0
- data/test/sass/templates/importee.sass +19 -0
- data/test/sass/templates/line_numbers.sass +13 -0
- data/test/sass/templates/mixin_bork.sass +5 -0
- data/test/sass/templates/mixins.sass +76 -0
- data/test/sass/templates/multiline.sass +20 -0
- data/test/sass/templates/nested.sass +25 -0
- data/test/sass/templates/nested_bork1.sass +2 -0
- data/test/sass/templates/nested_bork2.sass +2 -0
- data/test/sass/templates/nested_bork3.sass +2 -0
- data/test/sass/templates/nested_bork4.sass +2 -0
- data/test/sass/templates/nested_import.sass +2 -0
- data/test/sass/templates/nested_mixin_bork.sass +6 -0
- data/test/sass/templates/options.sass +2 -0
- data/test/sass/templates/parent_ref.sass +25 -0
- data/test/sass/templates/same_name_different_ext.sass +2 -0
- data/test/sass/templates/same_name_different_ext.scss +1 -0
- data/test/sass/templates/same_name_different_partiality.scss +1 -0
- data/test/sass/templates/script.sass +101 -0
- data/test/sass/templates/scss_import.scss +11 -0
- data/test/sass/templates/scss_importee.scss +1 -0
- data/test/sass/templates/single_import_loop.sass +1 -0
- data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +2 -0
- data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +3 -0
- data/test/sass/templates/subdir/subdir.sass +6 -0
- data/test/sass/templates/units.sass +11 -0
- data/test/sass/templates/warn.sass +3 -0
- data/test/sass/templates/warn_imported.sass +4 -0
- data/test/sass/test_helper.rb +8 -0
- data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
- data/test/sass/util/subset_map_test.rb +91 -0
- data/test/sass/util_test.rb +313 -0
- data/test/test_helper.rb +80 -0
- metadata +348 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
|
3
|
+
require File.dirname(__FILE__) + '/test_helper'
|
|
4
|
+
|
|
5
|
+
require 'sass/plugin'
|
|
6
|
+
|
|
7
|
+
class ImporterTest < Test::Unit::TestCase
|
|
8
|
+
|
|
9
|
+
class FruitImporter < Sass::Importers::Base
|
|
10
|
+
def find(name, context = nil)
|
|
11
|
+
if name =~ %r{fruits/(\w+)(\.s[ac]ss)?}
|
|
12
|
+
fruit = $1
|
|
13
|
+
color = case $1
|
|
14
|
+
when "apple"
|
|
15
|
+
"red"
|
|
16
|
+
when "orange"
|
|
17
|
+
"orange"
|
|
18
|
+
else
|
|
19
|
+
"blue"
|
|
20
|
+
end
|
|
21
|
+
contents = %Q{
|
|
22
|
+
$#{fruit}-color: #{color} !default;
|
|
23
|
+
@mixin #{fruit} {
|
|
24
|
+
color: $#{fruit}-color;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
Sass::Engine.new(contents, :filename => name, :syntax => :scss, :importer => self)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def key(name, context)
|
|
32
|
+
[self.class.name, name]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# This class proves that you can override the extension scheme for importers
|
|
37
|
+
class ReversedExtImporter < Sass::Importers::Filesystem
|
|
38
|
+
def extensions
|
|
39
|
+
{"sscs" => :scss, "ssas" => :sass}
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# This importer maps one import to another import
|
|
44
|
+
# based on the mappings passed to importer's constructor.
|
|
45
|
+
class IndirectImporter < Sass::Importers::Base
|
|
46
|
+
def initialize(mappings, mtimes)
|
|
47
|
+
@mappings = mappings
|
|
48
|
+
@mtimes = mtimes
|
|
49
|
+
end
|
|
50
|
+
def find_relative(uri, base, options)
|
|
51
|
+
nil
|
|
52
|
+
end
|
|
53
|
+
def find(name, options)
|
|
54
|
+
if @mappings.has_key?(name)
|
|
55
|
+
Sass::Engine.new(
|
|
56
|
+
%Q[@import "#{@mappings[name]}";],
|
|
57
|
+
options.merge(
|
|
58
|
+
:filename => name,
|
|
59
|
+
:syntax => :scss,
|
|
60
|
+
:importer => self
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
def mtime(uri, options)
|
|
66
|
+
@mtimes.fetch(uri, @mtimes.has_key?(uri) ? Time.now : nil)
|
|
67
|
+
end
|
|
68
|
+
def key(uri, options)
|
|
69
|
+
[self.class.name, uri]
|
|
70
|
+
end
|
|
71
|
+
def to_s
|
|
72
|
+
"IndirectImporter(#{@mappings.keys.join(", ")})"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# This importer maps the import to single class
|
|
77
|
+
# based on the mappings passed to importer's constructor.
|
|
78
|
+
class ClassImporter < Sass::Importers::Base
|
|
79
|
+
def initialize(mappings, mtimes)
|
|
80
|
+
@mappings = mappings
|
|
81
|
+
@mtimes = mtimes
|
|
82
|
+
end
|
|
83
|
+
def find_relative(uri, base, options)
|
|
84
|
+
nil
|
|
85
|
+
end
|
|
86
|
+
def find(name, options)
|
|
87
|
+
if @mappings.has_key?(name)
|
|
88
|
+
Sass::Engine.new(
|
|
89
|
+
%Q[.#{name}{#{@mappings[name]}}],
|
|
90
|
+
options.merge(
|
|
91
|
+
:filename => name,
|
|
92
|
+
:syntax => :scss,
|
|
93
|
+
:importer => self
|
|
94
|
+
)
|
|
95
|
+
)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
def mtime(uri, options)
|
|
99
|
+
@mtimes.fetch(uri, @mtimes.has_key?(uri) ? Time.now : nil)
|
|
100
|
+
end
|
|
101
|
+
def key(uri, options)
|
|
102
|
+
[self.class.name, uri]
|
|
103
|
+
end
|
|
104
|
+
def to_s
|
|
105
|
+
"ClassImporter(#{@mappings.keys.join(", ")})"
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_can_resolve_generated_imports
|
|
110
|
+
scss_file = %Q{
|
|
111
|
+
$pear-color: green;
|
|
112
|
+
@import "fruits/apple"; @import "fruits/orange"; @import "fruits/pear";
|
|
113
|
+
.apple { @include apple; }
|
|
114
|
+
.orange { @include orange; }
|
|
115
|
+
.pear { @include pear; }
|
|
116
|
+
}
|
|
117
|
+
css_file = <<CSS
|
|
118
|
+
.apple { color: red; }
|
|
119
|
+
|
|
120
|
+
.orange { color: orange; }
|
|
121
|
+
|
|
122
|
+
.pear { color: green; }
|
|
123
|
+
CSS
|
|
124
|
+
options = {:style => :compact, :load_paths => [FruitImporter.new], :syntax => :scss}
|
|
125
|
+
assert_equal css_file, Sass::Engine.new(scss_file, options).render
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def test_extension_overrides
|
|
129
|
+
FileUtils.mkdir_p(absolutize("tmp"))
|
|
130
|
+
open(absolutize("tmp/foo.ssas"), "w") {|f| f.write(".foo\n reversed: true\n")}
|
|
131
|
+
open(absolutize("tmp/bar.sscs"), "w") {|f| f.write(".bar {reversed: true}\n")}
|
|
132
|
+
scss_file = %Q{
|
|
133
|
+
@import "foo", "bar";
|
|
134
|
+
@import "foo.ssas", "bar.sscs";
|
|
135
|
+
}
|
|
136
|
+
css_file = <<CSS
|
|
137
|
+
.foo { reversed: true; }
|
|
138
|
+
|
|
139
|
+
.bar { reversed: true; }
|
|
140
|
+
|
|
141
|
+
.foo { reversed: true; }
|
|
142
|
+
|
|
143
|
+
.bar { reversed: true; }
|
|
144
|
+
CSS
|
|
145
|
+
options = {:style => :compact, :load_paths => [ReversedExtImporter.new(absolutize("tmp"))], :syntax => :scss}
|
|
146
|
+
assert_equal css_file, Sass::Engine.new(scss_file, options).render
|
|
147
|
+
ensure
|
|
148
|
+
FileUtils.rm_rf(absolutize("tmp"))
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def test_staleness_check_across_importers
|
|
152
|
+
file_system_importer = Sass::Importers::Filesystem.new(fixture_dir)
|
|
153
|
+
# Make sure the first import is older
|
|
154
|
+
indirect_importer = IndirectImporter.new({"apple" => "pear"}, {"apple" => Time.now - 1})
|
|
155
|
+
# Make css file is newer so the dependencies are the only way for the css file to be out of date.
|
|
156
|
+
FileUtils.touch(fixture_file("test_staleness_check_across_importers.css"))
|
|
157
|
+
# Make sure the first import is older
|
|
158
|
+
class_importer = ClassImporter.new({"pear" => %Q{color: green;}}, {"pear" => Time.now + 1})
|
|
159
|
+
|
|
160
|
+
options = {
|
|
161
|
+
:style => :compact,
|
|
162
|
+
:filename => fixture_file("test_staleness_check_across_importers.scss"),
|
|
163
|
+
:importer => file_system_importer,
|
|
164
|
+
:load_paths => [file_system_importer, indirect_importer, class_importer],
|
|
165
|
+
:syntax => :scss
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
assert_equal File.read(fixture_file("test_staleness_check_across_importers.css")),
|
|
169
|
+
Sass::Engine.new(File.read(fixture_file("test_staleness_check_across_importers.scss")), options).render
|
|
170
|
+
|
|
171
|
+
checker = Sass::Plugin::StalenessChecker.new(options)
|
|
172
|
+
|
|
173
|
+
assert checker.stylesheet_needs_update?(
|
|
174
|
+
fixture_file("test_staleness_check_across_importers.css"),
|
|
175
|
+
fixture_file("test_staleness_check_across_importers.scss"),
|
|
176
|
+
file_system_importer
|
|
177
|
+
)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def fixture_dir
|
|
181
|
+
File.join(File.dirname(__FILE__), "fixtures")
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def fixture_file(path)
|
|
185
|
+
File.join(fixture_dir, path)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def test_absolute_files_across_template_locations
|
|
189
|
+
importer = Sass::Importers::Filesystem.new(absolutize 'templates')
|
|
190
|
+
assert_not_nil importer.mtime(absolutize('more_templates/more1.sass'), {})
|
|
191
|
+
end
|
|
192
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
|
3
|
+
require 'pathname'
|
|
4
|
+
|
|
5
|
+
class LoggerTest < Test::Unit::TestCase
|
|
6
|
+
|
|
7
|
+
class InterceptedLogger < Sass::Logger::Base
|
|
8
|
+
|
|
9
|
+
attr_accessor :messages
|
|
10
|
+
|
|
11
|
+
def initialize(*args)
|
|
12
|
+
super
|
|
13
|
+
self.messages = []
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def reset!
|
|
17
|
+
self.messages = []
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def _log(*args)
|
|
21
|
+
messages << [args]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_global_sass_logger_instance_exists
|
|
27
|
+
assert Sass.logger.respond_to?(:warn)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_log_level_orders
|
|
31
|
+
logged_levels = {
|
|
32
|
+
:trace => [ [], [:trace, :debug, :info, :warn, :error]],
|
|
33
|
+
:debug => [ [:trace], [:debug, :info, :warn, :error]],
|
|
34
|
+
:info => [ [:trace, :debug], [:info, :warn, :error]],
|
|
35
|
+
:warn => [ [:trace, :debug, :info], [:warn, :error]],
|
|
36
|
+
:error => [ [:trace, :debug, :info, :warn], [:error]]
|
|
37
|
+
}
|
|
38
|
+
logged_levels.each do |level, (should_not_be_logged, should_be_logged)|
|
|
39
|
+
logger = Sass::Logger::Base.new(level)
|
|
40
|
+
should_not_be_logged.each do |should_level|
|
|
41
|
+
assert !logger.logging_level?(should_level)
|
|
42
|
+
end
|
|
43
|
+
should_be_logged.each do |should_level|
|
|
44
|
+
assert logger.logging_level?(should_level)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def test_logging_can_be_disabled
|
|
50
|
+
logger = InterceptedLogger.new
|
|
51
|
+
logger.error("message #1")
|
|
52
|
+
assert_equal 1, logger.messages.size
|
|
53
|
+
logger.reset!
|
|
54
|
+
logger.disabled = true
|
|
55
|
+
logger.error("message #2")
|
|
56
|
+
assert_equal 0, logger.messages.size
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
class MockImporter < Sass::Importers::Base
|
|
2
|
+
def initialize(name = "mock")
|
|
3
|
+
@name = name
|
|
4
|
+
@imports = Hash.new({})
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def find_relative(uri, base, options)
|
|
8
|
+
nil
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def find(uri, options)
|
|
12
|
+
contents = @imports[uri][:contents]
|
|
13
|
+
return unless contents
|
|
14
|
+
options[:syntax] = @imports[uri][:syntax]
|
|
15
|
+
options[:filename] = uri
|
|
16
|
+
options[:importer] = self
|
|
17
|
+
@imports[uri][:engine] = Sass::Engine.new(contents, options)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def mtime(uri, options)
|
|
21
|
+
@imports[uri][:mtime]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def key(uri, options)
|
|
25
|
+
["mock", uri]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def to_s
|
|
29
|
+
@name
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Methods for testing
|
|
33
|
+
|
|
34
|
+
def add_import(uri, contents, syntax = :scss, mtime = Time.now - 10)
|
|
35
|
+
@imports[uri] = {
|
|
36
|
+
:contents => contents,
|
|
37
|
+
:mtime => mtime,
|
|
38
|
+
:syntax => syntax
|
|
39
|
+
}
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def touch(uri)
|
|
43
|
+
@imports[uri][:mtime] = Time.now
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def engine(uri)
|
|
47
|
+
@imports[uri][:engine]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
body { font: Arial; background: blue; }
|
|
2
|
+
|
|
3
|
+
#page { width: 700px; height: 100; }
|
|
4
|
+
#page #header { height: 300px; }
|
|
5
|
+
#page #header h1 { font-size: 50px; color: blue; }
|
|
6
|
+
|
|
7
|
+
#content.user.show #container.top #column.left { width: 100px; }
|
|
8
|
+
#content.user.show #container.top #column.right { width: 600px; }
|
|
9
|
+
#content.user.show #container.bottom { background: brown; }
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* line 3, ../more_templates/more1.sass */
|
|
2
|
+
body {
|
|
3
|
+
font: Arial;
|
|
4
|
+
background: blue; }
|
|
5
|
+
|
|
6
|
+
/* line 7, ../more_templates/more1.sass */
|
|
7
|
+
#page {
|
|
8
|
+
width: 700px;
|
|
9
|
+
height: 100; }
|
|
10
|
+
/* line 10, ../more_templates/more1.sass */
|
|
11
|
+
#page #header {
|
|
12
|
+
height: 300px; }
|
|
13
|
+
/* line 12, ../more_templates/more1.sass */
|
|
14
|
+
#page #header h1 {
|
|
15
|
+
font-size: 50px;
|
|
16
|
+
color: blue; }
|
|
17
|
+
|
|
18
|
+
/* line 18, ../more_templates/more1.sass */
|
|
19
|
+
#content.user.show #container.top #column.left {
|
|
20
|
+
width: 100px; }
|
|
21
|
+
/* line 20, ../more_templates/more1.sass */
|
|
22
|
+
#content.user.show #container.top #column.right {
|
|
23
|
+
width: 600px; }
|
|
24
|
+
/* line 22, ../more_templates/more1.sass */
|
|
25
|
+
#content.user.show #container.bottom {
|
|
26
|
+
background: brown; }
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
@import url(basic.css);
|
|
2
|
+
@import url(../results/complex.css);
|
|
3
|
+
imported { otherconst: hello; myconst: goodbye; pre-mixin: here; }
|
|
4
|
+
|
|
5
|
+
body { font: Arial; background: blue; }
|
|
6
|
+
|
|
7
|
+
#page { width: 700px; height: 100; }
|
|
8
|
+
#page #header { height: 300px; }
|
|
9
|
+
#page #header h1 { font-size: 50px; color: blue; }
|
|
10
|
+
|
|
11
|
+
#content.user.show #container.top #column.left { width: 100px; }
|
|
12
|
+
#content.user.show #container.top #column.right { width: 600px; }
|
|
13
|
+
#content.user.show #container.bottom { background: brown; }
|
|
14
|
+
|
|
15
|
+
midrule { inthe: middle; }
|
|
16
|
+
|
|
17
|
+
body { font: Arial; background: blue; }
|
|
18
|
+
|
|
19
|
+
#page { width: 700px; height: 100; }
|
|
20
|
+
#page #header { height: 300px; }
|
|
21
|
+
#page #header h1 { font-size: 50px; color: blue; }
|
|
22
|
+
|
|
23
|
+
#content.user.show #container.top #column.left { width: 100px; }
|
|
24
|
+
#content.user.show #container.top #column.right { width: 600px; }
|
|
25
|
+
#content.user.show #container.bottom { background: brown; }
|
|
26
|
+
|
|
27
|
+
#foo { background-color: #bbaaff; }
|
|
28
|
+
|
|
29
|
+
nonimported { myconst: hello; otherconst: goodbye; post-mixin: here; }
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
body
|
|
4
|
+
:font Arial
|
|
5
|
+
:background blue
|
|
6
|
+
|
|
7
|
+
#page
|
|
8
|
+
:width 700px
|
|
9
|
+
:height 100
|
|
10
|
+
#header
|
|
11
|
+
:height 300px
|
|
12
|
+
h1
|
|
13
|
+
:font-size 50px
|
|
14
|
+
:color blue
|
|
15
|
+
|
|
16
|
+
#content.user.show
|
|
17
|
+
#container.top
|
|
18
|
+
#column.left
|
|
19
|
+
:width 100px
|
|
20
|
+
#column.right
|
|
21
|
+
:width 600px
|
|
22
|
+
#container.bottom
|
|
23
|
+
:background brown
|
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
|
3
|
+
require File.dirname(__FILE__) + '/test_helper'
|
|
4
|
+
require 'sass/plugin'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
|
|
7
|
+
module Sass::Script::Functions
|
|
8
|
+
def filename
|
|
9
|
+
filename = options[:filename].gsub(%r{.*((/[^/]+){4})}, '\1')
|
|
10
|
+
Sass::Script::String.new(filename)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def whatever
|
|
14
|
+
custom = options[:custom]
|
|
15
|
+
whatever = custom && custom[:whatever]
|
|
16
|
+
Sass::Script::String.new(whatever || "incorrect")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class SassPluginTest < Test::Unit::TestCase
|
|
21
|
+
@@templates = %w{
|
|
22
|
+
complex script parent_ref import scss_import alt
|
|
23
|
+
subdir/subdir subdir/nested_subdir/nested_subdir
|
|
24
|
+
options import_content filename_fn
|
|
25
|
+
}
|
|
26
|
+
@@templates += %w[import_charset import_charset_ibm866] unless Sass::Util.ruby1_8?
|
|
27
|
+
@@templates << 'import_charset_1_8' if Sass::Util.ruby1_8?
|
|
28
|
+
|
|
29
|
+
@@cache_store = Sass::CacheStores::Memory.new
|
|
30
|
+
|
|
31
|
+
def setup
|
|
32
|
+
FileUtils.mkdir_p tempfile_loc
|
|
33
|
+
FileUtils.mkdir_p tempfile_loc(nil,"more_")
|
|
34
|
+
set_plugin_opts
|
|
35
|
+
check_for_updates!
|
|
36
|
+
reset_mtimes
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def teardown
|
|
40
|
+
clean_up_sassc
|
|
41
|
+
Sass::Plugin.reset!
|
|
42
|
+
FileUtils.rm_r tempfile_loc
|
|
43
|
+
FileUtils.rm_r tempfile_loc(nil,"more_")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
@@templates.each do |name|
|
|
47
|
+
define_method("test_template_renders_correctly (#{name})") do
|
|
48
|
+
assert_renders_correctly(name)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def test_no_update
|
|
53
|
+
File.delete(tempfile_loc('basic'))
|
|
54
|
+
assert_needs_update 'basic'
|
|
55
|
+
check_for_updates!
|
|
56
|
+
assert_stylesheet_updated 'basic'
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_update_needed_when_modified
|
|
60
|
+
touch 'basic'
|
|
61
|
+
assert_needs_update 'basic'
|
|
62
|
+
check_for_updates!
|
|
63
|
+
assert_stylesheet_updated 'basic'
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def test_update_needed_when_dependency_modified
|
|
67
|
+
touch 'basic'
|
|
68
|
+
assert_needs_update 'import'
|
|
69
|
+
check_for_updates!
|
|
70
|
+
assert_stylesheet_updated 'basic'
|
|
71
|
+
assert_stylesheet_updated 'import'
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_update_needed_when_scss_dependency_modified
|
|
75
|
+
touch 'scss_importee'
|
|
76
|
+
assert_needs_update 'import'
|
|
77
|
+
check_for_updates!
|
|
78
|
+
assert_stylesheet_updated 'scss_importee'
|
|
79
|
+
assert_stylesheet_updated 'import'
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_scss_update_needed_when_dependency_modified
|
|
83
|
+
touch 'basic'
|
|
84
|
+
assert_needs_update 'scss_import'
|
|
85
|
+
check_for_updates!
|
|
86
|
+
assert_stylesheet_updated 'basic'
|
|
87
|
+
assert_stylesheet_updated 'scss_import'
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def test_update_needed_when_nested_import_dependency_modified
|
|
91
|
+
touch 'basic'
|
|
92
|
+
assert_needs_update 'nested_import'
|
|
93
|
+
check_for_updates!
|
|
94
|
+
assert_stylesheet_updated 'basic'
|
|
95
|
+
assert_stylesheet_updated 'scss_import'
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def test_no_updates_when_always_check_and_always_update_both_false
|
|
99
|
+
Sass::Plugin.options[:always_update] = false
|
|
100
|
+
Sass::Plugin.options[:always_check] = false
|
|
101
|
+
|
|
102
|
+
touch 'basic'
|
|
103
|
+
assert_needs_update 'basic'
|
|
104
|
+
check_for_updates!
|
|
105
|
+
|
|
106
|
+
# Check it's still stale
|
|
107
|
+
assert_needs_update 'basic'
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_full_exception_handling
|
|
111
|
+
File.delete(tempfile_loc('bork1'))
|
|
112
|
+
check_for_updates!
|
|
113
|
+
File.open(tempfile_loc('bork1')) do |file|
|
|
114
|
+
assert_equal(<<CSS.strip, file.read.split("\n")[0...6].join("\n"))
|
|
115
|
+
/*
|
|
116
|
+
Syntax error: Undefined variable: "$bork".
|
|
117
|
+
on line 2 of #{template_loc('bork1')}
|
|
118
|
+
|
|
119
|
+
1: bork
|
|
120
|
+
2: :bork $bork
|
|
121
|
+
CSS
|
|
122
|
+
end
|
|
123
|
+
File.delete(tempfile_loc('bork1'))
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def test_full_exception_with_block_comment
|
|
127
|
+
File.delete(tempfile_loc('bork5'))
|
|
128
|
+
check_for_updates!
|
|
129
|
+
File.open(tempfile_loc('bork5')) do |file|
|
|
130
|
+
assert_equal(<<CSS.strip, file.read.split("\n")[0...7].join("\n"))
|
|
131
|
+
/*
|
|
132
|
+
Syntax error: Undefined variable: "$bork".
|
|
133
|
+
on line 3 of #{template_loc('bork5')}
|
|
134
|
+
|
|
135
|
+
1: bork
|
|
136
|
+
2: /* foo *\\/
|
|
137
|
+
3: :bork $bork
|
|
138
|
+
CSS
|
|
139
|
+
end
|
|
140
|
+
File.delete(tempfile_loc('bork1'))
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def test_single_level_import_loop
|
|
144
|
+
File.delete(tempfile_loc('single_import_loop'))
|
|
145
|
+
check_for_updates!
|
|
146
|
+
File.open(tempfile_loc('single_import_loop')) do |file|
|
|
147
|
+
assert_equal(<<CSS.strip, file.read.split("\n")[0...2].join("\n"))
|
|
148
|
+
/*
|
|
149
|
+
Syntax error: An @import loop has been found: #{template_loc('single_import_loop')} imports itself
|
|
150
|
+
CSS
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def test_double_level_import_loop
|
|
155
|
+
File.delete(tempfile_loc('double_import_loop1'))
|
|
156
|
+
check_for_updates!
|
|
157
|
+
File.open(tempfile_loc('double_import_loop1')) do |file|
|
|
158
|
+
assert_equal(<<CSS.strip, file.read.split("\n")[0...4].join("\n"))
|
|
159
|
+
/*
|
|
160
|
+
Syntax error: An @import loop has been found:
|
|
161
|
+
#{template_loc('double_import_loop1')} imports #{template_loc('_double_import_loop2')}
|
|
162
|
+
#{template_loc('_double_import_loop2')} imports #{template_loc('double_import_loop1')}
|
|
163
|
+
CSS
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def test_nonfull_exception_handling
|
|
168
|
+
old_full_exception = Sass::Plugin.options[:full_exception]
|
|
169
|
+
Sass::Plugin.options[:full_exception] = false
|
|
170
|
+
|
|
171
|
+
File.delete(tempfile_loc('bork1'))
|
|
172
|
+
assert_raise(Sass::SyntaxError) {check_for_updates!}
|
|
173
|
+
ensure
|
|
174
|
+
Sass::Plugin.options[:full_exception] = old_full_exception
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def test_two_template_directories
|
|
178
|
+
set_plugin_opts :template_location => {
|
|
179
|
+
template_loc => tempfile_loc,
|
|
180
|
+
template_loc(nil,'more_') => tempfile_loc(nil,'more_')
|
|
181
|
+
}
|
|
182
|
+
check_for_updates!
|
|
183
|
+
['more1', 'more_import'].each { |name| assert_renders_correctly(name, :prefix => 'more_') }
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def test_two_template_directories_with_line_annotations
|
|
187
|
+
set_plugin_opts :line_comments => true,
|
|
188
|
+
:style => :nested,
|
|
189
|
+
:template_location => {
|
|
190
|
+
template_loc => tempfile_loc,
|
|
191
|
+
template_loc(nil,'more_') => tempfile_loc(nil,'more_')
|
|
192
|
+
}
|
|
193
|
+
check_for_updates!
|
|
194
|
+
assert_renders_correctly('more1_with_line_comments', 'more1', :prefix => 'more_')
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def test_doesnt_render_partials
|
|
198
|
+
assert !File.exists?(tempfile_loc('_partial'))
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def test_template_location_array
|
|
202
|
+
assert_equal [[template_loc, tempfile_loc]], Sass::Plugin.template_location_array
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def test_add_template_location
|
|
206
|
+
Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_"))
|
|
207
|
+
assert_equal(
|
|
208
|
+
[[template_loc, tempfile_loc], [template_loc(nil, "more_"), tempfile_loc(nil, "more_")]],
|
|
209
|
+
Sass::Plugin.template_location_array)
|
|
210
|
+
|
|
211
|
+
touch 'more1', 'more_'
|
|
212
|
+
touch 'basic'
|
|
213
|
+
assert_needs_update "more1", "more_"
|
|
214
|
+
assert_needs_update "basic"
|
|
215
|
+
check_for_updates!
|
|
216
|
+
assert_doesnt_need_update "more1", "more_"
|
|
217
|
+
assert_doesnt_need_update "basic"
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def test_remove_template_location
|
|
221
|
+
Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_"))
|
|
222
|
+
Sass::Plugin.remove_template_location(template_loc, tempfile_loc)
|
|
223
|
+
assert_equal(
|
|
224
|
+
[[template_loc(nil, "more_"), tempfile_loc(nil, "more_")]],
|
|
225
|
+
Sass::Plugin.template_location_array)
|
|
226
|
+
|
|
227
|
+
touch 'more1', 'more_'
|
|
228
|
+
touch 'basic'
|
|
229
|
+
assert_needs_update "more1", "more_"
|
|
230
|
+
assert_needs_update "basic"
|
|
231
|
+
check_for_updates!
|
|
232
|
+
assert_doesnt_need_update "more1", "more_"
|
|
233
|
+
assert_needs_update "basic"
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def test_import_same_name
|
|
237
|
+
assert_warning <<WARNING do
|
|
238
|
+
WARNING: In #{template_loc}:
|
|
239
|
+
There are multiple files that match the name "same_name_different_partiality.scss":
|
|
240
|
+
_same_name_different_partiality.scss
|
|
241
|
+
same_name_different_partiality.scss
|
|
242
|
+
WARNING
|
|
243
|
+
touch "_same_name_different_partiality"
|
|
244
|
+
assert_needs_update "same_name_different_partiality"
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Callbacks
|
|
249
|
+
|
|
250
|
+
def test_updating_stylesheets_callback
|
|
251
|
+
# Should run even when there's nothing to update
|
|
252
|
+
Sass::Plugin.options[:template_location] = nil
|
|
253
|
+
assert_callback :updating_stylesheets, []
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def test_updating_stylesheets_callback_with_never_update
|
|
257
|
+
Sass::Plugin.options[:never_update] = true
|
|
258
|
+
assert_no_callback :updating_stylesheets
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def test_updated_stylesheet_callback_for_updated_template
|
|
262
|
+
Sass::Plugin.options[:always_update] = false
|
|
263
|
+
touch 'basic'
|
|
264
|
+
assert_no_callback :updated_stylesheet, template_loc("complex"), tempfile_loc("complex") do
|
|
265
|
+
assert_callbacks(
|
|
266
|
+
[:updated_stylesheet, template_loc("basic"), tempfile_loc("basic")],
|
|
267
|
+
[:updated_stylesheet, template_loc("import"), tempfile_loc("import")])
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def test_updated_stylesheet_callback_for_fresh_template
|
|
272
|
+
Sass::Plugin.options[:always_update] = false
|
|
273
|
+
assert_no_callback :updated_stylesheet
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def test_updated_stylesheet_callback_for_error_template
|
|
277
|
+
Sass::Plugin.options[:always_update] = false
|
|
278
|
+
touch 'bork1'
|
|
279
|
+
assert_no_callback :updated_stylesheet
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def test_not_updating_stylesheet_callback_for_fresh_template
|
|
283
|
+
Sass::Plugin.options[:always_update] = false
|
|
284
|
+
assert_callback :not_updating_stylesheet, template_loc("basic"), tempfile_loc("basic")
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def test_not_updating_stylesheet_callback_for_updated_template
|
|
288
|
+
Sass::Plugin.options[:always_update] = false
|
|
289
|
+
assert_callback :not_updating_stylesheet, template_loc("complex"), tempfile_loc("complex") do
|
|
290
|
+
assert_no_callbacks(
|
|
291
|
+
[:updated_stylesheet, template_loc("basic"), tempfile_loc("basic")],
|
|
292
|
+
[:updated_stylesheet, template_loc("import"), tempfile_loc("import")])
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def test_not_updating_stylesheet_callback_with_never_update
|
|
297
|
+
Sass::Plugin.options[:never_update] = true
|
|
298
|
+
assert_no_callback :not_updating_stylesheet
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def test_not_updating_stylesheet_callback_for_partial
|
|
302
|
+
Sass::Plugin.options[:always_update] = false
|
|
303
|
+
assert_no_callback :not_updating_stylesheet, template_loc("_partial"), tempfile_loc("_partial")
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
def test_not_updating_stylesheet_callback_for_error
|
|
307
|
+
Sass::Plugin.options[:always_update] = false
|
|
308
|
+
touch 'bork1'
|
|
309
|
+
assert_no_callback :not_updating_stylesheet, template_loc("bork1"), tempfile_loc("bork1")
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def test_compilation_error_callback
|
|
313
|
+
Sass::Plugin.options[:always_update] = false
|
|
314
|
+
touch 'bork1'
|
|
315
|
+
assert_callback(:compilation_error,
|
|
316
|
+
lambda {|e| e.message == 'Undefined variable: "$bork".'},
|
|
317
|
+
template_loc("bork1"), tempfile_loc("bork1"))
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def test_compilation_error_callback_for_file_access
|
|
321
|
+
Sass::Plugin.options[:always_update] = false
|
|
322
|
+
assert_callback(:compilation_error,
|
|
323
|
+
lambda {|e| e.is_a?(Errno::ENOENT)},
|
|
324
|
+
template_loc("nonexistent"), tempfile_loc("nonexistent")) do
|
|
325
|
+
Sass::Plugin.update_stylesheets([[template_loc("nonexistent"), tempfile_loc("nonexistent")]])
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def test_creating_directory_callback
|
|
330
|
+
Sass::Plugin.options[:always_update] = false
|
|
331
|
+
dir = File.join(tempfile_loc, "subdir", "nested_subdir")
|
|
332
|
+
FileUtils.rm_r dir
|
|
333
|
+
assert_callback :creating_directory, dir
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
## Regression
|
|
337
|
+
|
|
338
|
+
def test_cached_dependencies_update
|
|
339
|
+
FileUtils.mv(template_loc("basic"), template_loc("basic", "more_"))
|
|
340
|
+
set_plugin_opts :load_paths => [template_loc(nil, "more_")]
|
|
341
|
+
|
|
342
|
+
touch 'basic', 'more_'
|
|
343
|
+
assert_needs_update "import"
|
|
344
|
+
check_for_updates!
|
|
345
|
+
assert_renders_correctly("import")
|
|
346
|
+
ensure
|
|
347
|
+
FileUtils.mv(template_loc("basic", "more_"), template_loc("basic"))
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
def test_cached_relative_import
|
|
351
|
+
old_always_update = Sass::Plugin.options[:always_update]
|
|
352
|
+
Sass::Plugin.options[:always_update] = true
|
|
353
|
+
check_for_updates!
|
|
354
|
+
assert_renders_correctly('subdir/subdir')
|
|
355
|
+
ensure
|
|
356
|
+
Sass::Plugin.options[:always_update] = old_always_update
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def test_cached_if
|
|
360
|
+
set_plugin_opts :cache_store => Sass::CacheStores::Filesystem.new(tempfile_loc + '/cache')
|
|
361
|
+
check_for_updates!
|
|
362
|
+
assert_renders_correctly 'if'
|
|
363
|
+
check_for_updates!
|
|
364
|
+
assert_renders_correctly 'if'
|
|
365
|
+
ensure
|
|
366
|
+
set_plugin_opts
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def test_cached_import_option
|
|
370
|
+
set_plugin_opts :custom => {:whatever => "correct"}
|
|
371
|
+
check_for_updates!
|
|
372
|
+
assert_renders_correctly "cached_import_option"
|
|
373
|
+
|
|
374
|
+
@@cache_store.reset!
|
|
375
|
+
set_plugin_opts :custom => nil, :always_update => false
|
|
376
|
+
check_for_updates!
|
|
377
|
+
assert_renders_correctly "cached_import_option"
|
|
378
|
+
|
|
379
|
+
set_plugin_opts :custom => {:whatever => "correct"}, :always_update => true
|
|
380
|
+
check_for_updates!
|
|
381
|
+
assert_renders_correctly "cached_import_option"
|
|
382
|
+
ensure
|
|
383
|
+
set_plugin_opts :custom => nil
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
private
|
|
387
|
+
|
|
388
|
+
def assert_renders_correctly(*arguments)
|
|
389
|
+
options = arguments.last.is_a?(Hash) ? arguments.pop : {}
|
|
390
|
+
prefix = options[:prefix]
|
|
391
|
+
result_name = arguments.shift
|
|
392
|
+
tempfile_name = arguments.shift || result_name
|
|
393
|
+
|
|
394
|
+
expected_str = File.read(result_loc(result_name, prefix))
|
|
395
|
+
actual_str = File.read(tempfile_loc(tempfile_name, prefix))
|
|
396
|
+
unless Sass::Util.ruby1_8?
|
|
397
|
+
expected_str = expected_str.force_encoding('IBM866') if result_name == 'import_charset_ibm866'
|
|
398
|
+
actual_str = actual_str.force_encoding('IBM866') if tempfile_name == 'import_charset_ibm866'
|
|
399
|
+
end
|
|
400
|
+
expected_lines = expected_str.split("\n")
|
|
401
|
+
actual_lines = actual_str.split("\n")
|
|
402
|
+
|
|
403
|
+
if actual_lines.first == "/*" && expected_lines.first != "/*"
|
|
404
|
+
assert(false, actual_lines[0..Sass::Util.enum_with_index(actual_lines).find {|l, i| l == "*/"}.last].join("\n"))
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
expected_lines.zip(actual_lines).each_with_index do |pair, line|
|
|
408
|
+
message = "template: #{result_name}\nline: #{line + 1}"
|
|
409
|
+
assert_equal(pair.first, pair.last, message)
|
|
410
|
+
end
|
|
411
|
+
if expected_lines.size < actual_lines.size
|
|
412
|
+
assert(false, "#{actual_lines.size - expected_lines.size} Trailing lines found in #{tempfile_name}.css: #{actual_lines[expected_lines.size..-1].join('\n')}")
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
def assert_stylesheet_updated(name)
|
|
417
|
+
assert_doesnt_need_update name
|
|
418
|
+
|
|
419
|
+
# Make sure it isn't an exception
|
|
420
|
+
expected_lines = File.read(result_loc(name)).split("\n")
|
|
421
|
+
actual_lines = File.read(tempfile_loc(name)).split("\n")
|
|
422
|
+
if actual_lines.first == "/*" && expected_lines.first != "/*"
|
|
423
|
+
assert(false, actual_lines[0..actual_lines.enum_with_index.find {|l, i| l == "*/"}.last].join("\n"))
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
def assert_callback(name, *expected_args)
|
|
428
|
+
run = false
|
|
429
|
+
received_args = nil
|
|
430
|
+
Sass::Plugin.send("on_#{name}") do |*args|
|
|
431
|
+
received_args = args
|
|
432
|
+
run ||= expected_args.zip(received_args).all? do |ea, ra|
|
|
433
|
+
ea.respond_to?(:call) ? ea.call(ra) : ea == ra
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
if block_given?
|
|
438
|
+
Sass::Util.silence_sass_warnings {yield}
|
|
439
|
+
else
|
|
440
|
+
check_for_updates!
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
assert run, "Expected #{name} callback to be run with arguments:\n #{expected_args.inspect}\nHowever, it got:\n #{received_args.inspect}"
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
def assert_no_callback(name, *unexpected_args)
|
|
447
|
+
Sass::Plugin.send("on_#{name}") do |*a|
|
|
448
|
+
next unless unexpected_args.empty? || a == unexpected_args
|
|
449
|
+
|
|
450
|
+
msg = "Expected #{name} callback not to be run"
|
|
451
|
+
if !unexpected_args.empty?
|
|
452
|
+
msg << " with arguments #{unexpected_args.inspect}"
|
|
453
|
+
elsif !a.empty?
|
|
454
|
+
msg << ",\n was run with arguments #{a.inspect}"
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
flunk msg
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
if block_given?
|
|
461
|
+
yield
|
|
462
|
+
else
|
|
463
|
+
check_for_updates!
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
def assert_callbacks(*args)
|
|
468
|
+
return check_for_updates! if args.empty?
|
|
469
|
+
assert_callback(*args.pop) {assert_callbacks(*args)}
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
def assert_no_callbacks(*args)
|
|
473
|
+
return check_for_updates! if args.empty?
|
|
474
|
+
assert_no_callback(*args.pop) {assert_no_callbacks(*args)}
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
def check_for_updates!
|
|
478
|
+
Sass::Util.silence_sass_warnings do
|
|
479
|
+
Sass::Plugin.check_for_updates
|
|
480
|
+
end
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
def assert_needs_update(*args)
|
|
484
|
+
assert(Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)),
|
|
485
|
+
"Expected #{template_loc(*args)} to need an update.")
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
def assert_doesnt_need_update(*args)
|
|
489
|
+
assert(!Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)),
|
|
490
|
+
"Expected #{template_loc(*args)} not to need an update.")
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
def touch(*args)
|
|
494
|
+
FileUtils.touch(template_loc(*args))
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
def reset_mtimes
|
|
498
|
+
Sass::Plugin::StalenessChecker.dependencies_cache = {}
|
|
499
|
+
atime = Time.now
|
|
500
|
+
mtime = Time.now - 5
|
|
501
|
+
Dir["{#{template_loc},#{tempfile_loc}}/**/*.{css,sass,scss}"].each {|f| File.utime(atime, mtime, f)}
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
def template_loc(name = nil, prefix = nil)
|
|
505
|
+
if name
|
|
506
|
+
scss = absolutize "#{prefix}templates/#{name}.scss"
|
|
507
|
+
File.exists?(scss) ? scss : absolutize("#{prefix}templates/#{name}.sass")
|
|
508
|
+
else
|
|
509
|
+
absolutize "#{prefix}templates"
|
|
510
|
+
end
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
def tempfile_loc(name = nil, prefix = nil)
|
|
514
|
+
if name
|
|
515
|
+
absolutize "#{prefix}tmp/#{name}.css"
|
|
516
|
+
else
|
|
517
|
+
absolutize "#{prefix}tmp"
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def result_loc(name = nil, prefix = nil)
|
|
522
|
+
if name
|
|
523
|
+
absolutize "#{prefix}results/#{name}.css"
|
|
524
|
+
else
|
|
525
|
+
absolutize "#{prefix}results"
|
|
526
|
+
end
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def set_plugin_opts(overrides = {})
|
|
530
|
+
Sass::Plugin.options.merge!(
|
|
531
|
+
:template_location => template_loc,
|
|
532
|
+
:css_location => tempfile_loc,
|
|
533
|
+
:style => :compact,
|
|
534
|
+
:always_update => true,
|
|
535
|
+
:never_update => false,
|
|
536
|
+
:full_exception => true,
|
|
537
|
+
:cache_store => @@cache_store
|
|
538
|
+
)
|
|
539
|
+
Sass::Plugin.options.merge!(overrides)
|
|
540
|
+
end
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
class Sass::Engine
|
|
544
|
+
alias_method :old_render, :render
|
|
545
|
+
|
|
546
|
+
def render
|
|
547
|
+
raise "bork bork bork!" if @template[0] == "{bork now!}"
|
|
548
|
+
old_render
|
|
549
|
+
end
|
|
550
|
+
end
|