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 +4 -4
- data/.rspec +3 -0
- data/Gemfile +6 -0
- data/README.md +10 -10
- data/bin/spectator +16 -5
- data/lib/spectator.rb +71 -82
- data/lib/spectator/color.rb +2 -0
- data/lib/spectator/debug.rb +10 -0
- data/lib/spectator/path_watcher.rb +50 -0
- data/lib/spectator/spec_runner.rb +16 -0
- data/lib/spectator/specs_matcher.rb +40 -0
- data/lib/spectator/success_notifier.rb +37 -0
- data/lib/spectator/ui.rb +122 -0
- data/lib/spectator/version.rb +1 -1
- data/spec/spec_helper.rb +82 -0
- data/spec/spectator_spec.rb +22 -0
- data/spectator.gemspec +2 -0
- metadata +30 -7
- data/lib/spectator/command_line.rb +0 -19
- data/lib/spectator/control.rb +0 -81
- data/lib/spectator/specs.rb +0 -69
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc53eefa112ce5dd549660142e9691fec2b7147e
|
4
|
+
data.tar.gz: be808d5963f8a0878c6cd51b0f6ef8dc2e4a4578
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3e3a241bb6569789aac25566d109e99330a07bf82021809e8f592d3138afd31e57b2f69e71b097d8037cf3486a4162ea6cd6a227dd01781548af11dfa3e668b
|
7
|
+
data.tar.gz: 80aff3fe557a50be933613d3977b8b7dc822d4933eb4adbe3eecf217aff9267e84c211fa0c7e5fad46f77c243a7a9719888eaa5d1418cc9c5592c875a9873b45
|
data/.rspec
ADDED
data/Gemfile
CHANGED
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
|
-
**`
|
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
|
-
**`
|
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
|
-
|
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
|
-
|
69
|
-
|
70
|
-
|
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
|
-
|
80
|
-
|
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
|
-
|
91
|
-
|
90
|
+
BASE_DIR_REGEXP: 'lib/opal'
|
91
|
+
SPEC_DIR_REGEXP: 'spec/cli'
|
92
92
|
```
|
93
93
|
|
94
94
|
spectator .my-spectator-config
|
data/bin/spectator
CHANGED
@@ -1,9 +1,19 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# coding: utf-8
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
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(
|
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.
|
28
|
+
config = Spectator.config(debug: ARGV.include?('--debug'))
|
29
|
+
Spectator.run(config)
|
data/lib/spectator.rb
CHANGED
@@ -1,109 +1,98 @@
|
|
1
|
-
|
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/
|
10
|
-
require 'spectator/
|
11
|
-
require 'spectator/
|
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
|
-
|
15
|
-
String.send :include, Term::ANSIColor
|
13
|
+
extend self
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
def config(overrides_hash = {})
|
16
|
+
Config.new(default_config_hash.merge(env_config_hash).merge(overrides_hash))
|
17
|
+
end
|
20
18
|
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
30
|
-
listener.start
|
31
|
-
sleep
|
32
|
-
end
|
37
|
+
Config = Class.new(OpenStruct)
|
33
38
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
46
|
-
|
47
|
-
end
|
51
|
+
def run
|
52
|
+
$spectator_debug = config.debug
|
48
53
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
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
|
-
|
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
|
-
|
90
|
-
|
82
|
+
ui.on(:run_all) do
|
83
|
+
next unless ui.can_run_specs?
|
91
84
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
-
|
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,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
|
data/lib/spectator/ui.rb
ADDED
@@ -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
|
data/lib/spectator/version.rb
CHANGED
data/spec/spec_helper.rb
ADDED
@@ -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
|
data/spectator.gemspec
CHANGED
@@ -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.
|
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-
|
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/
|
100
|
-
- lib/spectator/
|
101
|
-
- lib/spectator/
|
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: '
|
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
|
data/lib/spectator/control.rb
DELETED
@@ -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
|
data/lib/spectator/specs.rb
DELETED
@@ -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
|