rspec-interactive 0.9.1 → 0.9.4

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: dbc1f295bcf16bf85e5d6a6281de27ea2b51aa08f373272fb7d9e472ec13f3e9
4
- data.tar.gz: 36d80a0af500094c129970d522b2a3a3e6bbfc117549b9453f8a5f07ccbcbe33
3
+ metadata.gz: 58b63742b50c16f44d1cf19e2957e29ed07ef4a19c3ee91debed0624f519684a
4
+ data.tar.gz: 0217f523599d1ee0a104718bd3c2bd79aeaf9366d18a22f5abfdadb2ce1fc229
5
5
  SHA512:
6
- metadata.gz: 11ba7e2f1e90ddc985f6154b7fec1b738b2477481eb40efe92a822d11a39970799ed147a4ae5da4736b226d1fcb25fe372083fbb7a2346754f5a771456a9a01f
7
- data.tar.gz: e10376660d90bace5ea870d3b9f046780157c65e3ec489ca21aa409ae0dcbdacf60cfa11e49d9ba2ab947b06b71e9e3fd5d35b976346ee370b552e8fd07e0bb6
6
+ metadata.gz: 7d5dbf2e0ec74668264fee718f5e2edaa60f0bff510433f376ac8264a64afb61b2a3538e8604f3c8cc4e0c1e48b409bb4bccfaedb25e0b587145d7b9f4abbb11
7
+ data.tar.gz: 86bba6bf0ad9728ba06d9374a3efb7b74cb4736fb24f5a81799e7ed4d54c499c012153ca2e90096caf0ab3965098c38cccc28b2b9c0d031723e7cc698b0a4fcc
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rspec-interactive (0.9.0)
4
+ rspec-interactive (0.9.3)
5
5
  listen
6
6
  pry
7
7
  rspec-core
@@ -4,20 +4,20 @@ require 'optparse'
4
4
  require 'rspec-interactive'
5
5
 
6
6
  @options = {
7
- server: false,
8
- port: RSpec::Interactive::DEFAULT_PORT
7
+ server: true,
8
+ server_port: RSpec::Interactive::DEFAULT_PORT
9
9
  }
10
10
 
11
11
  parser = OptionParser.new do |opts|
12
12
  opts.banner = "Starts an interactive RSpec shell.\n\n"\
13
- "Usage: bundle exec rspec-interactive [--config config-file] [--server [--port <port>]]"
13
+ "Usage: bundle exec rspec-interactive [--config config-file] [--no-server] [--port <port>]"
14
14
 
15
15
  opts.on("-c", "--config <config-file>", String, "Optional. Path to the RSpec Interactive config file.") do |config_file|
16
16
  @options[:config_file] = config_file
17
17
  end
18
18
 
19
- opts.on("-s", "--server", "Optional. Enable server used by IDEs.") do
20
- @options[:server] = true
19
+ opts.on("--no-server", "Optional. Disable server.") do
20
+ @options[:server] = false
21
21
  end
22
22
 
23
23
  opts.on("-p", "--port <port>", Integer, "Optional. Server port. Defaults to #{RSpec::Interactive::DEFAULT_PORT}.") do |port|
@@ -26,4 +26,4 @@ parser = OptionParser.new do |opts|
26
26
 
27
27
  end.parse!
28
28
 
29
- RSpec::Interactive.start(config_file: @options[:config_file], server: @options[:server], port: @options[:port])
29
+ RSpec::Interactive.start(config_file: @options[:config_file], server: @options[:server], port: @options[:server_port])
@@ -0,0 +1,7 @@
1
+ RSpec::Interactive.configure do |config|
2
+ config.watch_dirs += ['lib']
3
+
4
+ config.configure_rspec do
5
+ RSpec.configuration.formatter = :documentation
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ module RSpec
2
+ module Interactive
3
+ class ClientOutput
4
+ def initialize(client)
5
+ @client = client
6
+ end
7
+
8
+ def print(str = "")
9
+ @client.print(str&.to_s || '')
10
+ end
11
+
12
+ def string
13
+ @output
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,12 @@
1
+ require 'pry'
2
+
3
+ class Pry
4
+ alias_method :old_eval, :eval
5
+
6
+ def eval(line, options = {})
7
+ RSpec::Interactive.eval do
8
+ old_eval(line, options)
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,15 @@
1
+ require 'rspec/core'
2
+
3
+ module RSpec
4
+ module Core
5
+ class Example
6
+ alias_method :old_run, :run
7
+
8
+ def run(example_group_instance, reporter)
9
+ execution_result.started_at = RSpec::Core::Time.now
10
+ old_run(example_group_instance, reporter)
11
+ end
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,44 @@
1
+ module RSpec
2
+ module Interactive
3
+ class Stdio
4
+ def self.capture(output)
5
+ raise ArgumentError, 'missing block' unless block_given?
6
+
7
+ stdout, stderr = STDOUT.dup, STDERR.dup
8
+
9
+ IO.pipe do |stdout_read, stdout_write|
10
+ IO.pipe do |stderr_read, stderr_write|
11
+ STDOUT.reopen(stdout_write)
12
+ STDERR.reopen(stderr_write)
13
+
14
+ stdout_write.close
15
+ stderr_write.close
16
+
17
+ stdout_thread = Thread.new do
18
+ while line = stdout_read.gets do
19
+ output.print(line)
20
+ end
21
+ end
22
+
23
+ stderr_thread = Thread.new do
24
+ while line = stderr_read.gets do
25
+ output.print(line)
26
+ end
27
+ end
28
+
29
+ begin
30
+ yield
31
+ ensure
32
+ # TODO: should the threads be killed here?
33
+ STDOUT.reopen stdout
34
+ STDERR.reopen stderr
35
+ end
36
+
37
+ stdout_thread.join
38
+ stderr_thread.join
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RSpec
4
4
  module Interactive
