From e11be0f3174adcec08ba9a88e10157372294ead2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 29 Mar 2013 18:20:09 +0100 Subject: [PATCH] Make Listen::Listener capable of listening to multiple directories It also deprecates Listen::MultiListener since all the logic has been generalized and moved to Listen::Listener. --- CHANGELOG.md | 3 + README.md | 28 +---- lib/listen.rb | 6 +- lib/listen/listener.rb | 82 +++++++++----- lib/listen/multi_listener.rb | 138 +---------------------- spec/listen/listener_spec.rb | 129 +++++++++++++++------- spec/listen/multi_listener_spec.rb | 171 ++--------------------------- spec/listen_spec.rb | 36 +++--- 8 files changed, 178 insertions(+), 415 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8cf3ebe..8d67f1ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ ### Improvements +- [#95][] Make `Listen::Listener` capable of listening to multiple directories. ([@rymai][]) +- [#95][] Deprecate `Listen::MultiListener`. ([@rymai][]) - Add `Listen::Adapter#pause`, `Listen::Adapter#unpause` and `Listen::Adapter#paused?`. ([@rymai][]) - Refactor `Listen::DirectoryRecord` internals. ([@rymai][]) - Refactor `Listen::DependencyManager` internals. ([@rymai][]) @@ -227,6 +229,7 @@ [#85]: https://github.com/guard/listen/issues/85 [#88]: https://github.com/guard/listen/issues/88 [#93]: https://github.com/guard/listen/issues/93 +[#95]: https://github.com/guard/listen/issues/95 [@Maher4Ever]: https://github.com/Maher4Ever [@akerbos]: https://github.com/akerbos [@antifuchs]: https://github.com/antifuchs diff --git a/README.md b/README.md index b691cf71..bf931f38 100644 --- a/README.md +++ b/README.md @@ -81,30 +81,6 @@ listener.unpause listener.stop ``` -## Listening to changes on multiple directories - -The Listen gem provides the `MultiListener` class to watch multiple directories and -handle their changes from a single listener: - -```ruby -listener = Listen::MultiListener.new('app/css', 'app/js') -listener.latency(0.5) - -# Configure the listener to your needs... - -listener.start # blocks execution! -```` - -For an easier access, the `Listen.to` method can also be used to create a multi-listener: - -``` ruby -listener = Listen.to('app/css', 'app/js') - .ignore(%r{^vendor/}) # both js/vendor and css/vendor will be ignored - .change(&assets_callback) - -listener.start # blocks execution! -``` - ## Changes callback Changes to the listened-to directories gets reported back to the user in a callback. @@ -168,7 +144,7 @@ Listen.to('/home/user/app/css', :relative_paths => true) do |modified, added, re end ``` -Passing the `:relative_paths => true` option won't work when listeneing to multiple +Passing the `:relative_paths => true` option won't work when listening to multiple directories: ```ruby @@ -224,7 +200,7 @@ Starting a listener blocks the current thread by default. That means any code af For advanced usage there is an option to disable this behavior and have the listener start working in the background without blocking. To enable non-blocking listening the `start` method of -the listener (be it `Listener` or `MultiListener`) needs to be called with `false` as a parameter. +the listener needs to be called with `false` as a parameter. Here is an example of using a listener in the non-blocking mode: diff --git a/lib/listen.rb b/lib/listen.rb index e90d7813..180897c0 100644 --- a/lib/listen.rb +++ b/lib/listen.rb @@ -25,11 +25,7 @@ module Adapters # @return [Listen::Listener] the file listener if no block given # def self.to(*args, &block) - listener = if args.length == 1 || ! args[1].is_a?(String) - Listener.new(*args, &block) - else - MultiListener.new(*args, &block) - end + listener = Listener.new(*args, &block) block ? listener.start : listener end diff --git a/lib/listen/listener.rb b/lib/listen/listener.rb index d94e161f..c45febb1 100644 --- a/lib/listen/listener.rb +++ b/lib/listen/listener.rb @@ -2,14 +2,11 @@ module Listen class Listener - attr_reader :directory, :directory_record, :adapter + attr_reader :directories, :directories_records, :adapter - # The default value for using relative paths in the callback. - DEFAULT_TO_RELATIVE_PATHS = false - - # Initializes the directory listener. + # Initializes the directories listener. # - # @param [String] directory the directory to listen to + # @param [String] directory the directories to listen to # @param [Hash] options the listen options # @option options [Regexp] ignore a pattern for ignoring paths # @option options [Regexp] filter a pattern for filtering paths @@ -23,15 +20,15 @@ class Listener # @yieldparam [Array] added the list of added files # @yieldparam [Array] removed the list of removed files # - def initialize(directory, options = {}, &block) - @block = block - @directory = Pathname.new(directory).realpath.to_s - @directory_record = DirectoryRecord.new(@directory) - @use_relative_paths = DEFAULT_TO_RELATIVE_PATHS + def initialize(*args, &block) + options = args.last.is_a?(Hash) ? args.pop : {} + directories = args.flatten + initialize_directories_and_directories_records(directories) + initialize_relative_paths_usage(options) + @block = block - @use_relative_paths = options.delete(:relative_paths) if options[:relative_paths] - @directory_record.ignore(*options.delete(:ignore)) if options[:ignore] - @directory_record.filter(*options.delete(:filter)) if options[:filter] + ignore(*options.delete(:ignore)) + filter(*options.delete(:filter)) @adapter_options = options end @@ -43,7 +40,7 @@ def initialize(directory, options = {}, &block) # @param [Boolean] blocking whether or not to block the current thread after starting # def start(blocking = true) - t = Thread.new { @directory_record.build } + t = Thread.new { build_directories_records } @adapter = initialize_adapter t.join @adapter.start(blocking) @@ -69,7 +66,7 @@ def pause # @return [Listen::Listener] the listener # def unpause - @directory_record.build + build_directories_records @adapter.unpause self end @@ -91,7 +88,7 @@ def paused? # @see Listen::DirectoryRecord#ignore # def ignore(*regexps) - @directory_record.ignore(*regexps) + @directories_records.each { |r| r.ignore(*regexps) } self end @@ -104,7 +101,7 @@ def ignore(*regexps) # @see Listen::DirectoryRecord#ignore! # def ignore!(*regexps) - @directory_record.ignore!(*regexps) + @directories_records.each { |r| r.ignore!(*regexps) } self end @@ -117,7 +114,7 @@ def ignore!(*regexps) # @see Listen::DirectoryRecord#filter # def filter(*regexps) - @directory_record.filter(*regexps) + @directories_records.each { |r| r.filter(*regexps) } self end @@ -130,7 +127,7 @@ def filter(*regexps) # @see Listen::DirectoryRecord#filter! # def filter!(*regexps) - @directory_record.filter!(*regexps) + @directories_records.each { |r| r.filter!(*regexps) } self end @@ -215,21 +212,56 @@ def change(&block) # modified, added, removed # @see Listen::DirectoryRecord#fetch_changes # def on_change(directories, options = {}) - changes = @directory_record.fetch_changes(directories, options.merge( - :relative_paths => @use_relative_paths - )) + changes = fetch_records_changes(directories, options) unless changes.values.all? { |paths| paths.empty? } - @block.call(changes[:modified],changes[:added],changes[:removed]) + @block.call(changes[:modified], changes[:added], changes[:removed]) end end private + def initialize_directories_and_directories_records(directories) + @directories = directories.map { |d| Pathname.new(d).realpath.to_s } + @directories_records = @directories.map { |d| DirectoryRecord.new(d) } + end + + def initialize_relative_paths_usage(options) + @use_relative_paths = @directories.one? && options.delete(:relative_paths) { true } + end + # Initializes an adapter passing it the callback and adapters' options. # def initialize_adapter callback = lambda { |changed_dirs, options| self.on_change(changed_dirs, options) } - Adapter.select_and_initialize(@directory, @adapter_options, &callback) + Adapter.select_and_initialize(@directories, @adapter_options, &callback) + end + + # Build the watched directories' records. + # + def build_directories_records + @directories_records.each { |r| r.build } + end + + # Returns the sum of all the changes to the directories records + # + # @param (see Listen::DirectoryRecord#fetch_changes) + # + # @return [Hash] the changes + # + def fetch_records_changes(directories_to_search, options) + @directories_records.inject({}) do |h, r| + # directory records skips paths outside their range, so passing the + # whole `directories` array is not a problem. + record_changes = r.fetch_changes(directories_to_search, options.merge(:relative_paths => @use_relative_paths)) + + if h.empty? + h.merge!(record_changes) + else + h.each { |k, v| h[k] += record_changes[k] } + end + + h + end end end diff --git a/lib/listen/multi_listener.rb b/lib/listen/multi_listener.rb index e726c9fd..5a6068a3 100644 --- a/lib/listen/multi_listener.rb +++ b/lib/listen/multi_listener.rb @@ -1,143 +1,15 @@ module Listen class MultiListener < Listener - attr_reader :directories, :directories_records, :adapter - # Initializes the multiple directories listener. + # This class is deprecated, please use Listen::Listener instead. # - # @param [String] directories the directories to listen to - # @param [Hash] options the listen options - # @option options [Regexp] ignore a pattern for ignoring paths - # @option options [Regexp] filter a pattern for filtering paths - # @option options [Float] latency the delay between checking for changes in seconds - # @option options [Boolean] force_polling whether to force the polling adapter or not - # @option options [String, Boolean] polling_fallback_message to change polling fallback message or remove it - # - # @yield [modified, added, removed] the changed files - # @yieldparam [Array] modified the list of modified files - # @yieldparam [Array] added the list of added files - # @yieldparam [Array] removed the list of removed files + # @see Listen::Listener + # @deprecated # def initialize(*args, &block) - options = args.last.is_a?(Hash) ? args.pop : {} - directories = args - - @block = block - @directories = directories.map { |d| Pathname.new(d).realpath.to_s } - @directories_records = @directories.map { |d| DirectoryRecord.new(d) } - - ignore(*options.delete(:ignore)) if options[:ignore] - filter(*options.delete(:filter)) if options[:filter] - - @adapter_options = options - end - - # Starts the listener by initializing the adapter and building - # the directory record concurrently, then it starts the adapter to watch - # for changes. - # - # @param [Boolean] blocking whether or not to block the current thread after starting - # - def start(blocking = true) - t = Thread.new { @directories_records.each { |r| r.build } } - @adapter = initialize_adapter - t.join - @adapter.start(blocking) - end - - # Unpauses the listener. - # - # @return [Listen::Listener] the listener - # - def unpause - @directories_records.each { |r| r.build } - @adapter.unpause - self - end - - # Adds ignored paths to the listener. - # - # @param (see Listen::DirectoryRecord#ignore) - # - # @return [Listen::Listener] the listener - # - def ignore(*paths) - @directories_records.each { |r| r.ignore(*paths) } - self - end - - # Replaces ignored paths in the listener. - # - # @param (see Listen::DirectoryRecord#ignore!) - # - # @return [Listen::Listener] the listener - # - def ignore!(*paths) - @directories_records.each { |r| r.ignore!(*paths) } - self - end - - # Adds file filters to the listener. - # - # @param (see Listen::DirectoryRecord#filter) - # - # @return [Listen::Listener] the listener - # - def filter(*regexps) - @directories_records.each { |r| r.filter(*regexps) } - self - end - - # Replaces file filters in the listener. - # - # @param (see Listen::DirectoryRecord#filter!) - # - # @return [Listen::Listener] the listener - # - def filter!(*regexps) - @directories_records.each { |r| r.filter!(*regexps) } - self + puts "[DEPRECATED] Listen::MultiListener is deprecated, please use Listen::Listener instead." + super end - # Runs the callback passing it the changes if there are any. - # - # @param (see Listen::DirectoryRecord#fetch_changes) - # - def on_change(directories_to_search, options = {}) - changes = fetch_records_changes(directories_to_search, options) - unless changes.values.all? { |paths| paths.empty? } - @block.call(changes[:modified],changes[:added],changes[:removed]) - end - end - - private - - # Initializes an adapter passing it the callback and adapters' options. - # - def initialize_adapter - callback = lambda { |changed_dirs, options| self.on_change(changed_dirs, options) } - Adapter.select_and_initialize(@directories, @adapter_options, &callback) - end - - # Returns the sum of all the changes to the directories records - # - # @param (see Listen::DirectoryRecord#fetch_changes) - # - # @return [Hash] the changes - # - def fetch_records_changes(directories_to_search, options) - @directories_records.inject({}) do |h, r| - # directory records skips paths outside their range, so passing the - # whole `directories` array is not a problem. - record_changes = r.fetch_changes(directories_to_search, options.merge(:relative_paths => DEFAULT_TO_RELATIVE_PATHS)) - - if h.empty? - h.merge!(record_changes) - else - h.each { |k, v| h[k] += record_changes[k] } - end - - h - end - end end end diff --git a/spec/listen/listener_spec.rb b/spec/listen/listener_spec.rb index cf82f1b6..8fff496a 100644 --- a/spec/listen/listener_spec.rb +++ b/spec/listen/listener_spec.rb @@ -1,48 +1,85 @@ require 'spec_helper' describe Listen::Listener do - let(:adapter) { mock(Listen::Adapter, :start => true).as_null_object } - let(:watched_directory) { File.dirname(__FILE__) } - - subject { described_class.new(watched_directory) } + let(:adapter) { mock(Listen::Adapter, :start => true).as_null_object } + let(:watched_directory) { File.dirname(__FILE__) } + let(:watched_directories) { [File.dirname(__FILE__), File.expand_path('../..', __FILE__)] } before do Listen::Adapter.stub(:select_and_initialize) { adapter } # Don't build a record of the files inside the base directory. - subject.directory_record.stub(:build) + Listen::DirectoryRecord.any_instance.stub(:build) end + subject { described_class.new(watched_directories) } it_should_behave_like 'a listener to changes on a file-system' describe '#initialize' do - context 'with no options' do - it 'sets the directory' do - subject.directory.should eq watched_directory + context 'listening to a single directory' do + subject { described_class.new(watched_directory) } + + it 'sets the directories' do + subject.directories.should eq [watched_directory] end - it 'converts the passed path into an absolute path - #21' do - described_class.new(File.join(watched_directory, '..')).directory.should eq File.expand_path('..', watched_directory) + context 'with no options' do + it 'sets the option for using relative paths in the callback to true' do + subject.instance_variable_get(:@use_relative_paths).should eq true + end end - it 'sets the option for using relative paths in the callback to the default one' do - subject.instance_variable_get(:@use_relative_paths).should eq described_class::DEFAULT_TO_RELATIVE_PATHS + context 'with :relative_paths => false' do + it 'sets the option for using relative paths in the callback to false' do + listener = described_class.new(watched_directories, :relative_paths => false) + listener.instance_variable_get(:@use_relative_paths).should eq false + end end end + context 'listening to multiple directories' do + subject { described_class.new(watched_directories) } + + it 'sets the directories' do + subject.directories.should eq watched_directories + end + + context 'with no options' do + it 'sets the option for using relative paths in the callback to false' do + subject.instance_variable_get(:@use_relative_paths).should eq false + end + end + + context 'with :relative_paths => true' do + it 'sets the option for using relative paths in the callback to false' do + listener = described_class.new(watched_directories, :relative_paths => true) + listener.instance_variable_get(:@use_relative_paths).should eq false + end + end + end + + it 'converts the passed path into an absolute path - #21' do + described_class.new(File.join(watched_directory, '..')).directories.should eq [File.expand_path('..', watched_directory)] + end + context 'with custom options' do - subject { described_class.new(watched_directory, :ignore => /\.ssh/, :filter => [/.*\.rb/,/.*\.md/], - :latency => 0.5, :force_polling => true, :relative_paths => true) } + let(:options) do + { + :ignore => /\.ssh/, :filter => [/.*\.rb/, /.*\.md/], + :latency => 0.5, :force_polling => true, :relative_paths => true + } + end + subject { described_class.new(watched_directory, options) } it 'passes the custom ignored paths to the directory record' do - subject.directory_record.ignoring_patterns.should include /\.ssh/ + subject.directories_records.each do |directory_record| + directory_record.ignoring_patterns.should include /\.ssh/ + end end it 'passes the custom filters to the directory record' do - subject.directory_record.filtering_patterns.should =~ [/.*\.rb/,/.*\.md/] - end - - it 'sets the cutom option for using relative paths in the callback' do - subject.instance_variable_get(:@use_relative_paths).should be_true + subject.directories_records.each do |directory_record| + directory_record.filtering_patterns.should =~ [/.*\.rb/,/.*\.md/] + end end it 'sets adapter_options' do @@ -53,12 +90,14 @@ describe '#start' do it 'selects and initializes an adapter' do - Listen::Adapter.should_receive(:select_and_initialize).with(watched_directory, {}) { adapter } + Listen::Adapter.should_receive(:select_and_initialize).with(watched_directories, {}) { adapter } subject.start end it 'builds the directory record' do - subject.directory_record.should_receive(:build) + subject.directories_records.each do |directory_record| + directory_record.should_receive(:build) + end subject.start end end @@ -71,7 +110,9 @@ describe '#unpause' do it 'rebuilds the directory record' do - subject.directory_record.should_receive(:build) + subject.directories_records.each do |directory_record| + directory_record.should_receive(:build) + end subject.unpause end end @@ -79,33 +120,40 @@ describe '#ignore'do it 'delegates the work to the directory record' do - subject.directory_record.should_receive(:ignore).with 'some_directory' + subject.directories_records.each do |directory_record| + directory_record.should_receive(:ignore).with 'some_directory' + end subject.ignore 'some_directory' end end describe '#ignore!'do it 'delegates the work to the directory record' do - subject.directory_record.should_receive(:ignore!).with 'some_directory' + subject.directories_records.each do |directory_record| + directory_record.should_receive(:ignore!).with 'some_directory' + end subject.ignore! 'some_directory' end end describe '#filter' do it 'delegates the work to the directory record' do - subject.directory_record.should_receive(:filter).with /\.txt$/ + subject.directories_records.each do |directory_record| + directory_record.should_receive(:filter).with /\.txt$/ + end subject.filter /\.txt$/ end end describe '#filter!' do it 'delegates the work to the directory record' do - subject.directory_record.should_receive(:filter!).with /\.txt$/ + subject.directories_records.each do |directory_record| + directory_record.should_receive(:filter!).with /\.txt$/ + end subject.filter! /\.txt$/ end end - describe '#on_change' do let(:directories) { %w{dir1 dir2 dir3} } let(:changes) { {:modified => [], :added => [], :removed => []} } @@ -113,23 +161,16 @@ before do @called = false - subject.directory_record.stub(:fetch_changes => changes) - end - - it 'fetches the changes of the directory record' do - subject.directory_record.should_receive(:fetch_changes).with( - directories, hash_including(:relative_paths => described_class::DEFAULT_TO_RELATIVE_PATHS) - ) - subject.on_change(directories) + subject.stub(:fetch_records_changes => changes) end - context 'with relative paths option set to true' do - subject { described_class.new(watched_directory, :relative_paths => true) } + it 'fetches the changes of all directories records' do + subject.unstub(:fetch_records_changes) - it 'fetches the changes of the directory record' do - subject.directory_record.should_receive(:fetch_changes).with(directories, hash_including(:relative_paths => true)) - subject.on_change(directories) + subject.directories_records.each do |record| + record.should_receive(:fetch_changes).with(directories, an_instance_of(Hash)).and_return(changes) end + subject.on_change(directories) end context 'with no changes to report' do @@ -149,7 +190,11 @@ end context 'with changes to report' do - let(:changes) { {:modified => %w{path1}, :added => [], :removed => %w{path2}} } + let(:changes) do + { + :modified => %w{path1}, :added => [], :removed => %w{path2} + } + end if RUBY_VERSION[/^1.8/] it 'runs the callback passing it the changes' do diff --git a/spec/listen/multi_listener_spec.rb b/spec/listen/multi_listener_spec.rb index 32e1c89f..0292c2c5 100644 --- a/spec/listen/multi_listener_spec.rb +++ b/spec/listen/multi_listener_spec.rb @@ -1,174 +1,19 @@ require 'spec_helper' describe Listen::MultiListener do - let(:adapter) { mock(Listen::Adapter, :start => true).as_null_object } - let(:watched_directories) { [File.dirname(__FILE__), File.expand_path('../..', __FILE__)] } - - subject { described_class.new(*watched_directories) } - - before do - Listen::Adapter.stub(:select_and_initialize) { adapter } - # Don't build a record of the files inside the base directory. - Listen::DirectoryRecord.any_instance.stub(:build) - end - - it_should_behave_like 'a listener to changes on a file-system' describe '#initialize' do - context 'with no options' do - it 'sets the directories' do - subject.directories.should =~ watched_directories - end - - it 'converts the passed paths into absolute paths - #21' do - paths = watched_directories.map { |d| File.join(d, '..') } - described_class.new(*paths).directories.should =~ watched_directories.map{ |d| File.expand_path('..', d) } - end + let(:options) do + { + :ignore => /\.ssh/, :filter => [/.*\.rb/, /.*\.md/], + :latency => 0.5, :force_polling => true + } end - context 'with custom options' do - subject do - args = watched_directories << {:ignore => /\.ssh/, :filter => [/.*\.rb/,/.*\.md/], :latency => 0.5, :force_polling => true} - described_class.new(*args) - end - - it 'passes the custom ignored paths to each directory record' do - subject.directories_records.each do |r| - r.ignoring_patterns.should include /\.ssh/ - end - end - - it 'passes the custom filters to each directory record' do - subject.directories_records.each do |r| - r.filtering_patterns.should =~ [/.*\.rb/,/.*\.md/] - end - end - - it 'sets adapter_options' do - subject.instance_variable_get(:@adapter_options).should eq(:latency => 0.5, :force_polling => true) - end - end - end - - describe '#start' do - it 'selects and initializes an adapter' do - Listen::Adapter.should_receive(:select_and_initialize).with(watched_directories, {}) { adapter } - subject.start - end - - it 'builds all directories records' do - subject.directories_records.each do |r| - r.should_receive(:build) - end - subject.start - end - end - - context 'with a started listener' do - before do - subject.stub(:initialize_adapter) { adapter } - subject.start - end - - describe '#unpause' do - it 'rebuilds all directories records' do - subject.directories_records.each do |r| - r.should_receive(:build) - end - subject.unpause - end - end - end - - describe '#ignore' do - it 'delegates the work to each directory record' do - subject.directories_records.each do |r| - r.should_receive(:ignore).with 'some_directory' - end - subject.ignore 'some_directory' + it 'forward directly to its superclass' do + Listen::Listener.should_receive(:new).with('foo', 'bar', options) + described_class.new('foo', 'bar', options) end end - describe '#ignore!' do - it 'delegates the work to each directory record' do - subject.directories_records.each do |r| - r.should_receive(:ignore!).with 'some_directory' - end - subject.ignore! 'some_directory' - end - end - - describe '#filter' do - it 'delegates the work to each directory record' do - subject.directories_records.each do |r| - r.should_receive(:filter).with /\.txt$/ - end - subject.filter /\.txt$/ - end - end - - describe '#filter!' do - it 'delegates the work to each directory record' do - subject.directories_records.each do |r| - r.should_receive(:filter!).with /\.txt$/ - end - subject.filter! /\.txt$/ - end - end - - describe '#on_change' do - let(:directories) { %w{dir1 dir2 dir3} } - let(:changes) { {:modified => [], :added => [], :removed => []} } - let(:callback) { Proc.new { @called = true } } - - before do - @called = false - subject.stub(:fetch_records_changes => changes) - end - - it 'fetches the changes of all directories records' do - subject.unstub(:fetch_records_changes) - - subject.directories_records.each do |record| - record.should_receive(:fetch_changes).with( - directories, hash_including(:relative_paths => described_class::DEFAULT_TO_RELATIVE_PATHS) - ).and_return(changes) - end - subject.on_change(directories) - end - - context 'with no changes to report' do - if RUBY_VERSION[/^1.8/] - it 'does not run the callback' do - subject.change(&callback) - subject.on_change(directories) - @called.should be_false - end - else - it 'does not run the callback' do - callback.should_not_receive(:call) - subject.change(&callback) - subject.on_change(directories) - end - end - end - - context 'with changes to report' do - let(:changes) { {:modified => %w{path1}, :added => [], :removed => %w{path2}} } - - if RUBY_VERSION[/^1.8/] - it 'runs the callback passing it the changes' do - subject.change(&callback) - subject.on_change(directories) - @called.should be_true - end - else - it 'runs the callback passing it the changes' do - callback.should_receive(:call).with(changes[:modified], changes[:added], changes[:removed]) - subject.change(&callback) - subject.on_change(directories) - end - end - end - end end diff --git a/spec/listen_spec.rb b/spec/listen_spec.rb index 9e35ecf9..612459e1 100644 --- a/spec/listen_spec.rb +++ b/spec/listen_spec.rb @@ -2,21 +2,20 @@ describe Listen do describe '#to' do - context 'with one path to listen to' do - let(:listener) { mock(Listen::Listener) } - let(:listener_class) { Listen::Listener } - - before { listener_class.stub(:new => listener) } + let(:listener) { mock(Listen::Listener) } + let(:listener_class) { Listen::Listener } + before { listener_class.stub(:new => listener) } + context 'with one path to listen to' do context 'without options' do - it 'creates an instance of Listner' do + it 'creates an instance of Listener' do listener_class.should_receive(:new).with('/path') described_class.to('/path') end end context 'with options' do - it 'creates an instance of Listner with the passed params' do + it 'creates an instance of Listener with the passed params' do listener_class.should_receive(:new).with('/path', :filter => '**/*') described_class.to('/path', :filter => '**/*') end @@ -29,7 +28,7 @@ end context 'with a block' do - it 'starts the listner after creating it' do + it 'starts the listener after creating it' do listener.should_receive(:start) described_class.to('/path', :filter => '**/*') { |modified, added, removed| } end @@ -37,34 +36,29 @@ end context 'with multiple paths to listen to' do - let(:multi_listener) { mock(Listen::MultiListener) } - let(:multi_listener_class) { Listen::MultiListener } - - before { multi_listener_class.stub(:new => multi_listener) } - context 'without options' do - it 'creates an instance of MultiListner' do - multi_listener_class.should_receive(:new).with('path1', 'path2') + it 'creates an instance of Listener' do + listener_class.should_receive(:new).with('path1', 'path2') described_class.to('path1', 'path2') end end context 'with options' do - it 'creates an instance of MultiListner with the passed params' do - multi_listener_class.should_receive(:new).with('path1', 'path2', :filter => '**/*') + it 'creates an instance of Listener with the passed params' do + listener_class.should_receive(:new).with('path1', 'path2', :filter => '**/*') described_class.to('path1', 'path2', :filter => '**/*') end end context 'without a block' do - it 'returns a MultiListener instance created with the passed params' do - described_class.to('path1', 'path2', :filter => '**/*').should eq multi_listener + it 'returns a Listener instance created with the passed params' do + described_class.to('path1', 'path2', :filter => '**/*').should eq listener end end context 'with a block' do - it 'starts a MultiListener instance after creating it with the passed params' do - multi_listener.should_receive(:start) + it 'starts a Listener instance after creating it with the passed params' do + listener.should_receive(:start) described_class.to('path1', 'path2', :filter => '**/*') { |modified, added, removed| } end end