rspec-interactive 0.9.1 → 0.9.4

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