5
- VERSION = "0.9.1"
5
+ VERSION = "0.9.4"
6
6
  end
7
7
  end
@@ -7,13 +7,17 @@ require 'shellwords'
7
7
  require 'socket'
8
8
  require 'teamcity/spec/runner/formatter/teamcity/formatter'
9
9
 
10
+ require 'rspec-interactive/client_output'
10
11
  require 'rspec-interactive/config'
11
12
  require 'rspec-interactive/input_completer'
13
+ require 'rspec-interactive/pry'
12
14
  require 'rspec-interactive/refresh_command'
13
15
  require 'rspec-interactive/rspec_command'
14
16
  require 'rspec-interactive/rspec_config_cache'
17
+ require 'rspec-interactive/rspec_core_example'
15
18
  require 'rspec-interactive/rubo_cop_command'
16
19
  require 'rspec-interactive/runner'
20
+ require 'rspec-interactive/stdio'
17
21
 
18
22
  module RSpec
19
23
  module Interactive
@@ -42,7 +46,7 @@ module RSpec
42
46
  @updated_files = []
43
47
  @stty_save = %x`stty -g`.chomp
44
48
  @file_change_mutex = Mutex.new
45
- @rspec_mutex = Mutex.new
49
+ @command_mutex = Mutex.new
46
50
  @output_stream = output_stream
47
51
  @input_stream = input_stream
48
52
  @error_stream = error_stream
@@ -52,14 +56,16 @@ module RSpec
52
56
  load config_file if config_file
53
57
 
54
58
  check_rails
59
+ trap_interrupt
55
60
  configure_pry
61
+ load_rspec_configuration
56
62
 
57
- @config_cache.record_configuration { @configuration.configure_rspec.call }
58
63
  start_file_watcher
59
64
 
60
65
  if server
66
+ @output_stream.puts "listening on port #{port}"
61
67
  server_thread = Thread.start do
62
- server = TCPServer.new 5678
68
+ server = TCPServer.new port
63
69
 
64
70
  while client = server.accept
65
71
  request = client.gets
@@ -84,11 +90,14 @@ module RSpec
84
90
  end
85
91
  end
86
92
 
87
- def self.configure_rspec(error_stream: @error_stream, output_stream: @output_stream)
88
- RSpec.configure do |config|
89
- config.error_stream = error_stream
90
- config.output_stream = output_stream
91
- config.start_time = RSpec::Core::Time.now
93
+ def self.trap_interrupt
94
+ trap('INT') do
95
+ if @runner
96
+ # We are on a different thread. There is a race here. Ignore nil.
97
+ @runner&.quit
98
+ else
99
+ raise Interrupt
100
+ end
92
101
  end
93
102
  end
94
103
 
@@ -104,7 +113,24 @@ module RSpec
104
113
  @listener.start
105
114
  end
106
115
 
116
+ def self.load_rspec_configuration
117
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
118
+ config_thread = Thread.start do
119
+ @config_cache.record_configuration { @configuration.configure_rspec.call }
120
+ end
121
+ unless config_thread.join(3)
122
+ @output_stream.puts "executing configure_rspec hook..."
123
+ end
124
+ config_thread.join
125
+
126
+ end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
127
+ @output_stream.puts "configure_rspec hook took #{(end_time - start_time).round} seconds" if end_time - start_time > 5
128
+ end
129
+
107
130
  def self.configure_pry
131
+ # Prevent Pry from trapping too. It will break ctrl-c handling.
132
+ Pry.config.should_trap_interrupts = false
133
+
108
134
  # Set up IO.
