rspec-interactive 0.1.0 → 0.2.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 +4 -4
- data/.gitignore +2 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +15 -4
- data/README.md +108 -0
- data/bin/console +1 -1
- data/bin/rspec-interactive +2 -2
- data/examples/debugged_spec.rb +9 -0
- data/examples/failing_spec.rb +11 -0
- data/examples/passing_spec.rb +11 -0
- data/lib/rspec-interactive.rb +66 -126
- data/lib/rspec-interactive/config_cache.rb +96 -0
- data/lib/rspec-interactive/input_completer.rb +24 -0
- data/lib/rspec-interactive/rspec_command.rb +67 -0
- data/lib/rspec-interactive/runner.rb +60 -29
- data/lib/rspec-interactive/version.rb +4 -2
- data/rspec-interactive.gemspec +5 -3
- metadata +52 -7
- data/lib/repo.rb +0 -8
- data/rspec-console-0.1.0.gem +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6034dc7e5c24528799a1fd53510f0eba5f0d2d599b9e9736371a8ee210319d68
|
4
|
+
data.tar.gz: 343e1fcaa3d42dbcfbb5b12dbfb8b6c33e7c44e80a2bfafdf22b9934ba63e986
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5af0bad059e46cd7933b3d83f48e2ebac13f6005817e5f7aee96ab3c27a153d89b136ba305881a76fd883c70b5f157534327c74608da4eeb28ed1158259f49c3
|
7
|
+
data.tar.gz: c2059760cf7053a80f3465f937bd8a69bff7e49740617c82f2663abe474454d7fee8317996b6ed07ea63618ab2b972b79527fab7bfa9f40e191825e3d79481e8
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,29 +1,40 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rspec-
|
5
|
-
listen
|
4
|
+
rspec-interactive (0.1.0)
|
5
|
+
listen (~> 3.5, >= 3.5.1)
|
6
|
+
pry (~> 0.14.1)
|
7
|
+
rspec-core (~> 3.10, >= 3.10.1)
|
6
8
|
|
7
9
|
GEM
|
8
10
|
remote: https://rubygems.org/
|
9
11
|
specs:
|
12
|
+
coderay (1.1.3)
|
13
|
+
diff-lcs (1.4.4)
|
10
14
|
ffi (1.15.0)
|
11
15
|
listen (3.5.1)
|
12
16
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
13
17
|
rb-inotify (~> 0.9, >= 0.9.10)
|
18
|
+
method_source (1.0.0)
|
19
|
+
pry (0.14.1)
|
20
|
+
coderay (~> 1.1)
|
21
|
+
method_source (~> 1.0)
|
14
22
|
rb-fsevent (0.11.0)
|
15
23
|
rb-inotify (0.10.1)
|
16
24
|
ffi (~> 1.0)
|
17
25
|
rspec-core (3.10.1)
|
18
26
|
rspec-support (~> 3.10.0)
|
27
|
+
rspec-expectations (3.10.1)
|
28
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
29
|
+
rspec-support (~> 3.10.0)
|
19
30
|
rspec-support (3.10.2)
|
20
31
|
|
21
32
|
PLATFORMS
|
22
33
|
x86_64-darwin-20
|
23
34
|
|
24
35
|
DEPENDENCIES
|
25
|
-
rspec-
|
26
|
-
rspec-
|
36
|
+
rspec-expectations
|
37
|
+
rspec-interactive!
|
27
38
|
|
28
39
|
BUNDLED WITH
|
29
40
|
2.2.17
|
data/README.md
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
# RSpec Interactive
|
2
|
+
|
3
|
+
**WARNING: New (or maybe old by now), experimental, untested and poorly documented. Use at your own risk.**
|
4
|
+
|
5
|
+
An Pry console capable of running specs.
|
6
|
+
|
7
|
+
## Installation & Configuration
|
8
|
+
|
9
|
+
Install:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'rspec-interactive'
|
13
|
+
```
|
14
|
+
|
15
|
+
Add a config file named `.rspec_interactive_config`:
|
16
|
+
|
17
|
+
```json
|
18
|
+
{
|
19
|
+
"configs": [
|
20
|
+
{
|
21
|
+
"name": "spec",
|
22
|
+
"watch_dirs": ["app"],
|
23
|
+
"init_script": "spec/spec_helper.rb"
|
24
|
+
},
|
25
|
+
{
|
26
|
+
"name": "spec_integration",
|
27
|
+
"watch_dirs": ["app"],
|
28
|
+
"init_script": "spec_integration/integration_helper.rb"
|
29
|
+
}
|
30
|
+
]
|
31
|
+
}
|
32
|
+
```
|
33
|
+
|
34
|
+
Update `.gitignore`
|
35
|
+
|
36
|
+
```shell
|
37
|
+
echo '.rspec_interactive_history' >> .gitignore
|
38
|
+
```
|
39
|
+
|
40
|
+
## Usage
|
41
|
+
|
42
|
+
See more examples below.
|
43
|
+
|
44
|
+
```shell
|
45
|
+
bundle exec rspec-interactive [spec name]
|
46
|
+
```
|
47
|
+
|
48
|
+
## Example Usage In This Repo
|
49
|
+
|
50
|
+
Start:
|
51
|
+
|
52
|
+
```shell
|
53
|
+
bundle exec rspec-interactive
|
54
|
+
```
|
55
|
+
|
56
|
+
Run a passing spec:
|
57
|
+
|
58
|
+
```shell
|
59
|
+
[1] pry(main)> rspec examples/passing_spec.rb
|
60
|
+
```
|
61
|
+
|
62
|
+
Inspect the result:
|
63
|
+
|
64
|
+
```shell
|
65
|
+
[2] pry(main)> result
|
66
|
+
```
|
67
|
+
|
68
|
+
Run a failing spec:
|
69
|
+
|
70
|
+
```shell
|
71
|
+
[3] pry(main)> rspec examples/failing_spec.rb
|
72
|
+
```
|
73
|
+
|
74
|
+
Inspect result history:
|
75
|
+
|
76
|
+
```shell
|
77
|
+
[4] pry(main)> results
|
78
|
+
```
|
79
|
+
|
80
|
+
Run an example group:
|
81
|
+
|
82
|
+
```shell
|
83
|
+
[5] pry(main)> rspec examples/passing_spec.rb:4
|
84
|
+
```
|
85
|
+
|
86
|
+
Run multiple specs:
|
87
|
+
|
88
|
+
```shell
|
89
|
+
[6] pry(main)> rspec examples/passing_spec.rb examples/failing_spec.rb
|
90
|
+
```
|
91
|
+
|
92
|
+
Debug a spec (use `exit` to resume while debugging):
|
93
|
+
|
94
|
+
```shell
|
95
|
+
[7] pry(main)> rspec examples/debugged_spec.rb
|
96
|
+
```
|
97
|
+
|
98
|
+
Run multiple specs using globbing (use `exit` to resume while debugging):
|
99
|
+
|
100
|
+
```shell
|
101
|
+
[8] pry(main)> rspec examples/*_spec.rb
|
102
|
+
```
|
103
|
+
|
104
|
+
Exit:
|
105
|
+
|
106
|
+
```shell
|
107
|
+
[9] pry(main)> exit
|
108
|
+
```
|
data/bin/console
CHANGED
data/bin/rspec-interactive
CHANGED
data/lib/rspec-interactive.rb
CHANGED
@@ -4,52 +4,73 @@ require 'json'
|
|
4
4
|
require 'listen'
|
5
5
|
require 'readline'
|
6
6
|
require 'rspec/core'
|
7
|
-
require '
|
7
|
+
require 'pry'
|
8
8
|
|
9
|
-
|
9
|
+
require 'rspec-interactive/runner'
|
10
|
+
require 'rspec-interactive/config_cache'
|
11
|
+
require 'rspec-interactive/input_completer'
|
12
|
+
require 'rspec-interactive/rspec_command'
|
10
13
|
|
11
|
-
module
|
12
|
-
|
14
|
+
module RSpec
|
15
|
+
module Interactive
|
13
16
|
|
14
17
|
HISTORY_FILE = '.rspec_interactive_history'.freeze
|
15
18
|
CONFIG_FILE = '.rspec_interactive_config'.freeze
|
16
|
-
MAX_HISTORY_ITEMS = 100
|
17
|
-
COMMANDS = ['help', 'rspec']
|
18
19
|
|
19
|
-
|
20
|
+
class <<self
|
21
|
+
attr_accessor :config, :stty_save, :mutex, :config_cache, :runner, :results, :result, :updated_files
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.start(args)
|
20
25
|
if args.size > 1
|
21
26
|
STDERR.puts "expected 0 or 1 argument, got: #{args.join(', ')}"
|
22
27
|
exit!(1)
|
23
28
|
end
|
24
29
|
|
30
|
+
@updated_files = []
|
31
|
+
@results = []
|
32
|
+
@config = get_config(args[0])
|
25
33
|
@stty_save = %x`stty -g`.chomp
|
26
34
|
@mutex = Mutex.new
|
27
|
-
@
|
28
|
-
load_config(args[0])
|
29
|
-
end
|
35
|
+
@config_cache = RSpec::Interactive::ConfigCache.new
|
30
36
|
|
31
|
-
|
37
|
+
load_rspec_config
|
38
|
+
check_rails
|
32
39
|
start_file_watcher
|
33
|
-
load_history
|
34
|
-
configure_auto_complete
|
35
40
|
trap_interrupt
|
36
|
-
|
41
|
+
configure_pry
|
42
|
+
|
43
|
+
Pry.start
|
37
44
|
end
|
38
45
|
|
39
|
-
|
46
|
+
def self.check_rails
|
47
|
+
if defined?(::Rails)
|
48
|
+
if ::Rails.application.config.cache_classes
|
49
|
+
STDERR.puts "warning: Rails.application.config.cache_classes enabled. Disable to ensure code is reloaded."
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
40
53
|
|
41
|
-
def
|
42
|
-
@
|
43
|
-
load @config["init_script"]
|
54
|
+
def self.load_rspec_config
|
55
|
+
@config_cache.record_configuration(&rspec_configuration)
|
44
56
|
end
|
45
57
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
|
58
|
+
def self.rspec_configuration
|
59
|
+
proc do
|
60
|
+
if @config["init_script"]
|
61
|
+
$LOAD_PATH << '.'
|
62
|
+
require @config["init_script"]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.get_config(name = nil)
|
68
|
+
unless File.exists? CONFIG_FILE
|
69
|
+
STDERR.puts "warning: #{CONFIG_FILE} not found, using default config"
|
70
|
+
return {}
|
50
71
|
end
|
51
72
|
|
52
|
-
configs = JSON.parse(File.read(CONFIG_FILE))["configs"]
|
73
|
+
configs = JSON.parse(File.read(CONFIG_FILE))["configs"] || []
|
53
74
|
if configs.empty?
|
54
75
|
STDERR.puts "no configs found in: #{CONFIG_FILE}"
|
55
76
|
exit!(1)
|
@@ -83,123 +104,42 @@ module RSpecInteractive
|
|
83
104
|
end
|
84
105
|
end
|
85
106
|
|
86
|
-
def trap_interrupt
|
107
|
+
def self.trap_interrupt
|
87
108
|
trap('INT') do
|
88
|
-
@
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
puts
|
93
|
-
system "stty", @stty_save
|
94
|
-
exit!(0)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def start_file_watcher
|
101
|
-
# Only polling seems to work in Docker.
|
102
|
-
listener = Listen.to(*@config["watch_dirs"], only: /\.rb$/, force_polling: true) do |modified, added, removed|
|
103
|
-
(added + modified).each { |filename| load filename }
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def load_history
|
108
|
-
if File.exists? HISTORY_FILE
|
109
|
-
lines = File.readlines(HISTORY_FILE)
|
110
|
-
lines.each do |line|
|
111
|
-
Readline::HISTORY << line.strip
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def configure_auto_complete
|
117
|
-
Readline.completion_append_character = ""
|
118
|
-
end
|
119
|
-
|
120
|
-
def start_console
|
121
|
-
loop do
|
122
|
-
buffer = Readline.readline('> ', true)&.strip
|
123
|
-
|
124
|
-
# Exit on ctrl-D.
|
125
|
-
if !buffer
|
109
|
+
if @runner
|
110
|
+
# We are on a different thread. There is a race here. Ignore nil.
|
111
|
+
@runner&.quit
|
112
|
+
else
|
126
113
|
puts
|
127
114
|
system "stty", @stty_save
|
128
115
|
exit!(0)
|
129
116
|
end
|
130
|
-
|
131
|
-
# Ignore blank lines.
|
132
|
-
if buffer.empty?
|
133
|
-
Readline::HISTORY.pop
|
134
|
-
next
|
135
|
-
end
|
136
|
-
|
137
|
-
# Write history to file.
|
138
|
-
if Readline::HISTORY.size > 0
|
139
|
-
file = File.open(HISTORY_FILE, 'w')
|
140
|
-
lines = Readline::HISTORY.to_a
|
141
|
-
lines[-[MAX_HISTORY_ITEMS, lines.size].min..-1].each do |line|
|
142
|
-
file.write(line.strip + "\n")
|
143
|
-
end
|
144
|
-
file.close
|
145
|
-
end
|
146
|
-
|
147
|
-
# Handle quoting, etc.
|
148
|
-
args = Shellwords.shellsplit(buffer)
|
149
|
-
next if args.empty?
|
150
|
-
|
151
|
-
command = args[0].strip
|
152
|
-
if COMMANDS.include?(command)
|
153
|
-
send command.to_sym, args[1..-1]
|
154
|
-
else
|
155
|
-
STDERR.puts "command not found: #{args[0]}"
|
156
|
-
end
|
157
117
|
end
|
158
118
|
end
|
159
119
|
|
160
|
-
def
|
161
|
-
|
162
|
-
STDERR.puts "invalid argument(s): #{args}"
|
163
|
-
return
|
164
|
-
end
|
165
|
-
|
166
|
-
print "commands:\n\n"
|
167
|
-
print "help - print this message\n"
|
168
|
-
print "rspec - execute the specified spec file(s), wildcards allowed\n"
|
169
|
-
end
|
120
|
+
def self.start_file_watcher
|
121
|
+
return unless @config["watch_dirs"]
|
170
122
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
123
|
+
# Only polling seems to work in Docker.
|
124
|
+
listener = Listen.to(*@config["watch_dirs"], only: /\.rb$/, force_polling: true) do |modified, added, removed|
|
125
|
+
@mutex.synchronize do
|
126
|
+
@updated_files.concat(added + modified)
|
127
|
+
end
|
175
128
|
end
|
129
|
+
listener.start
|
130
|
+
end
|
176
131
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
# Store formatters, if any, set by the init script. They will be cleared by RSpec below.
|
181
|
-
formatters = RSpec.configuration.formatters || []
|
182
|
-
|
183
|
-
# Initialize the runner. Also accessed by the signal handler above.
|
184
|
-
# RSpecInteractive::Runner sets RSpec.world.wants_to_quit to false. The signal
|
185
|
-
# handler sets it to true.
|
186
|
-
@mutex.synchronize { @runner = RSpecInteractive::Runner.new(filenames) }
|
187
|
-
|
188
|
-
# Run the specs.
|
189
|
-
@runner.run
|
132
|
+
def self.configure_pry
|
133
|
+
# Prevent Pry from trapping too. It will break ctrl-c handling.
|
134
|
+
Pry.config.should_trap_interrupts = false
|
190
135
|
|
191
|
-
#
|
192
|
-
|
136
|
+
# Set Pry to use Readline. This is the default anyway.
|
137
|
+
Pry.config.input = Readline
|
193
138
|
|
194
|
-
#
|
195
|
-
RSpec
|
139
|
+
# Use custom completer to get file completion.
|
140
|
+
Pry.config.completer = RSpec::Interactive::InputCompleter
|
196
141
|
|
197
|
-
|
198
|
-
# also modifies the list of formatters. Reset them to whatever the init script set.
|
199
|
-
if !RSpec.configuration.formatters.empty?
|
200
|
-
raise "internal error. expected formatters to be cleared."
|
201
|
-
end
|
202
|
-
formatters.each { |f| RSpec.configuration.add_formatter(f) }
|
142
|
+
Pry.config.history_file = HISTORY_FILE
|
203
143
|
end
|
204
144
|
end
|
205
145
|
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# Copied from https://github.com/nviennot/rspec-console/blob/master/lib/rspec-console/config_cache.rb
|
2
|
+
class RSpec::Interactive::ConfigCache
|
3
|
+
# We have to reset the RSpec.configuration, because it contains a lot of
|
4
|
+
# information related to the current test (what's running, what are the
|
5
|
+
# different test results, etc).
|
6
|
+
#
|
7
|
+
# RSpec.configuration gets also loaded with a bunch of stuff from the
|
8
|
+
# 'spec/spec_helper.rb' file. Often that instance is extended with other
|
9
|
+
# modules (FactoryGirl, Mocha,...) and we don't want to replace requires with
|
10
|
+
# load all around the place.
|
11
|
+
#
|
12
|
+
# Instead, we proxy and record whatever is done to RSpec.configuration during
|
13
|
+
# the first invocation of require('spec_helper'). This is done by interposing
|
14
|
+
# the RecordingProxy class on of RSpec.configuration.
|
15
|
+
attr_accessor :config_proxy, :root_shared_examples
|
16
|
+
|
17
|
+
class RecordingProxy < Struct.new(:target, :recorded_messages)
|
18
|
+
[:include, :extend].each do |method|
|
19
|
+
define_method(method) do |*args|
|
20
|
+
method_missing(method, *args)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_missing(method, *args, &block)
|
25
|
+
self.recorded_messages << [method, args, block]
|
26
|
+
self.target.send(method, *args, &block)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def record_configuration(&configuration_block)
|
31
|
+
ensure_configuration_setter!
|
32
|
+
|
33
|
+
original_config = ::RSpec.configuration
|
34
|
+
::RSpec.configuration = RecordingProxy.new(original_config, [])
|
35
|
+
|
36
|
+
configuration_block.call # spec helper is called during this yield, see #reset
|
37
|
+
|
38
|
+
self.config_proxy = ::RSpec.configuration
|
39
|
+
::RSpec.configuration = original_config
|
40
|
+
|
41
|
+
stash_shared_examples
|
42
|
+
|
43
|
+
forward_rspec_config_singleton_to(self.config_proxy)
|
44
|
+
end
|
45
|
+
|
46
|
+
def replay_configuration
|
47
|
+
::RSpec.configure do |config|
|
48
|
+
self.config_proxy.recorded_messages.each do |method, args, block|
|
49
|
+
# reporter caches config.output_stream which is not good as it
|
50
|
+
# prevents the runner to use a custom stdout.
|
51
|
+
next if method == :reporter
|
52
|
+
config.send(method, *args, &block)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
restore_shared_examples
|
57
|
+
|
58
|
+
forward_rspec_config_singleton_to(self.config_proxy)
|
59
|
+
end
|
60
|
+
|
61
|
+
def has_recorded_config?
|
62
|
+
!!self.config_proxy
|
63
|
+
end
|
64
|
+
|
65
|
+
def forward_rspec_config_singleton_to(config_proxy)
|
66
|
+
# an old version of rspec-rails/lib/rspec/rails/view_rendering.rb adds
|
67
|
+
# methods on the configuration singleton. This takes care of that.
|
68
|
+
::RSpec.configuration.singleton_class
|
69
|
+
.send(:define_method, :method_missing, &config_proxy.method(:send))
|
70
|
+
end
|
71
|
+
|
72
|
+
def stash_shared_examples
|
73
|
+
self.root_shared_examples = ::RSpec.world.shared_example_group_registry.send(:shared_example_groups).dup
|
74
|
+
end
|
75
|
+
|
76
|
+
def restore_shared_examples
|
77
|
+
shared_example_groups = ::RSpec.world.shared_example_group_registry.send(:shared_example_groups)
|
78
|
+
shared_example_groups.clear
|
79
|
+
|
80
|
+
self.root_shared_examples.each do |context, hash|
|
81
|
+
hash.each do |name, shared_module|
|
82
|
+
shared_example_groups[context][name] = shared_module
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def ensure_configuration_setter!
|
88
|
+
return if RSpec.respond_to?(:configuration=)
|
89
|
+
|
90
|
+
::RSpec.instance_eval do
|
91
|
+
def self.configuration=(value)
|
92
|
+
@configuration = value
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module RSpec::Interactive
|
2
|
+
class InputCompleter < Pry::InputCompleter
|
3
|
+
|
4
|
+
def rspec_completions(string)
|
5
|
+
line = Readline.line_buffer
|
6
|
+
before_current = Readline.point == string.length ? '' : line[0..(Readline.point - string.length)]
|
7
|
+
before_cursor = line[0..(Readline.point - 1)]
|
8
|
+
|
9
|
+
if line.match(/^ *rspec +/)
|
10
|
+
Dir[string + '*'].map { |filename| File.directory?(filename) ? "#{filename}/" : filename }
|
11
|
+
elsif before_current.strip.empty? && "rspec".match(/^#{Regexp.escape(string)}/)
|
12
|
+
["rspec "]
|
13
|
+
else
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(str, options = {})
|
19
|
+
rspec_completions = rspec_completions(str)
|
20
|
+
return rspec_completions if rspec_completions
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec::Interactive
|
4
|
+
class RSpecCommand < Pry::ClassCommand
|
5
|
+
match 'rspec'
|
6
|
+
description "Invoke RSpec."
|
7
|
+
|
8
|
+
banner <<-BANNER
|
9
|
+
Usage: rspec [arguments]
|
10
|
+
|
11
|
+
See https://relishapp.com/rspec/rspec-core/docs/command-line.
|
12
|
+
BANNER
|
13
|
+
|
14
|
+
command_options(
|
15
|
+
:keep_retval => true
|
16
|
+
)
|
17
|
+
|
18
|
+
def process
|
19
|
+
parsed_args = args.flat_map do |arg|
|
20
|
+
if arg.match(/[\*\?\[]/)
|
21
|
+
glob = Dir.glob(arg)
|
22
|
+
glob.empty? ? [arg] : glob
|
23
|
+
else
|
24
|
+
[arg]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
RSpec::Interactive.mutex.synchronize do
|
29
|
+
RSpec::Interactive.updated_files.uniq.each do |filename|
|
30
|
+
load filename
|
31
|
+
end
|
32
|
+
RSpec::Interactive.updated_files.clear
|
33
|
+
end
|
34
|
+
|
35
|
+
RSpec::Interactive.runner = RSpec::Interactive::Runner.new(parsed_args)
|
36
|
+
|
37
|
+
# Stop saving history in case a new Pry session is started for debugging.
|
38
|
+
Pry.config.history_save = false
|
39
|
+
|
40
|
+
# Run.
|
41
|
+
result = RSpec::Interactive.runner.run
|
42
|
+
RSpec::Interactive.runner = nil
|
43
|
+
|
44
|
+
# Save results
|
45
|
+
RSpec::Interactive.results << result
|
46
|
+
RSpec::Interactive.result = result
|
47
|
+
|
48
|
+
# Reenable history
|
49
|
+
Pry.config.history_save = true
|
50
|
+
|
51
|
+
# Reset
|
52
|
+
RSpec.clear_examples
|
53
|
+
RSpec.reset
|
54
|
+
RSpec::Interactive.config_cache.replay_configuration
|
55
|
+
|
56
|
+
Object.define_method :results do RSpec::Interactive.results end
|
57
|
+
Object.define_method :result do RSpec::Interactive.result end
|
58
|
+
|
59
|
+
puts "Result available at `result`. Result history available at `results`."
|
60
|
+
puts
|
61
|
+
|
62
|
+
result
|
63
|
+
end
|
64
|
+
|
65
|
+
Pry::Commands.add_command(::RSpec::Interactive::RSpecCommand)
|
66
|
+
end
|
67
|
+
end
|
@@ -1,46 +1,77 @@
|
|
1
1
|
require 'rspec/core'
|
2
2
|
|
3
|
-
module
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module RSpec
|
4
|
+
module Interactive
|
5
|
+
class ExampleGroupResult
|
6
|
+
attr_accessor :group, :success
|
7
|
+
|
8
|
+
def initialize(group, success)
|
9
|
+
@group = group
|
10
|
+
@success = success
|
11
|
+
end
|
8
12
|
end
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
@options.configure(RSpec.configuration)
|
13
|
-
return if RSpec.world.wants_to_quit
|
14
|
+
class Result
|
15
|
+
attr_accessor :groups, :success, :exit_code
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
def initialize(groups, success, exit_code)
|
18
|
+
@groups = groups
|
19
|
+
@success = success
|
20
|
+
@exit_code = exit_code
|
18
21
|
end
|
19
22
|
|
20
|
-
|
23
|
+
def inspect(original = false)
|
24
|
+
original ? super() : "<RSpec::Interactive::Result @success=#{@success}, @groups=[...]>"
|
25
|
+
end
|
26
|
+
end
|
21
27
|
|
22
|
-
|
23
|
-
|
28
|
+
class Runner
|
29
|
+
def initialize(args)
|
30
|
+
RSpec.world.wants_to_quit = false
|
31
|
+
@options = RSpec::Core::ConfigurationOptions.new(args)
|
32
|
+
end
|
24
33
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
34
|
+
def run()
|
35
|
+
begin
|
36
|
+
@options.configure(RSpec.configuration)
|
37
|
+
return if RSpec.world.wants_to_quit
|
30
38
|
|
31
|
-
|
32
|
-
|
33
|
-
|
39
|
+
RSpec.configuration.load_spec_files
|
40
|
+
ensure
|
41
|
+
RSpec.world.announce_filters
|
42
|
+
end
|
34
43
|
|
35
|
-
|
44
|
+
return RSpec.configuration.reporter.exit_early(RSpec.configuration.failure_exit_code) if RSpec.world.wants_to_quit
|
45
|
+
|
46
|
+
example_groups = RSpec.world.ordered_example_groups
|
47
|
+
examples_count = RSpec.world.example_count(example_groups)
|
48
|
+
|
49
|
+
result = RSpec.configuration.reporter.report(examples_count) do |reporter|
|
50
|
+
RSpec.configuration.with_suite_hooks do
|
51
|
+
if examples_count == 0 && RSpec.configuration.fail_if_no_examples
|
52
|
+
return RSpec.configuration.failure_exit_code
|
53
|
+
end
|
54
|
+
|
55
|
+
results = example_groups.map do |example_group|
|
56
|
+
group_success = example_group.run(reporter)
|
57
|
+
ExampleGroupResult.new(example_group, group_success)
|
58
|
+
end
|
59
|
+
|
60
|
+
success = results.all?(&:success)
|
61
|
+
exit_code = success ? 0 : 1
|
62
|
+
if RSpec.world.non_example_failure
|
63
|
+
success = false
|
64
|
+
exit_code = RSpec.configuration.failure_exit_code
|
65
|
+
end
|
66
|
+
Result.new(results, success, exit_code)
|
67
|
+
end
|
36
68
|
end
|
69
|
+
result
|
37
70
|
end
|
38
71
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
def quit
|
43
|
-
RSpec.world.wants_to_quit = true
|
72
|
+
def quit
|
73
|
+
RSpec.world.wants_to_quit = true
|
74
|
+
end
|
44
75
|
end
|
45
76
|
end
|
46
77
|
end
|
data/rspec-interactive.gemspec
CHANGED
@@ -4,7 +4,7 @@ require_relative "lib/rspec-interactive/version"
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "rspec-interactive"
|
7
|
-
spec.version =
|
7
|
+
spec.version = RSpec::Interactive::VERSION
|
8
8
|
spec.authors = ["Nick Dower"]
|
9
9
|
spec.email = ["nicholasdower@gmail.com"]
|
10
10
|
|
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
|
17
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
18
18
|
spec.metadata["source_code_uri"] = "https://github.com/nicholasdower/rspec-interactive"
|
19
|
-
spec.metadata["changelog_uri"] = "https://github.com/nicholasdower/rspec-interactive"
|
19
|
+
spec.metadata["changelog_uri"] = "https://github.com/nicholasdower/rspec-interactive/releases"
|
20
20
|
|
21
21
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
22
22
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
@@ -25,5 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.executables << 'rspec-interactive'
|
26
26
|
spec.require_paths = ["lib"]
|
27
27
|
|
28
|
-
spec.add_dependency
|
28
|
+
spec.add_dependency 'rspec-core', '~> 3.9.2', '>= 3.9.2'
|
29
|
+
spec.add_dependency 'listen', '~> 3.5', '>= 3.5.1'
|
30
|
+
spec.add_dependency 'pry', '~> 0.14.1'
|
29
31
|
end
|
metadata
CHANGED
@@ -1,29 +1,69 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-interactive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Dower
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-05-
|
11
|
+
date: 2021-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.9.2
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.9.2
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.9.2
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.9.2
|
13
33
|
- !ruby/object:Gem::Dependency
|
14
34
|
name: listen
|
15
35
|
requirement: !ruby/object:Gem::Requirement
|
16
36
|
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '3.5'
|
17
40
|
- - ">="
|
18
41
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
42
|
+
version: 3.5.1
|
20
43
|
type: :runtime
|
21
44
|
prerelease: false
|
22
45
|
version_requirements: !ruby/object:Gem::Requirement
|
23
46
|
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '3.5'
|
24
50
|
- - ">="
|
25
51
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
52
|
+
version: 3.5.1
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: pry
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 0.14.1
|
60
|
+
type: :runtime
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 0.14.1
|
27
67
|
description: An interactive console for running specs.
|
28
68
|
email:
|
29
69
|
- nicholasdower@gmail.com
|
@@ -36,15 +76,20 @@ files:
|
|
36
76
|
- Gemfile
|
37
77
|
- Gemfile.lock
|
38
78
|
- LICENSE.txt
|
79
|
+
- README.md
|
39
80
|
- Rakefile
|
40
81
|
- bin/console
|
41
82
|
- bin/rspec-interactive
|
42
83
|
- bin/setup
|
43
|
-
-
|
84
|
+
- examples/debugged_spec.rb
|
85
|
+
- examples/failing_spec.rb
|
86
|
+
- examples/passing_spec.rb
|
44
87
|
- lib/rspec-interactive.rb
|
88
|
+
- lib/rspec-interactive/config_cache.rb
|
89
|
+
- lib/rspec-interactive/input_completer.rb
|
90
|
+
- lib/rspec-interactive/rspec_command.rb
|
45
91
|
- lib/rspec-interactive/runner.rb
|
46
92
|
- lib/rspec-interactive/version.rb
|
47
|
-
- rspec-console-0.1.0.gem
|
48
93
|
- rspec-interactive.gemspec
|
49
94
|
homepage: https://github.com/nicholasdower/rspec-interactive
|
50
95
|
licenses:
|
@@ -52,7 +97,7 @@ licenses:
|
|
52
97
|
metadata:
|
53
98
|
homepage_uri: https://github.com/nicholasdower/rspec-interactive
|
54
99
|
source_code_uri: https://github.com/nicholasdower/rspec-interactive
|
55
|
-
changelog_uri: https://github.com/nicholasdower/rspec-interactive
|
100
|
+
changelog_uri: https://github.com/nicholasdower/rspec-interactive/releases
|
56
101
|
post_install_message:
|
57
102
|
rdoc_options: []
|
58
103
|
require_paths:
|
data/lib/repo.rb
DELETED
data/rspec-console-0.1.0.gem
DELETED
Binary file
|