spectator 1.2.11 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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