109
135
  Pry.config.input = Readline
110
136
  Pry.config.output = @output_stream
@@ -146,63 +172,75 @@ module RSpec
146
172
  end
147
173
 
148
174
  def self.rspec(args)
149
- @rspec_mutex.synchronize do
175
+ @runner = RSpec::Interactive::Runner.new(parse_args(args))
150
176
 
151
- @runner = RSpec::Interactive::Runner.new(parse_args(args))
177
+ refresh
152
178
 
153
- refresh
179
+ # Stop saving history in case a new Pry session is started for debugging.
180
+ Pry.config.history_save = false
154
181
 
155
- # Stop saving history in case a new Pry session is started for debugging.
156
- Pry.config.history_save = false
157
-
158
- # RSpec::Interactive-specific RSpec configuration
159
- configure_rspec
182
+ # RSpec::Interactive-specific RSpec configuration
183
+ RSpec.configure do |config|
184
+ config.error_stream = @error_stream
185
+ config.output_stream = @output_stream
186
+ config.start_time = RSpec::Core::Time.now
187
+ end
160
188
 
161
- # Run.
162
- exit_code = @runner.run
163
- @runner = nil
189
+ # Run.
190
+ exit_code = @runner.run
191
+ @runner = nil
164
192
 
165
- # Reenable history
166
- Pry.config.history_save = true
193
+ # Reenable history
194
+ Pry.config.history_save = true
167
195
 
168
- # Reset
169
- RSpec.clear_examples
170
- RSpec.reset
171
- @config_cache.replay_configuration
172
- rescue Interrupt
173
- @runner&.quit
174
- ensure
175
- @runner = nil
176
- end
196
+ # Reset
197
+ RSpec.clear_examples
198
+ RSpec.reset
199
+ @config_cache.replay_configuration
200
+ ensure
201
+ @runner = nil
177
202
  end
178
203
 
179
204
  def self.rspec_for_server(client, args)
180
- @rspec_mutex.synchronize do
181
- # Set the client so that logs are written to the client rathe than STDOUT.
182
- Spec::Runner::Formatter::TeamcityFormatter.client = client
183
-
184
- @runner = RSpec::Interactive::Runner.new(parse_args(args))
185
-
186
- refresh
205
+ @command_mutex.synchronize do
206
+ # Prevent the debugger from being used. The server isn't interactive.
207
+ disable_pry = ENV['DISABLE_PRY']
208
+ ENV['DISABLE_PRY'] = 'true'
209
+
210
+ output = ClientOutput.new(client)
211
+ Stdio.capture(ClientOutput.new(client)) do
212
+ @runner = RSpec::Interactive::Runner.new(parse_args(args))
213
+
214
+ refresh
215
+
216
+ # RSpec::Interactive-specific RSpec configuration
217
+ RSpec.configure do |config|
218
+ config.error_stream = @error_stream
219
+ config.output_stream = @output_stream
220
+ config.start_time = RSpec::Core::Time.now
221
+ end
187
222
 
188
- # Stop saving history in case a new Pry session is started for debugging.
189
- Pry.config.history_save = false
223
+ # RubyMine specifies --format. That causes a formatter to be added. It does not override
224
+ # the existing formatter (if one is set by default). Clear any formatters but resetting
225
+ # the loader.
226
+ RSpec.configuration.instance_variable_set(
227
+ :@formatter_loader,
228
+ RSpec::Core::Formatters::Loader.new(RSpec::Core::Reporter.new(RSpec.configuration)))
190
229
 
191
- # RSpec::Interactive-specific RSpec configuration
192
- configure_rspec
193
- RSpec.configuration.instance_variable_set(
194
- :@formatter_loader,
195
- RSpec::Core::Formatters::Loader.new(RSpec::Core::Reporter.new(RSpec.configuration)))
196
- RSpec.configuration.formatter = Spec::Runner::Formatter::TeamcityFormatter
230
+ # Always use the teamcity formatter, even though RubyMine always specifies it.
231
+ # This make manual testing of rspec-interactive easier.
232
+ RSpec.configuration.formatter = Spec::Runner::Formatter::TeamcityFormatter
197
233
 
198
- # Run.
199
- exit_code = @runner.run
234
+ # Run.
235
+ exit_code = @runner.run
200
236
 
201
- # Reset
202
- Spec::Runner::Formatter::TeamcityFormatter.client = nil
203
- RSpec.clear_examples
204
- RSpec.reset
205
- @config_cache.replay_configuration
237
+ # Reset
238
+ RSpec.clear_examples
239
+ RSpec.reset
240
+ @config_cache.replay_configuration
241
+ end
242
+ ensure
243
+ ENV['DISABLE_PRY'] = disable_pry
206
244
  end
