sass 3.1.0 → 3.3.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.
- checksums.yaml +7 -0
- data/CONTRIBUTING +1 -1
- data/MIT-LICENSE +2 -2
- data/README.md +29 -17
- data/Rakefile +43 -9
- data/VERSION +1 -1
- data/VERSION_DATE +1 -0
- data/VERSION_NAME +1 -1
- data/bin/sass +6 -1
- data/bin/sass-convert +6 -1
- data/bin/scss +6 -1
- data/ext/mkrf_conf.rb +27 -0
- data/lib/sass/cache_stores/base.rb +7 -3
- data/lib/sass/cache_stores/chain.rb +3 -2
- data/lib/sass/cache_stores/filesystem.rb +5 -7
- data/lib/sass/cache_stores/memory.rb +1 -1
- data/lib/sass/cache_stores/null.rb +2 -2
- data/lib/sass/callbacks.rb +2 -1
- data/lib/sass/css.rb +168 -53
- data/lib/sass/engine.rb +502 -174
- data/lib/sass/environment.rb +151 -111
- data/lib/sass/error.rb +7 -7
- data/lib/sass/exec.rb +176 -60
- data/lib/sass/features.rb +40 -0
- data/lib/sass/importers/base.rb +46 -7
- data/lib/sass/importers/deprecated_path.rb +51 -0
- data/lib/sass/importers/filesystem.rb +113 -30
- data/lib/sass/importers.rb +1 -0
- data/lib/sass/logger/base.rb +30 -0
- data/lib/sass/logger/log_level.rb +45 -0
- data/lib/sass/logger.rb +12 -0
- data/lib/sass/media.rb +213 -0
- data/lib/sass/plugin/compiler.rb +194 -104
- data/lib/sass/plugin/configuration.rb +18 -25
- data/lib/sass/plugin/merb.rb +1 -1
- data/lib/sass/plugin/staleness_checker.rb +37 -11
- data/lib/sass/plugin.rb +10 -13
- data/lib/sass/railtie.rb +2 -1
- data/lib/sass/repl.rb +5 -6
- data/lib/sass/script/css_lexer.rb +8 -4
- data/lib/sass/script/css_parser.rb +5 -2
- data/lib/sass/script/functions.rb +1547 -618
- data/lib/sass/script/lexer.rb +122 -72
- data/lib/sass/script/parser.rb +304 -135
- data/lib/sass/script/tree/funcall.rb +306 -0
- data/lib/sass/script/{interpolation.rb → tree/interpolation.rb} +43 -13
- data/lib/sass/script/tree/list_literal.rb +77 -0
- data/lib/sass/script/tree/literal.rb +45 -0
- data/lib/sass/script/tree/map_literal.rb +64 -0
- data/lib/sass/script/{node.rb → tree/node.rb} +30 -12
- data/lib/sass/script/{operation.rb → tree/operation.rb} +33 -21
- data/lib/sass/script/{string_interpolation.rb → tree/string_interpolation.rb} +14 -4
- data/lib/sass/script/{unary_operation.rb → tree/unary_operation.rb} +21 -9
- data/lib/sass/script/tree/variable.rb +57 -0
- data/lib/sass/script/tree.rb +15 -0
- data/lib/sass/script/value/arg_list.rb +36 -0
- data/lib/sass/script/value/base.rb +238 -0
- data/lib/sass/script/value/bool.rb +40 -0
- data/lib/sass/script/{color.rb → value/color.rb} +256 -74
- data/lib/sass/script/value/deprecated_false.rb +55 -0
- data/lib/sass/script/value/helpers.rb +155 -0
- data/lib/sass/script/value/list.rb +128 -0
- data/lib/sass/script/value/map.rb +70 -0
- data/lib/sass/script/value/null.rb +49 -0
- data/lib/sass/script/{number.rb → value/number.rb} +115 -62
- data/lib/sass/script/{string.rb → value/string.rb} +9 -11
- data/lib/sass/script/value.rb +12 -0
- data/lib/sass/script.rb +35 -9
- data/lib/sass/scss/css_parser.rb +2 -12
- data/lib/sass/scss/parser.rb +657 -230
- data/lib/sass/scss/rx.rb +17 -12
- data/lib/sass/scss/static_parser.rb +37 -6
- data/lib/sass/scss.rb +0 -1
- data/lib/sass/selector/abstract_sequence.rb +35 -3
- data/lib/sass/selector/comma_sequence.rb +29 -14
- data/lib/sass/selector/sequence.rb +371 -74
- data/lib/sass/selector/simple.rb +28 -13
- data/lib/sass/selector/simple_sequence.rb +163 -36
- data/lib/sass/selector.rb +138 -36
- data/lib/sass/shared.rb +3 -5
- data/lib/sass/source/map.rb +196 -0
- data/lib/sass/source/position.rb +39 -0
- data/lib/sass/source/range.rb +41 -0
- data/lib/sass/stack.rb +126 -0
- data/lib/sass/supports.rb +228 -0
- data/lib/sass/tree/at_root_node.rb +82 -0
- data/lib/sass/tree/comment_node.rb +34 -29
- 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 +3 -3
- data/lib/sass/tree/directive_node.rb +33 -3
- data/lib/sass/tree/each_node.rb +9 -9
- data/lib/sass/tree/extend_node.rb +20 -6
- data/lib/sass/tree/for_node.rb +6 -6
- data/lib/sass/tree/function_node.rb +12 -4
- data/lib/sass/tree/if_node.rb +2 -15
- data/lib/sass/tree/import_node.rb +11 -5
- data/lib/sass/tree/media_node.rb +27 -11
- data/lib/sass/tree/mixin_def_node.rb +15 -4
- data/lib/sass/tree/mixin_node.rb +27 -7
- data/lib/sass/tree/node.rb +69 -35
- data/lib/sass/tree/prop_node.rb +47 -31
- data/lib/sass/tree/return_node.rb +4 -3
- data/lib/sass/tree/root_node.rb +20 -4
- data/lib/sass/tree/rule_node.rb +37 -26
- data/lib/sass/tree/supports_node.rb +38 -0
- data/lib/sass/tree/trace_node.rb +33 -0
- data/lib/sass/tree/variable_node.rb +10 -4
- data/lib/sass/tree/visitors/base.rb +5 -8
- data/lib/sass/tree/visitors/check_nesting.rb +67 -52
- data/lib/sass/tree/visitors/convert.rb +134 -53
- data/lib/sass/tree/visitors/cssize.rb +245 -51
- 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 +331 -105
- data/lib/sass/tree/visitors/set_options.rb +125 -0
- data/lib/sass/tree/visitors/to_css.rb +259 -95
- data/lib/sass/tree/warn_node.rb +3 -3
- data/lib/sass/tree/while_node.rb +3 -3
- data/lib/sass/util/cross_platform_random.rb +19 -0
- data/lib/sass/util/multibyte_string_scanner.rb +157 -0
- data/lib/sass/util/normalized_map.rb +130 -0
- data/lib/sass/util/ordered_hash.rb +192 -0
- data/lib/sass/util/subset_map.rb +11 -2
- data/lib/sass/util/test.rb +9 -0
- data/lib/sass/util.rb +565 -39
- data/lib/sass/version.rb +27 -15
- data/lib/sass.rb +39 -4
- data/test/sass/cache_test.rb +15 -0
- data/test/sass/compiler_test.rb +223 -0
- data/test/sass/conversion_test.rb +901 -107
- data/test/sass/css2sass_test.rb +94 -0
- data/test/sass/engine_test.rb +1059 -164
- data/test/sass/exec_test.rb +86 -0
- data/test/sass/extend_test.rb +933 -837
- 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 +995 -136
- data/test/sass/importer_test.rb +338 -18
- data/test/sass/logger_test.rb +58 -0
- data/test/sass/more_results/more_import.css +2 -2
- data/test/sass/plugin_test.rb +114 -30
- data/test/sass/results/cached_import_option.css +3 -0
- data/test/sass/results/filename_fn.css +3 -0
- data/test/sass/results/import.css +2 -2
- data/test/sass/results/import_charset.css +1 -0
- data/test/sass/results/import_charset_1_8.css +1 -0
- data/test/sass/results/import_charset_ibm866.css +1 -0
- data/test/sass/results/import_content.css +1 -0
- data/test/sass/results/script.css +1 -1
- data/test/sass/results/scss_import.css +2 -2
- data/test/sass/results/units.css +2 -2
- data/test/sass/script_conversion_test.rb +43 -1
- data/test/sass/script_test.rb +380 -36
- data/test/sass/scss/css_test.rb +257 -75
- data/test/sass/scss/scss_test.rb +2322 -110
- data/test/sass/source_map_test.rb +887 -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_content.sass +3 -0
- data/test/sass/templates/_same_name_different_partiality.scss +1 -0
- data/test/sass/templates/bork5.sass +3 -0
- data/test/sass/templates/cached_import_option.scss +3 -0
- data/test/sass/templates/double_import_loop1.sass +1 -0
- data/test/sass/templates/filename_fn.scss +18 -0
- data/test/sass/templates/import_charset.sass +2 -0
- data/test/sass/templates/import_charset_1_8.sass +2 -0
- data/test/sass/templates/import_charset_ibm866.sass +2 -0
- data/test/sass/templates/import_content.sass +4 -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/single_import_loop.sass +1 -0
- data/test/sass/templates/subdir/import_up1.scss +1 -0
- data/test/sass/templates/subdir/import_up2.scss +1 -0
- data/test/sass/test_helper.rb +1 -1
- data/test/sass/util/multibyte_string_scanner_test.rb +147 -0
- data/test/sass/util/normalized_map_test.rb +51 -0
- data/test/sass/util_test.rb +183 -0
- data/test/sass/value_helpers_test.rb +181 -0
- data/test/test_helper.rb +45 -5
- data/vendor/listen/CHANGELOG.md +228 -0
- data/vendor/listen/CONTRIBUTING.md +38 -0
- data/vendor/listen/Gemfile +30 -0
- data/vendor/listen/Guardfile +8 -0
- data/vendor/{fssm → listen}/LICENSE +1 -1
- data/vendor/listen/README.md +315 -0
- data/vendor/listen/Rakefile +47 -0
- data/vendor/listen/Vagrantfile +96 -0
- data/vendor/listen/lib/listen/adapter.rb +214 -0
- data/vendor/listen/lib/listen/adapters/bsd.rb +112 -0
- data/vendor/listen/lib/listen/adapters/darwin.rb +85 -0
- data/vendor/listen/lib/listen/adapters/linux.rb +113 -0
- data/vendor/listen/lib/listen/adapters/polling.rb +67 -0
- data/vendor/listen/lib/listen/adapters/windows.rb +87 -0
- data/vendor/listen/lib/listen/dependency_manager.rb +126 -0
- data/vendor/listen/lib/listen/directory_record.rb +371 -0
- data/vendor/listen/lib/listen/listener.rb +225 -0
- data/vendor/listen/lib/listen/multi_listener.rb +143 -0
- data/vendor/listen/lib/listen/turnstile.rb +28 -0
- data/vendor/listen/lib/listen/version.rb +3 -0
- data/vendor/listen/lib/listen.rb +40 -0
- data/vendor/listen/listen.gemspec +22 -0
- data/vendor/listen/spec/listen/adapter_spec.rb +183 -0
- data/vendor/listen/spec/listen/adapters/bsd_spec.rb +36 -0
- data/vendor/listen/spec/listen/adapters/darwin_spec.rb +37 -0
- data/vendor/listen/spec/listen/adapters/linux_spec.rb +47 -0
- data/vendor/listen/spec/listen/adapters/polling_spec.rb +68 -0
- data/vendor/listen/spec/listen/adapters/windows_spec.rb +30 -0
- data/vendor/listen/spec/listen/dependency_manager_spec.rb +107 -0
- data/vendor/listen/spec/listen/directory_record_spec.rb +1225 -0
- data/vendor/listen/spec/listen/listener_spec.rb +169 -0
- data/vendor/listen/spec/listen/multi_listener_spec.rb +174 -0
- data/vendor/listen/spec/listen/turnstile_spec.rb +56 -0
- data/vendor/listen/spec/listen_spec.rb +73 -0
- data/vendor/listen/spec/spec_helper.rb +21 -0
- data/vendor/listen/spec/support/adapter_helper.rb +629 -0
- data/vendor/listen/spec/support/directory_record_helper.rb +55 -0
- data/vendor/listen/spec/support/fixtures_helper.rb +29 -0
- data/vendor/listen/spec/support/listeners_helper.rb +156 -0
- data/vendor/listen/spec/support/platform_helper.rb +15 -0
- metadata +344 -271
- data/lib/sass/less.rb +0 -382
- data/lib/sass/script/bool.rb +0 -18
- data/lib/sass/script/funcall.rb +0 -162
- data/lib/sass/script/list.rb +0 -76
- data/lib/sass/script/literal.rb +0 -245
- data/lib/sass/script/variable.rb +0 -54
- data/lib/sass/scss/sass_parser.rb +0 -11
- data/test/sass/less_conversion_test.rb +0 -653
- data/vendor/fssm/README.markdown +0 -55
- data/vendor/fssm/Rakefile +0 -59
- data/vendor/fssm/VERSION.yml +0 -5
- data/vendor/fssm/example.rb +0 -9
- data/vendor/fssm/fssm.gemspec +0 -77
- data/vendor/fssm/lib/fssm/backends/fsevents.rb +0 -36
- data/vendor/fssm/lib/fssm/backends/inotify.rb +0 -26
- data/vendor/fssm/lib/fssm/backends/polling.rb +0 -25
- data/vendor/fssm/lib/fssm/backends/rubycocoa/fsevents.rb +0 -131
- data/vendor/fssm/lib/fssm/monitor.rb +0 -26
- data/vendor/fssm/lib/fssm/path.rb +0 -91
- data/vendor/fssm/lib/fssm/pathname.rb +0 -502
- data/vendor/fssm/lib/fssm/state/directory.rb +0 -57
- data/vendor/fssm/lib/fssm/state/file.rb +0 -24
- data/vendor/fssm/lib/fssm/support.rb +0 -63
- data/vendor/fssm/lib/fssm/tree.rb +0 -176
- data/vendor/fssm/lib/fssm.rb +0 -33
- data/vendor/fssm/profile/prof-cache.rb +0 -40
- data/vendor/fssm/profile/prof-fssm-pathname.html +0 -1231
- data/vendor/fssm/profile/prof-pathname.rb +0 -68
- data/vendor/fssm/profile/prof-plain-pathname.html +0 -988
- data/vendor/fssm/profile/prof.html +0 -2379
- data/vendor/fssm/spec/path_spec.rb +0 -75
- data/vendor/fssm/spec/root/duck/quack.txt +0 -0
- data/vendor/fssm/spec/root/file.css +0 -0
- data/vendor/fssm/spec/root/file.rb +0 -0
- data/vendor/fssm/spec/root/file.yml +0 -0
- data/vendor/fssm/spec/root/moo/cow.txt +0 -0
- data/vendor/fssm/spec/spec_helper.rb +0 -14
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Listen::Listener do
|
4
|
+
let(:adapter) { mock(Listen::Adapter, :start => true).as_null_object }
|
5
|
+
let(:watched_directory) { File.dirname(__FILE__) }
|
6
|
+
|
7
|
+
subject { described_class.new(watched_directory) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
Listen::Adapter.stub(:select_and_initialize) { adapter }
|
11
|
+
# Don't build a record of the files inside the base directory.
|
12
|
+
subject.directory_record.stub(:build)
|
13
|
+
end
|
14
|
+
|
15
|
+
it_should_behave_like 'a listener to changes on a file-system'
|
16
|
+
|
17
|
+
describe '#initialize' do
|
18
|
+
context 'with no options' do
|
19
|
+
it 'sets the directory' do
|
20
|
+
subject.directory.should eq watched_directory
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'converts the passed path into an absolute path - #21' do
|
24
|
+
described_class.new(File.join(watched_directory, '..')).directory.should eq File.expand_path('..', watched_directory)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'sets the option for using relative paths in the callback to the default one' do
|
28
|
+
subject.instance_variable_get(:@use_relative_paths).should eq described_class::DEFAULT_TO_RELATIVE_PATHS
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with custom options' do
|
33
|
+
subject { described_class.new(watched_directory, :ignore => /\.ssh/, :filter => [/.*\.rb/,/.*\.md/],
|
34
|
+
:latency => 0.5, :force_polling => true, :relative_paths => true) }
|
35
|
+
|
36
|
+
it 'passes the custom ignored paths to the directory record' do
|
37
|
+
subject.directory_record.ignoring_patterns.should include /\.ssh/
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'passes the custom filters to the directory record' do
|
41
|
+
subject.directory_record.filtering_patterns.should =~ [/.*\.rb/,/.*\.md/]
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'sets the cutom option for using relative paths in the callback' do
|
45
|
+
subject.instance_variable_get(:@use_relative_paths).should be_true
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'sets adapter_options' do
|
49
|
+
subject.instance_variable_get(:@adapter_options).should eq(:latency => 0.5, :force_polling => true)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#start' do
|
55
|
+
it 'selects and initializes an adapter' do
|
56
|
+
Listen::Adapter.should_receive(:select_and_initialize).with(watched_directory, {}) { adapter }
|
57
|
+
subject.start
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'builds the directory record' do
|
61
|
+
subject.directory_record.should_receive(:build)
|
62
|
+
subject.start
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'with a started listener' do
|
67
|
+
before do
|
68
|
+
subject.stub(:initialize_adapter) { adapter }
|
69
|
+
subject.start
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#unpause' do
|
73
|
+
it 'rebuilds the directory record' do
|
74
|
+
subject.directory_record.should_receive(:build)
|
75
|
+
subject.unpause
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#ignore'do
|
81
|
+
it 'delegates the work to the directory record' do
|
82
|
+
subject.directory_record.should_receive(:ignore).with 'some_directory'
|
83
|
+
subject.ignore 'some_directory'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#ignore!'do
|
88
|
+
it 'delegates the work to the directory record' do
|
89
|
+
subject.directory_record.should_receive(:ignore!).with 'some_directory'
|
90
|
+
subject.ignore! 'some_directory'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '#filter' do
|
95
|
+
it 'delegates the work to the directory record' do
|
96
|
+
subject.directory_record.should_receive(:filter).with /\.txt$/
|
97
|
+
subject.filter /\.txt$/
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe '#filter!' do
|
102
|
+
it 'delegates the work to the directory record' do
|
103
|
+
subject.directory_record.should_receive(:filter!).with /\.txt$/
|
104
|
+
subject.filter! /\.txt$/
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
describe '#on_change' do
|
110
|
+
let(:directories) { %w{dir1 dir2 dir3} }
|
111
|
+
let(:changes) { {:modified => [], :added => [], :removed => []} }
|
112
|
+
let(:callback) { Proc.new { @called = true } }
|
113
|
+
|
114
|
+
before do
|
115
|
+
@called = false
|
116
|
+
subject.directory_record.stub(:fetch_changes => changes)
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'fetches the changes of the directory record' do
|
120
|
+
subject.directory_record.should_receive(:fetch_changes).with(
|
121
|
+
directories, hash_including(:relative_paths => described_class::DEFAULT_TO_RELATIVE_PATHS)
|
122
|
+
)
|
123
|
+
subject.on_change(directories)
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'with relative paths option set to true' do
|
127
|
+
subject { described_class.new(watched_directory, :relative_paths => true) }
|
128
|
+
|
129
|
+
it 'fetches the changes of the directory record' do
|
130
|
+
subject.directory_record.should_receive(:fetch_changes).with(directories, hash_including(:relative_paths => true))
|
131
|
+
subject.on_change(directories)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'with no changes to report' do
|
136
|
+
if RUBY_VERSION[/^1.8/]
|
137
|
+
it 'does not run the callback' do
|
138
|
+
subject.change(&callback)
|
139
|
+
subject.on_change(directories)
|
140
|
+
@called.should be_false
|
141
|
+
end
|
142
|
+
else
|
143
|
+
it 'does not run the callback' do
|
144
|
+
callback.should_not_receive(:call)
|
145
|
+
subject.change(&callback)
|
146
|
+
subject.on_change(directories)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'with changes to report' do
|
152
|
+
let(:changes) { {:modified => %w{path1}, :added => [], :removed => %w{path2}} }
|
153
|
+
|
154
|
+
if RUBY_VERSION[/^1.8/]
|
155
|
+
it 'runs the callback passing it the changes' do
|
156
|
+
subject.change(&callback)
|
157
|
+
subject.on_change(directories)
|
158
|
+
@called.should be_true
|
159
|
+
end
|
160
|
+
else
|
161
|
+
it 'runs the callback passing it the changes' do
|
162
|
+
callback.should_receive(:call).with(changes[:modified], changes[:added], changes[:removed])
|
163
|
+
subject.change(&callback)
|
164
|
+
subject.on_change(directories)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Listen::MultiListener do
|
4
|
+
let(:adapter) { mock(Listen::Adapter, :start => true).as_null_object }
|
5
|
+
let(:watched_directories) { [File.dirname(__FILE__), File.expand_path('../..', __FILE__)] }
|
6
|
+
|
7
|
+
subject { described_class.new(*watched_directories) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
Listen::Adapter.stub(:select_and_initialize) { adapter }
|
11
|
+
# Don't build a record of the files inside the base directory.
|
12
|
+
Listen::DirectoryRecord.any_instance.stub(:build)
|
13
|
+
end
|
14
|
+
|
15
|
+
it_should_behave_like 'a listener to changes on a file-system'
|
16
|
+
|
17
|
+
describe '#initialize' do
|
18
|
+
context 'with no options' do
|
19
|
+
it 'sets the directories' do
|
20
|
+
subject.directories.should =~ watched_directories
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'converts the passed paths into absolute paths - #21' do
|
24
|
+
paths = watched_directories.map { |d| File.join(d, '..') }
|
25
|
+
described_class.new(*paths).directories.should =~ watched_directories.map{ |d| File.expand_path('..', d) }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with custom options' do
|
30
|
+
subject do
|
31
|
+
args = watched_directories << {:ignore => /\.ssh/, :filter => [/.*\.rb/,/.*\.md/], :latency => 0.5, :force_polling => true}
|
32
|
+
described_class.new(*args)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'passes the custom ignored paths to each directory record' do
|
36
|
+
subject.directories_records.each do |r|
|
37
|
+
r.ignoring_patterns.should include /\.ssh/
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'passes the custom filters to each directory record' do
|
42
|
+
subject.directories_records.each do |r|
|
43
|
+
r.filtering_patterns.should =~ [/.*\.rb/,/.*\.md/]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'sets adapter_options' do
|
48
|
+
subject.instance_variable_get(:@adapter_options).should eq(:latency => 0.5, :force_polling => true)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#start' do
|
54
|
+
it 'selects and initializes an adapter' do
|
55
|
+
Listen::Adapter.should_receive(:select_and_initialize).with(watched_directories, {}) { adapter }
|
56
|
+
subject.start
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'builds all directories records' do
|
60
|
+
subject.directories_records.each do |r|
|
61
|
+
r.should_receive(:build)
|
62
|
+
end
|
63
|
+
subject.start
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'with a started listener' do
|
68
|
+
before do
|
69
|
+
subject.stub(:initialize_adapter) { adapter }
|
70
|
+
subject.start
|
71
|
+
end
|
72
|
+
|
73
|
+
describe '#unpause' do
|
74
|
+
it 'rebuilds all directories records' do
|
75
|
+
subject.directories_records.each do |r|
|
76
|
+
r.should_receive(:build)
|
77
|
+
end
|
78
|
+
subject.unpause
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '#ignore' do
|
84
|
+
it 'delegates the work to each directory record' do
|
85
|
+
subject.directories_records.each do |r|
|
86
|
+
r.should_receive(:ignore).with 'some_directory'
|
87
|
+
end
|
88
|
+
subject.ignore 'some_directory'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#ignore!' do
|
93
|
+
it 'delegates the work to each directory record' do
|
94
|
+
subject.directories_records.each do |r|
|
95
|
+
r.should_receive(:ignore!).with 'some_directory'
|
96
|
+
end
|
97
|
+
subject.ignore! 'some_directory'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe '#filter' do
|
102
|
+
it 'delegates the work to each directory record' do
|
103
|
+
subject.directories_records.each do |r|
|
104
|
+
r.should_receive(:filter).with /\.txt$/
|
105
|
+
end
|
106
|
+
subject.filter /\.txt$/
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#filter!' do
|
111
|
+
it 'delegates the work to each directory record' do
|
112
|
+
subject.directories_records.each do |r|
|
113
|
+
r.should_receive(:filter!).with /\.txt$/
|
114
|
+
end
|
115
|
+
subject.filter! /\.txt$/
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe '#on_change' do
|
120
|
+
let(:directories) { %w{dir1 dir2 dir3} }
|
121
|
+
let(:changes) { {:modified => [], :added => [], :removed => []} }
|
122
|
+
let(:callback) { Proc.new { @called = true } }
|
123
|
+
|
124
|
+
before do
|
125
|
+
@called = false
|
126
|
+
subject.stub(:fetch_records_changes => changes)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'fetches the changes of all directories records' do
|
130
|
+
subject.unstub(:fetch_records_changes)
|
131
|
+
|
132
|
+
subject.directories_records.each do |record|
|
133
|
+
record.should_receive(:fetch_changes).with(
|
134
|
+
directories, hash_including(:relative_paths => described_class::DEFAULT_TO_RELATIVE_PATHS)
|
135
|
+
).and_return(changes)
|
136
|
+
end
|
137
|
+
subject.on_change(directories)
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'with no changes to report' do
|
141
|
+
if RUBY_VERSION[/^1.8/]
|
142
|
+
it 'does not run the callback' do
|
143
|
+
subject.change(&callback)
|
144
|
+
subject.on_change(directories)
|
145
|
+
@called.should be_false
|
146
|
+
end
|
147
|
+
else
|
148
|
+
it 'does not run the callback' do
|
149
|
+
callback.should_not_receive(:call)
|
150
|
+
subject.change(&callback)
|
151
|
+
subject.on_change(directories)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context 'with changes to report' do
|
157
|
+
let(:changes) { {:modified => %w{path1}, :added => [], :removed => %w{path2}} }
|
158
|
+
|
159
|
+
if RUBY_VERSION[/^1.8/]
|
160
|
+
it 'runs the callback passing it the changes' do
|
161
|
+
subject.change(&callback)
|
162
|
+
subject.on_change(directories)
|
163
|
+
@called.should be_true
|
164
|
+
end
|
165
|
+
else
|
166
|
+
it 'runs the callback passing it the changes' do
|
167
|
+
callback.should_receive(:call).with(changes[:modified], changes[:added], changes[:removed])
|
168
|
+
subject.change(&callback)
|
169
|
+
subject.on_change(directories)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
def run_in_two_threads(proc1, proc2)
|
4
|
+
t1 = Thread.new &proc1
|
5
|
+
sleep test_latency # t1 must run before t2
|
6
|
+
t2 = Thread.new { proc2.call; Thread.kill t1 }
|
7
|
+
t2.join(test_latency * 2)
|
8
|
+
ensure
|
9
|
+
Thread.kill t1 if t1
|
10
|
+
Thread.kill t2 if t2
|
11
|
+
end
|
12
|
+
|
13
|
+
describe Listen::Turnstile do
|
14
|
+
before { @called = false }
|
15
|
+
|
16
|
+
describe '#wait' do
|
17
|
+
context 'without a signal' do
|
18
|
+
it 'blocks one thread indefinitely' do
|
19
|
+
run_in_two_threads lambda {
|
20
|
+
subject.wait
|
21
|
+
@called = true
|
22
|
+
}, lambda {
|
23
|
+
sleep test_latency
|
24
|
+
}
|
25
|
+
@called.should be_false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with a signal' do
|
30
|
+
it 'blocks one thread until it recieves a signal from another thread' do
|
31
|
+
run_in_two_threads lambda {
|
32
|
+
subject.wait
|
33
|
+
@called = true
|
34
|
+
}, lambda {
|
35
|
+
subject.signal
|
36
|
+
sleep test_latency
|
37
|
+
}
|
38
|
+
@called.should be_true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#signal' do
|
44
|
+
context 'without a wait-call before' do
|
45
|
+
it 'does nothing' do
|
46
|
+
run_in_two_threads lambda {
|
47
|
+
subject.signal
|
48
|
+
@called = true
|
49
|
+
}, lambda {
|
50
|
+
sleep test_latency
|
51
|
+
}
|
52
|
+
@called.should be_true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Listen do
|
4
|
+
describe '#to' do
|
5
|
+
context 'with one path to listen to' do
|
6
|
+
let(:listener) { mock(Listen::Listener) }
|
7
|
+
let(:listener_class) { Listen::Listener }
|
8
|
+
|
9
|
+
before { listener_class.stub(:new => listener) }
|
10
|
+
|
11
|
+
context 'without options' do
|
12
|
+
it 'creates an instance of Listner' do
|
13
|
+
listener_class.should_receive(:new).with('/path')
|
14
|
+
described_class.to('/path')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with options' do
|
19
|
+
it 'creates an instance of Listner with the passed params' do
|
20
|
+
listener_class.should_receive(:new).with('/path', :filter => '**/*')
|
21
|
+
described_class.to('/path', :filter => '**/*')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'without a block' do
|
26
|
+
it 'returns the listener' do
|
27
|
+
described_class.to('/path', :filter => '**/*').should eq listener
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'with a block' do
|
32
|
+
it 'starts the listner after creating it' do
|
33
|
+
listener.should_receive(:start)
|
34
|
+
described_class.to('/path', :filter => '**/*') { |modified, added, removed| }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with multiple paths to listen to' do
|
40
|
+
let(:multi_listener) { mock(Listen::MultiListener) }
|
41
|
+
let(:multi_listener_class) { Listen::MultiListener }
|
42
|
+
|
43
|
+
before { multi_listener_class.stub(:new => multi_listener) }
|
44
|
+
|
45
|
+
context 'without options' do
|
46
|
+
it 'creates an instance of MultiListner' do
|
47
|
+
multi_listener_class.should_receive(:new).with('path1', 'path2')
|
48
|
+
described_class.to('path1', 'path2')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'with options' do
|
53
|
+
it 'creates an instance of MultiListner with the passed params' do
|
54
|
+
multi_listener_class.should_receive(:new).with('path1', 'path2', :filter => '**/*')
|
55
|
+
described_class.to('path1', 'path2', :filter => '**/*')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'without a block' do
|
60
|
+
it 'returns a MultiListener instance created with the passed params' do
|
61
|
+
described_class.to('path1', 'path2', :filter => '**/*').should eq multi_listener
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'with a block' do
|
66
|
+
it 'starts a MultiListener instance after creating it with the passed params' do
|
67
|
+
multi_listener.should_receive(:start)
|
68
|
+
described_class.to('path1', 'path2', :filter => '**/*') { |modified, added, removed| }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'listen'
|
2
|
+
|
3
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
4
|
+
|
5
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.color_enabled = true
|
8
|
+
config.order = :random
|
9
|
+
config.filter_run :focus => true
|
10
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
11
|
+
config.run_all_when_everything_filtered = true
|
12
|
+
config.filter_run_excluding :broken => true
|
13
|
+
config.fail_fast = true
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_latency
|
17
|
+
0.1
|
18
|
+
end
|
19
|
+
|
20
|
+
# Crash loud in tests!
|
21
|
+
Thread.abort_on_exception = true
|