rspec-interactive 0.6.0 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 065d25cbce32ef3f5639e793c9f5db6d99c31a0c536d717ee49f05457251e4f3
4
- data.tar.gz: 8d981a7cf504ec21bb9f0fdd12606ee78e53d6461909b1d0f4ceb06084c616b6
3
+ metadata.gz: 44b14e54786342da3629408fcbaa937173a3965eb3913da0c852a1e7300ac710
4
+ data.tar.gz: 729af533ef4f4aa26201704430c7dd99c1902d3cd6ab7e924a258340f77a7664
5
5
  SHA512:
6
- metadata.gz: f5fd3e74737908f45f9eef622e977a71c8adfac52fb1141548f1e3960ee9839a234a1d4afc60ee0859cdeca6eb23e57a60ab9e77d4ed5475ea1f2e6429f74e5a
7
- data.tar.gz: 734f4c31df3dde4da275c7680364348a549997496abdcd8acaab8ab755fd922de1993b154d94e3646e8e723bc6057ad1766b5add826ac45e5307d25b440b3665
6
+ metadata.gz: d83fa6a30f885189a65de0a24cb639ff0e62e6e089378403f5698e75dea8761ab8e74dfd1fd05fe533f37070dd89f683ea9e95eac9ca4b9b0daa33e7b8d4cdf1
7
+ data.tar.gz: e2cd51ef90235dacf57a47feb4f8b4cdca4e8191c437c57acc73fe0990d055f98d4db6e0e38a84aae4e07fd342a60d34c75a3035ff2a4b86d0f88187cdb45d90
data/Gemfile CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ ruby '3.0.0'
4
+
3
5
  source "https://rubygems.org"
4
6
 
5
7
  gemspec
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rspec-interactive (0.5.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
- An Pry console capable of running specs.
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
@@ -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] = Shellwords.split(initial_rspec_args)
16
+ @options[:initial_rspec_args] = initial_rspec_args
18
17
  end
19
18
  end.parse!
20
19
 
@@ -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, removed|
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.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
-
117
+ def self.refresh
121
118
  @mutex.synchronize do
122
119
  @updated_files.uniq.each do |filename|
123
- @output_stream.puts "modified: #{filename}"
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 rspec_completions(string)
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(/^ *rspec +/)
9
+ if line.match(/^ *#{command} +/)
10
10
  Dir[string + '*'].map { |filename| File.directory?(filename) ? "#{filename}/" : filename }
11
- elsif before_current.strip.empty? && "rspec".match(/^#{Regexp.escape(string)}/)
12
- ["rspec "]
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 = rspec_completions(str)
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RSpec
4
4
  module Interactive
5
- VERSION = "0.6.0"
5
+ VERSION = "0.8.0"
6
6
  end
7
7
  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)"
@@ -7,7 +7,11 @@ examples = Tempfile.new('examples')
7
7
 
8
8
  config = Tempfile.new('config')
9
9
  config.write <<~EOF
10
- RSpec.configuration.example_status_persistence_file_path = "#{examples.path}"
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.configuration.example_status_persistence_file_path = "#{examples.path}"
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.6.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-20 00:00:00.000000000 Z
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