207
245
  end
208
246
 
@@ -214,5 +252,17 @@ module RSpec
214
252
  end
215
253
  end
216
254
 
255
+ def self.eval(&block)
256
+ if Thread.current.thread_variable_get('holding_lock')
257
+ yield
258
+ else
259
+ @command_mutex.synchronize do
260
+ Thread.current.thread_variable_set('holding_lock', true)
261
+ yield
262
+ ensure
263
+ Thread.current.thread_variable_set('holding_lock', false)
264
+ end
265
+ end
266
+ end
217
267
  end
218
268
  end
@@ -4,14 +4,6 @@ module Spec
4
4
  module Runner
5
5
  module Formatter
6
6
  class TeamcityFormatter
7
- class << self
8
- attr_accessor :client
9
- end
10
-
11
- def log(msg)
12
- TeamcityFormatter.client.puts(msg)
13
- msg
14
- end
15
7
  end
16
8
  end
17
9
  end
@@ -23,7 +23,6 @@ Gem::Specification.new do |spec|
23
23
  end
24
24
  spec.bindir = 'bin'
25
25
  spec.executables << 'rspec-interactive'
26
- spec.executables << 'rspec-interactive-run'
27
26
  spec.require_paths = ["lib"]
28
27
 
29
28
  spec.add_dependency 'rspec-core'
data/runner/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ ruby '3.0.0'
4
+
5
+ source "https://rubygems.org"
@@ -0,0 +1,14 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+
5
+ PLATFORMS
6
+ x86_64-darwin-20
7
+
8
+ DEPENDENCIES
9
+
10
+ RUBY VERSION
11
+ ruby 3.0.0p0
12
+
13
+ BUNDLED WITH
14
+ 2.3.6
data/runner/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # RSpec Interactive Runner
2
+
3
+ Use this directory as the working directory in RubyMine run configurations.
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'optparse'
4
- require 'rspec-interactive'
5
4
  require 'shellwords'
6
5
  require 'socket'
7
6
 
@@ -25,8 +24,8 @@ parser = OptionParser.new do |opts|
25
24
  end.parse
26
25
 
27
26
  server = TCPSocket.open(@options[:host], @options[:port])
28
- server.puts ARGV.map{|arg| Shellwords.escape arg}.join(' ')
27
+ server.puts ARGV.map{ |arg| Shellwords.escape arg }.join(' ')
29
28
  while response = server.gets do
30
- puts "response: #{response}"
29
+ puts response
31
30
  end
32
31
  server.close
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-interactive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Dower
@@ -71,7 +71,6 @@ email:
71
71
  - nicholasdower@gmail.com
72
72
  executables:
73
73
  - rspec-interactive
74
- - rspec-interactive-run
75
74
  extensions: []
76
75
  extra_rdoc_files: []
77
76
  files:
@@ -83,25 +82,33 @@ files:
83
82
  - Rakefile
84
83
  - bin/console
85
84
  - bin/rspec-interactive
86
- - bin/rspec-interactive-run
87
85
  - bin/setup
88
86
  - bin/test
87
+ - examples/config.rb
89
88
  - examples/debugged_spec.rb
90
89
  - examples/failing_spec.rb
91
90
  - examples/other_passing_spec.rb
92
91
  - examples/passing_spec.rb
93
92
  - examples/spec_with_syntax_error.rb
94
93
  - lib/rspec-interactive.rb
94
+ - lib/rspec-interactive/client_output.rb
95
95
  - lib/rspec-interactive/config.rb
96
96
  - lib/rspec-interactive/input_completer.rb
97
+ - lib/rspec-interactive/pry.rb
97
98
  - lib/rspec-interactive/refresh_command.rb
98
99
  - lib/rspec-interactive/rspec_command.rb
99
100
  - lib/rspec-interactive/rspec_config_cache.rb
101
+ - lib/rspec-interactive/rspec_core_example.rb
100
102
  - lib/rspec-interactive/rubo_cop_command.rb
101
103
  - lib/rspec-interactive/runner.rb
104
+ - lib/rspec-interactive/stdio.rb
102
105
  - lib/rspec-interactive/version.rb
103
106
  - lib/teamcity/spec/runner/formatter/teamcity/formatter.rb
104
107
  - rspec-interactive.gemspec
108
+ - runner/Gemfile
109
+ - runner/Gemfile.lock
110
+ - runner/README.md
111
+ - runner/rspec-interactive-run
105
112
  - scripts/release.sh
106
113
  - scripts/run-with-local-dep.sh
107
114
  - tests/debugged_spec_test.rb