spectator 1.2.11 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3250e47a3847d52f1c8b48be5b9c922a5cf38a83
4
- data.tar.gz: f37e2c2263492ccce1d604aabb257a086935ddcb
3
+ metadata.gz: cc53eefa112ce5dd549660142e9691fec2b7147e
4
+ data.tar.gz: be808d5963f8a0878c6cd51b0f6ef8dc2e4a4578
5
5
  SHA512:
6
- metadata.gz: 2ab6190cc9fd6f03e4bda7deca8191c9be17cc30d8e148f86edd2d1513294922f15c39e60b2a359df4fffd6cba3707b6ee2130a724d4500272a138e8c0490651
7
- data.tar.gz: ec6565d41c1195a15b757a6a91e8a73776a99df708e1639e76e481a134906a7bba97dfb724f1c1a324a699f70a28d6b405cacdd524dbeefc8efd4b28cd0ec5a1
6
+ metadata.gz: b3e3a241bb6569789aac25566d109e99330a07bf82021809e8f592d3138afd31e57b2f69e71b097d8037cf3486a4162ea6cd6a227dd01781548af11dfa3e668b
7
+ data.tar.gz: 80aff3fe557a50be933613d3977b8b7dc822d4933eb4adbe3eecf217aff9267e84c211fa0c7e5fad46f77c243a7a9719888eaa5d1418cc9c5592c875a9873b45
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --warnings
3
+ --require spec_helper
data/Gemfile CHANGED
@@ -2,3 +2,9 @@ source 'http://rubygems.org'
2
2
 
3
3
  # See gem's dependencies in: rspec-rails-watchr.gemspec
4
4
  gemspec
5
+
6
+ def self.osx?
7
+ RUBY_PLATFORM.include? 'darwin'
8
+ end
9
+
10
+ gem 'terminal-notifier' if osx?
data/README.md CHANGED
@@ -38,12 +38,12 @@ Type `a` and `ENTER` (or `CTRL+C` again) to execute the whole suite of specs.
38
38
 
39
39
  If you want to override some path matching:
40
40
 
41
- **`BASE_DIR_GLOB`:**
41
+ **`BASE_DIR_REGEXP`:**
42
42
 
43
43
  The glob that expanded will list the directories that contains the code. **Default:**
44
44
 
45
45
 
46
- **`SPEC_DIR_GLOB`:**
46
+ **`SPEC_DIR_REGEXP`:**
47
47
 
48
48
  The glob that expanded will list the directories that contains the specs. **Default:**
49
49
 
