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:
only:
- master
- hook
- stdin
- jruby_travis_ctime_bug
- guard_dependencies
env:
- GUARD_SLEEP=1
notifications:
recipients:
- thibaud@thibaud.me

View File

@ -1,6 +1,19 @@
## Master
### Bugs fixes:
- 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
@ -9,7 +22,7 @@
### 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][])
- JRuby & Rubinius support (beta). ([@thibaudgg][] and [@netzpirat][])
- JRuby & Rubinius support (beta). ([@thibaudgg][] & [@netzpirat][])
### New feature:
@ -272,6 +285,7 @@
[@niklas]: https://github.com/niklas
[@oliamb]: https://github.com/oliamb
[@pcreux]: https://github.com/pcreux
[@rmm5t]: https://github.com/rmm5t
[@rymai]: https://github.com/rymai
[@stereobooster]: https://github.com/stereobooster
[@stouset]: https://github.com/stouset

View File

@ -6,6 +6,7 @@ module Guard
autoload :UI, 'guard/ui'
autoload :Dsl, 'guard/dsl'
autoload :DslDescriber, 'guard/dsl_describer'
autoload :Group, 'guard/group'
autoload :Interactor, 'guard/interactor'
autoload :Listener, 'guard/listener'
autoload :Watcher, 'guard/watcher'
@ -13,11 +14,10 @@ module Guard
autoload :Hook, 'guard/hook'
class << self
attr_accessor :options, :guards, :groups, :interactor, :listener
attr_accessor :options, :interactor, :listener
# 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] notify if system notifications should be shown
# @option options [Boolean] debug if debug output should be shown
@ -28,7 +28,7 @@ module Guard
def setup(options = {})
@options = options
@guards = []
@groups = [:default]
@groups = [Group.new(:default)]
@interactor = Interactor.new
@listener = Listener.select_and_init(@options[:watchdir] ? File.expand_path(@options[:watchdir]) : Dir.pwd, options)
@ -41,10 +41,57 @@ module Guard
self
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
# 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] notify if system notifications should be shown
# @option options [Boolean] debug if debug output should be shown
@ -63,7 +110,8 @@ module Guard
end
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
listener.start
@ -74,7 +122,7 @@ module Guard
def stop
UI.info 'Bye bye...', :reset => true
listener.stop
guards.each { |guard| supervised_task(guard, :stop) }
execute_supervised_task_for_all_guards(:stop)
abort
end
@ -82,7 +130,7 @@ module Guard
#
def reload
run do
guards.each { |guard| supervised_task(guard, :reload) }
execute_supervised_task_for_all_guards(:reload)
end
end
@ -90,7 +138,7 @@ module Guard
#
def run_all
run do
guards.each { |guard| supervised_task(guard, :run_all) }
execute_supervised_task_for_all_guards(:run_all)
end
end
@ -107,29 +155,11 @@ module Guard
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
guards.each do |guard|
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
execute_supervised_task_for_all_guards(:run_on_change, paths)
end
end
@ -150,6 +180,41 @@ module Guard
listener.unlock
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
# if his work leads to a system failure.
#
@ -179,7 +244,7 @@ module Guard
# @param [String] name the Guard name
# @param [Array<Watcher>] watchers the list of declared watchers
# @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 = {})
if name.to_sym == :ego
@ -194,9 +259,17 @@ module Guard
# Add a Guard group.
#
# @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)
@groups << name.to_sym unless name.nil?
def add_group(name, options = {})
group = groups(name)
if group.nil?
group = Group.new(name, options)
@groups << group
end
group
end
# Tries to load the Guard main class.

View File

