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 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