rspec-interactive 0.2.0 → 0.6.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/Gemfile.lock +10 -10
- data/README.md +35 -31
- data/bin/rspec-interactive +17 -1
- data/bin/test +2 -0
- data/examples/failing_spec.rb +0 -4
- data/examples/other_passing_spec.rb +11 -0
- data/examples/spec_with_syntax_error.rb +5 -0
- data/lib/rspec-interactive.rb +84 -73
- data/lib/rspec-interactive/config.rb +23 -0
- data/lib/rspec-interactive/rspec_command.rb +2 -45
- data/lib/rspec-interactive/{config_cache.rb → rspec_config_cache.rb} +0 -0
- data/lib/rspec-interactive/runner.rb +37 -45
- data/lib/rspec-interactive/version.rb +1 -1
- data/rspec-interactive.gemspec +3 -3
- data/scripts/release.sh +25 -0
- data/scripts/run-with-local-dep.sh +36 -0
- data/tests/debugged_spec_test.rb +75 -0
- data/tests/eof_test.rb +10 -0
- data/tests/example_file_test.rb +54 -0
- data/tests/failing_spec_test.rb +41 -0
- data/tests/glob_test.rb +18 -0
- data/tests/line_number_test.rb +19 -0
- data/tests/passing_spec_test.rb +18 -0
- data/tests/rerun_failed_specs_test.rb +90 -0
- data/tests/spec_with_syntax_error_test.rb +30 -0
- data/tests/support/ansi.rb +32 -0
- data/tests/support/test_helper.rb +286 -0
- metadata +28 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 065d25cbce32ef3f5639e793c9f5db6d99c31a0c536d717ee49f05457251e4f3
|
4
|
+
data.tar.gz: 8d981a7cf504ec21bb9f0fdd12606ee78e53d6461909b1d0f4ceb06084c616b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5fd3e74737908f45f9eef622e977a71c8adfac52fb1141548f1e3960ee9839a234a1d4afc60ee0859cdeca6eb23e57a60ab9e77d4ed5475ea1f2e6429f74e5a
|
7
|
+
data.tar.gz: 734f4c31df3dde4da275c7680364348a549997496abdcd8acaab8ab755fd922de1993b154d94e3646e8e723bc6057ad1766b5add826ac45e5307d25b440b3665
|
data/Gemfile.lock
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rspec-interactive (0.
|
5
|
-
listen
|
6
|
-
pry
|
7
|
-
rspec-core
|
4
|
+
rspec-interactive (0.5.0)
|
5
|
+
listen
|
6
|
+
pry
|
7
|
+
rspec-core
|
8
8
|
|
9
9
|
GEM
|
10
10
|
remote: https://rubygems.org/
|
11
11
|
specs:
|
12
12
|
coderay (1.1.3)
|
13
13
|
diff-lcs (1.4.4)
|
14
|
-
ffi (1.15.
|
14
|
+
ffi (1.15.3)
|
15
15
|
listen (3.5.1)
|
16
16
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
17
17
|
rb-inotify (~> 0.9, >= 0.9.10)
|
@@ -22,12 +22,12 @@ GEM
|
|
22
22
|
rb-fsevent (0.11.0)
|
23
23
|
rb-inotify (0.10.1)
|
24
24
|
ffi (~> 1.0)
|
25
|
-
rspec-core (3.
|
26
|
-
rspec-support (~> 3.
|
27
|
-
rspec-expectations (3.
|
25
|
+
rspec-core (3.9.3)
|
26
|
+
rspec-support (~> 3.9.3)
|
27
|
+
rspec-expectations (3.9.4)
|
28
28
|
diff-lcs (>= 1.2.0, < 2.0)
|
29
|
-
rspec-support (~> 3.
|
30
|
-
rspec-support (3.
|
29
|
+
rspec-support (~> 3.9.0)
|
30
|
+
rspec-support (3.9.4)
|
31
31
|
|
32
32
|
PLATFORMS
|
33
33
|
x86_64-darwin-20
|
data/README.md
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# RSpec Interactive
|
2
2
|
|
3
|
-
**WARNING: New (or maybe old by now), experimental, untested and poorly documented. Use at your own risk.**
|
4
|
-
|
5
3
|
An Pry console capable of running specs.
|
6
4
|
|
7
5
|
## Installation & Configuration
|
@@ -12,23 +10,23 @@ Install:
|
|
12
10
|
gem 'rspec-interactive'
|
13
11
|
```
|
14
12
|
|
15
|
-
Add a config file
|
16
|
-
|
17
|
-
```
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
13
|
+
Add a config file which configures RSpec and RSpec::Interactive, for example `spec/rspec_interactive.rb`:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
RSpec::Interactive.configure do |config|
|
17
|
+
# Directories to watch for file changes. When a file changes, it will be reloaded like `load 'path/to/file'`.
|
18
|
+
config.watch_dirs += ["app", "lib", "config"]
|
19
|
+
|
20
|
+
# This block is invoked on startup. RSpec configuration must happen here so that it can be reloaded before each test run.
|
21
|
+
config.configure_rspec do
|
22
|
+
require './spec/spec_helper.rb'
|
23
|
+
end
|
24
|
+
|
25
|
+
# Invoked whenever a class is loaded due to a file change in one of the watch_dirs.
|
26
|
+
config.on_class_load do |clazz|
|
27
|
+
clazz.clear_validators! if clazz < ApplicationRecord
|
28
|
+
end
|
29
|
+
end
|
32
30
|
```
|
33
31
|
|
34
32
|
Update `.gitignore`
|
@@ -39,10 +37,10 @@ echo '.rspec_interactive_history' >> .gitignore
|
|
39
37
|
|
40
38
|
## Usage
|
41
39
|
|
42
|
-
|
40
|
+
Optionally, specify a config file with `--config <config-file>`. Optionally, specify arguments to an initial RSpec invocation with `--initial-rspec-args <initial-rspec-args>`.
|
43
41
|
|
44
42
|
```shell
|
45
|
-
bundle exec rspec-interactive [
|
43
|
+
bundle exec rspec-interactive [--config <config-file>] [--initial-rspec-args <initial-rspec-args>]
|
46
44
|
```
|
47
45
|
|
48
46
|
## Example Usage In This Repo
|
@@ -53,16 +51,16 @@ Start:
|
|
53
51
|
bundle exec rspec-interactive
|
54
52
|
```
|
55
53
|
|
56
|
-
|
54
|
+
Start with an initial RSpec invocation:
|
57
55
|
|
58
56
|
```shell
|
59
|
-
|
57
|
+
bundle exec rspec-interactive --initial-rspec-args examples/passing_spec.rb
|
60
58
|
```
|
61
59
|
|
62
|
-
|
60
|
+
Run a passing spec:
|
63
61
|
|
64
62
|
```shell
|
65
|
-
[
|
63
|
+
[1] pry(main)> rspec examples/passing_spec.rb
|
66
64
|
```
|
67
65
|
|
68
66
|
Run a failing spec:
|
@@ -71,12 +69,6 @@ Run a failing spec:
|
|
71
69
|
[3] pry(main)> rspec examples/failing_spec.rb
|
72
70
|
```
|
73
71
|
|
74
|
-
Inspect result history:
|
75
|
-
|
76
|
-
```shell
|
77
|
-
[4] pry(main)> results
|
78
|
-
```
|
79
|
-
|
80
72
|
Run an example group:
|
81
73
|
|
82
74
|
```shell
|
@@ -106,3 +98,15 @@ Exit:
|
|
106
98
|
```shell
|
107
99
|
[9] pry(main)> exit
|
108
100
|
```
|
101
|
+
|
102
|
+
## Running Tests
|
103
|
+
|
104
|
+
```shell
|
105
|
+
bundle exec bin/test
|
106
|
+
```
|
107
|
+
|
108
|
+
## Releasing
|
109
|
+
|
110
|
+
```shell
|
111
|
+
./scripts/release.sh <version>
|
112
|
+
```
|
data/bin/rspec-interactive
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require 'optparse'
|
3
4
|
require 'rspec-interactive'
|
5
|
+
require 'shellwords'
|
4
6
|
|
5
|
-
|
7
|
+
@options = {}
|
8
|
+
parser = OptionParser.new do |opts|
|
9
|
+
opts.banner = "Starts an interactive RSpec shell.\n\n"\
|
10
|
+
"Usage: bundle exec rspec-interactive [-c config-file] <initial-rspec-args>"
|
11
|
+
|
12
|
+
opts.on("-c", "--config <config-file>", String, "Optional. Path to the RSpec Interactive config file.") do |config_file|
|
13
|
+
@options[:config_file] = config_file
|
14
|
+
end
|
15
|
+
|
16
|
+
opts.on("-r", "--initial-rspec-args <initial-rspec-args>", String, "Optional. Arguments to pass to an initial invocation of RSpec.") do |initial_rspec_args|
|
17
|
+
@options[:initial_rspec_args] = Shellwords.split(initial_rspec_args)
|
18
|
+
end
|
19
|
+
end.parse!
|
20
|
+
|
21
|
+
RSpec::Interactive.start(config_file: @options[:config_file], initial_rspec_args: @options[:initial_rspec_args])
|
data/bin/test
ADDED
data/examples/failing_spec.rb
CHANGED
data/lib/rspec-interactive.rb
CHANGED
@@ -1,106 +1,69 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
1
|
require 'json'
|
4
2
|
require 'listen'
|
3
|
+
require 'pry'
|
5
4
|
require 'readline'
|
6
5
|
require 'rspec/core'
|
7
|
-
require 'pry'
|
8
6
|
|
9
7
|
require 'rspec-interactive/runner'
|
10
|
-
require 'rspec-interactive/
|
8
|
+
require 'rspec-interactive/config'
|
9
|
+
require 'rspec-interactive/rspec_config_cache'
|
11
10
|
require 'rspec-interactive/input_completer'
|
12
11
|
require 'rspec-interactive/rspec_command'
|
13
12
|
|
14
13
|
module RSpec
|
15
14
|
module Interactive
|
16
15
|
|
17
|
-
|
18
|
-
CONFIG_FILE = '.rspec_interactive_config'.freeze
|
16
|
+
DEFAULT_HISTORY_FILE = '.rspec_interactive_history'.freeze
|
19
17
|
|
20
|
-
class <<self
|
21
|
-
attr_accessor :
|
18
|
+
class << self
|
19
|
+
attr_accessor :configuration
|
22
20
|
end
|
23
21
|
|
24
|
-
def self.
|
25
|
-
|
26
|
-
|
27
|
-
exit!(1)
|
28
|
-
end
|
22
|
+
def self.configure(&block)
|
23
|
+
block.call(@configuration)
|
24
|
+
end
|
29
25
|
|
26
|
+
def self.start(config_file: nil, initial_rspec_args: nil, history_file: DEFAULT_HISTORY_FILE, input_stream: STDIN, output_stream: STDOUT, error_stream: STDERR)
|
27
|
+
@history_file = history_file
|
30
28
|
@updated_files = []
|
31
|
-
@results = []
|
32
|
-
@config = get_config(args[0])
|
33
29
|
@stty_save = %x`stty -g`.chomp
|
34
30
|
@mutex = Mutex.new
|
31
|
+
@output_stream = output_stream
|
32
|
+
@input_stream = input_stream
|
33
|
+
@error_stream = error_stream
|
35
34
|
@config_cache = RSpec::Interactive::ConfigCache.new
|
36
35
|
|
37
|
-
|
36
|
+
@configuration = Configuration.new
|
37
|
+
load config_file if config_file
|
38
|
+
|
39
|
+
@config_cache.record_configuration { @configuration.configure_rspec.call }
|
40
|
+
|
38
41
|
check_rails
|
39
42
|
start_file_watcher
|
40
43
|
trap_interrupt
|
41
44
|
configure_pry
|
42
45
|
|
46
|
+
if initial_rspec_args
|
47
|
+
rspec initial_rspec_args
|
48
|
+
end
|
49
|
+
|
43
50
|
Pry.start
|
51
|
+
@listener.stop if @listener
|
52
|
+
0
|
44
53
|
end
|
45
54
|
|
46
55
|
def self.check_rails
|
47
56
|
if defined?(::Rails)
|
48
57
|
if ::Rails.application.config.cache_classes
|
49
|
-
|
58
|
+
@error_stream.puts "warning: Rails.application.config.cache_classes enabled. Disable to ensure code is reloaded."
|
50
59
|
end
|
51
60
|
end
|
52
61
|
end
|
53
62
|
|
54
|
-
def self.
|
55
|
-
|
56
|
-
|
57
|
-
|
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 {}
|
71
|
-
end
|
72
|
-
|
73
|
-
configs = JSON.parse(File.read(CONFIG_FILE))["configs"] || []
|
74
|
-
if configs.empty?
|
75
|
-
STDERR.puts "no configs found in: #{CONFIG_FILE}"
|
76
|
-
exit!(1)
|
77
|
-
end
|
78
|
-
|
79
|
-
# If a specific config was specified, use it.
|
80
|
-
if name
|
81
|
-
config = configs.find { |e| e["name"] == name }
|
82
|
-
return config if config
|
83
|
-
STDERR.puts "invalid config: #{name}"
|
84
|
-
exit!(1)
|
85
|
-
end
|
86
|
-
|
87
|
-
# If there is only one, use it.
|
88
|
-
if configs.size == 1
|
89
|
-
return configs[0]
|
90
|
-
end
|
91
|
-
|
92
|
-
# Ask the user which to use.
|
93
|
-
loop do
|
94
|
-
names = configs.map { |e| e["name"] }
|
95
|
-
names[0] = "#{names[0]} (default)"
|
96
|
-
print "Multiple simultaneous configs not yet supported. Please choose a config. #{names.join(', ')}: "
|
97
|
-
answer = STDIN.gets.chomp
|
98
|
-
if answer.strip.empty?
|
99
|
-
return configs[0]
|
100
|
-
end
|
101
|
-
config = configs.find { |e| e["name"] == answer }
|
102
|
-
return config if config
|
103
|
-
STDERR.puts "invalid config: #{answer}"
|
63
|
+
def self.configure_rspec
|
64
|
+
RSpec.configure do |config|
|
65
|
+
config.error_stream = @error_stream
|
66
|
+
config.output_stream = @output_stream
|
104
67
|
end
|
105
68
|
end
|
106
69
|
|
@@ -110,7 +73,7 @@ module RSpec
|
|
110
73
|
# We are on a different thread. There is a race here. Ignore nil.
|
111
74
|
@runner&.quit
|
112
75
|
else
|
113
|
-
puts
|
76
|
+
@output_stream.puts
|
114
77
|
system "stty", @stty_save
|
115
78
|
exit!(0)
|
116
79
|
end
|
@@ -118,28 +81,76 @@ module RSpec
|
|
118
81
|
end
|
119
82
|
|
120
83
|
def self.start_file_watcher
|
121
|
-
return
|
84
|
+
return if @configuration.watch_dirs.empty?
|
122
85
|
|
123
86
|
# Only polling seems to work in Docker.
|
124
|
-
listener = Listen.to(*@
|
87
|
+
@listener = Listen.to(*@configuration.watch_dirs, only: /\.rb$/, force_polling: true) do |modified, added, removed|
|
125
88
|
@mutex.synchronize do
|
126
89
|
@updated_files.concat(added + modified)
|
127
90
|
end
|
128
91
|
end
|
129
|
-
listener.start
|
92
|
+
@listener.start
|
130
93
|
end
|
131
94
|
|
132
95
|
def self.configure_pry
|
133
96
|
# Prevent Pry from trapping too. It will break ctrl-c handling.
|
134
97
|
Pry.config.should_trap_interrupts = false
|
135
98
|
|
136
|
-
# Set
|
99
|
+
# Set up IO.
|
137
100
|
Pry.config.input = Readline
|
101
|
+
Pry.config.output = @output_stream
|
102
|
+
Readline.output = @output_stream
|
103
|
+
Readline.input = @input_stream
|
138
104
|
|
139
105
|
# Use custom completer to get file completion.
|
140
106
|
Pry.config.completer = RSpec::Interactive::InputCompleter
|
141
107
|
|
142
|
-
Pry.config.history_file =
|
108
|
+
Pry.config.history_file = @history_file
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.rspec(args)
|
112
|
+
parsed_args = args.flat_map do |arg|
|
113
|
+
if arg.match(/[\*\?\[]/)
|
114
|
+
glob = Dir.glob(arg)
|
115
|
+
glob.empty? ? [arg] : glob
|
116
|
+
else
|
117
|
+
[arg]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
@mutex.synchronize do
|
122
|
+
@updated_files.uniq.each do |filename|
|
123
|
+
@output_stream.puts "modified: #{filename}"
|
124
|
+
trace = TracePoint.new(:class) do |tp|
|
125
|
+
@configuration.on_class_load.call(tp.self)
|
126
|
+
end
|
127
|
+
trace.enable
|
128
|
+
load filename
|
129
|
+
trace.disable
|
130
|
+
@output_stream.puts
|
131
|
+
end
|
132
|
+
@updated_files.clear
|
133
|
+
end
|
134
|
+
|
135
|
+
@runner = RSpec::Interactive::Runner.new(parsed_args)
|
136
|
+
|
137
|
+
# Stop saving history in case a new Pry session is started for debugging.
|
138
|
+
Pry.config.history_save = false
|
139
|
+
|
140
|
+
# RSpec::Interactive-specific RSpec configuration
|
141
|
+
configure_rspec
|
142
|
+
|
143
|
+
# Run.
|
144
|
+
exit_code = @runner.run
|
145
|
+
@runner = nil
|
146
|
+
|
147
|
+
# Reenable history
|
148
|
+
Pry.config.history_save = true
|
149
|
+
|
150
|
+
# Reset
|
151
|
+
RSpec.clear_examples
|
152
|
+
RSpec.reset
|
153
|
+
@config_cache.replay_configuration
|
143
154
|
end
|
144
155
|
end
|
145
156
|
end
|