@ -81,7 +81,6 @@ module Guard
# 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 [String] guardfile the path to 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
::Guard.guards.clear
::Guard.groups.clear
@@options.delete(:guardfile_contents)
Dsl.evaluate_guardfile(@@options)
msg = 'Guardfile has been re-evaluated.'
@ -265,16 +265,19 @@ module Guard
# end
#
# @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
#
# @see Guard.add_group
# @see Dsl#guard
# @see Guard::DslDescriber
#
def group(name)
def group(name, options = {})
@groups = @@options[:group] || []
name = name.to_sym
if block_given? && (@groups.empty? || @groups.map(&:to_sym).include?(name))
::Guard.add_group(name.to_s.downcase, options)
@current_group = name
yield if block_given?
@ -299,6 +302,8 @@ module Guard
# @param [Hash] options the options accepted by the Guard
# @yield a block where you can declare several watch patterns and actions
#
# @see Guard.add_guard
# @see Dsl#group
# @see Dsl#watch
# @see Guard::DslDescriber
#
@ -309,7 +314,7 @@ module Guard
yield if block_given?
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
# 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
# @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)
@watchers << ::Guard::Watcher.new(pattern, action)
end
@ -337,6 +345,8 @@ module Guard
# @param [Array] args the callback arguments
# @yield a block with listeners
#
# @see Guard::Hook
#
def callback(*args, &listener)
listener, events = args.size > 1 ? args : [listener, args[0]]
@callbacks << { :events => events, :listener => listener }
@ -349,6 +359,8 @@ module Guard
#
# @param [Array] paths the list of paths to ignore
#
# @see Guard::Listener
#
def ignore_paths(*paths)
UI.info "Ignoring paths: #{ paths.join(', ') }"
::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
# @yield a block where you can declare several guards
#
# @see Guard::Dsl
# @see Guard::Dsl#group
#
def group(name)
@@guardfile_structure << { :group => name.to_sym, :guards => [] }
@ -42,13 +42,13 @@ module Guard
@group = false
end
# Declare a guard.
# Declares a Guard.
#
# @param [String] name the Guard name
# @param [Hash] options the options accepted by the Guard
# @yield a block where you can declare several watch patterns and actions
#
# @see Guard::Dsl
# @see Guard::Dsl#guard
#
def guard(name, options = {})
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.
#
# @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 = {})
@group = options.delete(:group) || :default
@group = options[:group] ? options.delete(:group).to_sym : :default
@watchers, @options = watchers, options
end
@ -89,4 +89,5 @@ module Guard
end
end
end

View File

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

View File

@ -43,7 +43,6 @@ module Guard
# Initialize the listener.
#
# @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 [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.
#
# @param [Array<String>] dirs the list of directories
# @param [Hash] options the options
# @option options [Symbol] all whether to include all files
#
def potentially_modified_files(dirs, options = {})

View File

@ -43,7 +43,6 @@ module Guard
# @see .image_path
#
# @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 [String] title the notification title
#
@ -80,7 +79,7 @@ module Guard
# @param [Symbol, String] the image to user
# @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
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 [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
default_options = { :body => message, :summary => title, :icon_path => image_path(image), :transient => true }
Libnotify.show default_options.merge(options) if enabled?
@ -117,7 +116,7 @@ module Guard
# @param [Symbol, String] the image to user
# @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
default_options = { :message => message, :title => title, :type => image_level(image), :time => 3 }
Notifu.show default_options.merge(options) if enabled?

View File

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

184
man/guard
View File

@ -17,6 +17,91 @@
.
.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>
.
@ -48,7 +133,7 @@
\fBguard\fR
.
.P
\fI!DOCTYPE html\fR
<p\fI!DOCTYPE html\fR
.
.P
.
@ -96,6 +181,103 @@
.
.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=\'tc\'>September 2011</li>
<li class=\'tr\'>guard</li>

View File

@ -41,7 +41,7 @@ Tells Guard to watch PATH instead of \fB\./\fR\.
.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\.
.
.SS "init <a href=\"guard\.html\">GUARD</a>"
.SS "init [GUARD]"
If no Guardfile is present in the current directory, creates an empty Guardfile\.
.
.P

View File

@ -112,7 +112,7 @@
<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>
<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>

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>
</div>
<ol class='man-decor man-head man head'>
@ -71,10 +73,10 @@
<p><var>!DOCTYPE html</var>
<html>
<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)" />
<title>guard</title>
<style media="all" type="text/css">
<style type="text/css" media="all">
/<em> style: man </em>/
body#manpage {margin:0}
.mp {max-width:100ex;padding:0 9ex 1ex 4ex}
@ -129,6 +131,8 @@
<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;
</code></pre>
<p> </p>
@ -151,6 +155,231 @@
<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;
&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>
<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)" />
@ -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
.\" 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>

View File

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

View File

