Import Upstream version 1.2.1

parents
/.bundle/
/.yardoc
/Gemfile.lock
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
*.bundle
*.so
*.o
*.a
mkmf.log
--color
--require spec_helper
--format doc
inherit_from:
- .rubocop_todo.yml
AllCops:
Exclude:
- guard-compat.gemspec
# This configuration was generated by `rubocop --auto-gen-config`
# on 2014-12-05 08:15:00 +0100 using RuboCop version 0.27.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 4
Style/Documentation:
Enabled: false
source 'https://rubygems.org'
# Specify your gem's dependencies in guard-compat.gemspec
gemspec
group :development do
gem 'rspec', require: false
gem 'rubocop', require: false
end
Copyright (c) 2014 Cezary Baginski
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Guard::Compat
Currently, provides only a test helper for testing custom Guard plugins.
## Usage (in a Guard plugin)
In your gemspec:
```ruby
s.add_dependency('guard-compat', '~> 1.0')
```
In all your plugin files (e.g. `lib/guard/myplugin.rb`):
```ruby
# Don't require "guard/plugin" here or in any other plugin's files
require 'guard/compat/plugin'
module Guard
class MyPlugin < Plugin
# (...)
end
end
```
### IMPORTANT
1. Do not include *any* files from Guard directly (if you need something from Guard which Guard::Compat doesn't provide, file an issue)
2. Include 'guard/compat/plugin' is *all* your files which use `Guard::Plugin`
3. Make sure you include the `< Plugin` part in *every* file which add classes or methods to your plugin class (important if your plugin consists of multiple files/sub class)
4. Remove requires from your spec_helper and explicitly add them to each test/file
And in your plugin tests (e.g. `spec/lib/guard/myplugin_spec.rb`):
```ruby
require 'guard/compat/test/helper'
require 'guard/myplugin'
# And your tests instantiating your plugin go here...
RSpec.describe Guard::Myplugin do
```
### Migrating your API calls
`Guard::UI` => `Guard::Compat::UI` (or Compat::UI for short)
`Guard::Notifier.notify` => `Guard::Compat::UI.notify`
`Guard::Watcher.match_files` => `Guard::Compat.matching_files` (Watcher is otherwise unavailable - see Guard::Less template for passing patterns as plugin options)
### New API
* `Guard::UI.color` => for creating ANSI colored text if currently enabled in Guard
* `Guard::UI.color_enabled?` => for checking if ANSI color output is currently enabled in Guard
* `Guard::UI.watched_directories` => compatible way of obtaining watched_directories (recommended instead of accessing Watcher patterns or pattern subgroup hacks)
(Open an issue if you feel something important is missing)
## Example
See [lib/guard/compat/example.rb](https://github.com/guard/guard-compat/blob/master/lib/guard/compat/example.rb ) for an example plugin implementation.
See [spec/guard/compat/example_spec.rb](https://github.com/guard/guard-compat/blob/master/spec/guard/compat/example_spec.rb) for an example on how to test plugins using Guard::Compat.
See [spec/guard/compat/example_template_spec.rb](https://github.com/guard/guard-compat/blob/master/spec/guard/compat/example_template_spec.rb) for an example on how to test plugin templates.
## Contributing
1. Fork it ( https://github.com/guard/guard-compat/fork )
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request
require 'bundler/gem_tasks'
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec) do |t|
t.verbose = false unless ENV.key?('CI')
end
require 'rubocop/rake_task'
RuboCop::RakeTask.new(:rubocop)
task default: [:spec, :rubocop]
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'guard/compat/version'
Gem::Specification.new do |spec|
spec.name = 'guard-compat'
spec.version = Guard::Compat::VERSION
spec.authors = ['Cezary Baginski']
spec.email = ['cezary@chronomantic.net']
spec.summary = 'Tools for developing Guard compatible plugins'
spec.description = 'Helps creating valid Guard plugins and testing them'
spec.homepage = ''
spec.license = 'MIT'
spec.files = `git ls-files -z`.split("\x0")
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ['lib']
spec.add_development_dependency 'bundler', '~> 1.7'
spec.add_development_dependency 'rake', '~> 10.0'
end
require 'guard/compat/version'
module Guard
module Compat
# Your code goes here...
end
end
# NOTE: Do NOT require "guard/plugin" - it will either be already required, or
# a stub will be supplied by the test class
module Guard
class MyPlugin < Plugin
def start
Guard::Compat::UI.notify('foo')
Guard::Compat::UI.color('foo')
Guard::Compat::UI.info('foo')
Guard::Compat::UI.warning('foo')
Guard::Compat::UI.error('foo')
Guard::Compat::UI.debug('foo')
Guard::Compat::UI.deprecation('foo')
end
def run_all
Guard::Compat::UI.notify('foo', bar: :baz)
Guard::Compat::UI.color('foo', :white)
Guard::Compat::UI.info('foo', bar: :baz)
Guard::Compat::UI.warning('foo', bar: :baz)
Guard::Compat::UI.error('foo', bar: :baz)
Guard::Compat::UI.debug('foo', bar: :baz)
Guard::Compat::UI.deprecation('foo', bar: :baz)
end
def run_on_modifications
Guard::Compat::UI.color_enabled?
Guard::Compat.matching_files(self, ['foo'])
Guard::Compat.watched_directories
end
end
end
# Note: currently, this file only exists to allow Bundler to require this file
# without crashing (e.g. when Guard hasn't been included)
unless Object.const_defined?('Guard')
module Guard
end
end
unless Guard.const_defined?('Plugin')
# Provided empty definition so requiring the plugin without Guard won't crash
# (e.g. when added to a Gemfile without `require: false`)
module Guard
class Plugin
def initialize(_options = {})
msg = 'either Guard has not been required or you did not' \
' include guard/compat/test/helper'
fail NotImplementedError, msg
end
end
end
end
module Guard
module Compat
# TODO: this is just a temporary workaround to allow plugins
# to use watcher patterns in run_all
def self.matching_files(plugin, files)
unless Guard.const_defined?('Watcher')
msg = 'either Guard has not been required or you did not' \
' stub this method in your plugin tests'
fail NotImplementedError, msg
end
# TODO: uniq not tested
# TODO: resolve symlinks and then uniq?
Guard::Watcher.match_files(plugin, files).uniq
end
def self.watched_directories
unless Guard.const_defined?('CLI')
fail NotImplementedError, 'either Guard has not been required or'\
' you did not stub this method in your plugin tests'
end
if Guard.respond_to?(:state)
# TODO: the new version is temporary
Guard.state.session.watchdirs.map { |d| Pathname(d) }
else
dirs = Array(Guard.options(:watchdir))
dirs.empty? ? [Pathname.pwd] : dirs.map { |d| Pathname(d) }
end
end
module UI
def self.color(text, *colors)
if Guard.const_defined?(:UI)
Guard::UI.send(:color, text, *colors)
else
text
end
end
def self.color_enabled?
if Guard.const_defined?(:UI)
Guard::UI.send(:color_enabled?)
else
false
end
end
def self.info(message, options = {})
if Guard.const_defined?(:UI)
Guard::UI.info(message, options)
else
$stdout.puts(message)
end
end
def self.warning(message, options = {})
if Guard.const_defined?(:UI)
Guard::UI.warning(message, options)
else
$stdout.puts(message)
end
end
def self.error(message, options = {})
if Guard.const_defined?(:UI)
Guard::UI.error(message, options)
else
$stderr.puts(message)
end
end
def self.debug(message, options = {})
if Guard.const_defined?(:UI)
Guard::UI.debug(message, options)
else
$stdout.puts(message)
end
end
def self.deprecation(message, options = {})
if Guard.const_defined?(:UI)
Guard::UI.deprecation(message, options)
else
$stdout.puts(message)
end
end
def self.notify(msg, options = {})
return $stdout.puts(msg) unless Guard.const_defined?(:UI)
return Notifier.notify(msg, options) if Notifier.respond_to?(:notify)
# test helper was included
note = 'NOTE: Notification is disabled when testing Guard plugins'\
' (it makes no sense)'
$stderr.puts(note)
$stdout.puts(msg)
end
end
end
end
# Minimal stub allowing a plugin to work
require 'guard/compat/plugin'
module Guard
# Monkey patch Plugin to just keep the interface
class Plugin
attr_reader :options
alias_method :old_initialize, :initialize
def initialize(options = {})
@options = options
end
remove_method(:old_initialize)
end
# Stub, but allow real Notifier to be used, because e.g. guard-minitest uses
# is while guard-process is being tested
unless Guard.const_defined?('Notifier')
module Notifier
# NOTE: do not implement anything here, so using any UI methods
# causes tests to fail
end
end
# Stub, but allow real UI to be used, because e.g. guard-minitest uses it
# through using Guard::Notifier
unless Guard.const_defined?('UI')
module UI
# NOTE: do not implement anything here, so using any UI methods
# causes tests to fail
end
end
end
module Guard
module Compat
module Test
class Template
class Session
class MultipleGuardNotImplemented < NotImplementedError
def message
'multiple guards not supported!'
end
end
class GlobalWatchesNotImplemented < NotImplementedError
def message
'global watches not supported!'
end
end
def initialize(path, content)
@watches = {}
@current = nil
instance_eval(content, path, 1)
end
def match(file)
_watches.map do |expr, block|
next unless (match = file.match(expr))
block.nil? ? [file] : block.call([file] + match.captures)
end.flatten.compact.uniq
end
def guard(name, _options = {})
@current = name
@watches[@current] = []
yield
@current = nil
end
def watch(expr, &block)
@watches[@current] << [expr, block]
end
private
def _watches
keys = @watches.keys
fail ArgumentError, 'no watches!' if keys.empty?
fail MultipleGuardNotImplemented if keys.size > 1
key = keys.first
fail GlobalWatchesNotImplemented if key.nil?
@watches[key]
end
end
def initialize(plugin_class)
name = plugin_class.to_s.sub('Guard::', '').downcase
path = format('lib/guard/%s/templates/Guardfile', name)
content = File.read(path)
@session = Session.new(path, content)
end
def changed(file)
@session.match(file)
end
end
end
end
end
module Guard
module Compat
VERSION = '1.2.1'
end
end
# This is the only file the plugin should require
require 'guard/compat/test/helper'
require 'guard/compat/example'
RSpec.describe Guard::MyPlugin, exclude_stubs: [Guard::Plugin] do
let(:options) { { foo: :bar } }
subject { described_class.new(options) }
before do
meths = %w(info warning error deprecation debug notify color color_enabled?)
meths.each do |type|
allow(Guard::Compat::UI).to receive(type.to_sym)
end
end
it 'passes options' do
expect(subject.options).to include(foo: :bar)
end
it 'works without options' do
expect { described_class.new }.to_not raise_error
end
describe '#start' do
before { subject.start }
%w(info warning error deprecation debug notify).each do |type|
specify do
expect(Guard::Compat::UI).to have_received(type.to_sym).with('foo')
end
end
end
describe '#run_all' do
before { subject.run_all }
%w(info warning error deprecation debug notify).each do |type|
specify do
expect(Guard::Compat::UI).to have_received(type.to_sym)
.with('foo', bar: :baz)
end
end
end
describe '#run_on_modifications' do
before do
allow(Guard::Compat).to receive(:matching_files)
allow(Guard::Compat).to receive(:watched_directories)
end
before { subject.run_on_modifications }
specify { expect(Guard::Compat::UI).to have_received(:color_enabled?) }
specify { expect(Guard::Compat).to have_received(:matching_files) }
end
end
require 'guard/compat/test/template'
require 'guard/compat/example'
RSpec.describe Guard::MyPlugin do
describe 'template' do
subject { Guard::Compat::Test::Template.new(described_class) }
# Stub the template, because we are testing the helper, not the plugin
let(:template_contents) do
<<-EOS
guard :myplugin do
watch(/(foo).rb/) { |m| "spec/\#{m[1]}_spec.rb" }
watch(/bar.rb/)
end
EOS
end
before do
allow(IO).to receive(:read)
.with('lib/guard/myplugin/templates/Guardfile')
.and_return(template_contents)
end
it 'translates changes' do
expect(subject.changed('foo.rb')).to eq(['spec/foo_spec.rb'])
expect(subject.changed('bar.rb')).to eq(['bar.rb'])
end
end
end
# This test requires UI be not defined to simulate using plugin outside Guard
require 'guard/compat/plugin'
Guard.send(:remove_const, :UI) if Guard.const_defined?(:UI)
RSpec.describe Guard::Compat do
context 'when Guard is not loaded' do
describe '.color' do
it 'returns uncolored text' do
expect(Guard::Compat::UI.color('foo', 'red')).to eq('foo')
end
end
describe '.color_enabled?' do
it 'returns false' do
expect(Guard::Compat::UI.color_enabled?).to be(false)
end
end
describe '.info' do
it 'outputs to stdout' do
expect($stdout).to receive(:puts).with('foo')
Guard::Compat::UI.info('foo')
end
end
describe '.warning' do
it 'outputs to stdout' do
expect($stdout).to receive(:puts).with('foo')
Guard::Compat::UI.warning('foo')
end
end
describe '.error' do
it 'outputs to stdout' do
expect($stderr).to receive(:puts).with('foo')
Guard::Compat::UI.error('foo')
end
end
describe '.debug' do
it 'outputs to stdout' do
expect($stdout).to receive(:puts).with('foo')
Guard::Compat::UI.debug('foo')
end
end
describe '.deprecation' do
it 'outputs to stdout' do
expect($stdout).to receive(:puts).with('foo')
Guard::Compat::UI.deprecation('foo')
end
end
describe '.notify' do
it 'outputs to stdout' do
expect($stdout).to receive(:puts).with('foo')
Guard::Compat::UI.notify('foo')
end
end
end
end
# The `.rspec` file also contains a few flags that are not defaults but that
# users commonly want.
#
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
RSpec.configure do |config|
# rspec-expectations config goes here. You can use an alternate
# assertion/expectation library such as wrong or the stdlib/minitest
# assertions if you prefer.
config.expect_with :rspec do |expectations|
# This option will default to `true` in RSpec 4. It makes the `description`
# and `failure_message` of custom matchers include text for helper methods
# defined using `chain`, e.g.:
# be_bigger_than(2).and_smaller_than(4).description
# # => "be bigger than 2 and smaller than 4"
# ...rather than:
# # => "be bigger than 2"
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
# rspec-mocks config goes here. You can use an alternate test double
# library (such as bogus or mocha) by changing the `mock_with` option here.
config.mock_with :rspec do |mocks|
# Prevents you from mocking or stubbing a method that does not exist on
# a real object. This is generally recommended, and will default to
# `true` in RSpec 4.
mocks.verify_doubled_constant_names = true
mocks.verify_partial_doubles = true
end
# The settings below are suggested to provide a good initial experience
# with RSpec, but feel free to customize to your heart's content.
# These two settings work together to allow you to limit a spec run
# to individual examples or groups you care about by tagging them with
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
# get run.
config.filter_run focus: ENV['CI'] != 'true'
config.run_all_when_everything_filtered = true
config.disable_monkey_patching!
# This setting enables warnings. It's recommended, but in some cases may
# be too noisy due to issues in dependencies.
config.warnings = true
# Many RSpec users commonly either run the entire suite or an individual
# file, and it's useful to allow more verbose output when running an
# individual spec file.
if config.files_to_run.one?
# Use the documentation formatter for detailed output,
# unless a formatter has already been configured
# (e.g. via a command-line flag).
config.default_formatter = 'doc'
end
# Print the 10 slowest examples and example groups at the
# end of the spec run, to help surface which specs are running
# particularly slow.
# config.profile_examples = 10
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = :random
# Seed global randomization in this process using the `--seed` CLI option.
# Setting this allows you to use `--seed` to deterministically reproduce
# test failures related to randomization by passing the same `--seed` value
# as the one that triggered the failure.
Kernel.srand config.seed
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment