rspec-interactive 0.6.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +4 -1
- data/README.md +34 -3
- data/bin/rspec-interactive +1 -2
- data/lib/rspec-interactive.rb +44 -16
- data/lib/rspec-interactive/config.rb +7 -1
- data/lib/rspec-interactive/input_completer.rb +9 -5
- data/lib/rspec-interactive/refresh_command.rb +22 -0
- data/lib/rspec-interactive/rubo_cop_command.rb +24 -0
- data/lib/rspec-interactive/version.rb +1 -1
- data/scripts/release.sh +3 -0
- data/tests/example_file_test.rb +5 -1
- data/tests/rerun_failed_specs_test.rb +6 -2
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44b14e54786342da3629408fcbaa937173a3965eb3913da0c852a1e7300ac710
|
4
|
+
data.tar.gz: 729af533ef4f4aa26201704430c7dd99c1902d3cd6ab7e924a258340f77a7664
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d83fa6a30f885189a65de0a24cb639ff0e62e6e089378403f5698e75dea8761ab8e74dfd1fd05fe533f37070dd89f683ea9e95eac9ca4b9b0daa33e7b8d4cdf1
|
7
|
+
data.tar.gz: e2cd51ef90235dacf57a47feb4f8b4cdca4e8191c437c57acc73fe0990d055f98d4db6e0e38a84aae4e07fd342a60d34c75a3035ff2a4b86d0f88187cdb45d90
|
data/Gemfile
CHANGED
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.7.2)
|
5
5
|
listen
|
6
6
|
pry
|
7
7
|
rspec-core
|
@@ -36,5 +36,8 @@ DEPENDENCIES
|
|
36
36
|
rspec-expectations
|
37
37
|
rspec-interactive!
|
38
38
|
|
39
|
+
RUBY VERSION
|
40
|
+
ruby 3.0.0p0
|
41
|
+
|
39
42
|
BUNDLED WITH
|
40
43
|
2.2.17
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# RSpec Interactive
|
2
2
|
|
3
|
-
|
3
|
+
A Pry console capable of running specs.
|
4
4
|
|
5
5
|
## Installation & Configuration
|
6
6
|
|
@@ -17,7 +17,7 @@ RSpec::Interactive.configure do |config|
|
|
17
17
|
# Directories to watch for file changes. When a file changes, it will be reloaded like `load 'path/to/file'`.
|
18
18
|
config.watch_dirs += ["app", "lib", "config"]
|
19
19
|
|
20
|
-
# This block is invoked on startup. RSpec configuration must happen here so that it can be reloaded before each test run.
|
20
|
+
# This block is invoked on startup. RSpec configuration must happen here so that it can be cached and reloaded before each test run.
|
21
21
|
config.configure_rspec do
|
22
22
|
require './spec/spec_helper.rb'
|
23
23
|
end
|
@@ -26,6 +26,13 @@ RSpec::Interactive.configure do |config|
|
|
26
26
|
config.on_class_load do |clazz|
|
27
27
|
clazz.clear_validators! if clazz < ApplicationRecord
|
28
28
|
end
|
29
|
+
|
30
|
+
# Invoked before each invocation of RSpec. Can also be manually invoked by typing `refresh` in the console.
|
31
|
+
# Any modified/added files will be loaded via `load` before invoking.
|
32
|
+
config.refresh do
|
33
|
+
FactoryBot.reload
|
34
|
+
Rails.application.reloader.reload!
|
35
|
+
end
|
29
36
|
end
|
30
37
|
```
|
31
38
|
|
@@ -35,6 +42,31 @@ Update `.gitignore`
|
|
35
42
|
echo '.rspec_interactive_history' >> .gitignore
|
36
43
|
```
|
37
44
|
|
45
|
+
### A Note About FactoryBot
|
46
|
+
|
47
|
+
It is not possible to reload a file containing FactoryBot factory definitions via `load` because FactoryBot does not allow factories to be redefined. Be carefule not to add any directories to `watch_dirs` which contain factory definitions. Instead, you should configure the location of your factories like the following in your `spec_helper.rb`:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
FactoryBot.definition_file_paths = %w(spec/factories)
|
51
|
+
FactoryBot.find_definitions # Only if not using Rails
|
52
|
+
```
|
53
|
+
|
54
|
+
Then add the following to your RSpec Interactive config
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
RSpec::Interactive.configure do |config|
|
58
|
+
config.refresh do
|
59
|
+
FactoryBot.reload
|
60
|
+
end
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
This will cause factories to be reloaded before each test run and also whenever the `refresh` command is invoked in the console.
|
65
|
+
|
66
|
+
See: https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#configure-your-test-suite
|
67
|
+
|
68
|
+
See: https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#rails-preloaders-and-rspec
|
69
|
+
|
38
70
|
## Usage
|
39
71
|
|
40
72
|
Optionally, specify a config file with `--config <config-file>`. Optionally, specify arguments to an initial RSpec invocation with `--initial-rspec-args <initial-rspec-args>`.
|
@@ -80,7 +112,6 @@ Run multiple specs:
|
|
80
112
|
```shell
|
81
113
|
[6] pry(main)> rspec examples/passing_spec.rb examples/failing_spec.rb
|
82
114
|
```
|
83
|
-
|
84
115
|
Debug a spec (use `exit` to resume while debugging):
|
85
116
|
|
86
117
|
```shell
|
data/bin/rspec-interactive
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require 'optparse'
|
4
4
|
require 'rspec-interactive'
|
5
|
-
require 'shellwords'
|
6
5
|
|
7
6
|
@options = {}
|
8
7
|
parser = OptionParser.new do |opts|
|
@@ -14,7 +13,7 @@ parser = OptionParser.new do |opts|
|
|
14
13
|
end
|
15
14
|
|
16
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|
|
17
|
-
@options[:initial_rspec_args] =
|
16
|
+
@options[:initial_rspec_args] = initial_rspec_args
|
18
17
|
end
|
19
18
|
end.parse!
|
20
19
|
|
data/lib/rspec-interactive.rb
CHANGED
@@ -3,12 +3,15 @@ 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
9
|
require 'rspec-interactive/config'
|
9
10
|
require 'rspec-interactive/rspec_config_cache'
|
10
11
|
require 'rspec-interactive/input_completer'
|
12
|
+
require 'rspec-interactive/refresh_command'
|
11
13
|
require 'rspec-interactive/rspec_command'
|
14
|
+
require 'rspec-interactive/rubo_cop_command'
|
12
15
|
|
13
16
|
module RSpec
|
14
17
|
module Interactive
|
@@ -36,15 +39,18 @@ module RSpec
|
|
36
39
|
@configuration = Configuration.new
|
37
40
|
load config_file if config_file
|
38
41
|
|
39
|
-
@config_cache.record_configuration { @configuration.configure_rspec.call }
|
40
|
-
|
41
42
|
check_rails
|
42
|
-
start_file_watcher
|
43
43
|
trap_interrupt
|
44
44
|
configure_pry
|
45
45
|
|
46
|
+
@init_thread = Thread.start {
|
47
|
+
@config_cache.record_configuration { @configuration.configure_rspec.call }
|
48
|
+
start_file_watcher
|
49
|
+
}
|
50
|
+
|
46
51
|
if initial_rspec_args
|
47
|
-
rspec initial_rspec_args
|
52
|
+
open(@history_file, 'a') { |f| f.puts "rspec #{initial_rspec_args.strip}" }
|
53
|
+
rspec Shellwords.split(initial_rspec_args)
|
48
54
|
end
|
49
55
|
|
50
56
|
Pry.start
|
@@ -84,7 +90,7 @@ module RSpec
|
|
84
90
|
return if @configuration.watch_dirs.empty?
|
85
91
|
|
86
92
|
# Only polling seems to work in Docker.
|
87
|
-
@listener = Listen.to(*@configuration.watch_dirs, only: /\.rb$/, force_polling: true) do |modified, added
|
93
|
+
@listener = Listen.to(*@configuration.watch_dirs, only: /\.rb$/, force_polling: true) do |modified, added|
|
88
94
|
@mutex.synchronize do
|
89
95
|
@updated_files.concat(added + modified)
|
90
96
|
end
|
@@ -108,19 +114,10 @@ module RSpec
|
|
108
114
|
Pry.config.history_file = @history_file
|
109
115
|
end
|
110
116
|
|
111
|
-
def self.
|
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
|
-
|
117
|
+
def self.refresh
|
121
118
|
@mutex.synchronize do
|
122
119
|
@updated_files.uniq.each do |filename|
|
123
|
-
@output_stream.puts "
|
120
|
+
@output_stream.puts "changed: #{filename}"
|
124
121
|
trace = TracePoint.new(:class) do |tp|
|
125
122
|
@configuration.on_class_load.call(tp.self)
|
126
123
|
end
|
@@ -131,9 +128,30 @@ module RSpec
|
|
131
128
|
end
|
132
129
|
@updated_files.clear
|
133
130
|
end
|
131
|
+
@configuration.refresh.call
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.rspec(args)
|
135
|
+
parsed_args = args.flat_map do |arg|
|
136
|
+
if arg.match(/[\*\?\[]/)
|
137
|
+
glob = Dir.glob(arg)
|
138
|
+
glob.empty? ? [arg] : glob
|
139
|
+
else
|
140
|
+
[arg]
|
141
|
+
end
|
142
|
+
end
|
134
143
|
|
144
|
+
# Initialize the runner before waiting for the init thread so that the interrupt
|
145
|
+
# handler will cancel the RSpec invocation rather than kill the app.
|
135
146
|
@runner = RSpec::Interactive::Runner.new(parsed_args)
|
136
147
|
|
148
|
+
if @init_thread&.alive?
|
149
|
+
@init_thread.join
|
150
|
+
@init_thread = nil
|
151
|
+
end
|
152
|
+
|
153
|
+
refresh
|
154
|
+
|
137
155
|
# Stop saving history in case a new Pry session is started for debugging.
|
138
156
|
Pry.config.history_save = false
|
139
157
|
|
@@ -151,6 +169,16 @@ module RSpec
|
|
151
169
|
RSpec.clear_examples
|
152
170
|
RSpec.reset
|
153
171
|
@config_cache.replay_configuration
|
172
|
+
ensure
|
173
|
+
@runner = nil
|
174
|
+
end
|
175
|
+
|
176
|
+
def self.rubo_cop(args)
|
177
|
+
if defined?(RuboCop)
|
178
|
+
RuboCop::CLI.new.run args
|
179
|
+
else
|
180
|
+
@error_stream.puts "fatal: RuboCop not found. Is the gem installed in this project?"
|
181
|
+
end
|
154
182
|
end
|
155
183
|
end
|
156
184
|
end
|
@@ -1,12 +1,13 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Interactive
|
3
3
|
class Configuration
|
4
|
-
attr_accessor :watch_dirs, :configure_rspec, :on_class_load
|
4
|
+
attr_accessor :watch_dirs, :configure_rspec, :on_class_load, :refresh
|
5
5
|
|
6
6
|
def initialize
|
7
7
|
@watch_dirs = []
|
8
8
|
@configure_rspec = proc {}
|
9
9
|
@on_class_load = proc {}
|
10
|
+
@refresh = proc {}
|
10
11
|
end
|
11
12
|
|
12
13
|
def configure_rspec(&block)
|
@@ -18,6 +19,11 @@ module RSpec
|
|
18
19
|
return @on_class_load unless block
|
19
20
|
@on_class_load = block
|
20
21
|
end
|
22
|
+
|
23
|
+
def refresh(&block)
|
24
|
+
return @refresh unless block
|
25
|
+
@refresh = block
|
26
|
+
end
|
21
27
|
end
|
22
28
|
end
|
23
29
|
end
|
@@ -1,23 +1,27 @@
|
|
1
1
|
module RSpec::Interactive
|
2
2
|
class InputCompleter < Pry::InputCompleter
|
3
3
|
|
4
|
-
def
|
4
|
+
def cli_completions(command, string)
|
5
5
|
line = Readline.line_buffer
|
6
6
|
before_current = Readline.point == string.length ? '' : line[0..(Readline.point - string.length)]
|
7
7
|
before_cursor = line[0..(Readline.point - 1)]
|
8
8
|
|
9
|
-
if line.match(/^
|
9
|
+
if line.match(/^ *#{command} +/)
|
10
10
|
Dir[string + '*'].map { |filename| File.directory?(filename) ? "#{filename}/" : filename }
|
11
|
-
elsif before_current.strip.empty? &&
|
12
|
-
["
|
11
|
+
elsif before_current.strip.empty? && command.match(/^#{Regexp.escape(string)}/)
|
12
|
+
["#{command} "]
|
13
13
|
else
|
14
14
|
nil
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
def call(str, options = {})
|
19
|
-
rspec_completions =
|
19
|
+
rspec_completions = cli_completions('rspec', str)
|
20
20
|
return rspec_completions if rspec_completions
|
21
|
+
|
22
|
+
rubocop_completions = cli_completions('rubocop', str)
|
23
|
+
return rubocop_completions if rubocop_completions
|
24
|
+
|
21
25
|
super
|
22
26
|
end
|
23
27
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec::Interactive
|
4
|
+
class RefreshCommand < Pry::ClassCommand
|
5
|
+
match 'refresh'
|
6
|
+
description "Load any files in watched directories which have changed since the last refresh or rspec invocation."
|
7
|
+
|
8
|
+
banner <<-BANNER
|
9
|
+
Usage: refresh
|
10
|
+
BANNER
|
11
|
+
|
12
|
+
command_options(
|
13
|
+
:keep_retval => false
|
14
|
+
)
|
15
|
+
|
16
|
+
def process
|
17
|
+
RSpec::Interactive.refresh
|
18
|
+
end
|
19
|
+
|
20
|
+
Pry::Commands.add_command(::RSpec::Interactive::RefreshCommand)
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec::Interactive
|
4
|
+
class RuboCopCommand < Pry::ClassCommand
|
5
|
+
match 'rubocop'
|
6
|
+
description "Invoke RuboCop."
|
7
|
+
|
8
|
+
banner <<-BANNER
|
9
|
+
Usage: rubocop [arguments]
|
10
|
+
|
11
|
+
See https://docs.rubocop.org/rubocop/usage/basic_usage.html
|
12
|
+
BANNER
|
13
|
+
|
14
|
+
command_options(
|
15
|
+
:keep_retval => false
|
16
|
+
)
|
17
|
+
|
18
|
+
def process
|
19
|
+
RSpec::Interactive.rubo_cop(args)
|
20
|
+
end
|
21
|
+
|
22
|
+
Pry::Commands.add_command(::RSpec::Interactive::RuboCopCommand)
|
23
|
+
end
|
24
|
+
end
|
data/scripts/release.sh
CHANGED
@@ -15,6 +15,8 @@ fi
|
|
15
15
|
NEW_VERSION=$1
|
16
16
|
CURRENT_VERSION=$(grep VERSION lib/rspec-interactive/version.rb | cut -d'"' -f 2)
|
17
17
|
|
18
|
+
bundle exec bin/test
|
19
|
+
|
18
20
|
echo "Updating from v$CURRENT_VERSION to v$NEW_VERSION. Press enter to continue."
|
19
21
|
read
|
20
22
|
|
@@ -23,3 +25,4 @@ gem build
|
|
23
25
|
gem push rspec-interactive-$NEW_VERSION.gem
|
24
26
|
bundle install
|
25
27
|
git commit -a -m "v$NEW_VERSION Release"
|
28
|
+
open "https://github.com/nicholasdower/rspec-interactive/releases/new?title=v$NEW_VERSION%20Release&tag=v$NEW_VERSION&target=$(git rev-parse HEAD)"
|
data/tests/example_file_test.rb
CHANGED
@@ -7,7 +7,11 @@ examples = Tempfile.new('examples')
|
|
7
7
|
|
8
8
|
config = Tempfile.new('config')
|
9
9
|
config.write <<~EOF
|
10
|
-
RSpec.
|
10
|
+
RSpec::Interactive.configure do |config|
|
11
|
+
config.configure_rspec do
|
12
|
+
RSpec.configuration.example_status_persistence_file_path = "#{examples.path}"
|
13
|
+
end
|
14
|
+
end
|
11
15
|
EOF
|
12
16
|
config.rewind
|
13
17
|
|
@@ -4,11 +4,15 @@ examples = Tempfile.new('examples')
|
|
4
4
|
|
5
5
|
config = Tempfile.new('config')
|
6
6
|
config.write <<~EOF
|
7
|
-
RSpec.
|
7
|
+
RSpec::Interactive.configure do |config|
|
8
|
+
config.configure_rspec do
|
9
|
+
RSpec.configuration.example_status_persistence_file_path = "#{examples.path}"
|
10
|
+
end
|
11
|
+
end
|
8
12
|
EOF
|
9
13
|
config.rewind
|
10
14
|
|
11
|
-
Test.test "failing spec with example file", config_path: config.path do
|
15
|
+
Test.test "rerun failing spec with example file", config_path: config.path do
|
12
16
|
await_prompt
|
13
17
|
|
14
18
|
RSpec.configuration.backtrace_exclusion_patterns = [ /.*/ ]
|
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.8.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-06-
|
11
|
+
date: 2021-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-core
|
@@ -78,8 +78,10 @@ files:
|
|
78
78
|
- lib/rspec-interactive.rb
|
79
79
|
- lib/rspec-interactive/config.rb
|
80
80
|
- lib/rspec-interactive/input_completer.rb
|
81
|
+
- lib/rspec-interactive/refresh_command.rb
|
81
82
|
- lib/rspec-interactive/rspec_command.rb
|
82
83
|
- lib/rspec-interactive/rspec_config_cache.rb
|
84
|
+
- lib/rspec-interactive/rubo_cop_command.rb
|
83
85
|
- lib/rspec-interactive/runner.rb
|
84
86
|
- lib/rspec-interactive/version.rb
|
85
87
|
- rspec-interactive.gemspec
|