rspec-interactive 0.9.6 → 0.9.9
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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/rspec-interactive/client_output.rb +7 -0
- data/lib/rspec-interactive/pry.rb +1 -1
- data/lib/rspec-interactive/stdio.rb +1 -40
- data/lib/rspec-interactive/string_output.rb +7 -0
- data/lib/rspec-interactive/threaded_output.rb +33 -0
- data/lib/rspec-interactive/version.rb +1 -1
- data/lib/rspec-interactive.rb +117 -65
- data/runner/rspec-interactive-run +8 -4
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c87a284feb4bf76bac68cda8cbe5703a66f04a856c8e2aed9e27d30b89e2654e
|
4
|
+
data.tar.gz: 9336d2bff3ba1973921f8d7ba6a36d88bc11d4acd1c2b2ee86d7c47cb58d0356
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36afe559f97bc7cdee9e6833655f23e6092004b800e53beed28099afb8db6ce5511bc8177c9cc648ffc0a558bd221ca2ff13c5ff44e76132c20af99b30281fda
|
7
|
+
data.tar.gz: '097084b7f1fec026f08433a8d12d56997b83a8deb8852026fc04dc1f3e7ec5410433e0758b374724cb2b5450f7b5be4e4db2d9953241a7bbd703f610f032e6ef'
|
data/Gemfile.lock
CHANGED
@@ -1,52 +1,13 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Interactive
|
3
3
|
class Stdio
|
4
|
-
def self.
|
4
|
+
def self.capture(stdout:, stderr:)
|
5
5
|
old_stdout, old_stderr = $stdout, $stderr
|
6
6
|
$stdout, $stderr = stdout, stderr
|
7
7
|
yield
|
8
8
|
ensure
|
9
9
|
$stdout, $stderr = old_stdout, old_stderr
|
10
10
|
end
|
11
|
-
|
12
|
-
def self.capture(stdout:, stderr:)
|
13
|
-
raise ArgumentError, 'missing block' unless block_given?
|
14
|
-
|
15
|
-
old_stdout, old_stderr = STDOUT.dup, STDERR.dup
|
16
|
-
|
17
|
-
IO.pipe do |stdout_read, stdout_write|
|
18
|
-
IO.pipe do |stderr_read, stderr_write|
|
19
|
-
STDOUT.reopen(stdout_write)
|
20
|
-
STDERR.reopen(stderr_write)
|
21
|
-
|
22
|
-
stdout_write.close
|
23
|
-
stderr_write.close
|
24
|
-
|
25
|
-
stdout_thread = Thread.new do
|
26
|
-
while line = stdout_read.gets do
|
27
|
-
stdout.print(line)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
stderr_thread = Thread.new do
|
32
|
-
while line = stderr_read.gets do
|
33
|
-
stderr.print(line)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
begin
|
38
|
-
yield
|
39
|
-
ensure
|
40
|
-
# TODO: should the threads be killed here?
|
41
|
-
STDOUT.reopen old_stdout
|
42
|
-
STDERR.reopen old_stderr
|
43
|
-
end
|
44
|
-
|
45
|
-
stdout_thread.join
|
46
|
-
stderr_thread.join
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
11
|
end
|
51
12
|
end
|
52
13
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Interactive
|
3
|
+
class ThreadedOutput
|
4
|
+
attr_reader :string
|
5
|
+
|
6
|
+
def initialize(thread_map:, default:)
|
7
|
+
@thread_map = thread_map
|
8
|
+
@default = default
|
9
|
+
@string = ''
|
10
|
+
end
|
11
|
+
|
12
|
+
def write(name, str = "")
|
13
|
+
(@thread_map[Thread.current] || @default).write(name, str)
|
14
|
+
end
|
15
|
+
|
16
|
+
def puts(str = "")
|
17
|
+
(@thread_map[Thread.current] || @default).puts(str)
|
18
|
+
end
|
19
|
+
|
20
|
+
def print(str = "")
|
21
|
+
(@thread_map[Thread.current] || @default).puts(str)
|
22
|
+
end
|
23
|
+
|
24
|
+
def flush
|
25
|
+
(@thread_map[Thread.current] || @default).flush
|
26
|
+
end
|
27
|
+
|
28
|
+
def closed?
|
29
|
+
(@thread_map[Thread.current] || @default).closed?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/rspec-interactive.rb
CHANGED
@@ -19,6 +19,7 @@ require 'rspec-interactive/rubo_cop_command'
|
|
19
19
|
require 'rspec-interactive/runner'
|
20
20
|
require 'rspec-interactive/stdio'
|
21
21
|
require 'rspec-interactive/string_output'
|
22
|
+
require 'rspec-interactive/threaded_output'
|
22
23
|
|
23
24
|
module RSpec
|
24
25
|
module Interactive
|
@@ -47,7 +48,7 @@ module RSpec
|
|
47
48
|
@updated_files = []
|
48
49
|
@stty_save = %x`stty -g`.chomp
|
49
50
|
@file_change_mutex = Mutex.new
|
50
|
-
@
|
51
|
+
@rspec_mutex = Mutex.new
|
51
52
|
@output_stream = output_stream
|
52
53
|
@input_stream = input_stream
|
53
54
|
@error_stream = error_stream
|
@@ -61,29 +62,44 @@ module RSpec
|
|
61
62
|
configure_pry
|
62
63
|
|
63
64
|
@startup_thread = Thread.start do
|
64
|
-
|
65
|
-
Stdio.capture2(stdout: @startup_output, stderr: @startup_output) do
|
66
|
-
@config_cache.record_configuration { @configuration.configure_rspec.call }
|
67
|
-
start_file_watcher
|
68
|
-
end
|
69
|
-
|
65
|
+
Thread.current.report_on_exception = false
|
70
66
|
if server
|
71
67
|
@server_thread = Thread.start do
|
72
68
|
server = TCPServer.new port
|
73
69
|
|
74
|
-
while
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
70
|
+
while true
|
71
|
+
break unless client = server.accept
|
72
|
+
begin
|
73
|
+
request = client.gets
|
74
|
+
args = Shellwords.split(request)
|
75
|
+
rspec_for_server(client, args)
|
76
|
+
rescue StandardError => e
|
77
|
+
# It would be nice to log to the client here but it might be
|
78
|
+
# disconnected or disconnect before we successfully write. Any
|
79
|
+
# error here is unexpected so just log to the console.
|
80
|
+
@output_stream.puts
|
81
|
+
@output_stream.puts 'error handling client request'
|
82
|
+
log_exception(@output_stream, e)
|
83
|
+
ensure
|
84
|
+
client.close
|
85
|
+
end
|
79
86
|
end
|
80
87
|
end
|
81
88
|
end
|
89
|
+
|
90
|
+
@startup_output = StringOutput.new
|
91
|
+
output = ThreadedOutput.new(thread_map: { Thread.current => @startup_output }, default: @output_stream)
|
92
|
+
|
93
|
+
Stdio.capture(stdout: output, stderr: output) do
|
94
|
+
@config_cache.record_configuration { @configuration.configure_rspec.call }
|
95
|
+
start_file_watcher
|
96
|
+
end
|
82
97
|
end
|
83
98
|
|
84
99
|
Pry.start
|
85
100
|
@listener.stop if @listener
|
86
101
|
@server_thread.exit if @server_thread
|
102
|
+
@startup_thread.exit if @startup_thread
|
87
103
|
0
|
88
104
|
end
|
89
105
|
|
@@ -141,17 +157,17 @@ module RSpec
|
|
141
157
|
Pry.config.history_file = @history_file
|
142
158
|
end
|
143
159
|
|
144
|
-
def self.refresh
|
160
|
+
def self.refresh(output: @output_stream)
|
145
161
|
@file_change_mutex.synchronize do
|
146
162
|
@updated_files.uniq.each do |filename|
|
147
|
-
|
163
|
+
output.puts "changed: #{filename}"
|
148
164
|
trace = TracePoint.new(:class) do |tp|
|
149
165
|
@configuration.on_class_load.call(tp.self)
|
150
166
|
end
|
151
167
|
trace.enable
|
152
168
|
load filename
|
153
169
|
trace.disable
|
154
|
-
|
170
|
+
output.puts
|
155
171
|
end
|
156
172
|
@updated_files.clear
|
157
173
|
end
|
@@ -180,50 +196,60 @@ module RSpec
|
|
180
196
|
end
|
181
197
|
|
182
198
|
def self.rspec(args)
|
183
|
-
@
|
199
|
+
@rspec_mutex.synchronize do
|
200
|
+
begin
|
201
|
+
@runner = RSpec::Interactive::Runner.new(parse_args(args))
|
184
202
|
|
185
|
-
|
203
|
+
refresh
|
186
204
|
|
187
|
-
|
188
|
-
|
205
|
+
# Stop saving history in case a new Pry session is started for debugging.
|
206
|
+
Pry.config.history_save = false
|
189
207
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
208
|
+
# RSpec::Interactive-specific RSpec configuration
|
209
|
+
RSpec.configure do |config|
|
210
|
+
config.error_stream = @error_stream
|
211
|
+
config.output_stream = @output_stream
|
212
|
+
config.start_time = RSpec::Core::Time.now
|
213
|
+
end
|
196
214
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
215
|
+
# Run.
|
216
|
+
@runner.run
|
217
|
+
ensure
|
218
|
+
@runner = nil
|
201
219
|
|
202
|
-
|
203
|
-
|
220
|
+
# Reenable history
|
221
|
+
Pry.config.history_save = true
|
204
222
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
223
|
+
# Reset
|
224
|
+
RSpec.clear_examples
|
225
|
+
RSpec.reset
|
226
|
+
@config_cache.replay_configuration
|
227
|
+
end
|
228
|
+
end
|
209
229
|
end
|
210
230
|
|
211
231
|
def self.rspec_for_server(client, args)
|
212
|
-
@
|
213
|
-
# Prevent the debugger from being used. The server isn't interactive.
|
232
|
+
@rspec_mutex.synchronize do
|
214
233
|
disable_pry = ENV['DISABLE_PRY']
|
215
|
-
ENV['DISABLE_PRY'] = 'true'
|
216
|
-
|
217
234
|
output = ClientOutput.new(client)
|
235
|
+
|
236
|
+
ENV['TEAMCITY_RAKE_RUNNER_DEBUG_OUTPUT_CAPTURER_ENABLED'] = 'false'
|
237
|
+
Rake::TeamCity::RunnerCommon.class_variable_set(:@@original_stdout, output)
|
238
|
+
|
239
|
+
return unless await_startup(output: output)
|
240
|
+
|
218
241
|
Stdio.capture(stdout: output, stderr: output) do
|
219
|
-
|
242
|
+
# Prevent the debugger from being used. The server isn't interactive.
|
243
|
+
ENV['DISABLE_PRY'] = 'true'
|
220
244
|
|
221
|
-
|
245
|
+
runner = RSpec::Interactive::Runner.new(parse_args(args))
|
246
|
+
|
247
|
+
refresh(output: output)
|
222
248
|
|
223
249
|
# RSpec::Interactive-specific RSpec configuration
|
224
250
|
RSpec.configure do |config|
|
225
|
-
config.error_stream =
|
226
|
-
config.output_stream =
|
251
|
+
config.error_stream = output
|
252
|
+
config.output_stream = output
|
227
253
|
config.start_time = RSpec::Core::Time.now
|
228
254
|
end
|
229
255
|
|
@@ -239,15 +265,19 @@ module RSpec
|
|
239
265
|
RSpec.configuration.formatter = Spec::Runner::Formatter::TeamcityFormatter
|
240
266
|
|
241
267
|
# Run.
|
242
|
-
|
268
|
+
runner.run
|
269
|
+
rescue Errno::EPIPE, IOError
|
270
|
+
# Don't care.
|
271
|
+
ensure
|
272
|
+
ENV['DISABLE_PRY'] = disable_pry
|
273
|
+
runner = nil
|
243
274
|
|
244
275
|
# Reset
|
245
276
|
RSpec.clear_examples
|
246
277
|
RSpec.reset
|
278
|
+
|
247
279
|
@config_cache.replay_configuration
|
248
280
|
end
|
249
|
-
ensure
|
250
|
-
ENV['DISABLE_PRY'] = disable_pry
|
251
281
|
end
|
252
282
|
end
|
253
283
|
|
@@ -259,28 +289,50 @@ module RSpec
|
|
259
289
|
end
|
260
290
|
end
|
261
291
|
|
262
|
-
def self.eval(&block)
|
263
|
-
if
|
292
|
+
def self.eval(line, options, &block)
|
293
|
+
return yield if line.nil? # EOF
|
294
|
+
return yield if line.empty? # blank line
|
295
|
+
|
296
|
+
if await_startup
|
264
297
|
yield
|
265
298
|
else
|
266
|
-
@
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
end
|
277
|
-
@startup_output = nil
|
278
|
-
end
|
279
|
-
yield
|
280
|
-
ensure
|
281
|
-
Thread.current.thread_variable_set('holding_lock', false)
|
282
|
-
end
|
299
|
+
@output_stream.puts
|
300
|
+
true
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def self.await_startup(output: @output_stream)
|
305
|
+
return true unless @startup_thread
|
306
|
+
|
307
|
+
if @startup_thread.alive?
|
308
|
+
output.puts 'waiting for configure_rspec...'
|
283
309
|
end
|
310
|
+
|
311
|
+
begin
|
312
|
+
@startup_thread.join
|
313
|
+
@startup_thread = nil
|
314
|
+
print_startup_output(output: output)
|
315
|
+
true
|
316
|
+
rescue Interrupt
|
317
|
+
false
|
318
|
+
rescue StandardError => e
|
319
|
+
print_startup_output(output: output)
|
320
|
+
output.puts 'configure_rspec failed'
|
321
|
+
log_exception(output, e)
|
322
|
+
false
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
def self.log_exception(output, e)
|
327
|
+
output.puts "#{e.backtrace[0]}: #{e.message} (#{e.class})"
|
328
|
+
e.backtrace[1..-1].each { |b| output.puts "\t#{b}" }
|
329
|
+
end
|
330
|
+
|
331
|
+
def self.print_startup_output(output: @output_stream)
|
332
|
+
return if @startup_output.nil? || @startup_output.string.empty?
|
333
|
+
|
334
|
+
output.puts(@startup_output.string)
|
335
|
+
@startup_output = nil
|
284
336
|
end
|
285
337
|
end
|
286
338
|
end
|
@@ -24,8 +24,12 @@ parser = OptionParser.new do |opts|
|
|
24
24
|
end.parse
|
25
25
|
|
26
26
|
server = TCPSocket.open(@options[:host], @options[:port])
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
begin
|
28
|
+
server.puts ARGV.map{ |arg| Shellwords.escape arg }.join(' ')
|
29
|
+
server.close_write
|
30
|
+
while response = server.gets do
|
31
|
+
puts response
|
32
|
+
end
|
33
|
+
ensure
|
34
|
+
server.close
|
30
35
|
end
|
31
|
-
server.close
|
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.9.
|
4
|
+
version: 0.9.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Dower
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-02-
|
11
|
+
date: 2022-02-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-core
|
@@ -103,6 +103,7 @@ files:
|
|
103
103
|
- lib/rspec-interactive/runner.rb
|
104
104
|
- lib/rspec-interactive/stdio.rb
|
105
105
|
- lib/rspec-interactive/string_output.rb
|
106
|
+
- lib/rspec-interactive/threaded_output.rb
|
106
107
|
- lib/rspec-interactive/version.rb
|
107
108
|
- lib/teamcity/spec/runner/formatter/teamcity/formatter.rb
|
108
109
|
- rspec-interactive.gemspec
|