rspec-interactive 0.5.0 → 0.7.2
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 +48 -7
- data/bin/rspec-interactive +16 -10
- data/lib/rspec-interactive.rb +39 -16
- data/lib/rspec-interactive/config.rb +7 -1
- data/lib/rspec-interactive/refresh_command.rb +22 -0
- data/lib/rspec-interactive/version.rb +1 -1
- data/scripts/release.sh +28 -0
- data/{run-with-local-dep.sh → scripts/run-with-local-dep.sh} +0 -0
- data/tests/example_file_test.rb +5 -1
- data/tests/rerun_failed_specs_test.rb +6 -2
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e56b91e4f1d28feae7da156d8e4f3ddec5aeffe5847f0ecf6c28150f9f2ac1d
|
4
|
+
data.tar.gz: 9b88b87a123b207b1478413b0e963bee0a25255163977cd2982cd8d9a0d21742
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5acd4df05e27db03f66f66f96f9cc43692485abbfe04ee5e680589689c274bde396f07c893b2138cea6db745a4fcc2b9a127caaf7a8c0ccb7c5a2acedd60b6e
|
7
|
+
data.tar.gz: 534a6ba41f06820271a60a5844fc72e19bb92730067bda01d84ad791fd5c99ce35b4f94b60badb862a7f5de183dbc5a799bfb8280f07162660e99a1b186d74d1
|
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.1)
|
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
|
|
@@ -13,13 +13,11 @@ gem 'rspec-interactive'
|
|
13
13
|
Add a config file which configures RSpec and RSpec::Interactive, for example `spec/rspec_interactive.rb`:
|
14
14
|
|
15
15
|
```ruby
|
16
|
-
load 'spec/spec_helper.rb'
|
17
|
-
|
18
16
|
RSpec::Interactive.configure do |config|
|
19
17
|
# Directories to watch for file changes. When a file changes, it will be reloaded like `load 'path/to/file'`.
|
20
18
|
config.watch_dirs += ["app", "lib", "config"]
|
21
19
|
|
22
|
-
# 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.
|
23
21
|
config.configure_rspec do
|
24
22
|
require './spec/spec_helper.rb'
|
25
23
|
end
|
@@ -28,6 +26,13 @@ RSpec::Interactive.configure do |config|
|
|
28
26
|
config.on_class_load do |clazz|
|
29
27
|
clazz.clear_validators! if clazz < ApplicationRecord
|
30
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
|
31
36
|
end
|
32
37
|
```
|
33
38
|
|
@@ -37,12 +42,37 @@ Update `.gitignore`
|
|
37
42
|
echo '.rspec_interactive_history' >> .gitignore
|
38
43
|
```
|
39
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
|
+
|
40
70
|
## Usage
|
41
71
|
|
42
|
-
|
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>`.
|
43
73
|
|
44
74
|
```shell
|
45
|
-
bundle exec rspec-interactive
|
75
|
+
bundle exec rspec-interactive [--config <config-file>] [--initial-rspec-args <initial-rspec-args>]
|
46
76
|
```
|
47
77
|
|
48
78
|
## Example Usage In This Repo
|
@@ -53,6 +83,12 @@ Start:
|
|
53
83
|
bundle exec rspec-interactive
|
54
84
|
```
|
55
85
|
|
86
|
+
Start with an initial RSpec invocation:
|
87
|
+
|
88
|
+
```shell
|
89
|
+
bundle exec rspec-interactive --initial-rspec-args examples/passing_spec.rb
|
90
|
+
```
|
91
|
+
|
56
92
|
Run a passing spec:
|
57
93
|
|
58
94
|
```shell
|
@@ -76,7 +112,6 @@ Run multiple specs:
|
|
76
112
|
```shell
|
77
113
|
[6] pry(main)> rspec examples/passing_spec.rb examples/failing_spec.rb
|
78
114
|
```
|
79
|
-
|
80
115
|
Debug a spec (use `exit` to resume while debugging):
|
81
116
|
|
82
117
|
```shell
|
@@ -100,3 +135,9 @@ Exit:
|
|
100
135
|
```shell
|
101
136
|
bundle exec bin/test
|
102
137
|
```
|
138
|
+
|
139
|
+
## Releasing
|
140
|
+
|
141
|
+
```shell
|
142
|
+
./scripts/release.sh <version>
|
143
|
+
```
|
data/bin/rspec-interactive
CHANGED
@@ -1,14 +1,20 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require 'optparse'
|
3
4
|
require 'rspec-interactive'
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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,11 +3,13 @@ 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'
|
12
14
|
|
13
15
|
module RSpec
|
@@ -23,7 +25,7 @@ module RSpec
|
|
23
25
|
block.call(@configuration)
|
24
26
|
end
|
25
27
|
|
26
|
-
def self.start(config_file: nil, history_file: DEFAULT_HISTORY_FILE, input_stream: STDIN, output_stream: STDOUT, error_stream: STDERR)
|
28
|
+
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
29
|
@history_file = history_file
|
28
30
|
@updated_files = []
|
29
31
|
@stty_save = %x`stty -g`.chomp
|
@@ -36,13 +38,20 @@ module RSpec
|
|
36
38
|
@configuration = Configuration.new
|
37
39
|
load config_file if config_file
|
38
40
|
|
39
|
-
@config_cache.record_configuration { @configuration.configure_rspec.call }
|
40
|
-
|
41
41
|
check_rails
|
42
|
-
start_file_watcher
|
43
42
|
trap_interrupt
|
44
43
|
configure_pry
|
45
44
|
|
45
|
+
@init_thread = Thread.start {
|
46
|
+
@config_cache.record_configuration { @configuration.configure_rspec.call }
|
47
|
+
start_file_watcher
|
48
|
+
}
|
49
|
+
|
50
|
+
if initial_rspec_args
|
51
|
+
open(@history_file, 'a') { |f| f.puts "rspec #{initial_rspec_args.strip}" }
|
52
|
+
rspec Shellwords.split(initial_rspec_args)
|
53
|
+
end
|
54
|
+
|
46
55
|
Pry.start
|
47
56
|
@listener.stop if @listener
|
48
57
|
0
|
@@ -80,7 +89,7 @@ module RSpec
|
|
80
89
|
return if @configuration.watch_dirs.empty?
|
81
90
|
|
82
91
|
# Only polling seems to work in Docker.
|
83
|
-
@listener = Listen.to(*@configuration.watch_dirs, only: /\.rb$/, force_polling: true) do |modified, added
|
92
|
+
@listener = Listen.to(*@configuration.watch_dirs, only: /\.rb$/, force_polling: true) do |modified, added|
|
84
93
|
@mutex.synchronize do
|
85
94
|
@updated_files.concat(added + modified)
|
86
95
|
end
|
@@ -104,19 +113,10 @@ module RSpec
|
|
104
113
|
Pry.config.history_file = @history_file
|
105
114
|
end
|
106
115
|
|
107
|
-
def self.
|
108
|
-
parsed_args = args.flat_map do |arg|
|
109
|
-
if arg.match(/[\*\?\[]/)
|
110
|
-
glob = Dir.glob(arg)
|
111
|
-
glob.empty? ? [arg] : glob
|
112
|
-
else
|
113
|
-
[arg]
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
116
|
+
def self.refresh
|
117
117
|
@mutex.synchronize do
|
118
118
|
@updated_files.uniq.each do |filename|
|
119
|
-
@output_stream.puts "
|
119
|
+
@output_stream.puts "changed: #{filename}"
|
120
120
|
trace = TracePoint.new(:class) do |tp|
|
121
121
|
@configuration.on_class_load.call(tp.self)
|
122
122
|
end
|
@@ -127,9 +127,30 @@ module RSpec
|
|
127
127
|
end
|
128
128
|
@updated_files.clear
|
129
129
|
end
|
130
|
+
@configuration.refresh.call
|
131
|
+
end
|
130
132
|
|
133
|
+
def self.rspec(args)
|
134
|
+
parsed_args = args.flat_map do |arg|
|
135
|
+
if arg.match(/[\*\?\[]/)
|
136
|
+
glob = Dir.glob(arg)
|
137
|
+
glob.empty? ? [arg] : glob
|
138
|
+
else
|
139
|
+
[arg]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Initialize the runner before waiting for the init thread so that the interrupt
|
144
|
+
# handler will cancel the RSpec invocation rather than kill the app.
|
131
145
|
@runner = RSpec::Interactive::Runner.new(parsed_args)
|
132
146
|
|
147
|
+
if @init_thread&.alive?
|
148
|
+
@init_thread.join
|
149
|
+
@init_thread = nil
|
150
|
+
end
|
151
|
+
|
152
|
+
refresh
|
153
|
+
|
133
154
|
# Stop saving history in case a new Pry session is started for debugging.
|
134
155
|
Pry.config.history_save = false
|
135
156
|
|
@@ -147,6 +168,8 @@ module RSpec
|
|
147
168
|
RSpec.clear_examples
|
148
169
|
RSpec.reset
|
149
170
|
@config_cache.replay_configuration
|
171
|
+
ensure
|
172
|
+
@runner = nil
|
150
173
|
end
|
151
174
|
end
|
152
175
|
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
|
@@ -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
|
data/scripts/release.sh
ADDED
@@ -0,0 +1,28 @@
|
|
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
|
+
bundle exec bin/test
|
19
|
+
|
20
|
+
echo "Updating from v$CURRENT_VERSION to v$NEW_VERSION. Press enter to continue."
|
21
|
+
read
|
22
|
+
|
23
|
+
sed -E -i '' "s/VERSION = \"[^\"]+\"/VERSION = \"$NEW_VERSION\"/g" lib/rspec-interactive/version.rb
|
24
|
+
gem build
|
25
|
+
gem push rspec-interactive-$NEW_VERSION.gem
|
26
|
+
bundle install
|
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)"
|
File without changes
|
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.7.2
|
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-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-core
|
@@ -78,12 +78,14 @@ 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
|
83
84
|
- lib/rspec-interactive/runner.rb
|
84
85
|
- lib/rspec-interactive/version.rb
|
85
86
|
- rspec-interactive.gemspec
|
86
|
-
-
|
87
|
+
- scripts/release.sh
|
88
|
+
- scripts/run-with-local-dep.sh
|
87
89
|
- tests/debugged_spec_test.rb
|
88
90
|
- tests/eof_test.rb
|
89
91
|
- tests/example_file_test.rb
|