rspec-interactive 0.3.1 → 0.7.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 +2 -2
- data/README.md +31 -21
- data/bin/rspec-interactive +16 -1
- data/examples/other_passing_spec.rb +11 -0
- data/examples/spec_with_syntax_error.rb +5 -0
- data/lib/rspec-interactive.rb +74 -77
- data/lib/rspec-interactive/config.rb +23 -0
- data/lib/rspec-interactive/rspec_command.rb +1 -46
- data/lib/rspec-interactive/{config_cache.rb → rspec_config_cache.rb} +0 -0
- data/lib/rspec-interactive/runner.rb +12 -30
- data/lib/rspec-interactive/version.rb +1 -1
- data/scripts/release.sh +25 -0
- data/scripts/run-with-local-dep.sh +36 -0
- data/tests/debugged_spec_test.rb +37 -0
- data/tests/eof_test.rb +10 -0
- data/tests/example_file_test.rb +54 -0
- data/tests/glob_test.rb +18 -0
- data/tests/line_number_test.rb +19 -0
- data/tests/rerun_failed_specs_test.rb +90 -0
- data/tests/spec_with_syntax_error_test.rb +30 -0
- data/tests/support/test_helper.rb +33 -17
- metadata +14 -4
- data/tests/invalid_config_test.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1f9390c00756ace39f74e3af9d78410cf2890000285035537c2ec6ce6b9e861
|
4
|
+
data.tar.gz: 8d07aec8a3fb5bc78849dbf403a3d30aeb1fec9bdbb38cef2204672e84ba3e9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f585f27c12cc58f2ccb1f8a9d1baf5c05139b58244cba1daf0228c7a9ff8bff71bc0ad79bc0d87ae27ac7580138cb3607ae51c84f3a11d2443fe03f8eaff183
|
7
|
+
data.tar.gz: d8bd001d9bd1be1b3cfa21ec69bcd70b9cb55f3d684bcc336f71e458aa20483a30ced6977c40e4055e9871698246e6e494f805a3fd210a3ec0310dfe72ef25e4
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rspec-interactive (0.
|
4
|
+
rspec-interactive (0.6.1)
|
5
5
|
listen
|
6
6
|
pry
|
7
7
|
rspec-core
|
@@ -11,7 +11,7 @@ GEM
|
|
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)
|
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,6 +51,12 @@ Start:
|
|
53
51
|
bundle exec rspec-interactive
|
54
52
|
```
|
55
53
|
|
54
|
+
Start with an initial RSpec invocation:
|
55
|
+
|
56
|
+
```shell
|
57
|
+
bundle exec rspec-interactive --initial-rspec-args examples/passing_spec.rb
|
58
|
+
```
|
59
|
+
|
56
60
|
Run a passing spec:
|
57
61
|
|
58
62
|
```shell
|
@@ -100,3 +104,9 @@ Exit:
|
|
100
104
|
```shell
|
101
105
|
bundle exec bin/test
|
102
106
|
```
|
107
|
+
|
108
|
+
## Releasing
|
109
|
+
|
110
|
+
```shell
|
111
|
+
./scripts/release.sh <version>
|
112
|
+
```
|
data/bin/rspec-interactive
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require 'optparse'
|
3
4
|
require 'rspec-interactive'
|
4
5
|
|
5
|
-
|
6
|
+
@options = {}
|
7
|
+
parser = OptionParser.new do |opts|
|
8
|
+
opts.banner = "Starts an interactive RSpec shell.\n\n"\
|
9
|
+
"Usage: bundle exec rspec-interactive [-c config-file] <initial-rspec-args>"
|
10
|
+
|
11
|
+
opts.on("-c", "--config <config-file>", String, "Optional. Path to the RSpec Interactive config file.") do |config_file|
|
12
|
+
@options[:config_file] = config_file
|
13
|
+
end
|
14
|
+
|
15
|
+
opts.on("-r", "--initial-rspec-args <initial-rspec-args>", String, "Optional. Arguments to pass to an initial invocation of RSpec.") do |initial_rspec_args|
|
16
|
+
@options[:initial_rspec_args] = initial_rspec_args
|
17
|
+
end
|
18
|
+
end.parse!
|
19
|
+
|
20
|
+
RSpec::Interactive.start(config_file: @options[:config_file], initial_rspec_args: @options[:initial_rspec_args])
|
data/lib/rspec-interactive.rb
CHANGED
@@ -3,9 +3,11 @@ require 'listen'
|
|
3
3
|
require 'pry'
|
4
4
|
require 'readline'
|
5
5
|
require 'rspec/core'
|
6
|
+
require 'shellwords'
|
6
7
|
|
7
8
|
require 'rspec-interactive/runner'
|
8
|
-
require 'rspec-interactive/
|
9
|
+
require 'rspec-interactive/config'
|
10
|
+
require 'rspec-interactive/rspec_config_cache'
|
9
11
|
require 'rspec-interactive/input_completer'
|
10
12
|
require 'rspec-interactive/rspec_command'
|
11
13
|
|
@@ -13,23 +15,18 @@ module RSpec
|
|
13
15
|
module Interactive
|
14
16
|
|
15
17
|
DEFAULT_HISTORY_FILE = '.rspec_interactive_history'.freeze
|
16
|
-
DEFAULT_CONFIG_FILE = '.rspec_interactive_config'.freeze
|
17
18
|
|
18
|
-
class <<self
|
19
|
-
attr_accessor :
|
20
|
-
attr_accessor :config, :mutex, :config_cache, :runner, :results, :result, :updated_files
|
19
|
+
class << self
|
20
|
+
attr_accessor :configuration
|
21
21
|
end
|
22
22
|
|
23
|
-
def self.
|
24
|
-
|
25
|
-
|
26
|
-
return 1
|
27
|
-
end
|
23
|
+
def self.configure(&block)
|
24
|
+
block.call(@configuration)
|
25
|
+
end
|
28
26
|
|
29
|
-
|
27
|
+
def self.start(config_file: nil, initial_rspec_args: nil, history_file: DEFAULT_HISTORY_FILE, input_stream: STDIN, output_stream: STDOUT, error_stream: STDERR)
|
30
28
|
@history_file = history_file
|
31
29
|
@updated_files = []
|
32
|
-
@results = []
|
33
30
|
@stty_save = %x`stty -g`.chomp
|
34
31
|
@mutex = Mutex.new
|
35
32
|
@output_stream = output_stream
|
@@ -37,16 +34,25 @@ module RSpec
|
|
37
34
|
@error_stream = error_stream
|
38
35
|
@config_cache = RSpec::Interactive::ConfigCache.new
|
39
36
|
|
40
|
-
@
|
41
|
-
|
37
|
+
@configuration = Configuration.new
|
38
|
+
load config_file if config_file
|
42
39
|
|
43
|
-
load_rspec_config
|
44
40
|
check_rails
|
45
41
|
start_file_watcher
|
46
42
|
trap_interrupt
|
47
43
|
configure_pry
|
48
44
|
|
45
|
+
@init_thread = Thread.start {
|
46
|
+
@config_cache.record_configuration { @configuration.configure_rspec.call }
|
47
|
+
}
|
48
|
+
|
49
|
+
if initial_rspec_args
|
50
|
+
open(@history_file, 'a') { |f| f.puts "rspec #{initial_rspec_args.strip}" }
|
51
|
+
rspec Shellwords.split(initial_rspec_args)
|
52
|
+
end
|
53
|
+
|
49
54
|
Pry.start
|
55
|
+
@listener.stop if @listener
|
50
56
|
0
|
51
57
|
end
|
52
58
|
|
@@ -58,10 +64,6 @@ module RSpec
|
|
58
64
|
end
|
59
65
|
end
|
60
66
|
|
61
|
-
def self.load_rspec_config
|
62
|
-
@config_cache.record_configuration(&rspec_configuration)
|
63
|
-
end
|
64
|
-
|
65
67
|
def self.configure_rspec
|
66
68
|
RSpec.configure do |config|
|
67
69
|
config.error_stream = @error_stream
|
@@ -69,61 +71,6 @@ module RSpec
|
|
69
71
|
end
|
70
72
|
end
|
71
73
|
|
72
|
-
def self.rspec_configuration
|
73
|
-
proc do
|
74
|
-
if @config["init_script"]
|
75
|
-
$LOAD_PATH << '.'
|
76
|
-
require @config["init_script"]
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def self.get_config(name = nil)
|
82
|
-
unless @config_file && File.exists?(@config_file)
|
83
|
-
@error_stream.puts "warning: config file not found, using default config" if @config_file
|
84
|
-
return {}
|
85
|
-
end
|
86
|
-
|
87
|
-
begin
|
88
|
-
configs = JSON.parse(File.read(@config_file))["configs"] || []
|
89
|
-
rescue JSON::ParserError => e
|
90
|
-
@error_stream.puts "failed to parse config file"
|
91
|
-
return nil
|
92
|
-
end
|
93
|
-
|
94
|
-
if configs.empty?
|
95
|
-
@error_stream.puts "no configs found in config file"
|
96
|
-
return nil
|
97
|
-
end
|
98
|
-
|
99
|
-
# If a specific config was specified, use it.
|
100
|
-
if name
|
101
|
-
config = configs.find { |e| e["name"] == name }
|
102
|
-
return config if config
|
103
|
-
@error_stream.puts "invalid config: #{name}"
|
104
|
-
return nil
|
105
|
-
end
|
106
|
-
|
107
|
-
# If there is only one, use it.
|
108
|
-
if configs.size == 1
|
109
|
-
return configs[0]
|
110
|
-
end
|
111
|
-
|
112
|
-
# Ask the user which to use.
|
113
|
-
loop do
|
114
|
-
names = configs.map { |e| e["name"] }
|
115
|
-
names[0] = "#{names[0]} (default)"
|
116
|
-
print "Multiple simultaneous configs not yet supported. Please choose a config. #{names.join(', ')}: "
|
117
|
-
answer = @input_stream.gets.chomp
|
118
|
-
if answer.strip.empty?
|
119
|
-
return configs[0]
|
120
|
-
end
|
121
|
-
config = configs.find { |e| e["name"] == answer }
|
122
|
-
return config if config
|
123
|
-
@error_stream.puts "invalid config: #{answer}"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
74
|
def self.trap_interrupt
|
128
75
|
trap('INT') do
|
129
76
|
if @runner
|
@@ -138,15 +85,15 @@ module RSpec
|
|
138
85
|
end
|
139
86
|
|
140
87
|
def self.start_file_watcher
|
141
|
-
return
|
88
|
+
return if @configuration.watch_dirs.empty?
|
142
89
|
|
143
90
|
# Only polling seems to work in Docker.
|
144
|
-
listener = Listen.to(*@
|
91
|
+
@listener = Listen.to(*@configuration.watch_dirs, only: /\.rb$/, force_polling: true) do |modified, added, removed|
|
145
92
|
@mutex.synchronize do
|
146
93
|
@updated_files.concat(added + modified)
|
147
94
|
end
|
148
95
|
end
|
149
|
-
listener.start
|
96
|
+
@listener.start
|
150
97
|
end
|
151
98
|
|
152
99
|
def self.configure_pry
|
@@ -164,5 +111,55 @@ module RSpec
|
|
164
111
|
|
165
112
|
Pry.config.history_file = @history_file
|
166
113
|
end
|
114
|
+
|
115
|
+
def self.rspec(args)
|
116
|
+
if @init_thread&.alive?
|
117
|
+
@init_thread.join
|
118
|
+
@init_thread = nil
|
119
|
+
end
|
120
|
+
|
121
|
+
parsed_args = args.flat_map do |arg|
|
122
|
+
if arg.match(/[\*\?\[]/)
|
123
|
+
glob = Dir.glob(arg)
|
124
|
+
glob.empty? ? [arg] : glob
|
125
|
+
else
|
126
|
+
[arg]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
@mutex.synchronize do
|
131
|
+
@updated_files.uniq.each do |filename|
|
132
|
+
@output_stream.puts "modified: #{filename}"
|
133
|
+
trace = TracePoint.new(:class) do |tp|
|
134
|
+
@configuration.on_class_load.call(tp.self)
|
135
|
+
end
|
136
|
+
trace.enable
|
137
|
+
load filename
|
138
|
+
trace.disable
|
139
|
+
@output_stream.puts
|
140
|
+
end
|
141
|
+
@updated_files.clear
|
142
|
+
end
|
143
|
+
|
144
|
+
@runner = RSpec::Interactive::Runner.new(parsed_args)
|
145
|
+
|
146
|
+
# Stop saving history in case a new Pry session is started for debugging.
|
147
|
+
Pry.config.history_save = false
|
148
|
+
|
149
|
+
# RSpec::Interactive-specific RSpec configuration
|
150
|
+
configure_rspec
|
151
|
+
|
152
|
+
# Run.
|
153
|
+
exit_code = @runner.run
|
154
|
+
@runner = nil
|
155
|
+
|
156
|
+
# Reenable history
|
157
|
+
Pry.config.history_save = true
|
158
|
+
|
159
|
+
# Reset
|
160
|
+
RSpec.clear_examples
|
161
|
+
RSpec.reset
|
162
|
+
@config_cache.replay_configuration
|
163
|
+
end
|
167
164
|
end
|
168
165
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Interactive
|
3
|
+
class Configuration
|
4
|
+
attr_accessor :watch_dirs, :configure_rspec, :on_class_load
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@watch_dirs = []
|
8
|
+
@configure_rspec = proc {}
|
9
|
+
@on_class_load = proc {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def configure_rspec(&block)
|
13
|
+
return @configure_rspec unless block
|
14
|
+
@configure_rspec = block
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_class_load(&block)
|
18
|
+
return @on_class_load unless block
|
19
|
+
@on_class_load = block
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -16,52 +16,7 @@ module RSpec::Interactive
|
|
16
16
|
)
|
17
17
|
|
18
18
|
def process
|
19
|
-
|
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
|
-
# RSpec::Interactive-specific RSpec configuration
|
41
|
-
RSpec::Interactive.configure_rspec
|
42
|
-
|
43
|
-
# Run.
|
44
|
-
result = RSpec::Interactive.runner.run
|
45
|
-
RSpec::Interactive.runner = nil
|
46
|
-
|
47
|
-
# Save results
|
48
|
-
RSpec::Interactive.results << result
|
49
|
-
RSpec::Interactive.result = result
|
50
|
-
|
51
|
-
# Reenable history
|
52
|
-
Pry.config.history_save = true
|
53
|
-
|
54
|
-
# Reset
|
55
|
-
RSpec.clear_examples
|
56
|
-
RSpec.reset
|
57
|
-
RSpec::Interactive.config_cache.replay_configuration
|
58
|
-
|
59
|
-
if !RSpec::Interactive.result.success && ::RSpec.configuration.example_status_persistence_file_path
|
60
|
-
RSpec::Interactive.output_stream.puts "Rerun failures by executing the previous command with --only-failures or --next-failure."
|
61
|
-
RSpec::Interactive.output_stream.puts
|
62
|
-
end
|
63
|
-
|
64
|
-
result
|
19
|
+
RSpec::Interactive.rspec(args)
|
65
20
|
end
|
66
21
|
|
67
22
|
Pry::Commands.add_command(::RSpec::Interactive::RSpecCommand)
|
File without changes
|
@@ -2,29 +2,6 @@ require 'rspec/core'
|
|
2
2
|
|
3
3
|
module RSpec
|
4
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
|
12
|
-
end
|
13
|
-
|
14
|
-
class Result
|
15
|
-
attr_accessor :group_results, :success, :exit_code
|
16
|
-
|
17
|
-
def initialize(group_results, success, exit_code)
|
18
|
-
@group_results = group_results
|
19
|
-
@success = success
|
20
|
-
@exit_code = exit_code
|
21
|
-
end
|
22
|
-
|
23
|
-
def inspect(original = false)
|
24
|
-
original ? super() : "<RSpec::Interactive::Result @success=#{@success}, @group_results=[...]>"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
5
|
class Runner
|
29
6
|
def initialize(args)
|
30
7
|
::RSpec.world.wants_to_quit = false
|
@@ -46,28 +23,33 @@ module RSpec
|
|
46
23
|
example_groups = ::RSpec.world.ordered_example_groups
|
47
24
|
examples_count = ::RSpec.world.example_count(example_groups)
|
48
25
|
|
49
|
-
|
26
|
+
exit_code = ::RSpec.configuration.reporter.report(examples_count) do |reporter|
|
50
27
|
::RSpec.configuration.with_suite_hooks do
|
51
28
|
if examples_count == 0 && ::RSpec.configuration.fail_if_no_examples
|
52
29
|
return ::RSpec.configuration.failure_exit_code
|
53
30
|
end
|
54
31
|
|
55
32
|
group_results = example_groups.map do |example_group|
|
56
|
-
|
57
|
-
ExampleGroupResult.new(example_group, group_success)
|
33
|
+
example_group.run(reporter)
|
58
34
|
end
|
59
35
|
|
60
|
-
success = group_results.all?
|
36
|
+
success = group_results.all?
|
61
37
|
exit_code = success ? 0 : 1
|
62
38
|
if ::RSpec.world.non_example_failure
|
63
39
|
success = false
|
64
40
|
exit_code = ::RSpec.configuration.failure_exit_code
|
65
41
|
end
|
66
42
|
persist_example_statuses
|
67
|
-
|
43
|
+
exit_code
|
68
44
|
end
|
69
45
|
end
|
70
|
-
|
46
|
+
|
47
|
+
if exit_code != 0 && ::RSpec.configuration.example_status_persistence_file_path
|
48
|
+
::RSpec.configuration.output_stream.puts "Rerun failures by executing the previous command with --only-failures or --next-failure."
|
49
|
+
::RSpec.configuration.output_stream.puts
|
50
|
+
end
|
51
|
+
|
52
|
+
exit_code
|
71
53
|
end
|
72
54
|
|
73
55
|
def quit
|
@@ -80,7 +62,7 @@ module RSpec
|
|
80
62
|
|
81
63
|
::RSpec::Core::ExampleStatusPersister.persist(::RSpec.world.all_examples, path)
|
82
64
|
rescue SystemCallError => e
|
83
|
-
RSpec
|
65
|
+
::RSpec.configuration.error_stream.puts "warning: failed to write results to #{path}"
|
84
66
|
end
|
85
67
|
end
|
86
68
|
end
|
data/scripts/release.sh
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
if [ $# -ne 1 ]; then
|
6
|
+
echo "usage: $0 <version>" >&2
|
7
|
+
exit 1
|
8
|
+
fi
|
9
|
+
|
10
|
+
if [ -n "$(git status --porcelain)" ]; then
|
11
|
+
echo "error: stage or commit your changes." >&2
|
12
|
+
exit 1;
|
13
|
+
fi
|
14
|
+
|
15
|
+
NEW_VERSION=$1
|
16
|
+
CURRENT_VERSION=$(grep VERSION lib/rspec-interactive/version.rb | cut -d'"' -f 2)
|
17
|
+
|
18
|
+
echo "Updating from v$CURRENT_VERSION to v$NEW_VERSION. Press enter to continue."
|
19
|
+
read
|
20
|
+
|
21
|
+
sed -E -i '' "s/VERSION = \"[^\"]+\"/VERSION = \"$NEW_VERSION\"/g" lib/rspec-interactive/version.rb
|
22
|
+
gem build
|
23
|
+
gem push rspec-interactive-$NEW_VERSION.gem
|
24
|
+
bundle install
|
25
|
+
git commit -a -m "v$NEW_VERSION Release"
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
# Used to quickly test a development version of a gem in the current
|
4
|
+
# directory. Adds a local copy of the specified gem, at the specified
|
5
|
+
# path, to the current directory's Gemfile and executes the specified
|
6
|
+
# command. Upon completion, the Gemfile will be returned to its
|
7
|
+
# previous state.
|
8
|
+
|
9
|
+
if [ $# -ne 3 ]; then
|
10
|
+
echo "usage: $0 <gem-name> <path> <command>" >&2
|
11
|
+
exit 1
|
12
|
+
fi
|
13
|
+
|
14
|
+
GEM_NAME=$1
|
15
|
+
GEM_PATH=$2
|
16
|
+
COMMAND=$3
|
17
|
+
|
18
|
+
if [ -d $GEM_NAME ]; then
|
19
|
+
echo "directory exists: $GEM_NAME" >&2
|
20
|
+
exit 1
|
21
|
+
fi
|
22
|
+
|
23
|
+
OLD_DEP=$(grep "'$GEM_NAME'" Gemfile)
|
24
|
+
if [ $? -ne 0 ]; then
|
25
|
+
echo "$GEM_NAME not found in Gemfile" >&2
|
26
|
+
exit 1
|
27
|
+
fi
|
28
|
+
|
29
|
+
cp Gemfile Gemfile.save
|
30
|
+
cp Gemfile.lock Gemfile.lock.save
|
31
|
+
cp -R $GEM_PATH $GEM_NAME
|
32
|
+
sed -i '' -E "s/^( *gem '$GEM_NAME').*/\1, path: '$GEM_NAME'/g" Gemfile
|
33
|
+
$COMMAND
|
34
|
+
rm -rf $GEM_NAME
|
35
|
+
mv Gemfile.lock.save Gemfile.lock
|
36
|
+
mv Gemfile.save Gemfile
|
data/tests/debugged_spec_test.rb
CHANGED
@@ -31,6 +31,43 @@ Test.test "debugged spec" do
|
|
31
31
|
|
32
32
|
[2] pry(main)> exit
|
33
33
|
EOF
|
34
|
+
end
|
35
|
+
|
36
|
+
Test.test "debugger does not add to history" do
|
37
|
+
await_prompt
|
38
|
+
input "rspec examples/debugged_spec.rb"
|
39
|
+
await_prompt
|
40
|
+
input '"this should not show up in history"'
|
41
|
+
await_prompt
|
42
|
+
input "exit"
|
43
|
+
await_prompt
|
44
|
+
input "exit"
|
45
|
+
await_termination
|
46
|
+
expect_output <<~EOF
|
47
|
+
[1] pry(main)> rspec examples/debugged_spec.rb
|
48
|
+
|
49
|
+
From: /Users/nickdower/Development/rspec-interactive/examples/debugged_spec.rb:6 :
|
50
|
+
|
51
|
+
1: require 'rspec/core'
|
52
|
+
2: require 'pry'
|
53
|
+
3:
|
54
|
+
4: describe "example spec" do
|
55
|
+
5: it "gets debugged" do
|
56
|
+
=> 6: binding.pry
|
57
|
+
7: expect(true).to eq(true)
|
58
|
+
8: end
|
59
|
+
9: end
|
60
|
+
|
61
|
+
[1] pry(#<RSpec::ExampleGroups::ExampleSpec>)> "this should not show up in history"
|
62
|
+
=> "this should not show up in history"
|
63
|
+
[2] pry(#<RSpec::ExampleGroups::ExampleSpec>)> exit
|
64
|
+
.
|
65
|
+
|
66
|
+
Finished in 0 seconds (files took 0 seconds to load)
|
67
|
+
1 example, 0 failures
|
68
|
+
|
69
|
+
[2] pry(main)> exit
|
70
|
+
EOF
|
34
71
|
|
35
72
|
expect_history <<~EOF
|
36
73
|
rspec examples/debugged_spec.rb
|
data/tests/eof_test.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require_relative 'support/test_helper'
|
2
|
+
|
3
|
+
Test.test "exiting via ctrl-d" do
|
4
|
+
await_prompt
|
5
|
+
ctrl_d
|
6
|
+
await_termination
|
7
|
+
# No newlines in tests because we return false from tty? in test_helper.rb.
|
8
|
+
# In the real app, Pry will add a newline because tty? is true.
|
9
|
+
expect_output '[1] pry(main)> '
|
10
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require_relative 'support/test_helper'
|
2
|
+
|
3
|
+
RSpec.configuration.backtrace_exclusion_patterns = [ /.*/ ]
|
4
|
+
RSpec.configuration.backtrace_inclusion_patterns = [ /examples\/failing_spec.rb/ ]
|
5
|
+
|
6
|
+
examples = Tempfile.new('examples')
|
7
|
+
|
8
|
+
config = Tempfile.new('config')
|
9
|
+
config.write <<~EOF
|
10
|
+
RSpec.configuration.example_status_persistence_file_path = "#{examples.path}"
|
11
|
+
EOF
|
12
|
+
config.rewind
|
13
|
+
|
14
|
+
Test.test "failing spec with example file", config_path: config.path do
|
15
|
+
await_prompt
|
16
|
+
input "rspec examples/failing_spec.rb"
|
17
|
+
await_prompt
|
18
|
+
input "exit"
|
19
|
+
await_termination
|
20
|
+
expect_output <<~EOF
|
21
|
+
[1] pry(main)> rspec examples/failing_spec.rb
|
22
|
+
F
|
23
|
+
|
24
|
+
Failures:
|
25
|
+
|
26
|
+
1) example spec fails
|
27
|
+
Failure/Error: expect(true).to eq(false)
|
28
|
+
|
29
|
+
expected: false
|
30
|
+
got: true
|
31
|
+
|
32
|
+
(compared using ==)
|
33
|
+
|
34
|
+
Diff:
|
35
|
+
@@ -1 +1 @@
|
36
|
+
-false
|
37
|
+
+true
|
38
|
+
# ./examples/failing_spec.rb:5:in `block (2 levels) in <top (required)>'
|
39
|
+
|
40
|
+
Finished in 0 seconds (files took 0 seconds to load)
|
41
|
+
1 example, 1 failure
|
42
|
+
|
43
|
+
Failed examples:
|
44
|
+
|
45
|
+
rspec ./examples/failing_spec.rb:4 # example spec fails
|
46
|
+
|
47
|
+
Rerun failures by executing the previous command with --only-failures or --next-failure.
|
48
|
+
|
49
|
+
[2] pry(main)> exit
|
50
|
+
EOF
|
51
|
+
end
|
52
|
+
|
53
|
+
config.close
|
54
|
+
examples.close
|
data/tests/glob_test.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'support/test_helper'
|
2
|
+
|
3
|
+
Test.test "passing spec" do
|
4
|
+
await_prompt
|
5
|
+
input "rspec examples/*passing*_spec.rb"
|
6
|
+
await_prompt
|
7
|
+
input "exit"
|
8
|
+
await_termination
|
9
|
+
expect_output <<~EOF
|
10
|
+
[1] pry(main)> rspec examples/*passing*_spec.rb
|
11
|
+
....
|
12
|
+
|
13
|
+
Finished in 0 seconds (files took 0 seconds to load)
|
14
|
+
4 examples, 0 failures
|
15
|
+
|
16
|
+
[2] pry(main)> exit
|
17
|
+
EOF
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'support/test_helper'
|
2
|
+
|
3
|
+
Test.test "running example group at line number" do
|
4
|
+
await_prompt
|
5
|
+
input "rspec examples/passing_spec.rb:8"
|
6
|
+
await_prompt
|
7
|
+
input "exit"
|
8
|
+
await_termination
|
9
|
+
expect_output <<~EOF
|
10
|
+
[1] pry(main)> rspec examples/passing_spec.rb:8
|
11
|
+
Run options: include {:locations=>{"./examples/passing_spec.rb"=>[8]}}
|
12
|
+
.
|
13
|
+
|
14
|
+
Finished in 0 seconds (files took 0 seconds to load)
|
15
|
+
1 example, 0 failures
|
16
|
+
|
17
|
+
[2] pry(main)> exit
|
18
|
+
EOF
|
19
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require_relative 'support/test_helper'
|
2
|
+
|
3
|
+
examples = Tempfile.new('examples')
|
4
|
+
|
5
|
+
config = Tempfile.new('config')
|
6
|
+
config.write <<~EOF
|
7
|
+
RSpec.configuration.example_status_persistence_file_path = "#{examples.path}"
|
8
|
+
EOF
|
9
|
+
config.rewind
|
10
|
+
|
11
|
+
Test.test "failing spec with example file", config_path: config.path do
|
12
|
+
await_prompt
|
13
|
+
|
14
|
+
RSpec.configuration.backtrace_exclusion_patterns = [ /.*/ ]
|
15
|
+
RSpec.configuration.backtrace_inclusion_patterns = [ /examples\/failing_spec.rb/ ]
|
16
|
+
|
17
|
+
input "rspec examples/failing_spec.rb examples/passing_spec.rb"
|
18
|
+
await_prompt
|
19
|
+
|
20
|
+
RSpec.configuration.backtrace_exclusion_patterns = [ /.*/ ]
|
21
|
+
RSpec.configuration.backtrace_inclusion_patterns = [ /examples\/failing_spec.rb/ ]
|
22
|
+
|
23
|
+
input "rspec examples/failing_spec.rb examples/passing_spec.rb --only-failures"
|
24
|
+
await_prompt
|
25
|
+
input "exit"
|
26
|
+
await_termination
|
27
|
+
expect_output <<~EOF
|
28
|
+
[1] pry(main)> rspec examples/failing_spec.rb examples/passing_spec.rb
|
29
|
+
F..
|
30
|
+
|
31
|
+
Failures:
|
32
|
+
|
33
|
+
1) example spec fails
|
34
|
+
Failure/Error: expect(true).to eq(false)
|
35
|
+
|
36
|
+
expected: false
|
37
|
+
got: true
|
38
|
+
|
39
|
+
(compared using ==)
|
40
|
+
|
41
|
+
Diff:
|
42
|
+
@@ -1 +1 @@
|
43
|
+
-false
|
44
|
+
+true
|
45
|
+
# ./examples/failing_spec.rb:5:in `block (2 levels) in <top (required)>'
|
46
|
+
|
47
|
+
Finished in 0 seconds (files took 0 seconds to load)
|
48
|
+
3 examples, 1 failure
|
49
|
+
|
50
|
+
Failed examples:
|
51
|
+
|
52
|
+
rspec ./examples/failing_spec.rb:4 # example spec fails
|
53
|
+
|
54
|
+
Rerun failures by executing the previous command with --only-failures or --next-failure.
|
55
|
+
|
56
|
+
[2] pry(main)> rspec examples/failing_spec.rb examples/passing_spec.rb --only-failures
|
57
|
+
Run options: include {:last_run_status=>"failed"}
|
58
|
+
F
|
59
|
+
|
60
|
+
Failures:
|
61
|
+
|
62
|
+
1) example spec fails
|
63
|
+
Failure/Error: expect(true).to eq(false)
|
64
|
+
|
65
|
+
expected: false
|
66
|
+
got: true
|
67
|
+
|
68
|
+
(compared using ==)
|
69
|
+
|
70
|
+
Diff:
|
71
|
+
@@ -1 +1 @@
|
72
|
+
-false
|
73
|
+
+true
|
74
|
+
# ./examples/failing_spec.rb:5:in `block (2 levels) in <top (required)>'
|
75
|
+
|
76
|
+
Finished in 0 seconds (files took 0 seconds to load)
|
77
|
+
1 example, 1 failure
|
78
|
+
|
79
|
+
Failed examples:
|
80
|
+
|
81
|
+
rspec ./examples/failing_spec.rb:4 # example spec fails
|
82
|
+
|
83
|
+
Rerun failures by executing the previous command with --only-failures or --next-failure.
|
84
|
+
|
85
|
+
[3] pry(main)> exit
|
86
|
+
EOF
|
87
|
+
end
|
88
|
+
|
89
|
+
config.close
|
90
|
+
examples.close
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'support/test_helper'
|
2
|
+
|
3
|
+
RSpec.configuration.backtrace_exclusion_patterns = [ /.*/ ]
|
4
|
+
RSpec.configuration.backtrace_inclusion_patterns = [ /`load_spec_files'/ ]
|
5
|
+
|
6
|
+
Test.test "spec with syntax error" do
|
7
|
+
await_prompt
|
8
|
+
input "rspec examples/spec_with_syntax_error.rb"
|
9
|
+
await_prompt
|
10
|
+
input "exit"
|
11
|
+
await_termination
|
12
|
+
expect_equal "output", output.gsub(/.+(?=(\\|\/)[a-z_-]+[.]rb:[0-9]+:.*)/, ' [...]'), <<~EOF
|
13
|
+
[1] pry(main)> rspec examples/spec_with_syntax_error.rb
|
14
|
+
|
15
|
+
An error occurred while loading ./examples/spec_with_syntax_error.rb.
|
16
|
+
Failure/Error: ::RSpec.configuration.load_spec_files
|
17
|
+
|
18
|
+
SyntaxError:
|
19
|
+
[...]/spec_with_syntax_error.rb:5: unterminated string meets end of file
|
20
|
+
[...]/spec_with_syntax_error.rb:5: syntax error, unexpected end-of-input, expecting `end'
|
21
|
+
[...]/configuration.rb:1607:in `load_spec_files'
|
22
|
+
No examples found.
|
23
|
+
|
24
|
+
|
25
|
+
Finished in 0 seconds (files took 0 seconds to load)
|
26
|
+
0 examples, 0 failures, 1 error occurred outside of examples
|
27
|
+
|
28
|
+
[2] pry(main)> exit
|
29
|
+
EOF
|
30
|
+
end
|
@@ -109,9 +109,16 @@ module Readline
|
|
109
109
|
Thread.current.kill
|
110
110
|
end
|
111
111
|
|
112
|
+
response = @next_response[0]
|
113
|
+
@next_response.clear
|
114
|
+
|
112
115
|
temp = Tempfile.new('input')
|
113
|
-
|
114
|
-
|
116
|
+
|
117
|
+
unless response.nil?
|
118
|
+
temp.write("#{response}\n")
|
119
|
+
temp.rewind
|
120
|
+
end
|
121
|
+
|
115
122
|
input_read = File.new(temp.path, 'r')
|
116
123
|
Readline.input = input_read
|
117
124
|
|
@@ -172,13 +179,17 @@ class Test
|
|
172
179
|
@history_temp_file = Tempfile.new('history')
|
173
180
|
|
174
181
|
@interactive_thread = Thread.start do
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
+
begin
|
183
|
+
@result = RSpec::Interactive.start(
|
184
|
+
config_file: config_path,
|
185
|
+
history_file: @history_temp_file.path,
|
186
|
+
input_stream: STDIN,
|
187
|
+
output_stream: @output_write,
|
188
|
+
error_stream: @error_write)
|
189
|
+
ensure
|
190
|
+
RSpec.clear_examples
|
191
|
+
RSpec.reset
|
192
|
+
end
|
182
193
|
end
|
183
194
|
|
184
195
|
begin
|
@@ -212,6 +223,7 @@ class Test
|
|
212
223
|
@history_temp_file.close
|
213
224
|
|
214
225
|
Readline.reset
|
226
|
+
Pry.reset_defaults
|
215
227
|
end
|
216
228
|
|
217
229
|
def await_termination
|
@@ -231,6 +243,10 @@ class Test
|
|
231
243
|
Readline.puts(string)
|
232
244
|
end
|
233
245
|
|
246
|
+
def ctrl_d
|
247
|
+
Readline.ctrl_d
|
248
|
+
end
|
249
|
+
|
234
250
|
def output
|
235
251
|
@output_temp_file.rewind
|
236
252
|
File.read(@output_temp_file.path).gsub("\e[0G", "")
|
@@ -251,20 +267,20 @@ class Test
|
|
251
267
|
end
|
252
268
|
|
253
269
|
def expect_output(expected)
|
254
|
-
|
255
|
-
raise "unexpected output:\n expected: #{expected.inspect}\n actual: #{output.inspect}"
|
256
|
-
end
|
270
|
+
expect_equal("output", output, expected)
|
257
271
|
end
|
258
272
|
|
259
273
|
def expect_error_output(expected)
|
260
|
-
|
261
|
-
raise "unexpected error output:\n expected: #{expected.inspect}\n actual: #{error_output.inspect}"
|
262
|
-
end
|
274
|
+
expect_equal("error output", error_output, expected)
|
263
275
|
end
|
264
276
|
|
265
277
|
def expect_result(expected)
|
266
|
-
|
267
|
-
|
278
|
+
expect_equal("result", @result, expected)
|
279
|
+
end
|
280
|
+
|
281
|
+
def expect_equal(name, actual, expected)
|
282
|
+
if expected != actual
|
283
|
+
raise "unexpected #{name}:\n expected: #{expected.inspect}\n actual: #{actual.inspect}"
|
268
284
|
end
|
269
285
|
end
|
270
286
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-interactive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.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-
|
11
|
+
date: 2021-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-core
|
@@ -72,18 +72,28 @@ files:
|
|
72
72
|
- bin/test
|
73
73
|
- examples/debugged_spec.rb
|
74
74
|
- examples/failing_spec.rb
|
75
|
+
- examples/other_passing_spec.rb
|
75
76
|
- examples/passing_spec.rb
|
77
|
+
- examples/spec_with_syntax_error.rb
|
76
78
|
- lib/rspec-interactive.rb
|
77
|
-
- lib/rspec-interactive/
|
79
|
+
- lib/rspec-interactive/config.rb
|
78
80
|
- lib/rspec-interactive/input_completer.rb
|
79
81
|
- lib/rspec-interactive/rspec_command.rb
|
82
|
+
- lib/rspec-interactive/rspec_config_cache.rb
|
80
83
|
- lib/rspec-interactive/runner.rb
|
81
84
|
- lib/rspec-interactive/version.rb
|
82
85
|
- rspec-interactive.gemspec
|
86
|
+
- scripts/release.sh
|
87
|
+
- scripts/run-with-local-dep.sh
|
83
88
|
- tests/debugged_spec_test.rb
|
89
|
+
- tests/eof_test.rb
|
90
|
+
- tests/example_file_test.rb
|
84
91
|
- tests/failing_spec_test.rb
|
85
|
-
- tests/
|
92
|
+
- tests/glob_test.rb
|
93
|
+
- tests/line_number_test.rb
|
86
94
|
- tests/passing_spec_test.rb
|
95
|
+
- tests/rerun_failed_specs_test.rb
|
96
|
+
- tests/spec_with_syntax_error_test.rb
|
87
97
|
- tests/support/ansi.rb
|
88
98
|
- tests/support/test_helper.rb
|
89
99
|
homepage: https://github.com/nicholasdower/rspec-interactive
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require_relative 'support/test_helper'
|
2
|
-
|
3
|
-
config = Tempfile.new('config')
|
4
|
-
config.write '{'
|
5
|
-
config.rewind
|
6
|
-
|
7
|
-
Test.test "invalid config", config_path: config.path do
|
8
|
-
await_termination
|
9
|
-
expect_error_output <<~EOF
|
10
|
-
failed to parse config file
|
11
|
-
EOF
|
12
|
-
expect_result 1
|
13
|
-
end
|
14
|
-
config.close
|
15
|
-
|
16
|
-
config = Tempfile.new('config')
|
17
|
-
config.write '{}'
|
18
|
-
config.rewind
|
19
|
-
|
20
|
-
Test.test "empty config", config_path: config.path do
|
21
|
-
await_termination
|
22
|
-
expect_error_output <<~EOF
|
23
|
-
no configs found in config file
|
24
|
-
EOF
|
25
|
-
expect_result 1
|
26
|
-
end
|