@@ -58,16 +58,16 @@ The full command that will run your specs. **Default:** `bundle exec rspec` (or
58
58
 
59
59
  ```shell
60
60
  # this will match lib/opal/parser.rb to spec/cli/parser.rb
61
- BASE_DIR_GLOB='lib/opal' SPEC_DIR_GLOB='spec/cli' spectator
61
+ BASE_DIR_REGEXP='lib/opal' SPEC_DIR_REGEXP='spec/cli' spectator
62
62
  ```
63
63
 
64
64
 
65
65
  #### Exported ENV variables
66
66
 
67
67
  ```shell
68
- export BASE_DIR_GLOB="{opal/corelib,stdlib}"
69
- export SPEC_DIR_GLOB="spec/{corelib,stdlib}"
70
- export RSPEC_COMMAND="bundle exec mspec run -t ./bin/opal -I$(dirname $(gem which mspec)) -Ilib -rmspec/opal/mspec_fixes.rb"
68
+ BASE_DIR_REGEXP: '(?:opal/corelib|stdlib|spec)'
69
+ SPEC_DIR_REGEXP: '(?:spec/corelib/core|spec/stdlib/\w+/spec)'
70
+ RSPEC_COMMAND: 'bundle exec ./bin/opal-mspec'
71
71
  spectator
72
72
  ```
73
73
 
@@ -76,8 +76,8 @@ spectator
76
76
 
77
77
  ```yaml
78
78
  # contents of ".spectator" file
79
- BASE_DIR_GLOB: 'lib/opal'
80
- SPEC_DIR_GLOB: 'spec/cli'
79
+ BASE_DIR_REGEXP: 'lib/opal'
80
+ SPEC_DIR_REGEXP: 'spec/cli'
81
81
  ```
82
82
 
83
83
  spectator
@@ -87,8 +87,8 @@ SPEC_DIR_GLOB: 'spec/cli'
87
87
 
88
88
  ```shell
89
89
  # contents of ".my-spectator-config" file
90
- BASE_DIR_GLOB: 'lib/opal'
91
- SPEC_DIR_GLOB: 'spec/cli'
90
+ BASE_DIR_REGEXP: 'lib/opal'
91
+ SPEC_DIR_REGEXP: 'spec/cli'
92
92
  ```
93
93
 
94
94
  spectator .my-spectator-config
@@ -1,9 +1,19 @@
1
1
  #!/usr/bin/env ruby
2
2
  # coding: utf-8
3
3
 
4
-
5
- if %w[--help help -h].include? ARGV.first
6
- echo "Spectator doesn't take any arguments, to run the whole suite hit CTRL-C, type 'a' and press ENTER."
4
+ usage = "Usage: spectator [yaml-config]"
5
+ case ARGV.first
6
+ when '-h'
7
+ puts usage
8
+ when '--help', 'help'
9
+ puts usage
10
+ puts
11
+ puts "To control spectator hit CTRL-C while it's running."
12
+ puts "You'll get this prompt:"
13
+ puts "--- What to do now? (q=quit, a=all-specs): "
14
+ puts
15
+ puts 'Hit CTRL-C again or type "q" and then ENTER to quit.'
16
+ puts 'Type "a" and then ENTER to run the full spec suite.'
7
17
  exit
8
18
  end
9
19
 
@@ -11,8 +21,9 @@ require 'spectator'
11
21
 
12
22
  require 'yaml'
13
23
  config_file = ARGV.first || '.spectator'
14
- YAML.load_file(config).each do |name, value|
24
+ YAML.load_file(config_file).each do |name, value|
15
25
  ENV[name] ||= value
16
26
  end if File.exist? config_file
17
27
 
18
- Spectator.run
28
+ config = Spectator.config(debug: ARGV.include?('--debug'))
29
+ Spectator.run(config)
@@ -1,109 +1,98 @@
1
- # coding: utf-8
2
-
3
- require 'term/ansicolor'
1
+ require 'ostruct'
4
2
  require 'thread'
5
- require 'listen'
6
- require 'set'
7
-
8
3
  require 'spectator/version'
9
- require 'spectator/command_line'
10
- require 'spectator/specs'
11
- require 'spectator/control'
4
+ require 'spectator/debug'
5
+ require 'spectator/color'
6
+ require 'spectator/path_watcher'
7
+ require 'spectator/specs_matcher'
8
+ require 'spectator/success_notifier'
9
+ require 'spectator/spec_runner'
10
+ require 'spectator/ui'
12
11
 
13
12
  module Spectator
14
- class Runner
15
- String.send :include, Term::ANSIColor
13
+ extend self
16
14
 
17
- include CommandLine
18
- include Specs
19
- include Control
15
+ def config(overrides_hash = {})
16
+ Config.new(default_config_hash.merge(env_config_hash).merge(overrides_hash))
17
+ end
20
18
 
21
- def matchers
22
- @matchers ||= []
23
- end
19
+ def env_config_hash
20
+ config = {}
21
+ config[:rspec_command] = ENV['RSPEC_COMMAND'] if ENV['RSPEC_COMMAND']
22
+ config[:spec_dir_regexp] = ENV['SPEC_DIR_REGEXP'] if ENV['SPEC_DIR_REGEXP']
23
+ config[:base_dir_regexp] = ENV['BASE_DIR_REGEXP'] if ENV['BASE_DIR_REGEXP']
24
+ config[:debug] = ENV['SPECTATOR_DEBUG'] if ENV['SPECTATOR_DEBUG']
25
+ config
26
+ end
24
27
 
25
- def queue
26
- @queue ||= Queue.new
27
- end
28
+ def default_config_hash
29
+ {
30
+ rspec_command: (File.exist?('.rspec') ? 'rspec' : 'spec'),
31
+ spec_dir_regexp: 'spec',
32
+ base_dir_regexp: 'app|lib|script',
33
+ debug: false,
34
+ }
35
+ end
28
36
 
29
- def watch_paths!
30
- listener.start
31
- sleep
32
- end
37
+ Config = Class.new(OpenStruct)
33
38
 
34
- def listener
35
- @listener ||= begin
36
- listener = Listen.to(Dir.pwd, :relative_paths => true)
37
- listener = listener.filter %r{^(app|spec|lib|script)/}
38
- listener = listener.change do |modified, added, removed|
39
- [modified, added].flatten.each { |relative| queue.push relative }
40
- end
41
- end
39
+ class Runner
40
+ def initialize(config)
41
+ @config = config
42
+ @path_watcher = PathWatcher.new(config)
43
+ @ui = UI.new(config)
44
+ @spec_runner = SpecRunner.new(config)
45
+ @success_notifier = SuccessNotifier.new(config)
46
+ @specs_matcher = SpecsMatcher.new(config)
42
47
  end
43
48
 
49
+ attr_reader :config, :path_watcher, :ui, :spec_runner, :success_notifier, :specs_matcher
44
50
 
45
- def puts *args
46
- print args.join("\n")+"\n"
47
- end
51
+ def run
52
+ $spectator_debug = config.debug
48
53
 
49
- def run_specs specs
50
- rules.each do |(regexp, action)|
51
- regexp = Regexp.new(regexp)
52
- if file =~ regexp
53
- m = regexp.match(file)
54
- action.call(m)
54
+ path_watcher.on_change { ui << :run_specs }
55
+ path_watcher.watch_paths!
56
+
57
+ ui.on(:run_specs) do
58
+ next unless ui.can_run_specs?
59
+ ui.status = :running_specs
60
+ files = path_watcher.pop_files
61
+ specs = specs_matcher.specs_for(files)
62
+ if specs.any?
63
+ result = ui.run spec_runner.command(specs)
64
+ success_notifier.notify(result)
55
65
  end
66
+ ui.wait_for_changes
56
67
  end
57
- end
58
-
59
- def wait_for_changes
60
- puts '--- Waiting for changes...'.cyan
61
68
 
62
- loop do
63
- sleep 0.1 while queue.empty? or interrupted?
64
-
65
- files = []
66
- queue.size.times do
67
- files << queue.pop
69
+ ui.on(:interrupt) do
70
+ puts ' (Interrupted with CTRL+C)'.red
71
+ p [ui.status, ui.interrupted_status]
72
+ case ui.interrupted_status
73
+ when :wait_for_input then ui.exit
74
+ when :running_specs then ui.wait_for_changes
75
+ when :exiting then Kernel.abort
76
+ else Thread.new { ui.ask_what_to_do }
68
77
  end
69
-
70
- files.compact!
71
- redo if files.empty?
72
-
73
- rspec_files(*specs_for(files))
74
78
  end
75
- end
76
79
 
77
- def specs_for files
78
- specs = Set.new
79
- files = [files] unless files.respond_to? :each
80
- files.each do |file|
81
- matched = matchers.map do |matcher|
82
- file.scan(matcher).flatten.first.to_s.gsub(/\.rb$/,'')
83
- end.flatten.reject(&:empty?)
84
- specs += matched.uniq.map { |m| specs_for_file(m) }.flatten
85
- end
86
- specs.to_a
87
- end
80
+ trap('INT') { ui.interrupt! }
88
81
 
89
- def initialize &block
90
- yield self if block_given?
82
+ ui.on(:run_all) do
83
+ next unless ui.can_run_specs?
91
84
 
92
- spec_dir_glob = ENV['SPEC_DIR_GLOB'] || 'spec'
93
- base_dir_glob = ENV['BASE_DIR_GLOB'] || 'app|lib|script'
94
- matchers << %r{^#{spec_dir_glob}/(.*)_spec\.rb$}
95
- matchers << %r{^(?:#{base_dir_glob})/(.*)(?:\.rb|\.\w+|)$}
85
+ ui.status = :running_specs
86
+ result = ui.run(spec_runner.command)
87
+ success_notifier.notify(result)
88
+ ui.status = nil if ui.status == :running_specs
89
+ end
96
90
 
97
- trap_int!
98
- Thread.abort_on_exception = true
99
- @runner = Thread.new { wait_for_changes }
100
- watch_paths!
91
+ ui.start
101
92
  end
102
93
  end
103
94
 
104
-
105
-
106
- def self.run
107
- Runner.new
95
+ def run(*args, &block)
96
+ Runner.new(*args, &block).run
108
97
  end
109
98
  end
@@ -0,0 +1,2 @@
1
+ require 'term/ansicolor'
2
+ String.send :include, Term::ANSIColor
@@ -0,0 +1,10 @@
1
+ module Kernel
2
+ alias real_p p
3
+ def p(*args)
4
+ real_p(*args) if $spectator_debug
5
+ end
6
+ def p_print(*args)
7
+ print(*args) if $spectator_debug
8
+ end
9
+ end
10
+
@@ -0,0 +1,50 @@
1
+ require 'listen'
2
+ require 'thread'
3
+ require 'spectator/debug'
4
+
5
+ module Spectator
6
+ class PathWatcher
7
+
8
+ def initialize(config)
9
+ @config = config
10
+ @queue = Queue.new
11
+ end
12
+
13
+ def has_changed_files?
14
+ queue.size > 0
15
+ end
16
+
17
+ def on_change &block
18
+ @on_change = block if block_given?
19
+ @on_change
20
+ end
21
+
22
+ def pop_files
23
+ files = []
24
+ queue.size.times { files << queue.pop }
25
+ files
26
+ end
27
+
28
+ def watch_paths!
29
+ listener.start
30
+ end
31
+
32
+ attr_reader :queue, :config
33
+ private :queue, :config
34
+
35
+ def listener
36
+ @listener ||= begin
37
+ listener = Listen.to(Dir.pwd, :relative_paths => true)
38
+ p [:watching, config.base_dir_regexp]
39
+ listener = listener.filter %r{^(#{config.base_dir_regexp}|#{config.spec_dir_regexp})/}
40
+ listener = listener.change do |modified, added, removed|
41
+ p ['modified, added, removed', modified, added, removed]
42
+ files = [modified, added].flatten
43
+ files.each { |relative| queue.push relative }
44
+ p on_change
45
+ on_change.call(files) if on_change && files.any?
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,16 @@
1
+ module Spectator
2
+ class SpecRunner
3
+ def initialize(config)
4
+ @config = config
5
+ end
6
+ attr_reader :config
7
+
8
+ def command files = default_files
9
+ "#{config.rspec_command} #{files.join(' ')}"
10
+ end
11
+
12
+ def default_files
13
+ Dir['**/**'].grep(%r{^(?:#{config.spec_dir_regexp}\b)/?$})
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,40 @@
1
+ require 'spectator/debug'
2
+ require 'spectator/color'
3
+
4
+ module Spectator
5
+ class SpecsMatcher
6
+ def initialize(config)
7
+ @config = config
8
+ @matchers = [
9
+ %r{^#{config.spec_dir_regexp}/(.*)_spec\.rb$},
10
+ %r{^(?:#{config.base_dir_regexp})/(.*)(?:\.rb|\.\w+|)$},
11
+ ]
12
+ end
13
+ attr_reader :matchers
14
+
15
+ def specs_for(files)
16
+ files.flat_map do |path|
17
+ matchable_paths = self.matchable_paths(path)
18
+ print "--- Searching specs for #{path.inspect} (as: #{matchable_paths.join(", ")})...".yellow
19
+ specs = match_specs(matchable_paths)
20
+ puts specs.empty? ? ' nothing found.'.red : " #{specs.size} matched.".green
21
+ specs
22
+ end
23
+ end
24
+
25
+ def matchable_paths(file)
26
+ matchers.map do |matcher|
27
+ file.scan(matcher).flatten.first.to_s.gsub(/\.rb$/,'')
28
+ end.flatten.reject(&:empty?)
29
+ end
30
+
31
+ def match_specs matchable_paths
32
+ matchable_paths.uniq.map do |path|
33
+ # Dir['**/**'].grep(%r{^#{config.spec_dir_regexp}}).grep(/\b#{path}((_spec)?\.rb)?$/)
34
+ Dir['**/**'].grep(%r{^#{config.spec_dir_regexp}}).grep(/\b#{path}_spec\.rb$/)
35
+ end.flatten
36
+ end
37
+
38
+ attr_reader :config, :files
39
+ end
40
+ end
@@ -0,0 +1,37 @@
1
+ require 'notify'
2
+
3
+ module Spectator
4
+ class SuccessNotifier
5
+
6
+ def initialize(config)
7
+ @config ||= config
8
+ if osx?
9
+ begin
10
+ require 'terminal-notifier'
11
+ rescue LoadError => e
12
+ $stderr.puts e.message
13
+ $stderr.puts 'On OSX you should use notification center: gem install terminal-notifier'.red
14
+ end
15
+ end
16
+ end
17
+
18
+ def notify(success)
19
+ message = success ? success_message : failed_message
20
+ Thread.new { Notify.notify 'RSpec Result:', message }
21
+ end
22
+
23
+ def success_message
24
+ @success_message ||= osx? ? '🎉 SUCCESS'.freeze :
25
+ '♥♥ SUCCESS :) ♥♥'.freeze
26
+ end
27
+
28
+ def failed_message
29
+ @failed_message ||= osx? ? '💔 FAILED'.freeze :
30
+ '♠♠ FAILED >:( ♠♠'.freeze
31
+ end
32
+
33
+ def osx?
34
+ @osx ||= RUBY_PLATFORM.include? 'darwin'
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,122 @@
1
+ require 'thread'
2
+ require 'spectator/debug'
3
+ require 'spectator/color'
4
+
5
+ module Spectator
6
+ class UI
7
+ def initialize(config)
8
+ @mutex = Mutex.new
9
+ @status_mutex = Mutex.new
10
+ @status = nil
11
+ @status_callbacks = {}
12
+ @callbacks = {}
13
+ @queue = Queue.new
14
+ end
15
+
16
+ def << event
17
+ @queue << event
18
+ p event
19
+ end
20
+
21
+ def start
22
+ queue = @queue
23
+ mutex = @mutex
24
+
25
+ thread = Thread.new do
26
+ loop do
27
+ wait_for_changes
28
+ event = queue.pop
29
+ p [:queue, event]
30
+ mutex.synchronize { @callbacks[event].call }
31
+ end
32
+ end
33
+ p thread
34
+ Thread.pass
35
+ sleep
36
+ end
37
+
38
+ attr_reader :status
39
+
40
+ def status= status
41
+ @status_mutex.synchronize do
42
+ @status = status
43
+ (@status_callbacks[status] || noop).call
44
+ end
45
+ end
46
+
47
+ def noop
48
+ @noop ||= lambda {}
49
+ end
50
+
51
+ def interrupt!
52
+ self.interrupted_status = status
53
+ self << :interrupt
54
+ end
55
+
56
+ attr_accessor :interrupted_status
57
+
58
+ def on_status status, &block
59
+ @status_callbacks[status] = block
60
+ end
61
+
62
+ def on event, &block
63
+ @callbacks[event] = block
64
+ end
65
+
66
+ def ask_what_to_do
67
+ self.status = :wait_for_input
68
+ answer = ask('--- What to do now? (q=quit, a=all-specs): ')
69
+ case answer
70
+ when 'q' then exit
71
+ when 'a' then run_all
72
+ else
73
+ puts '--- Bad input, ignored.'.yellow
74
+ wait_for_changes
75
+ end
76
+ end
77
+
78
+ def run_all
79
+ self.status = :waiting_for_changes
80
+ self << :run_all
81
+ end
82
+
83
+ def wait_for_changes
84
+ return if status == :waiting_for_changes
85
+ self.status = :waiting_for_changes
86
+ puts '--- Waiting for changes...'.cyan
87
+ end
88
+
89
+ def ask question
90
+ print question.yellow
91
+ $stdout.flush
92
+ STDIN.gets.chomp.strip.downcase
93
+ end
94
+
95
+ def exit
96
+ self.status = :exiting
97
+ puts '--- Exiting...'.white
98
+ super
99
+ end
100
+
101
+ def terminal_columns
102
+ cols = `stty -a 2>&1`.scan(/ (\d+) columns/).flatten.first
103
+ $?.success? ? cols.to_i : 80
104
+ end
105
+
106
+ def run cmd
107
+ $running = true
108
+ start = Time.now
109
+ puts "=== running: #{cmd} ".ljust(terminal_columns, '=').cyan
110
+ success = system cmd
111
+ puts "=== time: #{(Time.now - start).to_i} seconds ".ljust(terminal_columns, '=').cyan
112
+ success
113
+ ensure
114
+ $running = false
115
+ end
116
+
117
+ def can_run_specs?
118
+ p [:can_run_specs?, status]
119
+ status == :waiting_for_changes
120
+ end
121
+ end
122
+ end
@@ -1,3 +1,3 @@
1
1
  module Spectator
2
- VERSION = '1.2.11'
2
+ VERSION = '1.3.0'
3
3
  end
@@ -0,0 +1,82 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
4
+ # file to always be loaded, without a need to explicitly require it in any files.
5
+ #
6
+ # Given that it is always loaded, you are encouraged to keep this file as
7
+ # light-weight as possible. Requiring heavyweight dependencies from this file
8
+ # (such as loading up an entire rails app) will add to the boot time of your
9
+ # test suite on EVERY test run, even for an individual file that may not need
10
+ # all of that loaded.
11
+ #
12
+ # The `.rspec` file also contains a few flags that are not defaults but that
13
+ # users commonly want.
14
+ #
15
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
16
+ RSpec.configure do |config|
17
+ # The settings below are suggested to provide a good initial experience
18
+ # with RSpec, but feel free to customize to your heart's content.
19
+ =begin
20
+ # These two settings work together to allow you to limit a spec run
21
+ # to individual examples or groups you care about by tagging them with
22
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
23
+ # get run.
24
+ config.filter_run :focus
25
+ config.run_all_when_everything_filtered = true
26
+
27
+ # Many RSpec users commonly either run the entire suite or an individual
28
+ # file, and it's useful to allow more verbose output when running an
29
+ # individual spec file.
30
+ if config.files_to_run.one?
31
+ # RSpec filters the backtrace by default so as not to be so noisy.
32
+ # This causes the full backtrace to be printed when running a single
33
+ # spec file (e.g. to troubleshoot a particular spec failure).
34
+ config.full_backtrace = true
35
+
36
+ # Use the documentation formatter for detailed output,
37
+ # unless a formatter has already been configured
38
+ # (e.g. via a command-line flag).
39
+ config.formatter = 'doc' if config.formatters.none?
40
+ end
41
+
42
+ # Print the 10 slowest examples and example groups at the
43
+ # end of the spec run, to help surface which specs are running
44
+ # particularly slow.
45
+ config.profile_examples = 10
46
+
47
+ # Run specs in random order to surface order dependencies. If you find an
48
+ # order dependency and want to debug it, you can fix the order by providing
49
+ # the seed, which is printed after each run.
50
+ # --seed 1234
51
+ config.order = :random
52
+
53
+ # Seed global randomization in this process using the `--seed` CLI option.
54
+ # Setting this allows you to use `--seed` to deterministically reproduce
55
+ # test failures related to randomization by passing the same `--seed` value
56
+ # as the one that triggered the failure.
57
+ Kernel.srand config.seed
58
+
59
+ # rspec-expectations config goes here. You can use an alternate
60
+ # assertion/expectation library such as wrong or the stdlib/minitest
61
+ # assertions if you prefer.
62
+ config.expect_with :rspec do |expectations|
63
+ # Enable only the newer, non-monkey-patching expect syntax.
64
+ # For more details, see:
65
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
66
+ expectations.syntax = :expect
67
+ end
68
+
69
+ # rspec-mocks config goes here. You can use an alternate test double
70
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
71
+ config.mock_with :rspec do |mocks|
72
+ # Enable only the newer, non-monkey-patching expect syntax.
73
+ # For more details, see:
74
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
75
+ mocks.syntax = :expect
76
+
77
+ # Prevents you from mocking or stubbing a method that does not exist on
78
+ # a real object. This is generally recommended.
79
+ mocks.verify_partial_doubles = true
80
+ end
81
+ =end
82
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ require 'spectator'
3
+
4
+ $spectator_debug = true
5
+
6
+ describe Spectator do
7
+ it 'does something' do
8
+ #nope
9
+ end
10
+ end
11
+
12
+ describe Spectator::SpecRunner do
13
+ let(:config) { Spectator.config }
14
+ subject(:runner) { described_class.new(config) }
15
+
16
+ describe '#default_files' do
17
+ it 'is spec dir' do
18
+ expect(runner.default_files).to eq(['spec'])
19
+ end
20
+ end
21
+
22
+ end
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
20
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
21
  s.require_paths = %w[lib]
22
+ s.required_ruby_version = '>= 1.9'
22
23
 
23
24
  s.add_dependency 'listen', '~> 1.3.0'
24
25
  s.add_dependency 'term-ansicolor', '~> 1.2.2'
@@ -26,4 +27,5 @@ Gem::Specification.new do |s|
26
27
 
27
28
  s.add_development_dependency 'rake', '~> 10'
28
29
  s.add_development_dependency 'bundler', '~> 1.0'
30
+ s.add_development_dependency 'rspec', '>= 3.0.0.beta2'
29
31
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spectator
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.11
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elia
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-24 00:00:00.000000000 Z
12
+ date: 2014-04-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: listen
@@ -81,6 +81,20 @@ dependencies:
81
81
  - - "~>"
82
82
  - !ruby/object:Gem::Version
83
83
  version: '1.0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: rspec
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 3.0.0.beta2
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: 3.0.0.beta2
84
98
  description: Watches specs for a Ruby (1.8 or 1.9) or Rails (2 or 3) project
85
99
  email:
86
100
  - elia@schito.me
@@ -90,16 +104,23 @@ extensions: []
90
104
  extra_rdoc_files: []
91
105
  files:
92
106
  - ".gitignore"
107
+ - ".rspec"
93
108
  - Gemfile
94
109
  - MIT-LICENSE
95
110
  - README.md
96
111
  - Rakefile
97
112
  - bin/spectator
98
113
  - lib/spectator.rb
99
- - lib/spectator/command_line.rb
100
- - lib/spectator/control.rb
101
- - lib/spectator/specs.rb
114
+ - lib/spectator/color.rb
115
+ - lib/spectator/debug.rb
116
+ - lib/spectator/path_watcher.rb
117
+ - lib/spectator/spec_runner.rb
118
+ - lib/spectator/specs_matcher.rb
119
+ - lib/spectator/success_notifier.rb
120
+ - lib/spectator/ui.rb
102
121
  - lib/spectator/version.rb
122
+ - spec/spec_helper.rb
123
+ - spec/spectator_spec.rb
103
124
  - spectator.gemspec
104
125
  homepage: ''
105
126
  licenses:
@@ -113,7 +134,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
134
  requirements:
114
135
  - - ">="
115
136
  - !ruby/object:Gem::Version
116
- version: '0'
137
+ version: '1.9'
117
138
  required_rubygems_version: !ruby/object:Gem::Requirement
118
139
  requirements:
119
140
  - - ">="
@@ -125,4 +146,6 @@ rubygems_version: 2.2.2
125
146
  signing_key:
126
147
  specification_version: 4
127
148
  summary: Watches specs for a Ruby or Rails project
128
- test_files: []
149
+ test_files:
150
+ - spec/spec_helper.rb
151
+ - spec/spectator_spec.rb
@@ -1,19 +0,0 @@
1
- module Spectator
2
- module CommandLine
3
- def terminal_columns
4
- cols = `stty -a 2>&1`.scan(/ (\d+) columns/).flatten.first
5
- $?.success? ? cols.to_i : 0
6
- end
7
-
8
- def run cmd
9
- puts "=== running: #{cmd} ".ljust(terminal_columns, '=').cyan
10
- success = system cmd
11
- puts "===".ljust(terminal_columns, '=').cyan
12
- success
13
- end
14
-
15
- def clear!
16
- system 'clear'
17
- end
18
- end
19
- end
@@ -1,81 +0,0 @@
1
- require 'thread'
2
-
3
- module Spectator
4
- module Control
5
- def exit
6
- @exiting = true
7
- puts '--- Exiting...'.white
8
- Kernel.exit
9
- end
10
-
11
- def abort!
12
- puts '--- Forcing abort...'.white
13
- Kernel.abort("\n")
14
- end
15
-
16
- def trap_int!
17
- # Ctrl-C
18
- @interrupted ||= false
19
- @signal_queue = []
20
- @signals_handler = Thread.new do
21
- loop do
22
- sleep(0.3)
23
- if signal_queue.any?
24
- listener.pause
25
- ask_what_to_do!
26
- listener.unpause
27
- Thread.pass
28
- signal_queue.shift
29
- end
30
- end
31
- end
32
-
33
- Signal.trap('INT') do
34
- abort! if exiting?
35
- start_exit if interrupted?
36
- signal_queue << :int
37
- puts ' (Interrupted with CTRL+C)'.red
38
- end
39
- end
40
-
41
- attr_reader :signal_queue
42
-
43
-
44
- private
45
-
46
- def interrupted?
47
- signal_queue.any?
48
- end
49
-
50
- def ask_what_to_do!
51
- if @exiting
52
- abort!
53
- else
54
- answer = ask('--- What to do now? (q=quit, a=all-specs): ')
55
- case answer
56
- when 'q' then start_exit
57
- when 'a' then rspec_all
58
- else puts '--- Bad input, ignored.'.yellow
59
- end
60
- puts '--- Waiting for changes...'.cyan
61
- end
62
- end
63
-
64
- def start_exit
65
- return if exiting?
66
- @exiting = true
67
- exit
68
- end
69
-
70
- def exiting?
71
- @exiting
72
- end
73
-
74
- def ask question
75
- print question.yellow
76
- $stdout.flush
77
- STDIN.gets.chomp.strip.downcase
78
- end
79
-
80
- end
81
- end
@@ -1,69 +0,0 @@
1
- # coding: utf-8
2
-
3
- module Spectator
4
- module Specs
5
- def notify message
6
- Thread.new do
7
- begin
8
- require 'notify'
9
- Notify.notify 'RSpec Result:', message
10
- rescue
11
- nil
12
- end
13
- end
14
- end
15
-
16
- def rspec_command
17
- @rspec_command ||= File.exist?('./.rspec') ? 'rspec' : 'spec'
18
- end
19
-
20
- def full_rspec_command
21
- @full_rspec_command ||= ENV['RSPEC_COMMAND'] || "bundle exec #{rspec_command}"
22
- end
23
-
24
- def rspec options
25
- unless options.empty?
26
- success = run("#{full_rspec_command} #{options}")
27
- notify( success ? success_message : failed_message )
28
- end
29
- end
30
-
31
- def success_message
32
- @success_message ||= osx? ? '🎉 SUCCESS'.freeze :
33
- '♥♥ SUCCESS :) ♥♥'.freeze
34
- end
35
-
36
- def failed_message
37
- @failed_message ||= osx? ? '💔 FAILED'.freeze :
38
- '♠♠ FAILED >:( ♠♠'.freeze
39
- end
40
-
41
- def osx?
42
- @osx ||= RUBY_PLATFORM.include? 'darwin'
43
- end
44
-
45
- def rspec_all
46
- rspec ENV['SPEC_DIR_GLOB'] || 'spec'
47
- end
48
-
49
- def rspec_files *files
50
- rspec files.join(' ')
51
- end
52
-
53
- def specs_for_file(path)
54
- print "--- Searching specs for #{path.inspect}...".yellow
55
- specs = match_specs path, Dir['spec/**/*_spec.rb']
56
- puts specs.empty? ? ' nothing found.'.red : " #{specs.size} matched.".green
57
- specs
58
- end
59
-
60
- def default_rails_matcher path, specs
61
- specs.grep(/\b#{path}((_spec)?\.rb)?$/)
62
- end
63
-
64
- def match_specs path, specs
65
- matched_specs = @custom_matcher.call(path, specs) if @custom_matcher
66
- matched_specs = default_rails_matcher(path, specs) if matched_specs.nil?
67
- end
68
- end
69
- end