rspec-live 0.0.1
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.
- data/History.md +7 -0
- data/License.txt +21 -0
- data/README.md +25 -0
- data/bin/rspec-live +9 -0
- data/lib/formatters/inventory_formatter.rb +13 -0
- data/lib/formatters/update_formatter.rb +30 -0
- data/lib/rspec-live/backtrace.rb +66 -0
- data/lib/rspec-live/display.rb +68 -0
- data/lib/rspec-live/example.rb +53 -0
- data/lib/rspec-live/runner.rb +42 -0
- data/lib/rspec-live/suite.rb +94 -0
- data/lib/rspec-live/terminal.rb +121 -0
- data/lib/rspec-live/version.rb +3 -0
- data/lib/rspec-live/watcher.rb +42 -0
- metadata +109 -0
data/History.md
ADDED
data/License.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Brian Auton
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# rspec-live
|
2
|
+
|
3
|
+
rspec-live is a test runner and formatter for RSpec 3+ that shows the state of your test suite
|
4
|
+
clearly and concisely in a console window. As files in your project are updated, created, or
|
5
|
+
removed, rspec-live reruns your tests in the background and continually updates the displayed
|
6
|
+
status.
|
7
|
+
|
8
|
+
### Requirements
|
9
|
+
|
10
|
+
* Ruby 1.8.7 or newer
|
11
|
+
* RSpec 3.0.0 or newer
|
12
|
+
|
13
|
+
### Getting Started
|
14
|
+
|
15
|
+
Add the gem to your Gemfile,
|
16
|
+
|
17
|
+
gem 'rspec-live'
|
18
|
+
|
19
|
+
Update your bundle,
|
20
|
+
|
21
|
+
bundle
|
22
|
+
|
23
|
+
And start it up.
|
24
|
+
|
25
|
+
rspec-live
|
data/bin/rspec-live
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "rspec-live/suite"
|
3
|
+
require "rspec-live/runner"
|
4
|
+
require "rspec-live/watcher"
|
5
|
+
require "rspec-live/display"
|
6
|
+
|
7
|
+
display = RSpecLive::Display.new
|
8
|
+
suite = RSpecLive::Suite.new(RSpecLive::Runner.new, display.suite_display)
|
9
|
+
RSpecLive::Watcher.new(suite, display.watcher_display).start
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
class InventoryFormatter
|
4
|
+
RSpec::Core::Formatters.register self, :example_started
|
5
|
+
|
6
|
+
def initialize(output)
|
7
|
+
@output = output
|
8
|
+
end
|
9
|
+
|
10
|
+
def example_started(notification)
|
11
|
+
@output << "#{JSON.unparse(name: notification.example.location)}\n"
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
class UpdateFormatter
|
4
|
+
RSpec::Core::Formatters.register self, :example_passed, :example_failed, :example_pending
|
5
|
+
|
6
|
+
def initialize(output)
|
7
|
+
@output = output
|
8
|
+
end
|
9
|
+
|
10
|
+
def example_passed(notification)
|
11
|
+
report :name => notification.example.location, :status => "passed"
|
12
|
+
end
|
13
|
+
|
14
|
+
def example_failed(notification)
|
15
|
+
report({
|
16
|
+
:name => notification.example.location,
|
17
|
+
:status => "failed",
|
18
|
+
:backtrace => notification.exception.backtrace,
|
19
|
+
:message => notification.exception.message,
|
20
|
+
})
|
21
|
+
end
|
22
|
+
|
23
|
+
def example_pending(notification)
|
24
|
+
report :name => notification.example.location, :status => "pending"
|
25
|
+
end
|
26
|
+
|
27
|
+
def report(data)
|
28
|
+
@output << "#{JSON.unparse data}\n"
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module RSpecLive
|
2
|
+
class Backtrace
|
3
|
+
def initialize(data, verbosity)
|
4
|
+
@components = data.map { |text| BacktraceComponent.new text, verbosity }
|
5
|
+
end
|
6
|
+
|
7
|
+
def components
|
8
|
+
strip_setup collapsed_components.map(&:to_s)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def strip_setup(text_components)
|
14
|
+
list = text_components.dup
|
15
|
+
while ["gem:ruby", "gem:rspec-core"].include? list.last do
|
16
|
+
list = list[0, list.length-1]
|
17
|
+
end
|
18
|
+
list
|
19
|
+
end
|
20
|
+
|
21
|
+
def collapsed_components
|
22
|
+
@components.inject([]) do |group, component|
|
23
|
+
group.dup.tap do |new_group|
|
24
|
+
new_group << component unless group.last && (group.last.to_s == component.to_s)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class BacktraceComponent
|
31
|
+
def initialize(text, verbosity)
|
32
|
+
@file, @line, @method = text.split(":")
|
33
|
+
@verbosity = verbosity
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
local_file_reference || gem_reference || "other"
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def local_file_reference
|
43
|
+
if @file.start_with? Dir.pwd
|
44
|
+
ref = "#{@file.gsub(/^#{Dir.pwd}\//, "")}:#{@line}"
|
45
|
+
ref += ":#{cleaned_method}" if @verbosity > 1
|
46
|
+
ref
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def cleaned_method
|
51
|
+
@method.gsub(/^in `/, "").gsub(/'$/, "")
|
52
|
+
end
|
53
|
+
|
54
|
+
def gem_reference
|
55
|
+
if @file.include? "/gems/"
|
56
|
+
local_reference = @file.split("/gems/").last
|
57
|
+
path = local_reference.gsub(/^\/*/, "")
|
58
|
+
gem_name_parts = local_reference.split("/").first.split("-")
|
59
|
+
gem_name = gem_name_parts[0, gem_name_parts.length - 1].join("-")
|
60
|
+
ref = "gem:#{gem_name}"
|
61
|
+
ref += "/#{path}:#{@line}:#{cleaned_method}" if @verbosity > 2
|
62
|
+
ref
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "rspec-live/terminal"
|
2
|
+
|
3
|
+
module RSpecLive
|
4
|
+
class Display
|
5
|
+
attr_reader :watcher_display, :suite_display
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@terminal = Terminal.new
|
9
|
+
@watcher_display = WatcherDisplay.new(@terminal.add_section :xalign => :center)
|
10
|
+
@terminal.add_section :display => :block, :content => key_command_info, :color => :blue
|
11
|
+
@suite_display = SuiteDisplay.new(@terminal.add_section :display => :block)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def key_command_info
|
17
|
+
"Keys: A:show/hide-all N:next V:verbosity R:rerun Q:quit"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class WatcherDisplay
|
22
|
+
def initialize(section)
|
23
|
+
@section = section
|
24
|
+
end
|
25
|
+
|
26
|
+
def status=(status)
|
27
|
+
@section.content = "RSpec summary for #{File.basename Dir.pwd} (#{status})"
|
28
|
+
@section.refresh
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class SuiteDisplay
|
33
|
+
def initialize(section)
|
34
|
+
@section = section
|
35
|
+
end
|
36
|
+
|
37
|
+
def show_examples(examples, suite_status, detailed_examples, verbosity)
|
38
|
+
@section.clear
|
39
|
+
@section.add_section :display => :block
|
40
|
+
examples.map(&:status).each do |status|
|
41
|
+
@section.add_section :content => character[status], :color => color[status]
|
42
|
+
end
|
43
|
+
@section.add_section :display => :block
|
44
|
+
@section.add_section :content => "#{suite_status}", :display => :block
|
45
|
+
@section.add_section :display => :block
|
46
|
+
last_failed = true
|
47
|
+
bullet_width = (detailed_examples.length-1).to_s.length
|
48
|
+
detailed_examples.each_with_index do |example, index|
|
49
|
+
bullet = "#{index+1}.".rjust(bullet_width+1, " ")
|
50
|
+
@section.add_section :display => :block if (!last_failed && example.failed?)
|
51
|
+
@section.add_section :content => example.details(verbosity), :display => :block, :color => color[example.status], :wrap => true, :bullet => bullet
|
52
|
+
@section.add_section :display => :block if example.failed?
|
53
|
+
last_failed = example.failed?
|
54
|
+
end
|
55
|
+
@section.refresh
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def character
|
61
|
+
{:unknown => ".", :passed => ".", :failed => "F", :pending => "S"}
|
62
|
+
end
|
63
|
+
|
64
|
+
def color
|
65
|
+
{:unknown => :blue, :passed => :green, :failed => :red, :pending => :yellow}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "rspec-live/backtrace"
|
2
|
+
|
3
|
+
module RSpecLive
|
4
|
+
class Example
|
5
|
+
attr_reader :name, :status
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@name = ""
|
9
|
+
@status = :unknown
|
10
|
+
@backtrace = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def update(data)
|
14
|
+
@name = data["name"] if data["name"]
|
15
|
+
@status = data["status"].to_sym if data["status"]
|
16
|
+
@backtrace = data["backtrace"] if data["backtrace"]
|
17
|
+
@message = data["message"] if data["message"]
|
18
|
+
end
|
19
|
+
|
20
|
+
def status=(value)
|
21
|
+
@status = value.to_sym
|
22
|
+
end
|
23
|
+
|
24
|
+
def passed?
|
25
|
+
@status == :passed
|
26
|
+
end
|
27
|
+
|
28
|
+
def failed?
|
29
|
+
@status == :failed
|
30
|
+
end
|
31
|
+
|
32
|
+
def details(verbosity)
|
33
|
+
failed? ? failure_message(verbosity) : name_component
|
34
|
+
end
|
35
|
+
|
36
|
+
def name_component
|
37
|
+
"(" + @name.gsub(/^.\//, "") + ")"
|
38
|
+
end
|
39
|
+
|
40
|
+
def failure_message(verbosity)
|
41
|
+
([name_component] + backtrace_components(verbosity) + exception_components).compact.join " -> "
|
42
|
+
end
|
43
|
+
|
44
|
+
def backtrace_components(verbosity)
|
45
|
+
return [] if verbosity < 1
|
46
|
+
Backtrace.new(@backtrace, verbosity).components.reverse.map { |c| "(#{c})" }
|
47
|
+
end
|
48
|
+
|
49
|
+
def exception_components
|
50
|
+
[@message.gsub("\n", " ").strip.inspect]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "pty"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module RSpecLive
|
5
|
+
class Runner
|
6
|
+
def inventory(&block)
|
7
|
+
run "inventory", "--dry-run", &block
|
8
|
+
end
|
9
|
+
|
10
|
+
def update(&block)
|
11
|
+
run "update", &block
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def run(formatter, options="", &block)
|
17
|
+
PTY.spawn formatter_command(formatter, options) do |stdin, stdout, pid|
|
18
|
+
begin
|
19
|
+
stdin.each do |line|
|
20
|
+
block.call JSON.parse line
|
21
|
+
end
|
22
|
+
rescue Errno::EIO
|
23
|
+
end
|
24
|
+
end
|
25
|
+
rescue PTY::ChildExited
|
26
|
+
end
|
27
|
+
|
28
|
+
def formatter_command(formatter, options)
|
29
|
+
options << " --format #{formatter_class formatter}"
|
30
|
+
options << " --require #{formatter_source formatter}"
|
31
|
+
"rspec #{options}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def formatter_source(formatter)
|
35
|
+
File.join File.dirname(__FILE__), "../formatters/#{formatter}_formatter.rb"
|
36
|
+
end
|
37
|
+
|
38
|
+
def formatter_class(formatter)
|
39
|
+
"#{formatter.capitalize}Formatter"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require "rspec-live/example"
|
2
|
+
|
3
|
+
module RSpecLive
|
4
|
+
class Suite
|
5
|
+
def initialize(runner, display)
|
6
|
+
@runner = runner
|
7
|
+
@display = display
|
8
|
+
@example_names = []
|
9
|
+
@examples = {}
|
10
|
+
@show_all = false
|
11
|
+
@verbosity = 1
|
12
|
+
end
|
13
|
+
|
14
|
+
def toggle_all
|
15
|
+
@show_all = !@show_all
|
16
|
+
update_display
|
17
|
+
end
|
18
|
+
|
19
|
+
def inventory
|
20
|
+
@example_names = []
|
21
|
+
@runner.inventory do |example_data|
|
22
|
+
update_or_create_example example_data
|
23
|
+
update_display
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def update
|
28
|
+
@runner.update do |example_data|
|
29
|
+
update_or_create_example example_data
|
30
|
+
update_display
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def focus_next
|
35
|
+
@focused = detailed_examples[1].name if detailed_examples[1]
|
36
|
+
update_display
|
37
|
+
end
|
38
|
+
|
39
|
+
def clear_status
|
40
|
+
@examples.each_value { |example| example.status = :unknown }
|
41
|
+
end
|
42
|
+
|
43
|
+
def cycle_verbosity
|
44
|
+
@verbosity = (@verbosity + 1) % 4
|
45
|
+
update_display
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def next_visible(name)
|
51
|
+
end
|
52
|
+
|
53
|
+
def update_or_create_example(data)
|
54
|
+
name = data["name"]
|
55
|
+
@example_names << name unless @example_names.include? name
|
56
|
+
sort_example_names
|
57
|
+
@examples[name] ||= Example.new
|
58
|
+
@examples[name].update data
|
59
|
+
@examples[name]
|
60
|
+
end
|
61
|
+
|
62
|
+
def update_display
|
63
|
+
@display.show_examples ordered_examples, summary, detailed_examples, @verbosity
|
64
|
+
end
|
65
|
+
|
66
|
+
def detailed_examples
|
67
|
+
all = ordered_examples
|
68
|
+
if @focused
|
69
|
+
index = @example_names.index(@focused) || 0
|
70
|
+
all = all[index, all.length-index] + all[0, index]
|
71
|
+
end
|
72
|
+
@show_all ? all : all.select(&:failed?)
|
73
|
+
end
|
74
|
+
|
75
|
+
def ordered_examples
|
76
|
+
@example_names.map { |name| @examples[name] }
|
77
|
+
end
|
78
|
+
|
79
|
+
def sort_example_names
|
80
|
+
@example_names.sort_by! do |name|
|
81
|
+
file, line = name.split(":")
|
82
|
+
line = line.rjust(8, "0")
|
83
|
+
[file, line].join(":")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def summary
|
88
|
+
passed = ordered_examples.select(&:passed?).length
|
89
|
+
total = ordered_examples.length
|
90
|
+
percent = (100*passed/total.to_f).round
|
91
|
+
"#{passed} of #{total} examples passed (#{percent}%)"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require "curses"
|
2
|
+
|
3
|
+
module RSpecLive
|
4
|
+
class Terminal
|
5
|
+
def initialize
|
6
|
+
Terminal.reset_curses
|
7
|
+
@root_section = TerminalSection.new
|
8
|
+
Signal.trap("SIGWINCH", proc { Terminal.reset_curses; @root_section.refresh })
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.reset_curses
|
12
|
+
Curses.init_screen
|
13
|
+
Curses.curs_set 0
|
14
|
+
Curses.clear
|
15
|
+
Curses.refresh
|
16
|
+
Curses.start_color
|
17
|
+
Curses.use_default_colors
|
18
|
+
available_colors.each do |name|
|
19
|
+
Curses.init_pair color_constant(name), color_constant(name), -1
|
20
|
+
end
|
21
|
+
@width = `tput cols`.to_i
|
22
|
+
@height = `tput lines`.to_i
|
23
|
+
Curses.resizeterm @height, @width
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.width
|
27
|
+
@width
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_section(*args)
|
31
|
+
@root_section.add_section(*args)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.color_constant(name)
|
35
|
+
Curses.const_get "COLOR_#{name.to_s.upcase}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.available_colors
|
39
|
+
[:blue, :green, :red, :yellow, :white]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class TerminalSection
|
44
|
+
def initialize(parent = nil, options = {})
|
45
|
+
@content = ""
|
46
|
+
@parent = parent
|
47
|
+
options.each_pair { |key, value| instance_variable_set "@#{key}", value }
|
48
|
+
@children = []
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_section(options = {})
|
52
|
+
new_section = TerminalSection.new(self, options)
|
53
|
+
@children << new_section
|
54
|
+
new_section
|
55
|
+
end
|
56
|
+
|
57
|
+
def content=(value)
|
58
|
+
@content = value.to_s
|
59
|
+
end
|
60
|
+
|
61
|
+
def clear
|
62
|
+
@content = ""
|
63
|
+
@children = []
|
64
|
+
refresh
|
65
|
+
end
|
66
|
+
|
67
|
+
def refresh
|
68
|
+
if @parent
|
69
|
+
@parent.refresh
|
70
|
+
else
|
71
|
+
Curses.clear
|
72
|
+
Curses.setpos 0, 0
|
73
|
+
draw
|
74
|
+
Curses.refresh
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def draw
|
79
|
+
Curses.addstr "\n" if @display == :block
|
80
|
+
draw_left_margin
|
81
|
+
if @color
|
82
|
+
Curses.attron(color_attribute @color) { draw_content }
|
83
|
+
else
|
84
|
+
draw_content
|
85
|
+
end
|
86
|
+
draw_right_margin
|
87
|
+
@children.each(&:draw)
|
88
|
+
end
|
89
|
+
|
90
|
+
def draw_content
|
91
|
+
text = @content
|
92
|
+
bullet = @bullet ? "#{@bullet} " : ""
|
93
|
+
if @display == :block && @wrap
|
94
|
+
text = bullet + wrap_with_margin(text, Terminal.width-1, bullet.length)
|
95
|
+
end
|
96
|
+
Curses.addstr text
|
97
|
+
end
|
98
|
+
|
99
|
+
def wrap_with_margin(text, width, margin_width)
|
100
|
+
wrap(text, width - margin_width).split("\n").join("\n" + (" " * margin_width))
|
101
|
+
end
|
102
|
+
|
103
|
+
def wrap(text, width)
|
104
|
+
text.scan(/\S.{0,#{width-2}}\S(?=\s|$)|\S+/).join("\n")
|
105
|
+
end
|
106
|
+
|
107
|
+
def draw_left_margin
|
108
|
+
Curses.addstr(("=" * [0, (((Terminal.width - @content.length) / 2) - 1)].max) + " ") if @align == :center
|
109
|
+
end
|
110
|
+
|
111
|
+
def draw_right_margin
|
112
|
+
Curses.addstr(" " + ("=" * [0, (((Terminal.width - @content.length) / 2) - 2)].max)) if @align == :center
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def color_attribute(name)
|
118
|
+
Curses.color_pair(Terminal.color_constant name) | Curses::A_NORMAL
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "listen"
|
2
|
+
|
3
|
+
module RSpecLive
|
4
|
+
class Watcher
|
5
|
+
def initialize(suite, display)
|
6
|
+
@suite = suite
|
7
|
+
@display = display
|
8
|
+
end
|
9
|
+
|
10
|
+
def start
|
11
|
+
process_tests
|
12
|
+
Listen.to(Dir.pwd) { process_tests }.start
|
13
|
+
while perform_key_command; end
|
14
|
+
rescue Interrupt
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def perform_key_command
|
20
|
+
key = STDIN.getc.chr.downcase
|
21
|
+
@suite.toggle_all if key == "a"
|
22
|
+
@suite.focus_next if key == "n"
|
23
|
+
return false if key == "q"
|
24
|
+
reset if key == "r"
|
25
|
+
@suite.cycle_verbosity if key == "v"
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def reset
|
30
|
+
@suite.clear_status
|
31
|
+
process_tests
|
32
|
+
end
|
33
|
+
|
34
|
+
def process_tests
|
35
|
+
@display.status = "analyzing specs"
|
36
|
+
@suite.inventory
|
37
|
+
@display.status = "running specs"
|
38
|
+
@suite.update
|
39
|
+
@display.status = "watching for updates..."
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rspec-live
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Brian Auton
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-08-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - "~>"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.0.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: listen
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - "~>"
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 2.7.9
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - "~>"
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.7.9
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: curses
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.0.1
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.0.1
|
62
|
+
description:
|
63
|
+
email:
|
64
|
+
- brianauton@gmail.com
|
65
|
+
executables:
|
66
|
+
- rspec-live
|
67
|
+
extensions: []
|
68
|
+
extra_rdoc_files: []
|
69
|
+
files:
|
70
|
+
- lib/rspec-live/terminal.rb
|
71
|
+
- lib/rspec-live/example.rb
|
72
|
+
- lib/rspec-live/runner.rb
|
73
|
+
- lib/rspec-live/version.rb
|
74
|
+
- lib/rspec-live/suite.rb
|
75
|
+
- lib/rspec-live/watcher.rb
|
76
|
+
- lib/rspec-live/backtrace.rb
|
77
|
+
- lib/rspec-live/display.rb
|
78
|
+
- lib/formatters/inventory_formatter.rb
|
79
|
+
- lib/formatters/update_formatter.rb
|
80
|
+
- README.md
|
81
|
+
- History.md
|
82
|
+
- License.txt
|
83
|
+
- bin/rspec-live
|
84
|
+
homepage: http://github.com/brianauton/rspec-live
|
85
|
+
licenses:
|
86
|
+
- MIT
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 1.3.6
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 1.8.29
|
106
|
+
signing_key:
|
107
|
+
specification_version: 3
|
108
|
+
summary: Continually updating console output for RSpec 3+
|
109
|
+
test_files: []
|