Merge branch 'master' of git://github.com/guard/guard

Conflicts:
	lib/guard.rb
This commit is contained in:
Darren Pearce 2011-09-26 12:22:02 -06:00
commit 67882bcceb
29 changed files with 1170 additions and 302 deletions

View File

@ -7,9 +7,9 @@ rvm:
branches: branches:
only: only:
- master - master
- hook - guard_dependencies
- stdin env:
- jruby_travis_ctime_bug - GUARD_SLEEP=1
notifications: notifications:
recipients: recipients:
- thibaud@thibaud.me - thibaud@thibaud.me

View File

@ -1,6 +1,19 @@
## Master ## Master
### Bugs fixes:
- Pull request [#137](https://github.com/guard/guard/pull/137): Fix interacting with tools like ruby-debug. ([@hron][] & [@netzpirat][]) - Pull request [#137](https://github.com/guard/guard/pull/137): Fix interacting with tools like ruby-debug. ([@hron][] & [@netzpirat][])
- Pull request [#138](https://github.com/guard/guard/pull/138): Fixed comments in example scaffold to reference interactions. ([@rmm5t][] & [@netzpirat][])
### New feature:
- Issue [#97](https://github.com/guard/guard/issues/97): Guard dependencies. Task execution can now be halted if a Guard throws `:task_has_failed` and `Guard::Dsl#group` options include `:halt_on_fail => true`. ([@rymai][])
- Issue [#121](https://github.com/guard/guard/issues/121): `Guard.guards` and `Guard.groups` are now smart accessors. Filters can be passed to find a specific Guard/group or several Guards/groups that match (see YARDoc). ([@rymai][] & [@ches][])
- New `Guard::Group` class to store groups defined in Guardfile (with `Guard::Dsl#group`). ([@rymai][])
### Improvement:
- Full YARD documentation. ([@netzpirat][] & a little of [@rymai][])
## 0.7.0 - September 14, 2011 ## 0.7.0 - September 14, 2011
@ -9,7 +22,7 @@
### Major Changes ### Major Changes
- Posix Signals handlers (`Ctrl-C`, `Ctrl-\` and `Ctrl-Z`) are no more supported and replaced by `$stdin.gets`. Please refer to the "Interactions" section in the README for more information. ([@thibaudgg][]) - Posix Signals handlers (`Ctrl-C`, `Ctrl-\` and `Ctrl-Z`) are no more supported and replaced by `$stdin.gets`. Please refer to the "Interactions" section in the README for more information. ([@thibaudgg][])
- JRuby & Rubinius support (beta). ([@thibaudgg][] and [@netzpirat][]) - JRuby & Rubinius support (beta). ([@thibaudgg][] & [@netzpirat][])
### New feature: ### New feature:
@ -272,6 +285,7 @@
[@niklas]: https://github.com/niklas [@niklas]: https://github.com/niklas
[@oliamb]: https://github.com/oliamb [@oliamb]: https://github.com/oliamb
[@pcreux]: https://github.com/pcreux [@pcreux]: https://github.com/pcreux
[@rmm5t]: https://github.com/rmm5t
[@rymai]: https://github.com/rymai [@rymai]: https://github.com/rymai
[@stereobooster]: https://github.com/stereobooster [@stereobooster]: https://github.com/stereobooster
[@stouset]: https://github.com/stouset [@stouset]: https://github.com/stouset

View File

@ -6,6 +6,7 @@ module Guard
autoload :UI, 'guard/ui' autoload :UI, 'guard/ui'
autoload :Dsl, 'guard/dsl' autoload :Dsl, 'guard/dsl'
autoload :DslDescriber, 'guard/dsl_describer' autoload :DslDescriber, 'guard/dsl_describer'
autoload :Group, 'guard/group'
autoload :Interactor, 'guard/interactor' autoload :Interactor, 'guard/interactor'
autoload :Listener, 'guard/listener' autoload :Listener, 'guard/listener'
autoload :Watcher, 'guard/watcher' autoload :Watcher, 'guard/watcher'
@ -13,11 +14,10 @@ module Guard
autoload :Hook, 'guard/hook' autoload :Hook, 'guard/hook'
class << self class << self
attr_accessor :options, :guards, :groups, :interactor, :listener attr_accessor :options, :interactor, :listener
# Initialize the Guard singleton. # Initialize the Guard singleton.
# #
# @param [Hash] options the Guard options.
# @option options [Boolean] clear if auto clear the UI should be done # @option options [Boolean] clear if auto clear the UI should be done
# @option options [Boolean] notify if system notifications should be shown # @option options [Boolean] notify if system notifications should be shown
# @option options [Boolean] debug if debug output should be shown # @option options [Boolean] debug if debug output should be shown
@ -28,7 +28,7 @@ module Guard
def setup(options = {}) def setup(options = {})
@options = options @options = options
@guards = [] @guards = []
@groups = [:default] @groups = [Group.new(:default)]
@interactor = Interactor.new @interactor = Interactor.new
@listener = Listener.select_and_init(@options[:watchdir] ? File.expand_path(@options[:watchdir]) : Dir.pwd, options) @listener = Listener.select_and_init(@options[:watchdir] ? File.expand_path(@options[:watchdir]) : Dir.pwd, options)
@ -41,10 +41,57 @@ module Guard
self self
end end
# Smart accessor for retrieving a specific guard or several guards at once.
#
# @param [String, Symbol] filter return the guard with the given name, or nil if not found
# @param [Regexp] filter returns all guards matching the Regexp, or [] if no guard found
# @param [Hash] filter returns all guards matching the given Hash.
# Example: `{ :name => 'rspec', :group => 'backend' }`, or [] if no guard found
# @param [NilClass] filter returns all guards
#
# @see Guard.groups
#
def guards(filter = nil)
case filter
when String, Symbol
@guards.find { |guard| guard.class.to_s.downcase.sub('guard::', '') == filter.to_s.downcase.gsub('-', '') }
when Regexp
@guards.find_all { |guard| guard.class.to_s.downcase.sub('guard::', '') =~ filter }
when Hash
filter.inject(@guards) do |matches, (k, v)|
if k.to_sym == :name
matches.find_all { |guard| guard.class.to_s.downcase.sub('guard::', '') == v.to_s.downcase.gsub('-', '') }
else
matches.find_all { |guard| guard.send(k).to_sym == v.to_sym }
end
end
else
@guards
end
end
# Smart accessor for retrieving a specific group or several groups at once.
#
# @param [NilClass] filter returns all groups
# @param [String, Symbol] filter return the group with the given name, or nil if not found
# @param [Regexp] filter returns all groups matching the Regexp, or [] if no group found
#
# @see Guard.guards
#
def groups(filter = nil)
case filter
when String, Symbol
@groups.find { |group| group.name == filter.to_sym }
when Regexp
@groups.find_all { |group| group.name.to_s =~ filter }
else
@groups
end
end
# Start Guard by evaluate the `Guardfile`, initialize the declared Guards # Start Guard by evaluate the `Guardfile`, initialize the declared Guards
# and start the available file change listener. # and start the available file change listener.
# #
# @param [Hash] options the Guard options.
# @option options [Boolean] clear if auto clear the UI should be done # @option options [Boolean] clear if auto clear the UI should be done
# @option options [Boolean] notify if system notifications should be shown # @option options [Boolean] notify if system notifications should be shown
# @option options [Boolean] debug if debug output should be shown # @option options [Boolean] debug if debug output should be shown
@ -63,7 +110,8 @@ module Guard
end end
UI.info "Guard is now watching at '#{ listener.directory }'" UI.info "Guard is now watching at '#{ listener.directory }'"
guards.each { |guard| supervised_task(guard, :start) }
execute_supervised_task_for_all_guards(:start)
interactor.start interactor.start
listener.start listener.start
@ -74,7 +122,7 @@ module Guard
def stop def stop
UI.info 'Bye bye...', :reset => true UI.info 'Bye bye...', :reset => true
listener.stop listener.stop
guards.each { |guard| supervised_task(guard, :stop) } execute_supervised_task_for_all_guards(:stop)
abort abort
end end
@ -82,7 +130,7 @@ module Guard
# #
def reload def reload
run do run do
guards.each { |guard| supervised_task(guard, :reload) } execute_supervised_task_for_all_guards(:reload)
end end
end end
@ -90,7 +138,7 @@ module Guard
# #
def run_all def run_all
run do run do
guards.each { |guard| supervised_task(guard, :run_all) } execute_supervised_task_for_all_guards(:run_all)
end end
end end
@ -107,29 +155,11 @@ module Guard
end end
end end
# Trigger `run_on_change` on all Guards currently enabled and # Trigger `run_on_change` on all Guards currently enabled.
# #
def run_on_change(files) def run_on_change(paths)
run do run do
guards.each do |guard| execute_supervised_task_for_all_guards(:run_on_change, paths)
paths = Watcher.match_files(guard, files)
if @watch_all_modifications
unless paths.empty?
UI.debug "#{guard.class.name}#run_on_change with #{paths.inspect}"
supervised_task(guard, :run_on_change, paths.select {|f| !f.start_with?('!') })
deletions = paths.collect { |f| f.slice(1..-1) if f.start_with?('!') }.compact
unless deletions.empty?
UI.debug "#{guard.class.name}#run_on_deletion with #{deletions.inspect}"
supervised_task(guard, :run_on_deletion, deletions)
end
end
else
unless paths.empty?
UI.debug "#{guard.class.name}#run_on_change with #{paths.inspect}"
supervised_task(guard, :run_on_change, paths)
end
end
end
end end
end end
@ -150,6 +180,41 @@ module Guard
listener.unlock listener.unlock
end end
# Loop through all groups and execute the given task for each Guard in it,
# but halt the task execution for the all Guards within a group if one Guard
# throws `:task_has_failed` and the group has its `:halt_on_fail` option to `true`.
#
# @param [Symbol] task the task to run
# @param [Array] files the list of files to pass to the task
#
def execute_supervised_task_for_all_guards(task, files = nil)
groups.each do |group|
catch group.options[:halt_on_fail] == true ? :task_has_failed : :no_catch do
guards(:group => group.name).each do |guard|
if task == :run_on_change
paths = Watcher.match_files(guard, files)
unless paths.empty?
if @watch_all_modifications
UI.debug "#{guard.class.name}##{task} with #{paths.inspect}"
supervised_task(guard, task, paths.select {|f| !f.start_with?('!') })
deletions = paths.collect { |f| f.slice(1..-1) if f.start_with?('!') }.compact
unless deletions.empty?
UI.debug "#{guard.class.name}#run_on_deletion with #{deletions.inspect}"
supervised_task(guard, :run_on_deletion, deletions)
end
else
UI.debug "#{guard.class.name}##{task} with #{paths.inspect}"
supervised_task(guard, task, paths)
end
end
else
supervised_task(guard, task)
end
end
end
end
end
# Let a Guard execute its task, but fire it # Let a Guard execute its task, but fire it
# if his work leads to a system failure. # if his work leads to a system failure.
# #
@ -179,7 +244,7 @@ module Guard
# @param [String] name the Guard name # @param [String] name the Guard name
# @param [Array<Watcher>] watchers the list of declared watchers # @param [Array<Watcher>] watchers the list of declared watchers
# @param [Array<Hash>] callbacks the list of callbacks # @param [Array<Hash>] callbacks the list of callbacks
# @param [Hash] options the Guard options # @param [Hash] options the Guard options (see the given Guard documentation)
# #
def add_guard(name, watchers = [], callbacks = [], options = {}) def add_guard(name, watchers = [], callbacks = [], options = {})
if name.to_sym == :ego if name.to_sym == :ego
@ -194,9 +259,17 @@ module Guard
# Add a Guard group. # Add a Guard group.
# #
# @param [String] name the group name # @param [String] name the group name
# @option options [Boolean] halt_on_fail if a task execution
# should be halted for all Guards in this group if one Guard throws `:task_has_failed`
# @return [Guard::Group] the group added (or retrieved from the `@groups` variable if already present)
# #
def add_group(name) def add_group(name, options = {})
@groups << name.to_sym unless name.nil? group = groups(name)
if group.nil?
group = Group.new(name, options)
@groups << group
end
group
end end
# Tries to load the Guard main class. # Tries to load the Guard main class.

View File

@ -81,7 +81,6 @@ module Guard
# Evaluate the DSL methods in the `Guardfile`. # Evaluate the DSL methods in the `Guardfile`.
# #
# @param [Hash] options the Guard options
# @option options [Array<Symbol,String>] groups the groups to evaluate # @option options [Array<Symbol,String>] groups the groups to evaluate
# @option options [String] guardfile the path to a valid Guardfile # @option options [String] guardfile the path to a valid Guardfile
# @option options [String] guardfile_contents a string representing the content of a valid Guardfile # @option options [String] guardfile_contents a string representing the content of a valid Guardfile
@ -102,6 +101,7 @@ module Guard
# #
def reevaluate_guardfile def reevaluate_guardfile
::Guard.guards.clear ::Guard.guards.clear
::Guard.groups.clear
@@options.delete(:guardfile_contents) @@options.delete(:guardfile_contents)
Dsl.evaluate_guardfile(@@options) Dsl.evaluate_guardfile(@@options)
msg = 'Guardfile has been re-evaluated.' msg = 'Guardfile has been re-evaluated.'
@ -265,16 +265,19 @@ module Guard
# end # end
# #
# @param [Symbol, String] name the group's name called from the CLI # @param [Symbol, String] name the group's name called from the CLI
# @param [Hash] options the options accepted by the group
# @yield a block where you can declare several guards # @yield a block where you can declare several guards
# #
# @see Guard.add_group
# @see Dsl#guard # @see Dsl#guard
# @see Guard::DslDescriber # @see Guard::DslDescriber
# #
def group(name) def group(name, options = {})
@groups = @@options[:group] || [] @groups = @@options[:group] || []
name = name.to_sym name = name.to_sym
if block_given? && (@groups.empty? || @groups.map(&:to_sym).include?(name)) if block_given? && (@groups.empty? || @groups.map(&:to_sym).include?(name))
::Guard.add_group(name.to_s.downcase, options)
@current_group = name @current_group = name
yield if block_given? yield if block_given?
@ -299,6 +302,8 @@ module Guard
# @param [Hash] options the options accepted by the Guard # @param [Hash] options the options accepted by the Guard
# @yield a block where you can declare several watch patterns and actions # @yield a block where you can declare several watch patterns and actions
# #
# @see Guard.add_guard
# @see Dsl#group
# @see Dsl#watch # @see Dsl#watch
# @see Guard::DslDescriber # @see Guard::DslDescriber
# #
@ -309,7 +314,7 @@ module Guard
yield if block_given? yield if block_given?
options.update(:group => (@current_group || :default)) options.update(:group => (@current_group || :default))
::Guard.add_guard(name.to_s.downcase.to_sym, @watchers, @callbacks, options) ::Guard.add_guard(name.to_s.downcase, @watchers, @callbacks, options)
end end
# Define a pattern to be watched in order to run actions on file modification. # Define a pattern to be watched in order to run actions on file modification.
@ -327,6 +332,9 @@ module Guard
# @yieldparam [MatchData] m matches of the pattern # @yieldparam [MatchData] m matches of the pattern
# @yieldreturn a directory, a filename, an array of directories / filenames, or nothing (can be an arbitrary command) # @yieldreturn a directory, a filename, an array of directories / filenames, or nothing (can be an arbitrary command)
# #
# @see Guard::Watcher
# @see Dsl#guard
#
def watch(pattern, &action) def watch(pattern, &action)
@watchers << ::Guard::Watcher.new(pattern, action) @watchers << ::Guard::Watcher.new(pattern, action)
end end
@ -337,6 +345,8 @@ module Guard
# @param [Array] args the callback arguments # @param [Array] args the callback arguments
# @yield a block with listeners # @yield a block with listeners
# #
# @see Guard::Hook
#
def callback(*args, &listener) def callback(*args, &listener)
listener, events = args.size > 1 ? args : [listener, args[0]] listener, events = args.size > 1 ? args : [listener, args[0]]
@callbacks << { :events => events, :listener => listener } @callbacks << { :events => events, :listener => listener }
@ -349,6 +359,8 @@ module Guard
# #
# @param [Array] paths the list of paths to ignore # @param [Array] paths the list of paths to ignore
# #
# @see Guard::Listener
#
def ignore_paths(*paths) def ignore_paths(*paths)
UI.info "Ignoring paths: #{ paths.join(', ') }" UI.info "Ignoring paths: #{ paths.join(', ') }"
::Guard.listener.ignore_paths.push(*paths) ::Guard.listener.ignore_paths.push(*paths)

View File

@ -31,7 +31,7 @@ module Guard
# @param [String] name the group's name called from the CLI # @param [String] name the group's name called from the CLI
# @yield a block where you can declare several guards # @yield a block where you can declare several guards
# #
# @see Guard::Dsl # @see Guard::Dsl#group
# #
def group(name) def group(name)
@@guardfile_structure << { :group => name.to_sym, :guards => [] } @@guardfile_structure << { :group => name.to_sym, :guards => [] }
@ -42,13 +42,13 @@ module Guard
@group = false @group = false
end end
# Declare a guard. # Declares a Guard.
# #
# @param [String] name the Guard name # @param [String] name the Guard name
# @param [Hash] options the options accepted by the Guard # @param [Hash] options the options accepted by the Guard
# @yield a block where you can declare several watch patterns and actions # @yield a block where you can declare several watch patterns and actions
# #
# @see Guard::Dsl # @see Guard::Dsl#guard
# #
def guard(name, options = {}) def guard(name, options = {})
node = (@group ? @@guardfile_structure.last : @@guardfile_structure.first) node = (@group ? @@guardfile_structure.last : @@guardfile_structure.first)

22
lib/guard/group.rb Normal file
View File

@ -0,0 +1,22 @@
module Guard
# A group of Guards.
#
class Group
attr_accessor :name, :options
# Initialize a Group.
#
# @param [String] name the name of the group
# @option options [Boolean] halt_on_fail if a task execution
# should be halted for all Guards in this group if one Guard throws `:task_has_failed`
#
def initialize(name, options = {})
@name = name.to_sym
@options = options
end
end
end

View File

@ -16,10 +16,10 @@ module Guard
# Initialize a Guard. # Initialize a Guard.
# #
# @param [Array<Guard::Watcher>] watchers the Guard file watchers # @param [Array<Guard::Watcher>] watchers the Guard file watchers
# @param [Hash] options the custom Guard options. # @param [Hash] options the custom Guard options
# #
def initialize(watchers = [], options = {}) def initialize(watchers = [], options = {})
@group = options.delete(:group) || :default @group = options[:group] ? options.delete(:group).to_sym : :default
@watchers, @options = watchers, options @watchers, @options = watchers, options
end end
@ -89,4 +89,5 @@ module Guard
end end
end end
end end

View File

@ -37,6 +37,7 @@ module Guard
when 'stop', 'quit', 'exit', 's', 'q', 'e' when 'stop', 'quit', 'exit', 's', 'q', 'e'
::Guard.stop ::Guard.stop
when 'reload', 'r', 'z' when 'reload', 'r', 'z'
::Guard::Dsl.reevaluate_guardfile
::Guard.reload ::Guard.reload
when 'pause', 'p' when 'pause', 'p'
::Guard.pause ::Guard.pause

View File

@ -43,7 +43,6 @@ module Guard
# Initialize the listener. # Initialize the listener.
# #
# @param [String] directory the root directory to listen to # @param [String] directory the root directory to listen to
# @param [Hash] options the listener options
# @option options [Boolean] relativize_paths use only relative paths # @option options [Boolean] relativize_paths use only relative paths
# @option options [Array<String>] ignore_paths the paths to ignore by the listener # @option options [Array<String>] ignore_paths the paths to ignore by the listener
# #
@ -210,7 +209,6 @@ module Guard
# Gets a list of files that are in the modified directories. # Gets a list of files that are in the modified directories.
# #
# @param [Array<String>] dirs the list of directories # @param [Array<String>] dirs the list of directories
# @param [Hash] options the options
# @option options [Symbol] all whether to include all files # @option options [Symbol] all whether to include all files
# #
def potentially_modified_files(dirs, options = {}) def potentially_modified_files(dirs, options = {})

View File

@ -43,7 +43,6 @@ module Guard
# @see .image_path # @see .image_path
# #
# @param [String] the message to show # @param [String] the message to show
# @param [Hash] options the notification options
# @option options [Symbol, String] image the image symbol or path to an image # @option options [Symbol, String] image the image symbol or path to an image
# @option options [String] title the notification title # @option options [String] title the notification title
# #
@ -80,7 +79,7 @@ module Guard
# @param [Symbol, String] the image to user # @param [Symbol, String] the image to user
# @param [Hash] options the growl options # @param [Hash] options the growl options
# #
def self.notify_mac(title, message, image, options) def self.notify_mac(title, message, image, options = {})
require_growl # need for guard-rspec formatter that is called out of guard scope require_growl # need for guard-rspec formatter that is called out of guard scope
default_options = { :title => title, :icon => image_path(image), :name => APPLICATION_NAME } default_options = { :title => title, :icon => image_path(image), :name => APPLICATION_NAME }
@ -104,7 +103,7 @@ module Guard
# @param [Symbol, String] the image to user # @param [Symbol, String] the image to user
# @param [Hash] options the libnotify options # @param [Hash] options the libnotify options
# #
def self.notify_linux(title, message, image, options) def self.notify_linux(title, message, image, options = {})
require_libnotify # need for guard-rspec formatter that is called out of guard scope require_libnotify # need for guard-rspec formatter that is called out of guard scope
default_options = { :body => message, :summary => title, :icon_path => image_path(image), :transient => true } default_options = { :body => message, :summary => title, :icon_path => image_path(image), :transient => true }
Libnotify.show default_options.merge(options) if enabled? Libnotify.show default_options.merge(options) if enabled?
@ -117,7 +116,7 @@ module Guard
# @param [Symbol, String] the image to user # @param [Symbol, String] the image to user
# @param [Hash] options the notifu options # @param [Hash] options the notifu options
# #
def self.notify_windows(title, message, image, options) def self.notify_windows(title, message, image, options = {})
require_rbnotifu # need for guard-rspec formatter that is called out of guard scope require_rbnotifu # need for guard-rspec formatter that is called out of guard scope
default_options = { :message => message, :title => title, :type => image_level(image), :time => 3 } default_options = { :message => message, :title => title, :type => image_level(image), :time => 3 }
Notifu.show default_options.merge(options) if enabled? Notifu.show default_options.merge(options) if enabled?

View File

@ -10,7 +10,6 @@ module Guard
# Show an info message. # Show an info message.
# #
# @param [String] message the message to show # @param [String] message the message to show
# @param [Hash] options the options
# @option options [Boolean] reset whether to clean the output before # @option options [Boolean] reset whether to clean the output before
# #
def info(message, options = { }) def info(message, options = { })
@ -23,7 +22,6 @@ module Guard
# Show a red error message that is prefixed with ERROR. # Show a red error message that is prefixed with ERROR.
# #
# @param [String] message the message to show # @param [String] message the message to show
# @param [Hash] options the options
# @option options [Boolean] reset whether to clean the output before # @option options [Boolean] reset whether to clean the output before
# #
def error(message, options = { }) def error(message, options = { })
@ -36,7 +34,6 @@ module Guard
# Show a red deprecation message that is prefixed with DEPRECATION. # Show a red deprecation message that is prefixed with DEPRECATION.
# #
# @param [String] message the message to show # @param [String] message the message to show
# @param [Hash] options the options
# @option options [Boolean] reset whether to clean the output before # @option options [Boolean] reset whether to clean the output before
# #
def deprecation(message, options = { }) def deprecation(message, options = { })
@ -49,7 +46,6 @@ module Guard
# Show a debug message that is prefixed with DEBUG and a timestamp. # Show a debug message that is prefixed with DEBUG and a timestamp.
# #
# @param [String] message the message to show # @param [String] message the message to show
# @param [Hash] options the options
# @option options [Boolean] reset whether to clean the output before # @option options [Boolean] reset whether to clean the output before
# #
def debug(message, options = { }) def debug(message, options = { })

184
man/guard
View File

@ -17,6 +17,91 @@
. .
.nf .nf
<a href="#NAME">NAME</a>
<a href="#NAME">NAME</a>
<a href="#NAME">NAME</a>
<a href="#NAME">NAME</a>
.
.fi
.
.IP "" 0
.
.P
.
.P
.
.IP "" 4
.
.nf
<li class=\'tl\'>guard</li>
<li class=\'tc\'></li>
<li class=\'tr\'>guard</li>
.
.fi
.
.IP "" 0
.
.P
.
.P
.
.P
\fBguard\fR
.
.P
\fI!DOCTYPE html\fR
.
.P
.
.P
.
.IP "" 4
.
.nf
<a href="#NAME">NAME</a>
<a href="#NAME">NAME</a>
<a href="#NAME">NAME</a>
.
.fi
.
.IP "" 0
.
.P
.
.P
.
.IP "" 4
.
.nf
<li class=\'tl\'>guard</li>
<li class=\'tc\'></li>
<li class=\'tr\'>guard</li>
.
.fi
.
.IP "" 0
.
.P
.
.P
.
.P
\fBguard\fR
.
.P
\fI!DOCTYPE html\fR
.
.P
.
.P
.
.IP "" 4
.
.nf
<a href="#NAME">NAME</a> <a href="#NAME">NAME</a>
<a href="#NAME">NAME</a> <a href="#NAME">NAME</a>
. .
@ -48,7 +133,7 @@
\fBguard\fR \fBguard\fR
. .
.P .P
\fI!DOCTYPE html\fR <p\fI!DOCTYPE html\fR
. .
.P .P
. .
@ -96,6 +181,103 @@
. .
.nf .nf
<li class=\'tl\'></li>
<li class=\'tc\'>September 2011</li>
<li class=\'tr\'>guard</li>
.
.fi
.
.IP "" 0
.
.P
.
.P
.
.P
\fI<<<<<< HEAD\fR
.
.P
<p
.
.IP "" 4
.
.nf
<li class=\'tl\'></li>
<li class=\'tc\'>September 2011</li>
<li class=\'tr\'>guard</li>
.
.fi
.
.IP "" 0
.
.P
.
.P
.
.P
=======
.
.P
.
.IP "" 4
.
.nf
<li class=\'tl\'></li>
<li class=\'tc\'>September 2011</li>
<li class=\'tr\'>guard</li>
.
.fi
.
.IP "" 0
.
.P
.
.P
.
.P
.
.IP "" 4
.
.nf
<li class=\'tl\'></li>
<li class=\'tc\'>September 2011</li>
<li class=\'tr\'>guard</li>
.
.fi
.
.IP "" 0
.
.P
.
.P
.
.P
.
.IP "" 4
.
.nf
<li class=\'tl\'></li>
<li class=\'tc\'>September 2011</li>
<li class=\'tr\'>guard</li>
.
.fi
.
.IP "" 0
.
.P
.
.P
.
.P
.
.IP "" 4
.
.nf
<li class=\'tl\'></li> <li class=\'tl\'></li>
<li class=\'tc\'>September 2011</li> <li class=\'tc\'>September 2011</li>
<li class=\'tr\'>guard</li> <li class=\'tr\'>guard</li>

View File

@ -41,7 +41,7 @@ Tells Guard to watch PATH instead of \fB\./\fR\.
.P .P
\fB\-G\fR, \fB\-\-guardfile\fR \fIFILE\fR Tells Guard to use FILE as its Guardfile instead of \fB\./Guardfile\fR or \fB~/\.Guardfile\fR\. \fB\-G\fR, \fB\-\-guardfile\fR \fIFILE\fR Tells Guard to use FILE as its Guardfile instead of \fB\./Guardfile\fR or \fB~/\.Guardfile\fR\.
. .
.SS "init <a href=\"guard\.html\">GUARD</a>" .SS "init [GUARD]"
If no Guardfile is present in the current directory, creates an empty Guardfile\. If no Guardfile is present in the current directory, creates an empty Guardfile\.
. .
.P .P

View File

@ -112,7 +112,7 @@
<p><code>-G</code>, <code>--guardfile</code> <var>FILE</var> <p><code>-G</code>, <code>--guardfile</code> <var>FILE</var>
Tells Guard to use FILE as its Guardfile instead of <code>./Guardfile</code> or <code>~/.Guardfile</code>.</p> Tells Guard to use FILE as its Guardfile instead of <code>./Guardfile</code> or <code>~/.Guardfile</code>.</p>
<h3 id="init-GUARD">init <a href="guard.html">GUARD</a></h3> <h3 id="init-GUARD-">init [GUARD]</h3>
<p>If no Guardfile is present in the current directory, creates an empty Guardfile.</p> <p>If no Guardfile is present in the current directory, creates an empty Guardfile.</p>

View File

@ -56,6 +56,8 @@
<a href="#NAME">NAME</a> <a href="#NAME">NAME</a>
<a href="#NAME">NAME</a> <a href="#NAME">NAME</a>
<a href="#NAME">NAME</a> <a href="#NAME">NAME</a>
<a href="#NAME">NAME</a>
<a href="#NAME">NAME</a>
</div> </div>
<ol class='man-decor man-head man head'> <ol class='man-decor man-head man head'>
@ -71,10 +73,10 @@
<p><var>!DOCTYPE html</var> <p><var>!DOCTYPE html</var>
<html> <html>
<head> <head>
<meta value="text/html;charset=utf8" http-equiv="content-type" /> <meta http-equiv="content-type" value="text/html;charset=utf8" />
<meta name="generator" value="Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)" /> <meta name="generator" value="Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)" />
<title>guard</title> <title>guard</title>
<style media="all" type="text/css"> <style type="text/css" media="all">
/<em> style: man </em>/ /<em> style: man </em>/
body#manpage {margin:0} body#manpage {margin:0}
.mp {max-width:100ex;padding:0 9ex 1ex 4ex} .mp {max-width:100ex;padding:0 9ex 1ex 4ex}
@ -129,6 +131,8 @@
<pre><code>&lt;a href="#NAME"&gt;NAME&lt;/a&gt; <pre><code>&lt;a href="#NAME"&gt;NAME&lt;/a&gt;
&lt;a href="#NAME"&gt;NAME&lt;/a&gt; &lt;a href="#NAME"&gt;NAME&lt;/a&gt;
&lt;a href="#NAME"&gt;NAME&lt;/a&gt;
&lt;a href="#NAME"&gt;NAME&lt;/a&gt;
</code></pre> </code></pre>
<p> </p> <p> </p>
@ -151,6 +155,231 @@
<p><var>!DOCTYPE html</var> <p><var>!DOCTYPE html</var>
<html> <html>
<head>
<meta http-equiv="content-type" value="text/html;charset=utf8" />
<meta name="generator" value="Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)" />
<title>guard</title>
<style type="text/css" media="all">
/<em> style: man </em>/
body#manpage {margin:0}
.mp {max-width:100ex;padding:0 9ex 1ex 4ex}
.mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}
.mp h2 {margin:10px 0 0 0}
.mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}
.mp h3 {margin:0 0 0 4ex}
.mp dt {margin:0;clear:left}
.mp dt.flush {float:left;width:8ex}
.mp dd {margin:0 0 0 9ex}
.mp h1,.mp h2,.mp h3,.mp h4 {clear:left}
.mp pre {margin-bottom:20px}
.mp pre+h2,.mp pre+h3 {margin-top:22px}
.mp h2+pre,.mp h3+pre {margin-top:5px}
.mp img {display:block;margin:auto}
.mp h1.man-title {display:none}
.mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143}
.mp h2 {font-size:16px;line-height:1.25}
.mp h1 {font-size:20px;line-height:2}
.mp {text-align:justify;background:#fff}
.mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}
.mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}
.mp u {text-decoration:underline}
.mp code,.mp strong,.mp b {font-weight:bold;color:#131211}
.mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}
.mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff}
.mp b.man-ref {font-weight:normal;color:#434241}
.mp pre {padding:0 4ex}
.mp pre code {font-weight:normal;color:#434241}
.mp h2+pre,h3+pre {padding-left:0}
ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px}
ol.man-decor {width:100%}
ol.man-decor li.tl {text-align:left}
ol.man-decor li.tc {text-align:center;letter-spacing:4px}
ol.man-decor li.tr {text-align:right;float:right}
</style>
</head></html></p>
<!--
The following styles are deprecated and will be removed at some point:
div#man, div#man ol.man, div#man ol.head, div#man ol.man.
The .man-page, .man-decor, .man-head, .man-foot, .man-title, and
.man-navigation should be used instead.
-->
<p><body id="manpage">
<div class="mp" id="man" /></body></p>
<p> <div class="man-navigation" style="display:none" /></p>
<pre><code>&lt;a href="#NAME"&gt;NAME&lt;/a&gt;
&lt;a href="#NAME"&gt;NAME&lt;/a&gt;
&lt;a href="#NAME"&gt;NAME&lt;/a&gt;
</code></pre>
<p> </p>
<p> <ol class="man-decor man-head man head" /></p>
<pre><code>&lt;li class='tl'&gt;guard&lt;/li&gt;
&lt;li class='tc'&gt;&lt;/li&gt;
&lt;li class='tr'&gt;guard&lt;/li&gt;
</code></pre>
<p> </p>
<p> <h2 id="NAME">NAME</h2></p>
<p class="man-name">
<code>guard</code>
</p>
<p><var>!DOCTYPE html</var>
<html>
<head>
<meta http-equiv="content-type" value="text/html;charset=utf8" />
<meta name="generator" value="Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)" />
<title>guard</title>
<style type="text/css" media="all">
/<em> style: man </em>/
body#manpage {margin:0}
.mp {max-width:100ex;padding:0 9ex 1ex 4ex}
.mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}
.mp h2 {margin:10px 0 0 0}
.mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}
.mp h3 {margin:0 0 0 4ex}
.mp dt {margin:0;clear:left}
.mp dt.flush {float:left;width:8ex}
.mp dd {margin:0 0 0 9ex}
.mp h1,.mp h2,.mp h3,.mp h4 {clear:left}
.mp pre {margin-bottom:20px}
.mp pre+h2,.mp pre+h3 {margin-top:22px}
.mp h2+pre,.mp h3+pre {margin-top:5px}
.mp img {display:block;margin:auto}
.mp h1.man-title {display:none}
.mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143}
.mp h2 {font-size:16px;line-height:1.25}
.mp h1 {font-size:20px;line-height:2}
.mp {text-align:justify;background:#fff}
.mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}
.mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}
.mp u {text-decoration:underline}
.mp code,.mp strong,.mp b {font-weight:bold;color:#131211}
.mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}
.mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff}
.mp b.man-ref {font-weight:normal;color:#434241}
.mp pre {padding:0 4ex}
.mp pre code {font-weight:normal;color:#434241}
.mp h2+pre,h3+pre {padding-left:0}
ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px}
ol.man-decor {width:100%}
ol.man-decor li.tl {text-align:left}
ol.man-decor li.tc {text-align:center;letter-spacing:4px}
ol.man-decor li.tr {text-align:right;float:right}
</style>
</head></html></p>
<!--
The following styles are deprecated and will be removed at some point:
div#man, div#man ol.man, div#man ol.head, div#man ol.man.
The .man-page, .man-decor, .man-head, .man-foot, .man-title, and
.man-navigation should be used instead.
-->
<p><body id="manpage">
<div class="mp" id="man" /></body></p>
<p> <div class="man-navigation" style="display:none" /></p>
<pre><code>&lt;a href="#NAME"&gt;NAME&lt;/a&gt;
&lt;a href="#NAME"&gt;NAME&lt;/a&gt;
</code></pre>
<p> </p>
<p> <ol class="man-decor man-head man head" /></p>
<pre><code>&lt;li class='tl'&gt;guard&lt;/li&gt;
&lt;li class='tc'&gt;&lt;/li&gt;
&lt;li class='tr'&gt;guard&lt;/li&gt;
</code></pre>
<p> </p>
<p> <h2 id="NAME">NAME</h2></p>
<p class="man-name">
<code>guard</code>
</p>
<p>&lt;p<var>!DOCTYPE html</var>
<html>
<head> <head>
<meta value="text/html;charset=utf8" http-equiv="content-type" /> <meta value="text/html;charset=utf8" http-equiv="content-type" />
<meta name="generator" value="Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)" /> <meta name="generator" value="Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)" />
@ -260,6 +489,11 @@
<blockquote><blockquote><blockquote><blockquote><blockquote><blockquote><blockquote><p>master</p></blockquote></blockquote></blockquote></blockquote></blockquote></blockquote></blockquote>
<p>.\" generated with Ronn/v0.7.3 <p>.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
@ -375,6 +609,146 @@ https://github.com/guard/guard</p>
<p>
</p>
<p><var>&lt;&lt;&lt;&lt;&lt;&lt; HEAD</var></p>
<p>&lt;p <ol class="man-decor man-foot man foot" /></p>
<pre><code>&lt;li class='tl'&gt;&lt;/li&gt;
&lt;li class='tc'&gt;September 2011&lt;/li&gt;
&lt;li class='tr'&gt;guard&lt;/li&gt;
</code></pre>
<p> </p>
<p>
</p>
<p>=======</p>
<blockquote><blockquote><blockquote><blockquote><blockquote><blockquote><blockquote><p>master</p></blockquote></blockquote></blockquote></blockquote></blockquote></blockquote></blockquote>
<p> <ol class="man-decor man-foot man foot" /></p>
<pre><code>&lt;li class='tl'&gt;&lt;/li&gt;
&lt;li class='tc'&gt;September 2011&lt;/li&gt;
&lt;li class='tr'&gt;guard&lt;/li&gt;
</code></pre>
<p> </p>
<p>
</p>
<p> <ol class="man-decor man-foot man foot" /></p>
<pre><code>&lt;li class='tl'&gt;&lt;/li&gt;
&lt;li class='tc'&gt;September 2011&lt;/li&gt;
&lt;li class='tr'&gt;guard&lt;/li&gt;
</code></pre>
<p> </p>
<p>
</p>
<p> <ol class="man-decor man-foot man foot" /></p>
<pre><code>&lt;li class='tl'&gt;&lt;/li&gt;
&lt;li class='tc'&gt;September 2011&lt;/li&gt;
&lt;li class='tr'&gt;guard&lt;/li&gt;
</code></pre>
<p> </p>
<p>
</p>
<p> <ol class="man-decor man-foot man foot" /></p>
<pre><code>&lt;li class='tl'&gt;&lt;/li&gt;
&lt;li class='tc'&gt;September 2011&lt;/li&gt;
&lt;li class='tr'&gt;guard&lt;/li&gt;
</code></pre>
<p> </p>
<p> <p>
</p> </p>

View File

@ -6,8 +6,6 @@ describe Guard::DslDescriber do
user_config_path = File.expand_path(File.join('~', '.guard.rb')) user_config_path = File.expand_path(File.join('~', '.guard.rb'))
File.stub(:exist?).with(user_config_path) { false } File.stub(:exist?).with(user_config_path) { false }
end end
subject { described_class }
it 'should evaluate a Guardfile and create the right structure' do it 'should evaluate a Guardfile and create the right structure' do
mixed_guardfile_string = <<-GUARD mixed_guardfile_string = <<-GUARD
@ -28,13 +26,13 @@ group "b" do
end end
GUARD GUARD
subject.evaluate_guardfile(:guardfile_contents => mixed_guardfile_string) described_class.evaluate_guardfile(:guardfile_contents => mixed_guardfile_string)
subject.guardfile_structure.should == [ described_class.guardfile_structure.should == [
{ :guards => [ { :name => 'test', :options => { :a => :b } } ] }, { :guards => [ { :name => 'test', :options => { :a => :b } } ] },
{ :group => :a, :guards => [ { :name => 'test', :options => {} } ] }, { :group => :a, :guards => [ { :name => 'test', :options => {} } ] },
{ :group => :b, :guards => [ { :name => 'another', :options => {} } ] } { :group => :b, :guards => [ { :name => 'another', :options => {} } ] }
] ]
end end
end end

View File

@ -2,13 +2,14 @@ require 'spec_helper'
require 'guard/guard' require 'guard/guard'
describe Guard::Dsl do describe Guard::Dsl do
subject { described_class }
class Guard::Dummy < Guard::Guard; end class Guard::Dummy < Guard::Guard; end
before(:each) do before(:each) do
@local_guardfile_path = File.join(Dir.pwd, 'Guardfile') @local_guardfile_path = File.join(Dir.pwd, 'Guardfile')
@home_guardfile_path = File.expand_path(File.join("~", ".Guardfile")) @home_guardfile_path = File.expand_path(File.join("~", ".Guardfile"))
@user_config_path = File.expand_path(File.join("~", ".guard.rb")) @user_config_path = File.expand_path(File.join("~", ".guard.rb"))
::Guard.setup
::Guard.stub!(:options).and_return(:debug => true) ::Guard.stub!(:options).and_return(:debug => true)
::Guard.stub!(:guards).and_return([mock('Guard')]) ::Guard.stub!(:guards).and_return([mock('Guard')])
end end
@ -23,24 +24,24 @@ describe Guard::Dsl do
it "should use a string for initializing" do it "should use a string for initializing" do
Guard::UI.should_not_receive(:error) Guard::UI.should_not_receive(:error)
lambda { subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string) }.should_not raise_error lambda { described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string) }.should_not raise_error
subject.guardfile_contents.should == valid_guardfile_string described_class.guardfile_contents.should == valid_guardfile_string
end end
it "should use a given file over the default loc" do it "should use a given file over the default loc" do
fake_guardfile('/abc/Guardfile', "guard :foo") fake_guardfile('/abc/Guardfile', "guard :foo")
Guard::UI.should_not_receive(:error) Guard::UI.should_not_receive(:error)
lambda { subject.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error lambda { described_class.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error
subject.guardfile_contents.should == "guard :foo" described_class.guardfile_contents.should == "guard :foo"
end end
it "should use a default file if no other options are given" do it "should use a default file if no other options are given" do
fake_guardfile(@local_guardfile_path, "guard :bar") fake_guardfile(@local_guardfile_path, "guard :bar")
Guard::UI.should_not_receive(:error) Guard::UI.should_not_receive(:error)
lambda { subject.evaluate_guardfile }.should_not raise_error lambda { described_class.evaluate_guardfile }.should_not raise_error
subject.guardfile_contents.should == "guard :bar" described_class.guardfile_contents.should == "guard :bar"
end end
it "should use a string over any other method" do it "should use a string over any other method" do
@ -48,8 +49,8 @@ describe Guard::Dsl do
fake_guardfile(@local_guardfile_path, "guard :bar") fake_guardfile(@local_guardfile_path, "guard :bar")
Guard::UI.should_not_receive(:error) Guard::UI.should_not_receive(:error)
lambda { subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string) }.should_not raise_error lambda { described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string) }.should_not raise_error
subject.guardfile_contents.should == valid_guardfile_string described_class.guardfile_contents.should == valid_guardfile_string
end end
it "should use the given Guardfile over default Guardfile" do it "should use the given Guardfile over default Guardfile" do
@ -57,31 +58,31 @@ describe Guard::Dsl do
fake_guardfile(@local_guardfile_path, "guard :bar") fake_guardfile(@local_guardfile_path, "guard :bar")
Guard::UI.should_not_receive(:error) Guard::UI.should_not_receive(:error)
lambda { subject.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error lambda { described_class.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error
subject.guardfile_contents.should == "guard :foo" described_class.guardfile_contents.should == "guard :foo"
end end
it 'should append the user config file if present' do it 'should append the user config file if present' do
fake_guardfile('/abc/Guardfile', "guard :foo") fake_guardfile('/abc/Guardfile', "guard :foo")
fake_guardfile(@user_config_path, "guard :bar") fake_guardfile(@user_config_path, "guard :bar")
Guard::UI.should_not_receive(:error) Guard::UI.should_not_receive(:error)
lambda { subject.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error lambda { described_class.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error
subject.guardfile_contents_with_user_config.should == "guard :foo\nguard :bar" described_class.guardfile_contents_with_user_config.should == "guard :foo\nguard :bar"
end end
end end
it "displays an error message when no Guardfile is found" do it "displays an error message when no Guardfile is found" do
subject.stub(:guardfile_default_path).and_return("no_guardfile_here") described_class.stub(:guardfile_default_path).and_return("no_guardfile_here")
Guard::UI.should_receive(:error).with("No Guardfile found, please create one with `guard init`.") Guard::UI.should_receive(:error).with("No Guardfile found, please create one with `guard init`.")
lambda { subject.evaluate_guardfile }.should raise_error lambda { described_class.evaluate_guardfile }.should raise_error
end end
it "displays an error message when no guard are defined in Guardfile" do it "displays an error message when no guard are defined in Guardfile" do
::Guard::Dsl.stub!(:instance_eval_guardfile) ::Guard::Dsl.stub!(:instance_eval_guardfile)
::Guard.stub!(:guards).and_return([]) ::Guard.stub!(:guards).and_return([])
Guard::UI.should_receive(:error) Guard::UI.should_receive(:error)
subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string) described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string)
end end
describe "correctly reads data from its valid data source" do describe "correctly reads data from its valid data source" do
@ -89,22 +90,22 @@ describe Guard::Dsl do
disable_user_config disable_user_config
it "reads correctly from a string" do it "reads correctly from a string" do
lambda { subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string) }.should_not raise_error lambda { described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string) }.should_not raise_error
subject.guardfile_contents.should == valid_guardfile_string described_class.guardfile_contents.should == valid_guardfile_string
end end
it "reads correctly from a Guardfile" do it "reads correctly from a Guardfile" do
fake_guardfile('/abc/Guardfile', "guard :foo" ) fake_guardfile('/abc/Guardfile', "guard :foo" )
lambda { subject.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error lambda { described_class.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error
subject.guardfile_contents.should == "guard :foo" described_class.guardfile_contents.should == "guard :foo"
end end
it "reads correctly from a Guardfile" do it "reads correctly from a Guardfile" do
fake_guardfile(File.join(Dir.pwd, 'Guardfile'), valid_guardfile_string) fake_guardfile(File.join(Dir.pwd, 'Guardfile'), valid_guardfile_string)
lambda { subject.evaluate_guardfile }.should_not raise_error lambda { described_class.evaluate_guardfile }.should_not raise_error
subject.guardfile_contents.should == valid_guardfile_string described_class.guardfile_contents.should == valid_guardfile_string
end end
end end
@ -116,14 +117,14 @@ describe Guard::Dsl do
File.stub!(:read).with('/def/Guardfile') { raise Errno::EACCES.new("permission error") } File.stub!(:read).with('/def/Guardfile') { raise Errno::EACCES.new("permission error") }
Guard::UI.should_receive(:error).with(/^Error reading file/) Guard::UI.should_receive(:error).with(/^Error reading file/)
lambda { subject.evaluate_guardfile(:guardfile => '/def/Guardfile') }.should raise_error lambda { described_class.evaluate_guardfile(:guardfile => '/def/Guardfile') }.should raise_error
end end
it "raises error when given Guardfile doesn't exist" do it "raises error when given Guardfile doesn't exist" do
File.stub!(:exist?).with('/def/Guardfile') { false } File.stub!(:exist?).with('/def/Guardfile') { false }
Guard::UI.should_receive(:error).with(/No Guardfile exists at/) Guard::UI.should_receive(:error).with(/No Guardfile exists at/)
lambda { subject.evaluate_guardfile(:guardfile => '/def/Guardfile') }.should raise_error lambda { described_class.evaluate_guardfile(:guardfile => '/def/Guardfile') }.should raise_error
end end
it "raises error when resorting to use default, finds no default" do it "raises error when resorting to use default, finds no default" do
@ -131,24 +132,24 @@ describe Guard::Dsl do
File.stub!(:exist?).with(@home_guardfile_path) { false } File.stub!(:exist?).with(@home_guardfile_path) { false }
Guard::UI.should_receive(:error).with("No Guardfile found, please create one with `guard init`.") Guard::UI.should_receive(:error).with("No Guardfile found, please create one with `guard init`.")
lambda { subject.evaluate_guardfile }.should raise_error lambda { described_class.evaluate_guardfile }.should raise_error
end end
it "raises error when guardfile_content ends up empty or nil" do it "raises error when guardfile_content ends up empty or nil" do
Guard::UI.should_receive(:error).with(/The command file/) Guard::UI.should_receive(:error).with(/The command file/)
lambda { subject.evaluate_guardfile(:guardfile_contents => "") }.should raise_error lambda { described_class.evaluate_guardfile(:guardfile_contents => "") }.should raise_error
end end
it "doesn't raise error when guardfile_content is nil (skipped)" do it "doesn't raise error when guardfile_content is nil (skipped)" do
Guard::UI.should_not_receive(:error) Guard::UI.should_not_receive(:error)
lambda { subject.evaluate_guardfile(:guardfile_contents => nil) }.should_not raise_error lambda { described_class.evaluate_guardfile(:guardfile_contents => nil) }.should_not raise_error
end end
end end
it "displays an error message when Guardfile is not valid" do it "displays an error message when Guardfile is not valid" do
Guard::UI.should_receive(:error).with(/Invalid Guardfile, original error is:/) Guard::UI.should_receive(:error).with(/Invalid Guardfile, original error is:/)
lambda { subject.evaluate_guardfile(:guardfile_contents => invalid_guardfile_string ) }.should raise_error lambda { described_class.evaluate_guardfile(:guardfile_contents => invalid_guardfile_string ) }.should raise_error
end end
describe ".reevaluate_guardfile" do describe ".reevaluate_guardfile" do
@ -156,10 +157,10 @@ describe Guard::Dsl do
it "resets already definded guards before calling evaluate_guardfile" do it "resets already definded guards before calling evaluate_guardfile" do
Guard::Notifier.turn_off Guard::Notifier.turn_off
subject.evaluate_guardfile(:guardfile_contents => invalid_guardfile_string) described_class.evaluate_guardfile(:guardfile_contents => invalid_guardfile_string)
::Guard.guards.should_not be_empty ::Guard.guards.should_not be_empty
::Guard::Dsl.should_receive(:evaluate_guardfile) ::Guard::Dsl.should_receive(:evaluate_guardfile)
subject.reevaluate_guardfile described_class.reevaluate_guardfile
::Guard.guards.should be_empty ::Guard.guards.should be_empty
end end
end end
@ -172,14 +173,14 @@ describe Guard::Dsl do
context "when there is a local Guardfile" do context "when there is a local Guardfile" do
it "returns the path to the local Guardfile" do it "returns the path to the local Guardfile" do
File.stub(:exist?).with(local_path).and_return(true) File.stub(:exist?).with(local_path).and_return(true)
subject.guardfile_default_path.should == local_path described_class.guardfile_default_path.should == local_path
end end
end end
context "when there is a Guardfile in the user's home directory" do context "when there is a Guardfile in the user's home directory" do
it "returns the path to the user Guardfile" do it "returns the path to the user Guardfile" do
File.stub(:exist?).with(user_path).and_return(true) File.stub(:exist?).with(user_path).and_return(true)
subject.guardfile_default_path.should == user_path described_class.guardfile_default_path.should == user_path
end end
end end
@ -187,34 +188,34 @@ describe Guard::Dsl do
it "returns the path to the local Guardfile" do it "returns the path to the local Guardfile" do
File.stub(:exist?).with(local_path).and_return(true) File.stub(:exist?).with(local_path).and_return(true)
File.stub(:exist?).with(user_path).and_return(true) File.stub(:exist?).with(user_path).and_return(true)
subject.guardfile_default_path.should == local_path described_class.guardfile_default_path.should == local_path
end end
end end
end end
describe ".guardfile_include?" do describe ".guardfile_include?" do
it "detects a guard specified by a string with double quotes" do it "detects a guard specified by a string with double quotes" do
subject.stub(:guardfile_contents => 'guard "test" {watch("c")}') described_class.stub(:guardfile_contents => 'guard "test" {watch("c")}')
subject.guardfile_include?('test').should be_true described_class.guardfile_include?('test').should be_true
end end
it "detects a guard specified by a string with single quote" do it "detects a guard specified by a string with single quote" do
subject.stub(:guardfile_contents => 'guard \'test\' {watch("c")}') described_class.stub(:guardfile_contents => 'guard \'test\' {watch("c")}')
subject.guardfile_include?('test').should be_true described_class.guardfile_include?('test').should be_true
end end
it "detects a guard specified by a symbol" do it "detects a guard specified by a symbol" do
subject.stub(:guardfile_contents => 'guard :test {watch("c")}') described_class.stub(:guardfile_contents => 'guard :test {watch("c")}')
subject.guardfile_include?('test').should be_true described_class.guardfile_include?('test').should be_true
end end
it "detects a guard wrapped in parentheses" do it "detects a guard wrapped in parentheses" do
subject.stub(:guardfile_contents => 'guard(:test) {watch("c")}') described_class.stub(:guardfile_contents => 'guard(:test) {watch("c")}')
subject.guardfile_include?('test').should be_true described_class.guardfile_include?('test').should be_true
end end
end end
@ -225,7 +226,7 @@ describe Guard::Dsl do
::Guard.stub!(:listener).and_return(mock('Listener')) ::Guard.stub!(:listener).and_return(mock('Listener'))
::Guard.listener.should_receive(:ignore_paths).and_return(ignore_paths = ['faz']) ::Guard.listener.should_receive(:ignore_paths).and_return(ignore_paths = ['faz'])
subject.evaluate_guardfile(:guardfile_contents => "ignore_paths 'foo', 'bar'") described_class.evaluate_guardfile(:guardfile_contents => "ignore_paths 'foo', 'bar'")
ignore_paths.should == ['faz', 'foo', 'bar'] ignore_paths.should == ['faz', 'foo', 'bar']
end end
end end
@ -234,43 +235,43 @@ describe Guard::Dsl do
disable_user_config disable_user_config
it "evaluates only the specified string group" do it "evaluates only the specified string group" do
::Guard.should_receive(:add_guard).with(:pow, [], [], { :group => :default }) ::Guard.should_receive(:add_guard).with('pow', [], [], { :group => :default })
::Guard.should_receive(:add_guard).with(:test, [], [], { :group => :w }) ::Guard.should_receive(:add_guard).with('test', [], [], { :group => :w })
subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string, :group => ['w']) described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string, :group => [:w])
end end
it "evaluates only the specified symbol group" do it "evaluates only the specified symbol group" do
::Guard.should_receive(:add_guard).with(:pow, [], [], { :group => :default }) ::Guard.should_receive(:add_guard).with('pow', [], [], { :group => :default })
::Guard.should_receive(:add_guard).with(:test, [], [], { :group => :w }) ::Guard.should_receive(:add_guard).with('test', [], [], { :group => :w })
subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string, :group => [:w]) described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string, :group => [:w])
end end
it "evaluates only the specified groups" do it "evaluates only the specified groups (with their options)" do
::Guard.should_receive(:add_guard).with(:pow, [], [], { :group => :default }) ::Guard.should_receive(:add_guard).with('pow', [], [], { :group => :default })
::Guard.should_receive(:add_guard).with(:rspec, [], [], { :group => :x }) ::Guard.should_receive(:add_guard).with('rspec', [], [], { :group => :x })
::Guard.should_receive(:add_guard).with(:ronn, [], [], { :group => :x }) ::Guard.should_receive(:add_guard).with('ronn', [], [], { :group => :x })
::Guard.should_receive(:add_guard).with(:less, [], [], { :group => :y }) ::Guard.should_receive(:add_guard).with('less', [], [], { :group => :y })
subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string, :group => [:x, :y]) described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string, :group => [:x, :y])
end end
it "evaluates always guard outside any group (even when a group is given)" do it "evaluates always guard outside any group (even when a group is given)" do
::Guard.should_receive(:add_guard).with(:pow, [], [], { :group => :default }) ::Guard.should_receive(:add_guard).with('pow', [], [], { :group => :default })
::Guard.should_receive(:add_guard).with(:test, [], [], { :group => :w }) ::Guard.should_receive(:add_guard).with('test', [], [], { :group => :w })
subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string, :group => [:w]) described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string, :group => [:w])
end end
it "evaluates all groups when no group option is specified" do it "evaluates all groups when no group option is specified (with their options)" do
::Guard.should_receive(:add_guard).with(:pow, [], [], { :group => :default }) ::Guard.should_receive(:add_guard).with('pow', [], [], { :group => :default })
::Guard.should_receive(:add_guard).with(:test, [], [], { :group => :w }) ::Guard.should_receive(:add_guard).with('test', [], [], { :group => :w })
::Guard.should_receive(:add_guard).with(:rspec, [], [], { :group => :x }) ::Guard.should_receive(:add_guard).with('rspec', [], [], { :group => :x })
::Guard.should_receive(:add_guard).with(:ronn, [], [], { :group => :x }) ::Guard.should_receive(:add_guard).with('ronn', [], [], { :group => :x })
::Guard.should_receive(:add_guard).with(:less, [], [], { :group => :y }) ::Guard.should_receive(:add_guard).with('less', [], [], { :group => :y })
subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string) described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string)
end end
end end
@ -278,33 +279,33 @@ describe Guard::Dsl do
disable_user_config disable_user_config
it "loads a guard specified as a quoted string from the DSL" do it "loads a guard specified as a quoted string from the DSL" do
::Guard.should_receive(:add_guard).with(:test, [], [], { :group => :default }) ::Guard.should_receive(:add_guard).with('test', [], [], { :group => :default })
subject.evaluate_guardfile(:guardfile_contents => "guard 'test'") described_class.evaluate_guardfile(:guardfile_contents => "guard 'test'")
end end
it "loads a guard specified as a double quoted string from the DSL" do it "loads a guard specified as a double quoted string from the DSL" do
::Guard.should_receive(:add_guard).with(:test, [], [], { :group => :default }) ::Guard.should_receive(:add_guard).with('test', [], [], { :group => :default })
subject.evaluate_guardfile(:guardfile_contents => 'guard "test"') described_class.evaluate_guardfile(:guardfile_contents => 'guard "test"')
end end
it "loads a guard specified as a symbol from the DSL" do it "loads a guard specified as a symbol from the DSL" do
::Guard.should_receive(:add_guard).with(:test, [], [], { :group => :default }) ::Guard.should_receive(:add_guard).with('test', [], [], { :group => :default })
subject.evaluate_guardfile(:guardfile_contents => "guard :test") described_class.evaluate_guardfile(:guardfile_contents => "guard :test")
end end
it "loads a guard specified as a symbol and called with parens from the DSL" do it "loads a guard specified as a symbol and called with parens from the DSL" do
::Guard.should_receive(:add_guard).with(:test, [], [], { :group => :default }) ::Guard.should_receive(:add_guard).with('test', [], [], { :group => :default })
subject.evaluate_guardfile(:guardfile_contents => "guard(:test)") described_class.evaluate_guardfile(:guardfile_contents => "guard(:test)")
end end
it "receives options when specified, from normal arg" do it "receives options when specified, from normal arg" do
::Guard.should_receive(:add_guard).with(:test, [], [], { :opt_a => 1, :opt_b => 'fancy', :group => :default }) ::Guard.should_receive(:add_guard).with('test', [], [], { :opt_a => 1, :opt_b => 'fancy', :group => :default })
subject.evaluate_guardfile(:guardfile_contents => "guard 'test', :opt_a => 1, :opt_b => 'fancy'") described_class.evaluate_guardfile(:guardfile_contents => "guard 'test', :opt_a => 1, :opt_b => 'fancy'")
end end
end end
@ -312,14 +313,14 @@ describe Guard::Dsl do
disable_user_config disable_user_config
it "should receive watchers when specified" do it "should receive watchers when specified" do
::Guard.should_receive(:add_guard).with(:dummy, anything, anything, { :group => :default }) do |name, watchers, callbacks, options| ::Guard.should_receive(:add_guard).with('dummy', anything, anything, { :group => :default }) do |name, watchers, callbacks, options|
watchers.size.should == 2 watchers.size.should == 2
watchers[0].pattern.should == 'a' watchers[0].pattern.should == 'a'
watchers[0].action.call.should == proc { 'b' }.call watchers[0].action.call.should == proc { 'b' }.call
watchers[1].pattern.should == 'c' watchers[1].pattern.should == 'c'
watchers[1].action.should == nil watchers[1].action.should == nil
end end
subject.evaluate_guardfile(:guardfile_contents => " described_class.evaluate_guardfile(:guardfile_contents => "
guard :dummy do guard :dummy do
watch('a') { 'b' } watch('a') { 'b' }
watch('c') watch('c')
@ -335,14 +336,14 @@ describe Guard::Dsl do
end end
end end
::Guard.should_receive(:add_guard).with(:dummy, anything, anything, { :group => :default }) do |name, watchers, callbacks, options| ::Guard.should_receive(:add_guard).with('dummy', anything, anything, { :group => :default }) do |name, watchers, callbacks, options|
callbacks.should have(2).items callbacks.should have(2).items
callbacks[0][:events].should == :start_end callbacks[0][:events].should == :start_end
callbacks[0][:listener].call(Guard::Dummy, :start_end, 'foo').should == "Guard::Dummy executed 'start_end' hook with foo!" callbacks[0][:listener].call(Guard::Dummy, :start_end, 'foo').should == "Guard::Dummy executed 'start_end' hook with foo!"
callbacks[1][:events].should == [:start_begin, :run_all_begin] callbacks[1][:events].should == [:start_begin, :run_all_begin]
callbacks[1][:listener].should == MyCustomCallback callbacks[1][:listener].should == MyCustomCallback
end end
subject.evaluate_guardfile(:guardfile_contents => ' described_class.evaluate_guardfile(:guardfile_contents => '
guard :dummy do guard :dummy do
callback(:start_end) { |guard_class, event, args| "#{guard_class} executed \'#{event}\' hook with #{args}!" } callback(:start_end) { |guard_class, event, args| "#{guard_class} executed \'#{event}\' hook with #{args}!" }
callback(MyCustomCallback, [:start_begin, :run_all_begin]) callback(MyCustomCallback, [:start_begin, :run_all_begin])
@ -361,17 +362,17 @@ private
" "
guard :pow guard :pow
group 'w' do group :w do
guard 'test' guard :test
end end
group :x do group :x, :halt_on_fail => true do
guard 'rspec' guard :rspec
guard :ronn guard :ronn
end end
group 'y' do group :y do
guard 'less' guard :less
end end
" "
end end

19
spec/guard/group_spec.rb Normal file
View File

@ -0,0 +1,19 @@
require 'spec_helper'
describe Guard::Group do
describe ".initialize" do
it "accepts a name as a string and provides an accessor for it (returning a symbol)" do
described_class.new('foo').name.should eql :foo
end
it "accepts a name as a symbol and provides an accessor for it (returning a symbol)" do
described_class.new(:foo).name.should eql :foo
end
it "accepts options and provides an accessor for it" do
described_class.new('foo', :halt_on_fail => true).options.should == { :halt_on_fail => true }
end
end
end

View File

@ -2,48 +2,47 @@ require 'spec_helper'
require 'guard/guard' require 'guard/guard'
describe Guard::Hook do describe Guard::Hook do
subject { Guard::Hook }
class Guard::Dummy < Guard::Guard; end class Guard::Dummy < Guard::Guard; end
let(:guard_class) { ::Guard::Dummy } let(:guard_class) { ::Guard::Dummy }
let(:listener) { double('listener').as_null_object } let(:listener) { double('listener').as_null_object }
after { subject.reset_callbacks! } after { described_class.reset_callbacks! }
context "--module methods--" do describe "--module methods--" do
before { subject.add_callback(listener, guard_class, :start_begin) } before { described_class.add_callback(listener, guard_class, :start_begin) }
describe ".add_callback" do describe ".add_callback" do
it "can add a single callback" do it "can add a single callback" do
subject.has_callback?(listener, guard_class, :start_begin).should be_true described_class.has_callback?(listener, guard_class, :start_begin).should be_true
end end
it "can add multiple callbacks" do it "can add multiple callbacks" do
subject.add_callback(listener, guard_class, [:event1, :event2]) described_class.add_callback(listener, guard_class, [:event1, :event2])
subject.has_callback?(listener, guard_class, :event1).should be_true described_class.has_callback?(listener, guard_class, :event1).should be_true
subject.has_callback?(listener, guard_class, :event2).should be_true described_class.has_callback?(listener, guard_class, :event2).should be_true
end end
end end
describe ".notify" do describe ".notify" do
it "sends :call to the given Guard class's callbacks" do it "sends :call to the given Guard class's callbacks" do
listener.should_receive(:call).with(guard_class, :start_begin, "args") listener.should_receive(:call).with(guard_class, :start_begin, "args")
subject.notify(guard_class, :start_begin, "args") described_class.notify(guard_class, :start_begin, "args")
end end
it "runs only the given callbacks" do it "runs only the given callbacks" do
listener2 = double('listener2') listener2 = double('listener2')
subject.add_callback(listener2, guard_class, :start_end) described_class.add_callback(listener2, guard_class, :start_end)
listener2.should_not_receive(:call).with(guard_class, :start_end) listener2.should_not_receive(:call).with(guard_class, :start_end)
subject.notify(guard_class, :start_begin) described_class.notify(guard_class, :start_begin)
end end
it "runs callbacks only for the guard given" do it "runs callbacks only for the guard given" do
guard2_class = double('Guard::Dummy2').class guard2_class = double('Guard::Dummy2').class
subject.add_callback(listener, guard2_class, :start_begin) described_class.add_callback(listener, guard2_class, :start_begin)
listener.should_not_receive(:call).with(guard2_class, :start_begin) listener.should_not_receive(:call).with(guard2_class, :start_begin)
subject.notify(guard_class, :start_begin) described_class.notify(guard_class, :start_begin)
end end
end end
end end

View File

@ -1,7 +1,6 @@
require 'spec_helper' require 'spec_helper'
describe Guard::Listener do describe Guard::Listener do
subject { Guard::Listener }
describe ".select_and_init" do describe ".select_and_init" do
before(:each) { @target_os = RbConfig::CONFIG['target_os'] } before(:each) { @target_os = RbConfig::CONFIG['target_os'] }
@ -11,30 +10,30 @@ describe Guard::Listener do
RbConfig::CONFIG['target_os'] = 'darwin10.4.0' RbConfig::CONFIG['target_os'] = 'darwin10.4.0'
Guard::Darwin.stub(:usable?).and_return(true) Guard::Darwin.stub(:usable?).and_return(true)
Guard::Darwin.should_receive(:new) Guard::Darwin.should_receive(:new)
subject.select_and_init described_class.select_and_init
end end
it "uses the Windows listener on Windows" do it "uses the Windows listener on Windows" do
RbConfig::CONFIG['target_os'] = 'mingw' RbConfig::CONFIG['target_os'] = 'mingw'
Guard::Windows.stub(:usable?).and_return(true) Guard::Windows.stub(:usable?).and_return(true)
Guard::Windows.should_receive(:new) Guard::Windows.should_receive(:new)
subject.select_and_init described_class.select_and_init
end end
it "uses the Linux listener on Linux" do it "uses the Linux listener on Linux" do
RbConfig::CONFIG['target_os'] = 'linux' RbConfig::CONFIG['target_os'] = 'linux'
Guard::Linux.stub(:usable?).and_return(true) Guard::Linux.stub(:usable?).and_return(true)
Guard::Linux.should_receive(:new) Guard::Linux.should_receive(:new)
subject.select_and_init described_class.select_and_init
end end
it "forwards its arguments to the constructor" do it "forwards its arguments to the constructor" do
subject.stub!(:mac?).and_return(true) described_class.stub!(:mac?).and_return(true)
Guard::Darwin.stub!(:usable?).and_return(true) Guard::Darwin.stub!(:usable?).and_return(true)
path, opts = 'path', { :foo => 23 } path, opts = 'path', { :foo => 23 }
Guard::Darwin.should_receive(:new).with(path, opts).and_return(true) Guard::Darwin.should_receive(:new).with(path, opts).and_return(true)
subject.select_and_init(path, opts) described_class.select_and_init(path, opts)
end end
end end
@ -256,11 +255,11 @@ describe Guard::Listener do
describe "#ignore_paths" do describe "#ignore_paths" do
it "defaults to the default ignore paths" do it "defaults to the default ignore paths" do
subject.new.ignore_paths.should == Guard::Listener::DEFAULT_IGNORE_PATHS described_class.new.ignore_paths.should == Guard::Listener::DEFAULT_IGNORE_PATHS
end end
it "can be added to via :ignore_paths option" do it "can be added to via :ignore_paths option" do
listener = subject.new 'path', :ignore_paths => ['foo', 'bar'] listener = described_class.new 'path', :ignore_paths => ['foo', 'bar']
listener.ignore_paths.should include('foo', 'bar') listener.ignore_paths.should include('foo', 'bar')
end end
end end
@ -281,4 +280,5 @@ describe Guard::Listener do
end end
end end
end end
end end

View File

@ -2,26 +2,26 @@ require 'spec_helper'
require 'guard/listeners/darwin' require 'guard/listeners/darwin'
describe Guard::Darwin do describe Guard::Darwin do
subject { Guard::Darwin }
if windows? if windows?
it "isn't usable on windows" do it "isn't usable on windows" do
subject.should_not be_usable described_class.should_not be_usable
end end
end end
if linux? if linux?
it "isn't usable on linux" do it "isn't usable on linux" do
subject.should_not be_usable described_class.should_not be_usable
end end
end end
if mac? && Guard::Darwin.usable? if mac? && Guard::Darwin.usable?
it "is usable on 10.6" do it "is usable on 10.6" do
subject.should be_usable described_class.should be_usable
end end
it_should_behave_like "a listener that reacts to #on_change" it_should_behave_like "a listener that reacts to #on_change"
it_should_behave_like "a listener scoped to a specific directory" it_should_behave_like "a listener scoped to a specific directory"
end end
end end

View File

@ -3,23 +3,22 @@ require 'fileutils'
require 'guard/listeners/linux' require 'guard/listeners/linux'
describe Guard::Linux do describe Guard::Linux do
subject { Guard::Linux }
if mac? if mac?
it "isn't usable on 10.6" do it "isn't usable on 10.6" do
subject.should_not be_usable described_class.should_not be_usable
end end
end end
if windows? if windows?
it "isn't usable on windows" do it "isn't usable on windows" do
subject.should_not be_usable described_class.should_not be_usable
end end
end end
if linux? && Guard::Linux.usable? if linux? && Guard::Linux.usable?
it "is usable on linux" do it "is usable on linux" do
subject.should be_usable described_class.should be_usable
end end
describe "#start", :long_running => true do describe "#start", :long_running => true do
@ -72,6 +71,6 @@ describe Guard::Linux do
stop stop
File.open(file, 'w') {|f| f.write('') } File.open(file, 'w') {|f| f.write('') }
end end
end end
end end

View File

@ -2,8 +2,8 @@ require 'spec_helper'
require 'guard/listeners/polling' require 'guard/listeners/polling'
describe Guard::Polling do describe Guard::Polling do
subject { Guard::Polling }
it_should_behave_like "a listener that reacts to #on_change" it_should_behave_like "a listener that reacts to #on_change"
it_should_behave_like "a listener scoped to a specific directory" it_should_behave_like "a listener scoped to a specific directory"
end end

View File

@ -2,27 +2,26 @@ require 'spec_helper'
require 'guard/listeners/windows' require 'guard/listeners/windows'
describe Guard::Windows do describe Guard::Windows do
subject { Guard::Windows }
if linux? if linux?
it "isn't usable on linux" do it "isn't usable on linux" do
subject.should_not be_usable described_class.should_not be_usable
end end
end end
if mac? if mac?
it "isn't usable on Mac" do it "isn't usable on Mac" do
subject.should_not be_usable described_class.should_not be_usable
end end
end end
if windows? if windows?
it "is usable on Windows 2000 and later" do it "is usable on Windows 2000 and later" do
subject.should be_usable described_class.should be_usable
end end
it_should_behave_like "a listener that reacts to #on_change" it_should_behave_like "a listener that reacts to #on_change"
it_should_behave_like "a listener scoped to a specific directory" it_should_behave_like "a listener scoped to a specific directory"
end end
end end

View File

@ -1,12 +1,11 @@
require 'spec_helper' require 'spec_helper'
describe Guard::Notifier do describe Guard::Notifier do
subject { Guard::Notifier }
describe ".turn_off" do describe ".turn_off" do
before do before do
ENV["GUARD_NOTIFY"] = 'true' ENV["GUARD_NOTIFY"] = 'true'
subject.turn_off described_class.turn_off
end end
it "disables the notifications" do it "disables the notifications" do
@ -28,10 +27,10 @@ describe Guard::Notifier do
end end
it "loads the library and enables the notifications" do it "loads the library and enables the notifications" do
subject.should_receive(:require).with('growl_notify').and_return true described_class.should_receive(:require).with('growl_notify').and_return true
GrowlNotify.should_receive(:application_name).and_return '' GrowlNotify.should_receive(:application_name).and_return ''
subject.turn_on described_class.turn_on
subject.should be_enabled described_class.should be_enabled
end end
after do after do
@ -41,19 +40,19 @@ describe Guard::Notifier do
context "with the Growl library available" do context "with the Growl library available" do
it "loads the library and enables the notifications" do it "loads the library and enables the notifications" do
subject.should_receive(:require).with('growl_notify').and_raise LoadError described_class.should_receive(:require).with('growl_notify').and_raise LoadError
subject.should_receive(:require).with('growl').and_return true described_class.should_receive(:require).with('growl').and_return true
subject.turn_on described_class.turn_on
subject.should be_enabled described_class.should be_enabled
end end
end end
context "without the Growl library available" do context "without the Growl library available" do
it "disables the notifications" do it "disables the notifications" do
subject.should_receive(:require).with('growl_notify').and_raise LoadError described_class.should_receive(:require).with('growl_notify').and_raise LoadError
subject.should_receive(:require).with('growl').and_raise LoadError described_class.should_receive(:require).with('growl').and_raise LoadError
subject.turn_on described_class.turn_on
subject.should_not be_enabled described_class.should_not be_enabled
end end
end end
end end
@ -65,17 +64,17 @@ describe Guard::Notifier do
context "with the Libnotify library available" do context "with the Libnotify library available" do
it "loads the library and enables the notifications" do it "loads the library and enables the notifications" do
subject.should_receive(:require).with('libnotify').and_return true described_class.should_receive(:require).with('libnotify').and_return true
subject.turn_on described_class.turn_on
subject.should be_enabled described_class.should be_enabled
end end
end end
context "without the Libnotify library available" do context "without the Libnotify library available" do
it "disables the notifications" do it "disables the notifications" do
subject.should_receive(:require).with('libnotify').and_raise LoadError described_class.should_receive(:require).with('libnotify').and_raise LoadError
subject.turn_on described_class.turn_on
subject.should_not be_enabled described_class.should_not be_enabled
end end
end end
end end
@ -87,29 +86,29 @@ describe Guard::Notifier do
context "with the rb-notifu library available" do context "with the rb-notifu library available" do
it "loads the library and enables the notifications" do it "loads the library and enables the notifications" do
subject.should_receive(:require).with('rb-notifu').and_return true described_class.should_receive(:require).with('rb-notifu').and_return true
subject.turn_on described_class.turn_on
subject.should be_enabled described_class.should be_enabled
end end
end end
context "without the rb-notify library available" do context "without the rb-notify library available" do
it "disables the notifications" do it "disables the notifications" do
subject.should_receive(:require).with('rb-notifu').and_raise LoadError described_class.should_receive(:require).with('rb-notifu').and_raise LoadError
subject.turn_on described_class.turn_on
subject.should_not be_enabled described_class.should_not be_enabled
end end
end end
end end
end end
describe ".notify" do describe ".notify" do
before { subject.stub(:enabled?).and_return(true) } before { described_class.stub(:enabled?).and_return(true) }
context "on Mac OS" do context "on Mac OS" do
before do before do
RbConfig::CONFIG.should_receive(:[]).with('target_os').and_return 'darwin' RbConfig::CONFIG.should_receive(:[]).with('target_os').and_return 'darwin'
subject.stub(:require_growl) described_class.stub(:require_growl)
end end
context 'with growl gem' do context 'with growl gem' do
@ -128,13 +127,13 @@ describe Guard::Notifier do
:icon => Pathname.new(File.dirname(__FILE__)).join('../../images/success.png').to_s, :icon => Pathname.new(File.dirname(__FILE__)).join('../../images/success.png').to_s,
:name => "Guard" :name => "Guard"
) )
subject.notify 'great', :title => 'Guard' described_class.notify 'great', :title => 'Guard'
end end
it "don't passes the notification to Growl if library is not available" do it "don't passes the notification to Growl if library is not available" do
Growl.should_not_receive(:notify) Growl.should_not_receive(:notify)
subject.should_receive(:enabled?).and_return(true, false) described_class.should_receive(:enabled?).and_return(true, false)
subject.notify 'great', :title => 'Guard' described_class.notify 'great', :title => 'Guard'
end end
it "allows additional notification options" do it "allows additional notification options" do
@ -144,7 +143,7 @@ describe Guard::Notifier do
:name => "Guard", :name => "Guard",
:priority => 1 :priority => 1
) )
subject.notify 'great', :title => 'Guard', :priority => 1 described_class.notify 'great', :title => 'Guard', :priority => 1
end end
it "allows to overwrite a default notification option" do it "allows to overwrite a default notification option" do
@ -153,7 +152,7 @@ describe Guard::Notifier do
:icon => Pathname.new(File.dirname(__FILE__)).join('../../images/success.png').to_s, :icon => Pathname.new(File.dirname(__FILE__)).join('../../images/success.png').to_s,
:name => "Guard-Cucumber" :name => "Guard-Cucumber"
) )
subject.notify 'great', :title => 'Guard', :name => "Guard-Cucumber" described_class.notify 'great', :title => 'Guard', :name => "Guard-Cucumber"
end end
end end
@ -174,13 +173,13 @@ describe Guard::Notifier do
:application_name => "Guard", :application_name => "Guard",
:description => 'great' :description => 'great'
) )
subject.notify 'great', :title => 'Guard' described_class.notify 'great', :title => 'Guard'
end end
it "don't passes the notification to Growl if library is not available" do it "don't passes the notification to Growl if library is not available" do
GrowlNotify.should_not_receive(:send_notification) GrowlNotify.should_not_receive(:send_notification)
subject.should_receive(:enabled?).and_return(true, false) described_class.should_receive(:enabled?).and_return(true, false)
subject.notify 'great', :title => 'Guard' described_class.notify 'great', :title => 'Guard'
end end
it "allows additional notification options" do it "allows additional notification options" do
@ -191,7 +190,7 @@ describe Guard::Notifier do
:description => 'great', :description => 'great',
:priority => 1 :priority => 1
) )
subject.notify 'great', :title => 'Guard', :priority => 1 described_class.notify 'great', :title => 'Guard', :priority => 1
end end
it "throws out the application name since Guard should only use one Growl App Name while running" do it "throws out the application name since Guard should only use one Growl App Name while running" do
@ -201,15 +200,15 @@ describe Guard::Notifier do
:application_name => "Guard", :application_name => "Guard",
:description => 'great' :description => 'great'
) )
subject.notify 'great', :title => 'Guard', :name => "Guard-Cucumber" described_class.notify 'great', :title => 'Guard', :name => "Guard-Cucumber"
end end
end end
end end
context "on Linux" do context "on Linux" do
before do before do
RbConfig::CONFIG.should_receive(:[]).with('target_os').and_return 'linux' RbConfig::CONFIG.should_receive(:[]).with('target_os').and_return 'linux'
subject.stub(:require_libnotify) described_class.stub(:require_libnotify)
Object.send(:remove_const, :Libnotify) if defined?(Libnotify) Object.send(:remove_const, :Libnotify) if defined?(Libnotify)
Libnotify = Object.new Libnotify = Object.new
end end
@ -225,13 +224,13 @@ describe Guard::Notifier do
:icon_path => Pathname.new(File.dirname(__FILE__)).join('../../images/success.png').to_s, :icon_path => Pathname.new(File.dirname(__FILE__)).join('../../images/success.png').to_s,
:transient => true :transient => true
) )
subject.notify 'great', :title => 'Guard' described_class.notify 'great', :title => 'Guard'
end end
it "don't passes the notification to Libnotify if library is not available" do it "don't passes the notification to Libnotify if library is not available" do
Libnotify.should_not_receive(:show) Libnotify.should_not_receive(:show)
subject.should_receive(:enabled?).and_return(true, false) described_class.should_receive(:enabled?).and_return(true, false)
subject.notify 'great', :title => 'Guard' described_class.notify 'great', :title => 'Guard'
end end
it "allows additional notification options" do it "allows additional notification options" do
@ -242,7 +241,7 @@ describe Guard::Notifier do
:transient => true, :transient => true,
:urgency => :critical :urgency => :critical
) )
subject.notify 'great', :title => 'Guard', :urgency => :critical described_class.notify 'great', :title => 'Guard', :urgency => :critical
end end
it "allows to overwrite a default notification option" do it "allows to overwrite a default notification option" do
@ -252,14 +251,14 @@ describe Guard::Notifier do
:icon_path => '~/.guard/success.png', :icon_path => '~/.guard/success.png',
:transient => true :transient => true
) )
subject.notify 'great', :title => 'Guard', :icon_path => '~/.guard/success.png' described_class.notify 'great', :title => 'Guard', :icon_path => '~/.guard/success.png'
end end
end end
context "on Windows" do context "on Windows" do
before do before do
RbConfig::CONFIG.should_receive(:[]).with('target_os').and_return 'mswin' RbConfig::CONFIG.should_receive(:[]).with('target_os').and_return 'mswin'
subject.stub(:require_rbnotifu) described_class.stub(:require_rbnotifu)
Object.send(:remove_const, :Notifu) if defined?(Notifu) Object.send(:remove_const, :Notifu) if defined?(Notifu)
Notifu = Object.new Notifu = Object.new
end end
@ -275,13 +274,13 @@ describe Guard::Notifier do
:type => :info, :type => :info,
:time => 3 :time => 3
) )
subject.notify 'great', :title => 'Guard' described_class.notify 'great', :title => 'Guard'
end end
it "don't passes the notification to rb-notifu if library is not available" do it "don't passes the notification to rb-notifu if library is not available" do
Notifu.should_not_receive(:show) Notifu.should_not_receive(:show)
subject.should_receive(:enabled?).and_return(true, false) described_class.should_receive(:enabled?).and_return(true, false)
subject.notify 'great', :title => 'Guard' described_class.notify 'great', :title => 'Guard'
end end
it "allows additional notification options" do it "allows additional notification options" do
@ -292,7 +291,7 @@ describe Guard::Notifier do
:time => 3, :time => 3,
:nosound => true :nosound => true
) )
subject.notify 'great', :title => 'Guard', :nosound => true described_class.notify 'great', :title => 'Guard', :nosound => true
end end
it "allows to overwrite a default notification option" do it "allows to overwrite a default notification option" do
@ -302,7 +301,7 @@ describe Guard::Notifier do
:type => :info, :type => :info,
:time => 10 :time => 10
) )
subject.notify 'great', :title => 'Guard', :time => 10 described_class.notify 'great', :title => 'Guard', :time => 10
end end
end end
end end
@ -320,4 +319,5 @@ describe Guard::Notifier do
it { should_not be_enabled } it { should_not be_enabled }
end end
end end
end end

View File

@ -5,19 +5,19 @@ describe Guard::Watcher do
describe "#initialize" do describe "#initialize" do
it "requires a pattern parameter" do it "requires a pattern parameter" do
expect { Guard::Watcher.new }.to raise_error(ArgumentError) expect { described_class.new }.to raise_error(ArgumentError)
end end
context "with a pattern parameter" do context "with a pattern parameter" do
context "that is a string" do context "that is a string" do
it "keeps the string pattern unmodified" do it "keeps the string pattern unmodified" do
Guard::Watcher.new('spec_helper.rb').pattern.should == 'spec_helper.rb' described_class.new('spec_helper.rb').pattern.should == 'spec_helper.rb'
end end
end end
context "that is a regexp" do context "that is a regexp" do
it "keeps the regex pattern unmodified" do it "keeps the regex pattern unmodified" do
Guard::Watcher.new(/spec_helper\.rb/).pattern.should == /spec_helper\.rb/ described_class.new(/spec_helper\.rb/).pattern.should == /spec_helper\.rb/
end end
end end
@ -25,10 +25,10 @@ describe Guard::Watcher do
before(:each) { Guard::UI.should_receive(:info).any_number_of_times } before(:each) { Guard::UI.should_receive(:info).any_number_of_times }
it "converts the string automatically to a regex" do it "converts the string automatically to a regex" do
Guard::Watcher.new('^spec_helper.rb').pattern.should == /^spec_helper.rb/ described_class.new('^spec_helper.rb').pattern.should == /^spec_helper.rb/
Guard::Watcher.new('spec_helper.rb$').pattern.should == /spec_helper.rb$/ described_class.new('spec_helper.rb$').pattern.should == /spec_helper.rb$/
Guard::Watcher.new('spec_helper\.rb').pattern.should == /spec_helper\.rb/ described_class.new('spec_helper\.rb').pattern.should == /spec_helper\.rb/
Guard::Watcher.new('.*_spec.rb').pattern.should == /.*_spec.rb/ described_class.new('.*_spec.rb').pattern.should == /.*_spec.rb/
end end
end end
end end
@ -36,12 +36,12 @@ describe Guard::Watcher do
describe "#action" do describe "#action" do
it "sets the action to nothing by default" do it "sets the action to nothing by default" do
Guard::Watcher.new(/spec_helper\.rb/).action.should be_nil described_class.new(/spec_helper\.rb/).action.should be_nil
end end
it "sets the action to the supplied block" do it "sets the action to the supplied block" do
action = lambda { |m| "spec/#{m[1]}_spec.rb" } action = lambda { |m| "spec/#{m[1]}_spec.rb" }
Guard::Watcher.new(%r{^lib/(.*).rb}, action).action.should == action described_class.new(%r{^lib/(.*).rb}, action).action.should == action
end end
end end
@ -50,18 +50,18 @@ describe Guard::Watcher do
context "with a watcher without action" do context "with a watcher without action" do
context "that is a regex pattern" do context "that is a regex pattern" do
before(:all) { @guard.watchers = [Guard::Watcher.new(/.*_spec\.rb/)] } before(:all) { @guard.watchers = [described_class.new(/.*_spec\.rb/)] }
it "returns the paths that matches the regex" do it "returns the paths that matches the regex" do
Guard::Watcher.match_files(@guard, ['guard_rocks_spec.rb', 'guard_rocks.rb']).should == ['guard_rocks_spec.rb'] described_class.match_files(@guard, ['guard_rocks_spec.rb', 'guard_rocks.rb']).should == ['guard_rocks_spec.rb']
end end
end end
context "that is a string pattern" do context "that is a string pattern" do
before(:all) { @guard.watchers = [Guard::Watcher.new('guard_rocks_spec.rb')] } before(:all) { @guard.watchers = [described_class.new('guard_rocks_spec.rb')] }
it "returns the path that matches the string" do it "returns the path that matches the string" do
Guard::Watcher.match_files(@guard, ['guard_rocks_spec.rb', 'guard_rocks.rb']).should == ['guard_rocks_spec.rb'] described_class.match_files(@guard, ['guard_rocks_spec.rb', 'guard_rocks.rb']).should == ['guard_rocks_spec.rb']
end end
end end
end end
@ -69,79 +69,79 @@ describe Guard::Watcher do
context "with a watcher action without parameter" do context "with a watcher action without parameter" do
before(:all) do before(:all) do
@guard.watchers = [ @guard.watchers = [
Guard::Watcher.new('spec_helper.rb', lambda { 'spec' }), described_class.new('spec_helper.rb', lambda { 'spec' }),
Guard::Watcher.new('addition.rb', lambda { 1 + 1 }), described_class.new('addition.rb', lambda { 1 + 1 }),
Guard::Watcher.new('hash.rb', lambda { Hash[:foo, 'bar'] }), described_class.new('hash.rb', lambda { Hash[:foo, 'bar'] }),
Guard::Watcher.new('array.rb', lambda { ['foo', 'bar'] }), described_class.new('array.rb', lambda { ['foo', 'bar'] }),
Guard::Watcher.new('blank.rb', lambda { '' }), described_class.new('blank.rb', lambda { '' }),
Guard::Watcher.new(/^uptime\.rb/, lambda { `uptime > /dev/null` }) described_class.new(/^uptime\.rb/, lambda { `uptime > /dev/null` })
] ]
end end
it "returns a single file specified within the action" do it "returns a single file specified within the action" do
Guard::Watcher.match_files(@guard, ['spec_helper.rb']).should == ['spec'] described_class.match_files(@guard, ['spec_helper.rb']).should == ['spec']
end end
it "returns multiple files specified within the action" do it "returns multiple files specified within the action" do
Guard::Watcher.match_files(@guard, ['hash.rb']).should == ['foo', 'bar'] described_class.match_files(@guard, ['hash.rb']).should == ['foo', 'bar']
end end
it "returns multiple files by combining the results of different actions" do it "returns multiple files by combining the results of different actions" do
Guard::Watcher.match_files(@guard, ['spec_helper.rb', 'array.rb']).should == ['spec', 'foo', 'bar'] described_class.match_files(@guard, ['spec_helper.rb', 'array.rb']).should == ['spec', 'foo', 'bar']
end end
it "returns nothing if the action returns something other than a string or an array of strings" do it "returns nothing if the action returns something other than a string or an array of strings" do
Guard::Watcher.match_files(@guard, ['addition.rb']).should == [] described_class.match_files(@guard, ['addition.rb']).should == []
end end
it "returns nothing if the action response is empty" do it "returns nothing if the action response is empty" do
Guard::Watcher.match_files(@guard, ['blank.rb']).should == [] described_class.match_files(@guard, ['blank.rb']).should == []
end end
it "returns nothing if the action returns nothing" do it "returns nothing if the action returns nothing" do
Guard::Watcher.match_files(@guard, ['uptime.rb']).should == [] described_class.match_files(@guard, ['uptime.rb']).should == []
end end
end end
context "with a watcher action that takes a parameter" do context "with a watcher action that takes a parameter" do
before(:all) do before(:all) do
@guard.watchers = [ @guard.watchers = [
Guard::Watcher.new(%r{lib/(.*)\.rb}, lambda { |m| "spec/#{m[1]}_spec.rb" }), described_class.new(%r{lib/(.*)\.rb}, lambda { |m| "spec/#{m[1]}_spec.rb" }),
Guard::Watcher.new(/addition(.*)\.rb/, lambda { |m| 1 + 1 }), described_class.new(/addition(.*)\.rb/, lambda { |m| 1 + 1 }),
Guard::Watcher.new('hash.rb', lambda { Hash[:foo, 'bar'] }), described_class.new('hash.rb', lambda { Hash[:foo, 'bar'] }),
Guard::Watcher.new(/array(.*)\.rb/, lambda { |m| ['foo', 'bar'] }), described_class.new(/array(.*)\.rb/, lambda { |m| ['foo', 'bar'] }),
Guard::Watcher.new(/blank(.*)\.rb/, lambda { |m| '' }), described_class.new(/blank(.*)\.rb/, lambda { |m| '' }),
Guard::Watcher.new(/uptime(.*)\.rb/, lambda { |m| `uptime > /dev/null` }) described_class.new(/uptime(.*)\.rb/, lambda { |m| `uptime > /dev/null` })
] ]
end end
it "returns a substituted single file specified within the action" do it "returns a substituted single file specified within the action" do
Guard::Watcher.match_files(@guard, ['lib/my_wonderful_lib.rb']).should == ['spec/my_wonderful_lib_spec.rb'] described_class.match_files(@guard, ['lib/my_wonderful_lib.rb']).should == ['spec/my_wonderful_lib_spec.rb']
end end
it "returns multiple files specified within the action" do it "returns multiple files specified within the action" do
Guard::Watcher.match_files(@guard, ['hash.rb']).should == ['foo', 'bar'] described_class.match_files(@guard, ['hash.rb']).should == ['foo', 'bar']
end end
it "returns multiple files by combining the results of different actions" do it "returns multiple files by combining the results of different actions" do
Guard::Watcher.match_files(@guard, ['lib/my_wonderful_lib.rb', 'array.rb']).should == ['spec/my_wonderful_lib_spec.rb', 'foo', 'bar'] described_class.match_files(@guard, ['lib/my_wonderful_lib.rb', 'array.rb']).should == ['spec/my_wonderful_lib_spec.rb', 'foo', 'bar']
end end
it "returns nothing if the action returns something other than a string or an array of strings" do it "returns nothing if the action returns something other than a string or an array of strings" do
Guard::Watcher.match_files(@guard, ['addition.rb']).should == [] described_class.match_files(@guard, ['addition.rb']).should == []
end end
it "returns nothing if the action response is empty" do it "returns nothing if the action response is empty" do
Guard::Watcher.match_files(@guard, ['blank.rb']).should == [] described_class.match_files(@guard, ['blank.rb']).should == []
end end
it "returns nothing if the action returns nothing" do it "returns nothing if the action returns nothing" do
Guard::Watcher.match_files(@guard, ['uptime.rb']).should == [] described_class.match_files(@guard, ['uptime.rb']).should == []
end end
end end
context "with an exception that is raised" do context "with an exception that is raised" do
before(:all) { @guard.watchers = [Guard::Watcher.new('evil.rb', lambda { raise "EVIL" })] } before(:all) { @guard.watchers = [described_class.new('evil.rb', lambda { raise "EVIL" })] }
it "displays the error and backtrace" do it "displays the error and backtrace" do
Guard::UI.should_receive(:error) { |msg| Guard::UI.should_receive(:error) { |msg|
@ -149,31 +149,31 @@ describe Guard::Watcher do
msg.should include("EVIL") msg.should include("EVIL")
} }
Guard::Watcher.match_files(@guard, ['evil.rb']) described_class.match_files(@guard, ['evil.rb'])
end end
end end
end end
describe ".match_files?" do describe ".match_files?" do
before(:all) do before(:all) do
@guard1 = Guard::Guard.new([Guard::Watcher.new(/.*_spec\.rb/)]) @guard1 = Guard::Guard.new([described_class.new(/.*_spec\.rb/)])
@guard2 = Guard::Guard.new([Guard::Watcher.new('spec_helper.rb', 'spec')]) @guard2 = Guard::Guard.new([described_class.new('spec_helper.rb', 'spec')])
@guards = [@guard1, @guard2] @guards = [@guard1, @guard2]
end end
context "with a watcher that matches a file" do context "with a watcher that matches a file" do
specify { Guard::Watcher.match_files?(@guards, ['lib/my_wonderful_lib.rb', 'guard_rocks_spec.rb']).should be_true } specify { described_class.match_files?(@guards, ['lib/my_wonderful_lib.rb', 'guard_rocks_spec.rb']).should be_true }
end end
context "with no watcher that matches a file" do context "with no watcher that matches a file" do
specify { Guard::Watcher.match_files?(@guards, ['lib/my_wonderful_lib.rb']).should be_false } specify { described_class.match_files?(@guards, ['lib/my_wonderful_lib.rb']).should be_false }
end end
end end
describe "#match_file?" do describe "#match_file?" do
context "with a string pattern" do context "with a string pattern" do
context "that is a normal string" do context "that is a normal string" do
subject { Guard::Watcher.new('guard_rocks_spec.rb') } subject { described_class.new('guard_rocks_spec.rb') }
context "with a watcher that matches a file" do context "with a watcher that matches a file" do
specify { subject.match_file?('guard_rocks_spec.rb').should be_true } specify { subject.match_file?('guard_rocks_spec.rb').should be_true }
@ -185,7 +185,7 @@ describe Guard::Watcher do
end end
context "that is a string representing a regexp (deprecated)" do context "that is a string representing a regexp (deprecated)" do
subject { Guard::Watcher.new('^guard_rocks_spec\.rb$') } subject { described_class.new('^guard_rocks_spec\.rb$') }
context "with a watcher that matches a file" do context "with a watcher that matches a file" do
specify { subject.match_file?('guard_rocks_spec.rb').should be_true } specify { subject.match_file?('guard_rocks_spec.rb').should be_true }
@ -198,7 +198,7 @@ describe Guard::Watcher do
end end
context "that is a regexp pattern" do context "that is a regexp pattern" do
subject { Guard::Watcher.new(/.*_spec\.rb/) } subject { described_class.new(/.*_spec\.rb/) }
context "with a watcher that matches a file" do context "with a watcher that matches a file" do
specify { subject.match_file?('guard_rocks_spec.rb').should be_true } specify { subject.match_file?('guard_rocks_spec.rb').should be_true }
@ -214,11 +214,11 @@ describe Guard::Watcher do
before(:all) { Guard::Dsl.stub(:guardfile_path) { Dir.pwd + '/Guardfile' } } before(:all) { Guard::Dsl.stub(:guardfile_path) { Dir.pwd + '/Guardfile' } }
context "with files that match the Guardfile" do context "with files that match the Guardfile" do
specify { Guard::Watcher.match_guardfile?(['Guardfile', 'guard_rocks_spec.rb']).should be_true } specify { described_class.match_guardfile?(['Guardfile', 'guard_rocks_spec.rb']).should be_true }
end end
context "with no files that match the Guardfile" do context "with no files that match the Guardfile" do
specify { Guard::Watcher.match_guardfile?(['guard_rocks.rb', 'guard_rocks_spec.rb']).should be_false } specify { described_class.match_guardfile?(['guard_rocks.rb', 'guard_rocks_spec.rb']).should be_false }
end end
end end

View File

@ -15,7 +15,8 @@ describe Guard do
end end
it "initializes @groups" do it "initializes @groups" do
Guard.groups.should eql [:default] described_class.groups[0].name.should eql :default
described_class.groups[0].options.should == {}
end end
it "initializes the options" do it "initializes the options" do
@ -55,6 +56,118 @@ describe Guard do
end end
end end
describe ".guards" do
class Guard::FooBar < Guard::Guard; end
class Guard::FooBaz < Guard::Guard; end
subject do
guard = ::Guard.setup
@guard_foo_bar_backend = Guard::FooBar.new([], { :group => 'backend' })
@guard_foo_bar_frontend = Guard::FooBar.new([], { :group => 'frontend' })
@guard_foo_baz_backend = Guard::FooBaz.new([], { :group => 'backend' })
@guard_foo_baz_frontend = Guard::FooBaz.new([], { :group => 'frontend' })
guard.instance_variable_get("@guards").push(@guard_foo_bar_backend)
guard.instance_variable_get("@guards").push(@guard_foo_bar_frontend)
guard.instance_variable_get("@guards").push(@guard_foo_baz_backend)
guard.instance_variable_get("@guards").push(@guard_foo_baz_frontend)
guard
end
it "return @guards without any argument" do
subject.guards.should eql subject.instance_variable_get("@guards")
end
describe "find a guard by as string/symbol" do
it "find a guard by a string" do
subject.guards('foo-bar').should eql @guard_foo_bar_backend
end
it "find a guard by a symbol" do
subject.guards(:'foo-bar').should eql @guard_foo_bar_backend
end
it "returns nil if guard is not found" do
subject.guards('foo-foo').should be_nil
end
end
describe "find guards matching a regexp" do
it "with matches" do
subject.guards(/^foobar/).should eql [@guard_foo_bar_backend, @guard_foo_bar_frontend]
end
it "without matches" do
subject.guards(/foo$/).should eql []
end
end
describe "find guards by their group" do
it "group name is a string" do
subject.guards(:group => 'backend').should eql [@guard_foo_bar_backend, @guard_foo_baz_backend]
end
it "group name is a symbol" do
subject.guards(:group => :frontend).should eql [@guard_foo_bar_frontend, @guard_foo_baz_frontend]
end
it "returns [] if guard is not found" do
subject.guards(:group => :unknown).should eql []
end
end
describe "find guards by their group & name" do
it "group name is a string" do
subject.guards(:group => 'backend', :name => 'foo-bar').should eql [@guard_foo_bar_backend]
end
it "group name is a symbol" do
subject.guards(:group => :frontend, :name => :'foo-baz').should eql [@guard_foo_baz_frontend]
end
it "returns [] if guard is not found" do
subject.guards(:group => :unknown, :name => :'foo-baz').should eql []
end
end
end
describe ".groups" do
subject do
guard = ::Guard.setup
@group_backend = guard.add_group(:backend)
@group_backflip = guard.add_group(:backflip)
guard
end
it "return @groups without any argument" do
subject.groups.should eql subject.instance_variable_get("@groups")
end
describe "find a group by as string/symbol" do
it "find a group by a string" do
subject.groups('backend').should eql @group_backend
end
it "find a group by a symbol" do
subject.groups(:backend).should eql @group_backend
end
it "returns nil if group is not found" do
subject.groups(:foo).should be_nil
end
end
describe "find groups matching a regexp" do
it "with matches" do
subject.groups(/^back/).should eql [@group_backend, @group_backflip]
end
it "without matches" do
subject.groups(/back$/).should eql []
end
end
end
describe ".start" do describe ".start" do
it "basic check that core methods are called" do it "basic check that core methods are called" do
opts = { :my_opts => true, :guardfile => File.join(@fixture_path, "Guardfile") } opts = { :my_opts => true, :guardfile => File.join(@fixture_path, "Guardfile") }
@ -129,22 +242,28 @@ describe Guard do
end end
end end
describe ".add_group" do describe ".add_group" do
before(:each) do subject { ::Guard.setup }
Guard.setup
end
it "accepts group name as string" do it "accepts group name as string" do
Guard.add_group('backend') subject.add_group('backend')
Guard.groups.should eql [:default, :backend] subject.groups[0].name.should eql :default
subject.groups[1].name.should eql :backend
end end
it "accepts group name as symbol" do it "accepts group name as symbol" do
Guard.add_group(:backend) subject.add_group(:backend)
Guard.groups.should eql [:default, :backend] subject.groups[0].name.should eql :default
subject.groups[1].name.should eql :backend
end
it "accepts options" do
subject.add_group(:backend, { :halt_on_fail => true })
subject.groups[0].options.should == {}
subject.groups[1].options.should == { :halt_on_fail => true }
end end
end end
@ -223,12 +342,63 @@ describe Guard do
end end
end end
describe ".execute_supervised_task_for_all_guards" do
subject { ::Guard.setup }
before do
class Guard::Dummy < Guard::Guard; end
subject.add_group(:foo, { :halt_on_fail => true })
subject.add_group(:bar)
subject.add_guard(:dummy, [], [], { :group => :foo })
subject.add_guard(:dummy, [], [], { :group => :foo })
subject.add_guard(:dummy, [], [], { :group => :bar })
subject.add_guard(:dummy, [], [], { :group => :bar })
@sum = { :foo => 0, :bar => 0}
end
context "all tasks succeed" do
before do
subject.guards.each { |guard| guard.stub!(:task) { @sum[guard.group] += 1; true } }
end
it "executes the task for each guard in each group" do
subject.execute_supervised_task_for_all_guards(:task)
@sum.all? { |k, v| v == 2 }.should be_true
end
end
context "one guard fails (by returning false)" do
before do
subject.guards.each_with_index do |g, i|
g.stub!(:task) do
@sum[g.group] += i+1
if i % 2 == 0
throw :task_has_failed
else
true
end
end
end
end
it "executes the task only for guards that didn't fail for group with :halt_on_fail == true" do
subject.execute_supervised_task_for_all_guards(:task)
@sum[:foo].should eql 1
@sum[:bar].should eql 7
end
end
end
describe ".supervised_task" do describe ".supervised_task" do
subject { ::Guard.setup } subject { ::Guard.setup }
before(:each) do before do
@g = mock(Guard::Guard).as_null_object @g = mock(Guard::Guard).as_null_object
subject.guards.push(@g) subject.guards.push(@g)
subject.add_group(:foo, { :halt_on_fail => true })
end end
context "with a task that succeed" do context "with a task that succeed" do
@ -278,6 +448,14 @@ describe Guard do
end end
end end
context "with a task that return false and guard's group has the :halt_on_fail option == true" do
before(:each) { @g.stub!(:group) { :foo }; @g.stub!(:failing) { throw :task_has_failed } }
it "throws :task_has_failed" do
expect { subject.supervised_task(@g, :failing) }.to throw_symbol(:task_has_failed)
end
end
context "with a task that raises an exception" do context "with a task that raises an exception" do
before(:each) { @g.stub!(:failing) { raise "I break your system" } } before(:each) { @g.stub!(:failing) { raise "I break your system" } }

View File

@ -12,6 +12,7 @@ RSpec.configure do |config|
config.color_enabled = true config.color_enabled = true
config.filter_run :focus => true config.filter_run :focus => true
config.treat_symbols_as_metadata_keys_with_true_values = true
config.run_all_when_everything_filtered = true config.run_all_when_everything_filtered = true
config.before(:each) do config.before(:each) do

View File

@ -1,10 +1,14 @@
private private
def sleep_time
@sleep_time ||= ENV['GUARD_SLEEP'] ? ENV['GUARD_SLEEP'].to_f : 1
end
def start def start
sleep(@rest_delay || 1) sleep(sleep_time)
@listener.update_last_event @listener.update_last_event
Thread.new { @listener.start } Thread.new { @listener.start }
sleep(@rest_delay || 1) sleep(sleep_time)
end end
def record_results def record_results
@ -17,18 +21,17 @@ private
end end
def stop def stop
sleep(@rest_delay || 1) sleep(sleep_time)
@listener.stop @listener.stop
sleep(@rest_delay || 1) sleep(sleep_time)
end end
def results def results
@results.flatten @results.flatten
end end
shared_examples_for 'a listener that reacts to #on_change' do |rest_delay| shared_examples_for 'a listener that reacts to #on_change' do
before(:each) do before(:each) do
@rest_delay = rest_delay if rest_delay.is_a?(Integer) || rest_delay.is_a?(Float) # jruby workaround
@listener = described_class.new @listener = described_class.new
record_results record_results
end end
@ -115,9 +118,8 @@ shared_examples_for 'a listener that reacts to #on_change' do |rest_delay|
end end
shared_examples_for "a listener scoped to a specific directory" do |rest_delay| shared_examples_for "a listener scoped to a specific directory" do
before :each do before :each do
@rest_delay = rest_delay if rest_delay.is_a?(Integer) || rest_delay.is_a?(Float) # jruby workaround
@wd = @fixture_path.join("folder1") @wd = @fixture_path.join("folder1")
@listener = described_class.new @wd @listener = described_class.new @wd
end end