@ -2,13 +2,14 @@ require 'spec_helper'
require 'guard/guard'
describe Guard::Dsl do
subject { described_class }
class Guard::Dummy < Guard::Guard; end
before(:each) do
@local_guardfile_path = File.join(Dir.pwd, 'Guardfile')
@home_guardfile_path = File.expand_path(File.join("~", ".Guardfile"))
@user_config_path = File.expand_path(File.join("~", ".guard.rb"))
::Guard.setup
::Guard.stub!(:options).and_return(:debug => true)
::Guard.stub!(:guards).and_return([mock('Guard')])
end
@ -23,24 +24,24 @@ describe Guard::Dsl do
it "should use a string for initializing" do
Guard::UI.should_not_receive(:error)
lambda { subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string) }.should_not raise_error
subject.guardfile_contents.should == valid_guardfile_string
lambda { described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string) }.should_not raise_error
described_class.guardfile_contents.should == valid_guardfile_string
end
it "should use a given file over the default loc" do
fake_guardfile('/abc/Guardfile', "guard :foo")
Guard::UI.should_not_receive(:error)
lambda { subject.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error
subject.guardfile_contents.should == "guard :foo"
lambda { described_class.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error
described_class.guardfile_contents.should == "guard :foo"
end
it "should use a default file if no other options are given" do
fake_guardfile(@local_guardfile_path, "guard :bar")
Guard::UI.should_not_receive(:error)
lambda { subject.evaluate_guardfile }.should_not raise_error
subject.guardfile_contents.should == "guard :bar"
lambda { described_class.evaluate_guardfile }.should_not raise_error
described_class.guardfile_contents.should == "guard :bar"
end
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")
Guard::UI.should_not_receive(:error)
lambda { subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string) }.should_not raise_error
subject.guardfile_contents.should == valid_guardfile_string
lambda { described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string) }.should_not raise_error
described_class.guardfile_contents.should == valid_guardfile_string
end
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")
Guard::UI.should_not_receive(:error)
lambda { subject.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error
subject.guardfile_contents.should == "guard :foo"
lambda { described_class.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error
described_class.guardfile_contents.should == "guard :foo"
end
it 'should append the user config file if present' do
fake_guardfile('/abc/Guardfile', "guard :foo")
fake_guardfile(@user_config_path, "guard :bar")
Guard::UI.should_not_receive(:error)
lambda { subject.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error
subject.guardfile_contents_with_user_config.should == "guard :foo\nguard :bar"
lambda { described_class.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error
described_class.guardfile_contents_with_user_config.should == "guard :foo\nguard :bar"
end
end
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`.")
lambda { subject.evaluate_guardfile }.should raise_error
lambda { described_class.evaluate_guardfile }.should raise_error
end
it "displays an error message when no guard are defined in Guardfile" do
::Guard::Dsl.stub!(:instance_eval_guardfile)
::Guard.stub!(:guards).and_return([])
Guard::UI.should_receive(:error)
subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string)
described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string)
end
describe "correctly reads data from its valid data source" do
@ -89,22 +90,22 @@ describe Guard::Dsl do
disable_user_config
it "reads correctly from a string" do
lambda { subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string) }.should_not raise_error
subject.guardfile_contents.should == valid_guardfile_string
lambda { described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string) }.should_not raise_error
described_class.guardfile_contents.should == valid_guardfile_string
end
it "reads correctly from a Guardfile" do
fake_guardfile('/abc/Guardfile', "guard :foo" )
lambda { subject.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error
subject.guardfile_contents.should == "guard :foo"
lambda { described_class.evaluate_guardfile(:guardfile => '/abc/Guardfile') }.should_not raise_error
described_class.guardfile_contents.should == "guard :foo"
end
it "reads correctly from a Guardfile" do
fake_guardfile(File.join(Dir.pwd, 'Guardfile'), valid_guardfile_string)
lambda { subject.evaluate_guardfile }.should_not raise_error
subject.guardfile_contents.should == valid_guardfile_string
lambda { described_class.evaluate_guardfile }.should_not raise_error
described_class.guardfile_contents.should == valid_guardfile_string
end
end
@ -116,14 +117,14 @@ describe Guard::Dsl do
File.stub!(:read).with('/def/Guardfile') { raise Errno::EACCES.new("permission error") }
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
it "raises error when given Guardfile doesn't exist" do
File.stub!(:exist?).with('/def/Guardfile') { false }
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
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 }
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
it "raises error when guardfile_content ends up empty or nil" do
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
it "doesn't raise error when guardfile_content is nil (skipped)" do
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
it "displays an error message when Guardfile is not valid" do
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
describe ".reevaluate_guardfile" do
@ -156,10 +157,10 @@ describe Guard::Dsl do
it "resets already definded guards before calling evaluate_guardfile" do
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::Dsl.should_receive(:evaluate_guardfile)
subject.reevaluate_guardfile
described_class.reevaluate_guardfile
::Guard.guards.should be_empty
end
end
@ -172,14 +173,14 @@ describe Guard::Dsl do
context "when there is a local Guardfile" do
it "returns the path to the local Guardfile" do
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
context "when there is a Guardfile in the user's home directory" do
it "returns the path to the user Guardfile" do
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
@ -187,34 +188,34 @@ describe Guard::Dsl do
it "returns the path to the local Guardfile" do
File.stub(:exist?).with(local_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
describe ".guardfile_include?" 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
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
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
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
@ -225,7 +226,7 @@ describe Guard::Dsl do
::Guard.stub!(:listener).and_return(mock('Listener'))
::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']
end
end
@ -234,43 +235,43 @@ describe Guard::Dsl do
disable_user_config
it "evaluates only the specified string group" do
::Guard.should_receive(:add_guard).with(:pow, [], [], { :group => :default })
::Guard.should_receive(:add_guard).with(:test, [], [], { :group => :w })
::Guard.should_receive(:add_guard).with('pow', [], [], { :group => :default })
::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
it "evaluates only the specified symbol group" do
::Guard.should_receive(:add_guard).with(:pow, [], [], { :group => :default })
::Guard.should_receive(:add_guard).with(:test, [], [], { :group => :w })
::Guard.should_receive(:add_guard).with('pow', [], [], { :group => :default })
::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
it "evaluates only the specified groups" do
::Guard.should_receive(:add_guard).with(:pow, [], [], { :group => :default })
::Guard.should_receive(:add_guard).with(:rspec, [], [], { :group => :x })
::Guard.should_receive(:add_guard).with(:ronn, [], [], { :group => :x })
::Guard.should_receive(:add_guard).with(:less, [], [], { :group => :y })
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('rspec', [], [], { :group => :x })
::Guard.should_receive(:add_guard).with('ronn', [], [], { :group => :x })
::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
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(:test, [], [], { :group => :w })
::Guard.should_receive(:add_guard).with('pow', [], [], { :group => :default })
::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
it "evaluates all groups when no group option is specified" do
::Guard.should_receive(:add_guard).with(:pow, [], [], { :group => :default })
::Guard.should_receive(:add_guard).with(:test, [], [], { :group => :w })
::Guard.should_receive(:add_guard).with(:rspec, [], [], { :group => :x })
::Guard.should_receive(:add_guard).with(:ronn, [], [], { :group => :x })
::Guard.should_receive(:add_guard).with(:less, [], [], { :group => :y })
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('test', [], [], { :group => :w })
::Guard.should_receive(:add_guard).with('rspec', [], [], { :group => :x })
::Guard.should_receive(:add_guard).with('ronn', [], [], { :group => :x })
::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
@ -278,33 +279,33 @@ describe Guard::Dsl do
disable_user_config
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
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
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
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
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
@ -312,14 +313,14 @@ describe Guard::Dsl do
disable_user_config
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[0].pattern.should == 'a'
watchers[0].action.call.should == proc { 'b' }.call
watchers[1].pattern.should == 'c'
watchers[1].action.should == nil
end
subject.evaluate_guardfile(:guardfile_contents => "
described_class.evaluate_guardfile(:guardfile_contents => "
guard :dummy do
watch('a') { 'b' }
watch('c')
@ -335,14 +336,14 @@ describe Guard::Dsl do
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[0][:events].should == :start_end
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][:listener].should == MyCustomCallback
end
subject.evaluate_guardfile(:guardfile_contents => '
described_class.evaluate_guardfile(:guardfile_contents => '
guard :dummy do
callback(:start_end) { |guard_class, event, args| "#{guard_class} executed \'#{event}\' hook with #{args}!" }
callback(MyCustomCallback, [:start_begin, :run_all_begin])
@ -361,17 +362,17 @@ private
"
guard :pow
group 'w' do
guard 'test'
group :w do
guard :test
end
group :x do
guard 'rspec'
group :x, :halt_on_fail => true do
guard :rspec
guard :ronn
end
group 'y' do
guard 'less'
group :y do
guard :less
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'
describe Guard::Hook do
subject { Guard::Hook }
class Guard::Dummy < Guard::Guard; end
let(:guard_class) { ::Guard::Dummy }
let(:listener) { double('listener').as_null_object }
after { subject.reset_callbacks! }
after { described_class.reset_callbacks! }
context "--module methods--" do
before { subject.add_callback(listener, guard_class, :start_begin) }
describe "--module methods--" do
before { described_class.add_callback(listener, guard_class, :start_begin) }
describe ".add_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
it "can add multiple callbacks" do
subject.add_callback(listener, guard_class, [:event1, :event2])
subject.has_callback?(listener, guard_class, :event1).should be_true
subject.has_callback?(listener, guard_class, :event2).should be_true
described_class.add_callback(listener, guard_class, [:event1, :event2])
described_class.has_callback?(listener, guard_class, :event1).should be_true
described_class.has_callback?(listener, guard_class, :event2).should be_true
end
end
describe ".notify" do
it "sends :call to the given Guard class's callbacks" do
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
it "runs only the given callbacks" do
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)
subject.notify(guard_class, :start_begin)
described_class.notify(guard_class, :start_begin)
end
it "runs callbacks only for the guard given" do
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)
subject.notify(guard_class, :start_begin)
described_class.notify(guard_class, :start_begin)
end
end
end

View File

@ -1,7 +1,6 @@
require 'spec_helper'
describe Guard::Listener do
subject { Guard::Listener }
describe ".select_and_init" do
before(:each) { @target_os = RbConfig::CONFIG['target_os'] }
@ -11,30 +10,30 @@ describe Guard::Listener do
RbConfig::CONFIG['target_os'] = 'darwin10.4.0'
Guard::Darwin.stub(:usable?).and_return(true)
Guard::Darwin.should_receive(:new)
subject.select_and_init
described_class.select_and_init
end
it "uses the Windows listener on Windows" do
RbConfig::CONFIG['target_os'] = 'mingw'
Guard::Windows.stub(:usable?).and_return(true)
Guard::Windows.should_receive(:new)
subject.select_and_init
described_class.select_and_init
end
it "uses the Linux listener on Linux" do
RbConfig::CONFIG['target_os'] = 'linux'
Guard::Linux.stub(:usable?).and_return(true)
Guard::Linux.should_receive(:new)
subject.select_and_init
described_class.select_and_init
end
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)
path, opts = 'path', { :foo => 23 }
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
@ -256,11 +255,11 @@ describe Guard::Listener do
describe "#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
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')
end
end
@ -281,4 +280,5 @@ describe Guard::Listener do
end
end
end
end

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,19 +5,19 @@ describe Guard::Watcher do
describe "#initialize" do
it "requires a pattern parameter" do
expect { Guard::Watcher.new }.to raise_error(ArgumentError)
expect { described_class.new }.to raise_error(ArgumentError)
end
context "with a pattern parameter" do
context "that is a string" 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
context "that is a regexp" 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
@ -25,10 +25,10 @@ describe Guard::Watcher do
before(:each) { Guard::UI.should_receive(:info).any_number_of_times }
it "converts the string automatically to a regex" do
Guard::Watcher.new('^spec_helper.rb').pattern.should == /^spec_helper.rb/
Guard::Watcher.new('spec_helper.rb$').pattern.should == /spec_helper.rb$/
Guard::Watcher.new('spec_helper\.rb').pattern.should == /spec_helper\.rb/
Guard::Watcher.new('.*_spec.rb').pattern.should == /.*_spec.rb/
described_class.new('^spec_helper.rb').pattern.should == /^spec_helper.rb/
described_class.new('spec_helper.rb$').pattern.should == /spec_helper.rb$/
described_class.new('spec_helper\.rb').pattern.should == /spec_helper\.rb/
described_class.new('.*_spec.rb').pattern.should == /.*_spec.rb/
end
end
end
@ -36,12 +36,12 @@ describe Guard::Watcher do
describe "#action" 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
it "sets the action to the supplied block" do
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
@ -50,18 +50,18 @@ describe Guard::Watcher do
context "with a watcher without action" 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
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
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
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
@ -69,79 +69,79 @@ describe Guard::Watcher do
context "with a watcher action without parameter" do
before(:all) do
@guard.watchers = [
Guard::Watcher.new('spec_helper.rb', lambda { 'spec' }),
Guard::Watcher.new('addition.rb', lambda { 1 + 1 }),
Guard::Watcher.new('hash.rb', lambda { Hash[:foo, 'bar'] }),
Guard::Watcher.new('array.rb', lambda { ['foo', 'bar'] }),
Guard::Watcher.new('blank.rb', lambda { '' }),
Guard::Watcher.new(/^uptime\.rb/, lambda { `uptime > /dev/null` })
described_class.new('spec_helper.rb', lambda { 'spec' }),
described_class.new('addition.rb', lambda { 1 + 1 }),
described_class.new('hash.rb', lambda { Hash[:foo, 'bar'] }),
described_class.new('array.rb', lambda { ['foo', 'bar'] }),
described_class.new('blank.rb', lambda { '' }),
described_class.new(/^uptime\.rb/, lambda { `uptime > /dev/null` })
]
end
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
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
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
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
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
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
context "with a watcher action that takes a parameter" do
before(:all) do
@guard.watchers = [
Guard::Watcher.new(%r{lib/(.*)\.rb}, lambda { |m| "spec/#{m[1]}_spec.rb" }),
Guard::Watcher.new(/addition(.*)\.rb/, lambda { |m| 1 + 1 }),
Guard::Watcher.new('hash.rb', lambda { Hash[:foo, 'bar'] }),
Guard::Watcher.new(/array(.*)\.rb/, lambda { |m| ['foo', 'bar'] }),
Guard::Watcher.new(/blank(.*)\.rb/, lambda { |m| '' }),
Guard::Watcher.new(/uptime(.*)\.rb/, lambda { |m| `uptime > /dev/null` })
described_class.new(%r{lib/(.*)\.rb}, lambda { |m| "spec/#{m[1]}_spec.rb" }),
described_class.new(/addition(.*)\.rb/, lambda { |m| 1 + 1 }),
described_class.new('hash.rb', lambda { Hash[:foo, 'bar'] }),
described_class.new(/array(.*)\.rb/, lambda { |m| ['foo', 'bar'] }),
described_class.new(/blank(.*)\.rb/, lambda { |m| '' }),
described_class.new(/uptime(.*)\.rb/, lambda { |m| `uptime > /dev/null` })
]
end
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
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
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
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
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
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
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
Guard::UI.should_receive(:error) { |msg|
@ -149,31 +149,31 @@ describe Guard::Watcher do
msg.should include("EVIL")
}
Guard::Watcher.match_files(@guard, ['evil.rb'])
described_class.match_files(@guard, ['evil.rb'])
end
end
end
describe ".match_files?" do
before(:all) do
@guard1 = Guard::Guard.new([Guard::Watcher.new(/.*_spec\.rb/)])
@guard2 = Guard::Guard.new([Guard::Watcher.new('spec_helper.rb', 'spec')])
@guard1 = Guard::Guard.new([described_class.new(/.*_spec\.rb/)])
@guard2 = Guard::Guard.new([described_class.new('spec_helper.rb', 'spec')])
@guards = [@guard1, @guard2]
end
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
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
describe "#match_file?" do
context "with a string pattern" 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
specify { subject.match_file?('guard_rocks_spec.rb').should be_true }
@ -185,7 +185,7 @@ describe Guard::Watcher do
end
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
specify { subject.match_file?('guard_rocks_spec.rb').should be_true }
@ -198,7 +198,7 @@ describe Guard::Watcher do
end
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
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' } }
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
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

View File

@ -15,7 +15,8 @@ describe Guard do
end
it "initializes @groups" do
Guard.groups.should eql [:default]
described_class.groups[0].name.should eql :default
described_class.groups[0].options.should == {}
end
it "initializes the options" do
@ -55,6 +56,118 @@ describe Guard do
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
it "basic check that core methods are called" do
opts = { :my_opts => true, :guardfile => File.join(@fixture_path, "Guardfile") }
@ -129,22 +242,28 @@ describe Guard do
end
end
describe ".add_group" do
before(:each) do
Guard.setup
end
subject { ::Guard.setup }
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
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
@ -223,12 +342,63 @@ describe Guard do
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
subject { ::Guard.setup }
before(:each) do
before do
@g = mock(Guard::Guard).as_null_object
subject.guards.push(@g)
subject.add_group(:foo, { :halt_on_fail => true })
end
context "with a task that succeed" do
@ -278,6 +448,14 @@ describe Guard do
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
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.filter_run :focus => true
config.treat_symbols_as_metadata_keys_with_true_values = true
config.run_all_when_everything_filtered = true
config.before(:each) do

View File

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