Skip to content
Browse files

Merge pull request #378 from guard/scope-plugins-and-groups

Scope plugins and groups
  • Loading branch information...
2 parents 005a06a + 2c28e23 commit c4ebdd167857ad4bbce9a0ac7b9e3363862d649b @netzpirat netzpirat committed Dec 19, 2012
View
12 README.md
@@ -374,7 +374,7 @@ Notifications can also be disabled globally by setting a `GUARD_NOTIFY` environm
#### `-g`/`--group` option
-Only certain plugin groups can be run:
+Scope Guard to certain plugin groups on start:
```bash
$ guard --group group_name another_group_name
@@ -383,6 +383,15 @@ $ guard -g group_name another_group_name # shortcut
See the Guardfile DSL below for creating groups.
+#### `-P`/`--plugins` option
+
+Scope Guard to certain plugins on start:
+
+```bash
+$ guard --plugins plugin_name another_plugin_name
+$ guard -p plugin_name another_plugin_name # shortcut
+```
+
#### `-d`/`--debug` option
Guard can display debug information which can be very usefull for plugins
@@ -499,6 +508,7 @@ commands:
* `n`, `notification`: Toggles the notifications.
* `p`, `pause`: Toggles the file listener.
* `r`, `reload`: Reload all plugins.
+ * `o`, `scope`: Scope Guard actions to plugins or groups.
* `s`, `show`: Show all Guard plugins.
* `e`, `exit`: Stop all plugins and quit Guard
View
2 guard.gemspec
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
s.add_development_dependency 'bundler'
s.add_development_dependency 'rspec', '~> 2.12.0'
- s.add_development_dependency 'guard-rspec', '~> 2.1.0'
+ s.add_development_dependency 'guard-rspec', '~> 2.3.0'
s.files = Dir.glob('{bin,images,lib}/**/*') + %w[CHANGELOG.md LICENSE man/guard.1 man/guard.1.html README.md]
s.executable = 'guard'
View
36 lib/guard.rb
@@ -26,7 +26,7 @@ module Guard
DEV_NULL = WINDOWS ? "NUL" : "/dev/null"
class << self
- attr_accessor :options, :interactor, :runner, :listener, :lock
+ attr_accessor :options, :interactor, :runner, :listener, :lock, :scope
# Initialize the Guard singleton:
#
@@ -48,8 +48,9 @@ def setup(options = {})
@options = options
@watchdir = (options[:watchdir] && File.expand_path(options[:watchdir])) || Dir.pwd
@runner = ::Guard::Runner.new
+ @scope = { :plugins => [], :groups => []}
- if @options[:debug]
+ if options[:debug]
Thread.abort_on_exception = true
::Guard::UI.options[:level] = :debug
debug_command_execution
@@ -66,6 +67,14 @@ def setup(options = {})
::Guard::Dsl.evaluate_guardfile(options)
::Guard::UI.error 'No guards found in Guardfile, please add at least one.' if @guards.empty?
+ if options[:group]
+ @scope[:groups] = options[:group].map { |g| ::Guard.groups(g) }
+ end
+
+ if options[:plugin]
+ @scope[:plugins] = options[:plugin].map { |p| ::Guard.guards(p) }
+ end
+
runner.deprecation_warning if @options[:show_deprecations]
setup_notifier
@@ -189,6 +198,8 @@ def stop
# @param [Hash] scopes hash with a Guard plugin or a group scope
#
def reload(scopes = {})
+ scopes = convert_scopes(scopes)
+
within_preserved_state do
::Guard::UI.clear(:force => true)
::Guard::UI.action_with_scopes('Reload', scopes)
@@ -206,6 +217,8 @@ def reload(scopes = {})
# @param [Hash] scopes hash with a Guard plugin or a group scope
#
def run_all(scopes = {})
+ scopes = convert_scopes(scopes)
+
within_preserved_state do
::Guard::UI.clear(:force => true)
::Guard::UI.action_with_scopes('Run', scopes)
@@ -455,5 +468,24 @@ def deprecated_options_warning
::Guard::UI.deprecation(NO_VENDOR_DEPRECATION) if options[:no_vendor]
end
+ # Convert the old scope format to the new scope format.
+ #
+ # @example Convert old scopes
+ # convert_scopes({ :guard => :rspec, :group => :backend })
+ # => { :plugins => [:rspec], :groups => [:backend] }
+ #
+ def convert_scopes(scopes)
+ if scopes[:guard]
+ scopes[:plugins] = [scopes[:guard]]
+ scopes.delete(:guard)
+ end
+
+ if scopes[:group]
+ scopes[:groups] = [scopes[:group]]
+ scopes.delete(:group)
+ end
+
+ scopes
+ end
end
end
View
6 lib/guard/cli.rb
@@ -41,6 +41,12 @@ class CLI < Thor
:aliases => '-g',
:banner => 'Run only the passed groups'
+ method_option :plugin,
+ :type => :array,
+ :default => [],
+ :aliases => '-P',
+ :banner => 'Run only the passed plugins'
+
method_option :watchdir,
:type => :string,
:aliases => '-w',
View
32 lib/guard/commands/scope.rb
@@ -0,0 +1,32 @@
+module Guard
+ class Interactor
+
+ SCOPE = Pry::CommandSet.new do
+ create_command 'scope' do
+
+ group 'Guard'
+ description 'Scope Guard actions to groups and plugins.'
+
+ banner <<-BANNER
+ Usage: scope <scope>
+
+ Set the global Guard scope.
+ BANNER
+
+ def process(*entries)
+ scope, rest = ::Guard::Interactor.convert_scope(entries)
+
+ if rest.length == 0
+ ::Guard.scope = scope
+ else
+ output.puts "Unkown scope #{ rest.join(', ') }"
+ end
+ end
+
+ end
+ end
+
+ end
+end
+
+Pry.commands.import ::Guard::Interactor::SCOPE
View
3 lib/guard/dsl.rb
@@ -361,10 +361,9 @@ def interactor(options)
# @see Guard::DslDescriber
#
def group(name, options = {})
- @groups = @@options[:group] || []
name = name.to_sym
- if block_given? && (@groups.empty? || @groups.map(&:to_sym).include?(name))
+ if block_given?
::Guard.add_group(name.to_s.downcase, options)
@current_group = name
View
2 lib/guard/group.rb
@@ -37,7 +37,7 @@ def initialize(name, options = {})
# @return [String] the group name
#
def to_s
- "#{@name} group"
+ @name.to_s.capitalize
end
end
View
13 lib/guard/guard.rb
@@ -60,13 +60,13 @@ def initialize(watchers = [], options = {})
# Specify the source for the Guardfile template.
# Each Guard plugin can redefine this method to add its own logic.
- #
+ #
# @param [String] The plugin name
- #
+ #
def self.template(name)
File.read("#{ ::Guard.locate_guard(name) }/lib/guard/#{ name }/templates/Guardfile")
end
-
+
# Initialize the Guard plugin. This will copy the Guardfile template inside the Guard plugin gem.
# The template Guardfile must be located within the Gem at `lib/guard/guard-name/templates/Guardfile`.
#
@@ -152,12 +152,13 @@ def self.init(name)
# @!method run_on_removals(paths)
# Convert plugin to string representation. The
- # default just uses the plugin class name.
- #
+ # default just uses the plugin class name and
+ # removes the Guard module name.
+ #
# @return [String] the string representation
#
def to_s
- self.class.to_s
+ self.class.to_s.downcase.sub('guard::', '').capitalize
end
end
View
69 lib/guard/interactor.rb
@@ -15,22 +15,37 @@ class Interactor
require 'guard/commands/notification'
require 'guard/commands/pause'
require 'guard/commands/reload'
+ require 'guard/commands/scope'
require 'guard/commands/show'
# The default Ruby script to configure Guard Pry if the option `:guard_rc` is not defined.
- GUARD_RC = '~/.guardrc'
+ GUARD_RC = '~/.guardrc'
# The default Guard Pry history file if the option `:history_file` is not defined.
HISTORY_FILE = '~/.guard_history'
+ # List of shortcuts for each interactor command
+ SHORTCUTS = {
+ :help => 'h',
+ :all => 'a',
+ :reload => 'r',
+ :change => 'c',
+ :show => 's',
+ :scope => 'o',
+ :notification => 'n',
+ :pause => 'p',
+ :exit => 'e',
+ :quit => 'q'
+ }
+
class << self
# Get the interactor options
#
# @return [Hash] the options
#
def options
- @options ||= {}
+ @options ||= { }
end
# Set the interactor options
@@ -68,9 +83,9 @@ def enabled=(status)
def initialize
return if ENV['GUARD_ENV'] == 'test'
- Pry.config.should_load_rc = false
+ Pry.config.should_load_rc = false
Pry.config.should_load_local_rc = false
- Pry.config.history.file = self.class.options[:history_file] || HISTORY_FILE
+ Pry.config.history.file = self.class.options[:history_file] || HISTORY_FILE
load_guard_rc
@@ -101,12 +116,12 @@ def create_run_all_command
end
# Creates command aliases for the commands
- # `help`, `reload`, `change`, `show`, `notification`, `pause`, `exit` and `quit`,
+ # `help`, `reload`, `change`, `scope`, `notification`, `pause`, `exit` and `quit`,
# which will be the first letter of the command.
#
def create_command_aliases
- %w(help all reload change show notification pause exit quit).each do |command|
- Pry.commands.alias_command command[0].chr, command
+ SHORTCUTS.each do |command, shortcut|
+ Pry.commands.alias_command shortcut, command
end
end
@@ -155,10 +170,34 @@ def process
def configure_prompt
Pry.config.prompt = [
proc do |target_self, nest_level, pry|
- "[#{ pry.input_array.size }] #{ ::Guard.listener.paused? ? 'pause' : 'guard' }(#{ Pry.view_clip(target_self) })#{":#{ nest_level }" unless nest_level.zero? }> "
+ history = pry.input_array.size
+ process = ::Guard.listener.paused? ? 'pause' : 'guard'
+ clip = Pry.view_clip(target_self)
+ level = ":#{ nest_level }" unless nest_level.zero?
+ scope = if !::Guard.scope[:plugins].empty?
+ "{#{ ::Guard.scope[:plugins].join }} "
+ elsif !::Guard.scope[:groups].empty?
+ "{#{ ::Guard.scope[:groups].join }} "
+ else
+ ''
+ end
+
+ "[#{ history }] #{ scope }#{ process }(#{ clip })#{ level }> "
end,
proc do |target_self, nest_level, pry|
- "[#{ pry.input_array.size }] #{ ::Guard.listener.paused? ? 'pause' : 'guard' }(#{ Pry.view_clip(target_self) })#{":#{ nest_level }" unless nest_level.zero? }* "
+ history = pry.input_array.size
+ process = ::Guard.listener.paused? ? 'pause' : 'guard'
+ clip = Pry.view_clip(target_self)
+ level = ":#{ nest_level }" unless nest_level.zero?
+ scope = if !::Guard.scope[:plugins].empty?
+ "{#{ ::Guard.scope[:plugins].join }} "
+ elsif !::Guard.scope[:groups].empty?
+ "{#{ ::Guard.scope[:groups].join }} "
+ else
+ ''
+ end
+
+ "[#{ history }] #{ scope }#{ process }(#{ clip })#{ level }* "
end
]
end
@@ -208,13 +247,13 @@ def stty_exists?
# when stopping.
#
def store_terminal_settings
- @stty_save = `stty -g 2>#{DEV_NULL}`.chomp
+ @stty_save = `stty -g 2>#{ DEV_NULL }`.chomp
end
# Restore terminal settings
#
def restore_terminal_settings
- system("stty #{ @stty_save } 2>#{DEV_NULL}") if @stty_save
+ system("stty #{ @stty_save } 2>#{ DEV_NULL }") if @stty_save
end
# Converts and validates a plain text scope
@@ -224,14 +263,14 @@ def restore_terminal_settings
# @return [Hash, Array<String>] the plugin or group scope, the unknown entries
#
def self.convert_scope(entries)
- scopes = { }
+ scopes = { :plugins => [], :groups => [] }
unknown = []
entries.each do |entry|
- if guard = ::Guard.guards(entry)
- scopes[:guard] ||= guard
+ if plugin = ::Guard.guards(entry)
+ scopes[:plugins] << plugin
elsif group = ::Guard.groups(entry)
- scopes[:group] ||= group
+ scopes[:groups] << group
else
unknown << entry
end
View
54 lib/guard/runner.rb
@@ -7,7 +7,7 @@ class Runner
require 'guard'
require 'guard/ui'
require 'guard/watcher'
-
+
require 'lumberjack'
# Deprecation message for the `run_on_change` method
@@ -153,18 +153,23 @@ def run_first_task_found(guard, tasks, task_param)
# Loop through all groups and run the given task for each Guard plugin.
#
+ # If no scope is supplied, the global Guard scope is taken into account.
+ # If both a plugin and a group scope is given, then only the plugin scope
+ # is used.
+ #
# Stop the task run for the all Guard plugins within a group if one Guard
# throws `:task_has_failed`.
#
- # @param [Hash] scopes hash with a Guard plugin or a group scope
+ # @param [Hash] scopes hash with plugins or a groups scope
# @yield the task to run
#
def scoped_guards(scopes = {})
- if guard = scopes[:guard]
- yield(guard)
+ if guards = current_plugins_scope(scopes)
+ guards.each do |guard|
+ yield(guard)
+ end
else
- groups = scopes[:group] ? [scopes[:group]] : ::Guard.groups
- groups.each do |group|
+ current_groups_scope(scopes).each do |group|
catch :task_has_failed do
::Guard.guards(:group => group.name).each do |guard|
yield(guard)
@@ -188,5 +193,42 @@ def clearable?(guard, modified_paths, added_paths, removed_paths)
(REMOVAL_TASKS.any? { |task| guard.respond_to?(task) } && !removed_paths.empty?)
end
+ # Returns the current plugins scope.
+ # Local plugins scope wins over global plugins scope.
+ # If no plugins scope is found, then NO plugins are returned.
+ #
+ # @param [Hash] scopes hash with a local plugins or a groups scope
+ # @return [Array<Guard::Guard>] the plugins to scope to
+ #
+ def current_plugins_scope(scopes)
+ if scopes[:plugins] && !scopes[:plugins].empty?
+ scopes[:plugins]
+
+ elsif !::Guard.scope[:plugins].empty?
+ ::Guard.scope[:plugins]
+
+ else
+ nil
+ end
+ end
+
+ # Returns the current groups scope.
+ # Local groups scope wins over global groups scope.
+ # If no groups scope is found, then ALL groups are returned.
+ #
+ # @param [Hash] scopes hash with a local plugins or a groups scope
+ # @return [Array<Guard::Group>] the groups to scope to
+ #
+ def current_groups_scope(scopes)
+ if scopes[:groups] && !scopes[:groups].empty?
+ scopes[:groups]
+
+ elsif !::Guard.scope[:groups].empty?
+ ::Guard.scope[:groups]
+
+ else
+ ::Guard.groups
+ end
+ end
end
end
View
24 lib/guard/ui.rb
@@ -10,15 +10,15 @@ module Guard
# processing, please just write it to STDOUT with `puts`.
#
module UI
-
+
class << self
# Get the Guard::UI logger instance
#
def logger
@logger ||= Lumberjack::Logger.new($stderr, self.options)
end
-
+
# Get the logger options
#
# @return [Hash] the logger options
@@ -131,27 +131,35 @@ def clearable
# @param [Hash] scopes hash with a guard or a group scope
#
def action_with_scopes(action, scopes)
- scope_message ||= scopes[:guard]
- scope_message ||= scopes[:group]
+ plugins = scopes[:plugins] || []
+ groups = scopes[:groups] || []
+
+ if plugins.empty? && groups.empty?
+ plugins = ::Guard.scope[:plugins] || []
+ groups = ::Guard.scope[:groups] || []
+ end
+
+ scope_message ||= plugins.join(',') unless plugins.empty?
+ scope_message ||= groups.join(',') unless groups.empty?
scope_message ||= 'all'
- info "#{action} #{scope_message}"
+ info "#{ action } #{ scope_message }"
end
private
-
+
# Filters log messages depending on either the
# `:only`` or `:except` option.
#
# @param [String] plugin the calling plugin name
# @yield When the message should be logged
- # @yieldparam [String] param the calling plugin name
+ # @yieldparam [String] param the calling plugin name
#
def filter(plugin)
only = self.options[:only]
except = self.options[:except]
plugin = plugin || calling_plugin_name
-
+
if (!only && !except) || (only && only.match(plugin)) || (except && !except.match(plugin))
yield plugin
end
View
6 spec/guard/commands/all_spec.rb
@@ -16,21 +16,21 @@
describe '#perform' do
context 'without scope' do
it 'runs the :run_all action' do
- Guard.should_receive(:run_all).with({})
+ Guard.should_receive(:run_all).with({ :groups => [], :plugins => [] })
Pry.run_command 'all'
end
end
context 'with a valid Guard group scope' do
it 'runs the :run_all action with the given scope' do
- Guard.should_receive(:run_all).with({ :group => foo_group })
+ Guard.should_receive(:run_all).with({ :groups => [foo_group], :plugins => [] })
Pry.run_command 'all foo'
end
end
context 'with a valid Guard plugin scope' do
it 'runs the :run_all action with the given scope' do
- Guard.should_receive(:run_all).with({ :guard => bar_guard })
+ Guard.should_receive(:run_all).with({ :plugins => [bar_guard], :groups => [] })
Pry.run_command 'all bar'
end
end
View
6 spec/guard/commands/reload_spec.rb
@@ -16,21 +16,21 @@
describe '#perform' do
context 'without scope' do
it 'runs the :reload action' do
- Guard.should_receive(:reload).with({})
+ Guard.should_receive(:reload).with({ :groups => [], :plugins => [] })
Pry.run_command 'reload'
end
end
context 'with a valid Guard group scope' do
it 'runs the :reload action with the given scope' do
- Guard.should_receive(:reload).with({ :group => foo_group })
+ Guard.should_receive(:reload).with({ :groups => [foo_group], :plugins => [] })
Pry.run_command 'reload foo'
end
end
context 'with a valid Guard plugin scope' do
it 'runs the :reload action with the given scope' do
- Guard.should_receive(:reload).with({ :guard => bar_guard })
+ Guard.should_receive(:reload).with({ :plugins => [bar_guard], :groups => [] })
Pry.run_command 'reload bar'
end
end
View
32 spec/guard/dsl_spec.rb
@@ -422,37 +422,7 @@ def self.disable_user_config
describe "#group" 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 })
-
- 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 })
-
- described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string, :group => [:w])
- end
-
- 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 })
-
- 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 })
-
- described_class.evaluate_guardfile(:guardfile_contents => valid_guardfile_string, :group => [:w])
- end
-
- it "evaluates all groups when no group option is specified (with their options)" do
+ it "evaluates all groups" 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 })
View
2 spec/guard/group_spec.rb
@@ -19,7 +19,7 @@
describe '#to_s' do
it "output Group properly" do
group = described_class.new(:foo)
- group.to_s.should eq "foo group"
+ group.to_s.should eq "Foo"
end
end
View
4 spec/guard/guard_spec.rb
@@ -61,9 +61,9 @@
describe '#to_s' do
before(:all) { class Guard::Dummy < Guard::Guard; end }
- it "output Guard properly" do
+ it "output the short plugin name" do
guard = Guard::Dummy.new
- guard.to_s.should eq "Guard::Dummy"
+ guard.to_s.should eq "Dummy"
end
end
View
23 spec/guard/interactor_spec.rb
@@ -17,16 +17,31 @@
it 'returns a group scope' do
scopes, _ = Guard::Interactor.convert_scope %w(backend)
- scopes.should eql({ :group => @backend_group })
+ scopes.should eql({ :groups => [@backend_group], :plugins => [] })
scopes, _ = Guard::Interactor.convert_scope %w(frontend)
- scopes.should eql({ :group => @frontend_group })
+ scopes.should eql({ :groups => [@frontend_group], :plugins => [] })
end
it 'returns a plugin scope' do
scopes, _ = Guard::Interactor.convert_scope %w(foo)
- scopes.should eql({ :guard => @foo_guard })
+ scopes.should eql({ :plugins => [@foo_guard], :groups => [] })
scopes, _ = Guard::Interactor.convert_scope %w(bar)
- scopes.should eql({ :guard => @bar_guard })
+ scopes.should eql({ :plugins => [@bar_guard], :groups => [] })
+ end
+
+ it 'returns multiple group scopes' do
+ scopes, _ = Guard::Interactor.convert_scope %w(backend frontend)
+ scopes.should eql({ :groups => [@backend_group, @frontend_group], :plugins => [] })
+ end
+
+ it 'returns multiple plugin scopes' do
+ scopes, _ = Guard::Interactor.convert_scope %w(foo bar)
+ scopes.should eql({ :plugins => [@foo_guard, @bar_guard], :groups => [] })
+ end
+
+ it 'returns a plugin and group scope' do
+ scopes, _ = Guard::Interactor.convert_scope %w(foo backend)
+ scopes.should eql({ :plugins => [@foo_guard], :groups => [@backend_group] })
end
it 'returns the unkown scopes' do
View
12 spec/guard/runner_spec.rb
@@ -90,8 +90,8 @@
end
end
- context 'within the scope of a specified guard' do
- let(:scopes) { { :guard => bar1_guard } }
+ context 'within the scope of a specified local guard' do
+ let(:scopes) { { :plugins => [bar1_guard] } }
it 'executes the supervised task on the specified guard only' do
subject.should_receive(:run_supervised_task).with(bar1_guard, :my_task)
@@ -103,8 +103,8 @@
end
end
- context 'within the scope of a specified group' do
- let(:scopes) { { :group => foo_group } }
+ context 'within the scope of a specified local group' do
+ let(:scopes) { { :groups => [foo_group] } }
it 'executes the task on each guard in the specified group only' do
subject.should_receive(:run_supervised_task).with(foo_guard, :my_task)
@@ -121,11 +121,11 @@
let(:changes) { [ [], [], [] ] }
let(:watcher_module) { ::Guard::Watcher }
- before {
+ before do
subject.stub(:scoped_guards).and_yield(foo_guard)
subject.stub(:clearable?) { false }
watcher_module.stub(:match_files) { [] }
- }
+ end
it "always calls UI.clearable" do
Guard::UI.should_receive(:clearable)
View
34 spec/guard/ui_spec.rb
@@ -276,4 +276,38 @@
end
end
+ describe '.action_with_scopes' do
+ context 'with a plugins scope' do
+ it 'shows the plugin scoped action' do
+ Guard::UI.should_receive(:info).with('Reload rspec,jasmine')
+ Guard::UI.action_with_scopes('Reload', { :plugins => [:rspec, :jasmine] })
+ end
+ end
+
+ context 'with a groups scope' do
+ it 'shows the group scoped action' do
+ Guard::UI.should_receive(:info).with('Reload frontend')
+ Guard::UI.action_with_scopes('Reload', { :groups => [:frontend] })
+ end
+ end
+
+ context 'without a scope' do
+ context 'with a global plugin scope' do
+ it 'shows the global plugin scoped action' do
+ Guard.scope = { :groups => [:test] }
+ Guard::UI.should_receive(:info).with('Reload test')
+ Guard::UI.action_with_scopes('Reload', {})
+ end
+ end
+
+ context 'with a global group scope' do
+ it 'shows the global group scoped action' do
+ Guard.scope = { :groups => [:backend] }
+ Guard::UI.should_receive(:info).with('Reload backend')
+ Guard::UI.action_with_scopes('Reload', {})
+ end
+ end
+ end
+ end
+
end
View
145 spec/guard_spec.rb
@@ -13,13 +13,13 @@
subject.should be ::Guard
end
- it "initializes @guards" do
+ it "initializes the plugins" do
subject.guards.should eq []
end
- it "initializes @groups" do
+ it "initializes the groups" do
subject.groups[0].name.should eq :default
- subject.groups[0].options.should == {}
+ subject.groups[0].options.should == { }
end
it "initializes the options" do
@@ -61,6 +61,46 @@
subject
end
+ context 'without the group or plugin option' do
+ it "initializes the empty scope" do
+ subject.scope.should == { :groups => [], :plugins => [] }
+ end
+ end
+
+ context 'with the group option' do
+ let(:options) { {
+ :group => ['backend', 'frontend'],
+ :guardfile_contents => "group :backend do; end; group :frontend do; end; group :excluded do; end"
+ } }
+
+ it "initializes the group scope" do
+ subject.scope[:plugins].should be_empty
+ subject.scope[:groups].count.should be 2
+ subject.scope[:groups][0].name.should eql :backend
+ subject.scope[:groups][1].name.should eql :frontend
+ end
+ end
+
+ context 'with the plugin option' do
+ let(:options) { {
+ :plugin => ['cucumber', 'jasmine'],
+ :guardfile_contents => "guard :jasmine do; end; guard :cucumber do; end; guard :coffeescript do; end"
+ } }
+
+ before do
+ stub_const 'Guard::Jasmine', Class.new(Guard::Guard)
+ stub_const 'Guard::Cucumber', Class.new(Guard::Guard)
+ stub_const 'Guard::CoffeeScript', Class.new(Guard::Guard)
+ end
+
+ it "initializes the plugin scope" do
+ subject.scope[:groups].should be_empty
+ subject.scope[:plugins].count.should be 2
+ subject.scope[:plugins][0].class.should eql ::Guard::Cucumber
+ subject.scope[:plugins][1].class.should eql ::Guard::Jasmine
+ end
+ end
+
context 'when deprecations should be shown' do
let(:options) { { :show_deprecations => true, :guardfile => File.join(@fixture_path, "Guardfile") } }
subject { ::Guard.setup(options) }
@@ -270,7 +310,7 @@
describe ".setup_interactor" do
context 'with CLI options' do
before do
- @enabled = ::Guard::Interactor.enabled
+ @enabled = ::Guard::Interactor.enabled
::Guard::Interactor.enabled = true
end
@@ -330,35 +370,49 @@
subject.reload
end
- context 'with a scope' do
+ context 'with a old scope format' do
it 'does not re-evaluate the Guardfile' do
::Guard::Dsl.should_not_receive(:reevaluate_guardfile)
subject.reload({ :group => :frontend })
end
it 'reloads Guard' do
- ::Guard.should_receive(:reload).with({ :group => :frontend })
+ runner.should_receive(:run).with(:reload, { :groups => [:frontend] })
subject.reload({ :group => :frontend })
end
end
+ context 'with a new scope format' do
+ it 'does not re-evaluate the Guardfile' do
+ ::Guard::Dsl.should_not_receive(:reevaluate_guardfile)
+ subject.reload({ :groups => [:frontend] })
+ end
+
+ it 'reloads Guard' do
+ runner.should_receive(:run).with(:reload, { :groups => [:frontend] })
+ subject.reload({ :groups => [:frontend] })
+ end
+ end
+
context 'with an empty scope' do
it 'does re-evaluate the Guardfile' do
::Guard::Dsl.should_receive(:reevaluate_guardfile)
subject.reload
end
it 'does not reload Guard' do
- ::Guard.should_not_receive(:reload).with({ })
+ runner.should_not_receive(:run).with(:reload, { })
subject.reload
end
end
end
describe ".guards" do
before(:all) do
- class Guard::FooBar < Guard::Guard; end
- class Guard::FooBaz < Guard::Guard; end
+ class Guard::FooBar < Guard::Guard;
+ end
+ class Guard::FooBaz < Guard::Guard;
+ end
end
after(:all) do
@@ -369,7 +423,7 @@ class Guard::FooBaz < Guard::Guard; end
end
subject do
- guard = ::Guard.setup
+ 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' })
@@ -385,7 +439,7 @@ class Guard::FooBaz < Guard::Guard; end
subject.guards.should == subject.instance_variable_get("@guards")
end
- describe "find a guard by as string/symbol" do
+ context "find a guard by as string/symbol" do
it "find a guard by a string" do
subject.guards('foo-bar').should == @guard_foo_bar_backend
end
@@ -399,7 +453,7 @@ class Guard::FooBaz < Guard::Guard; end
end
end
- describe "find guards matching a regexp" do
+ context "find guards matching a regexp" do
it "with matches" do
subject.guards(/^foobar/).should == [@guard_foo_bar_backend, @guard_foo_bar_frontend]
end
@@ -409,7 +463,7 @@ class Guard::FooBaz < Guard::Guard; end
end
end
- describe "find guards by their group" do
+ context "find guards by their group" do
it "group name is a string" do
subject.guards(:group => 'backend').should == [@guard_foo_bar_backend, @guard_foo_baz_backend]
end
@@ -423,7 +477,7 @@ class Guard::FooBaz < Guard::Guard; end
end
end
- describe "find guards by their group & name" do
+ context "find guards by their group & name" do
it "group name is a string" do
subject.guards(:group => 'backend', :name => 'foo-bar').should == [@guard_foo_bar_backend]
end
@@ -440,17 +494,19 @@ class Guard::FooBaz < Guard::Guard; end
describe ".groups" do
subject do
- guard = ::Guard.setup
+ 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 == subject.instance_variable_get("@groups")
+ context 'without any argument' do
+ it "return all groups" do
+ subject.groups.should == subject.instance_variable_get("@groups")
+ end
end
- describe "find a group by as string/symbol" do
+ context "find a group by as string/symbol" do
it "find a group by a string" do
subject.groups('backend').should == @group_backend
end
@@ -464,7 +520,7 @@ class Guard::FooBaz < Guard::Guard; end
end
end
- describe "find groups matching a regexp" do
+ context "find groups matching a regexp" do
it "with matches" do
subject.groups(/^back/).should == [@group_backend, @group_backflip]
end
@@ -477,32 +533,32 @@ class Guard::FooBaz < Guard::Guard; end
describe ".setup_groups" do
subject do
- guard = ::Guard.setup(:guardfile => File.join(@fixture_path, "Guardfile"))
+ guard = ::Guard.setup(:guardfile => File.join(@fixture_path, "Guardfile"))
@group_backend = guard.add_group(:backend)
@group_backflip = guard.add_group(:backflip)
guard
end
- it "return @groups without any argument" do
- subject.groups.should have(3).items
-
+ it "initializes a default group" do
subject.setup_groups
subject.groups.should have(1).item
subject.groups[0].name.should eq :default
- subject.groups[0].options.should == {}
+ subject.groups[0].options.should == { }
end
end
describe ".setup_guards" do
- before(:all) { class Guard::FooBar < Guard::Guard; end }
+ before(:all) {
+ class Guard::FooBar < Guard::Guard;
+ end }
after(:all) do
::Guard.instance_eval { remove_const(:FooBar) }
end
subject do
- guard = ::Guard.setup(:guardfile => File.join(@fixture_path, "Guardfile"))
+ guard = ::Guard.setup(:guardfile => File.join(@fixture_path, "Guardfile"))
@group_backend = guard.add_guard(:foo_bar)
guard
end
@@ -554,7 +610,7 @@ class Guard::FooBaz < Guard::Guard; end
describe ".add_guard" do
before do
@guard_rspec_class = double('Guard::RSpec')
- @guard_rspec = double('Guard::RSpec', :is_a? => true)
+ @guard_rspec = double('Guard::RSpec', :is_a? => true)
::Guard.stub!(:get_guard_class) { @guard_rspec_class }
@@ -585,25 +641,25 @@ class Guard::FooBaz < Guard::Guard; end
context "with no watchers given" do
it "gives an empty array of watchers" do
- @guard_rspec_class.should_receive(:new).with([], {}).and_return(@guard_rspec)
+ @guard_rspec_class.should_receive(:new).with([], { }).and_return(@guard_rspec)
::Guard.add_guard(:rspec, [])
end
end
context "with watchers given" do
it "give the watchers array" do
- @guard_rspec_class.should_receive(:new).with([:foo], {}).and_return(@guard_rspec)
+ @guard_rspec_class.should_receive(:new).with([:foo], { }).and_return(@guard_rspec)
::Guard.add_guard(:rspec, [:foo])
end
end
context "with no options given" do
it "gives an empty hash of options" do
- @guard_rspec_class.should_receive(:new).with([], {}).and_return(@guard_rspec)
+ @guard_rspec_class.should_receive(:new).with([], { }).and_return(@guard_rspec)
- ::Guard.add_guard(:rspec, [], [], {})
+ ::Guard.add_guard(:rspec, [], [], { })
end
end
@@ -636,18 +692,18 @@ class Guard::FooBaz < Guard::Guard; end
it "accepts options" do
::Guard.add_group(:backend, { :halt_on_fail => true })
- ::Guard.groups[0].options.should eq({})
+ ::Guard.groups[0].options.should eq({ })
::Guard.groups[1].options.should eq({ :halt_on_fail => true })
end
end
describe '.within_preserved_state' do
subject { ::Guard.setup }
- before { subject.interactor = stub('interactor').as_null_object }
+ before { subject.interactor = stub('interactor').as_null_object }
it 'disallows running the block concurrently to avoid inconsistent states' do
subject.lock.should_receive(:synchronize)
- subject.within_preserved_state &Proc.new {}
+ subject.within_preserved_state &Proc.new { }
end
it 'runs the passed block' do
@@ -660,15 +716,15 @@ class Guard::FooBaz < Guard::Guard; end
it 'stops the interactor before running the block and starts it again when done' do
subject.interactor.should_receive(:stop)
subject.interactor.should_receive(:start)
- subject.within_preserved_state &Proc.new {}
+ subject.within_preserved_state &Proc.new { }
end
end
context 'without restart interactor enabled' do
it 'stops the interactor before running the block' do
subject.interactor.should_receive(:stop)
subject.interactor.should__not_receive(:start)
- subject.within_preserved_state &Proc.new {}
+ subject.within_preserved_state &Proc.new { }
end
end
end
@@ -691,15 +747,17 @@ class Guard::FooBaz < Guard::Guard; end
it "resolves the Guard class from string" do
Guard.should_receive(:require) { |classname|
classname.should eq 'guard/classname'
- class Guard::Classname; end
+ class Guard::Classname;
+ end
}
Guard.get_guard_class('classname').should == Guard::Classname
end
it "resolves the Guard class from symbol" do
Guard.should_receive(:require) { |classname|
classname.should eq 'guard/classname'
- class Guard::Classname; end
+ class Guard::Classname;
+ end
}
Guard.get_guard_class(:classname).should == Guard::Classname
end
@@ -711,7 +769,8 @@ class Guard::Classname; end
it "returns the Guard class" do
Guard.should_receive(:require) { |classname|
classname.should eq 'guard/dashed-class-name'
- class Guard::DashedClassName; end
+ class Guard::DashedClassName;
+ end
}
Guard.get_guard_class('dashed-class-name').should == Guard::DashedClassName
end
@@ -723,7 +782,8 @@ class Guard::DashedClassName; end
it "returns the Guard class" do
Guard.should_receive(:require) { |classname|
classname.should eq 'guard/underscore_class_name'
- class Guard::UnderscoreClassName; end
+ class Guard::UnderscoreClassName;
+ end
}
Guard.get_guard_class('underscore_class_name').should == Guard::UnderscoreClassName
end
@@ -735,7 +795,8 @@ class Guard::UnderscoreClassName; end
it "returns the Guard class" do
Guard.should_receive(:require) { |classname|
classname.should eq 'guard/vspec'
- class Guard::VSpec; end
+ class Guard::VSpec;
+ end
}
Guard.get_guard_class('vspec').should == Guard::VSpec
end
@@ -801,7 +862,7 @@ class Inline < Guard
before do
Guard.unstub(:debug_command_execution)
- @original_system = Kernel.method(:system)
+ @original_system = Kernel.method(:system)
@original_command = Kernel.method(:"`")
end
View
2 spec/spec_helper.rb
@@ -44,6 +44,8 @@
if ::Guard.options
::Guard.options[:debug] = false
end
+
+ Guard.scope = { :plugins => [], :groups => [] }
end
config.after(:all) do

0 comments on commit c4ebdd1

Please sign in to comment.
Something went wrong with that request. Please try again.