rspec-interactive 0.8.1 → 0.9.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: 255c2aca56cb003fad2c6e7e5f72cb75b2ed82f1820edb42294ded182dbdd25c
4
- data.tar.gz: afb9f469028aa3a4388585e6d34e281ce1bae8fe7227e73ba0939f2cf3585255
3
+ metadata.gz: 987faf5573f9ae7554f4983ee350beaf7ad9ef832544cea3b6f92114cf554788
4
+ data.tar.gz: 29e0c2b195497e1d2af2f7e8565ee64ae6039870f3bb685dc86e750c11342a71
5
5
  SHA512:
6
- metadata.gz: abae1515ca7dade3476088e21fef619f1cdda2b3b126f0a19db30b0aabd2f7250bee9874f11cccf5a836d39dd45d7b6a5848003a32637bf2eb925c4d229622dc
7
- data.tar.gz: 90c4118df931f6e30c3af286f8fb9a1a382bd30dfcd3d052480943fa4f305975784c87e51fddba17de4343ef0748169c07831dc52e7f31190efefef516216efa
6
+ metadata.gz: 2f3e0573bd9280ca150292045134b5eea34243661733aa68dda3ca03c086fc0275ecfecd919aaf022e5aeb943ca4523170e39e6d47c60f8ef59fc5b925fc60b4
7
+ data.tar.gz: 618437758587eb88be800508ef487960c1c760143e81594e89c3e80280a2eada7e3904e323c960b6dce2b40ec93eba6638e3dbda311d57144a95d6fef719a1d9
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  rspec-interactive-*.gem
2
2
  .rspec_interactive_history
3
3
  .rspec_interactive_config
4
+ .idea
data/Gemfile.lock CHANGED
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rspec-interactive (0.8.0)
4
+ rspec-interactive (0.8.1)
5
5
  listen
6
6
  pry
7
7
  rspec-core
8
+ rspec-teamcity (= 1.0.0)
8
9
 
9
10
  GEM
10
11
  remote: https://rubygems.org/
@@ -22,12 +23,21 @@ GEM
22
23
  rb-fsevent (0.11.0)
23
24
  rb-inotify (0.10.1)
24
25
  ffi (~> 1.0)
26
+ rspec (3.9.0)
27
+ rspec-core (~> 3.9.0)
28
+ rspec-expectations (~> 3.9.0)
29
+ rspec-mocks (~> 3.9.0)
25
30
  rspec-core (3.9.3)
26
31
  rspec-support (~> 3.9.3)
27
32
  rspec-expectations (3.9.4)
28
33
  diff-lcs (>= 1.2.0, < 2.0)
29
34
  rspec-support (~> 3.9.0)
35
+ rspec-mocks (3.9.1)
36
+ diff-lcs (>= 1.2.0, < 2.0)
37
+ rspec-support (~> 3.9.0)
30
38
  rspec-support (3.9.4)
39
+ rspec-teamcity (1.0.0)
40
+ rspec (>= 2.99, >= 2.14.2, < 4)
31
41
 
32
42
  PLATFORMS
33
43
  x86_64-darwin-20
data/README.md CHANGED
@@ -69,10 +69,10 @@ See: https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#ra
69
69
 
70
70
  ## Usage
71
71
 
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>`.
72
+ Optionally, specify a config file with `--config <config-file>`.
73
73
 
74
74
  ```shell
75
- bundle exec rspec-interactive [--config <config-file>] [--initial-rspec-args <initial-rspec-args>]
75
+ bundle exec rspec-interactive [--config <config-file>]
76
76
  ```
77
77
 
78
78
  ## Example Usage In This Repo
@@ -83,12 +83,6 @@ Start:
83
83
  bundle exec rspec-interactive
84
84
  ```
85
85
 
86
- Start with an initial RSpec invocation:
87
-
88
- ```shell
89
- bundle exec rspec-interactive --initial-rspec-args examples/passing_spec.rb
90
- ```
91
-
92
86
  Run a passing spec:
93
87
 
94
88
  ```shell
@@ -3,18 +3,27 @@
3
3
  require 'optparse'
4
4
  require 'rspec-interactive'
5
5
 
6
- @options = {}
6
+ @options = {
7
+ server: false,
8
+ port: RSpec::Interactive::DEFAULT_PORT
9
+ }
10
+
7
11
  parser = OptionParser.new do |opts|
8
12
  opts.banner = "Starts an interactive RSpec shell.\n\n"\
9
- "Usage: bundle exec rspec-interactive [-c config-file] <initial-rspec-args>"
13
+ "Usage: bundle exec rspec-interactive [--config config-file] [--server [--port <port>]]"
10
14
 
11
15
  opts.on("-c", "--config <config-file>", String, "Optional. Path to the RSpec Interactive config file.") do |config_file|
12
16
  @options[:config_file] = config_file
13
17
  end
14
18
 
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|
16
- @options[:initial_rspec_args] = initial_rspec_args
19
+ opts.on("-s", "--server", "Optional. Enable server used by IDEs.") do
20
+ @options[:server] = true
21
+ end
22
+
23
+ opts.on("-p", "--port <port>", Integer, "Optional. Server port. Defaults to #{RSpec::Interactive::DEFAULT_PORT}.") do |port|
24
+ @options[:port] = port
17
25
  end
26
+
18
27
  end.parse!
19
28
 
20
- RSpec::Interactive.start(config_file: @options[:config_file], initial_rspec_args: @options[:initial_rspec_args])
29
+ RSpec::Interactive.start(config_file: @options[:config_file], server: @options[:server], port: @options[:port])
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'rspec-interactive'
5
+ require 'shellwords'
6
+ require 'socket'
7
+
8
+ @options = {
9
+ host: 'localhost',
10
+ port: RSpec::Interactive::DEFAULT_PORT
11
+ }
12
+
13
+ parser = OptionParser.new do |opts|
14
+ opts.banner = "Executes RSpec by connecting to a running RSpec Interactive shell.\n\n"\
15
+ "Usage: bundle exec rspec-interactive-run [--host <host>] [--port <port>] [rspec-args]"
16
+
17
+ opts.on("-h", "--host <host>", String, "Optional. Server host. Defaults to localhost.") do |host|
18
+ @options[:host] = host
19
+ end
20
+
21
+ opts.on("-p", "--port <port>", Integer, "Optional. Server port. Defaults to #{RSpec::Interactive::DEFAULT_PORT}.") do |port|
22
+ @options[:port] = port
23
+ end
24
+
25
+ end.parse
26
+
27
+ server = TCPSocket.open(@options[:host], @options[:port])
28
+ server.puts ARGV.map{|arg| Shellwords.escape arg}.join(' ')
29
+ while response = server.gets do
30
+ puts "response: #{response}"
31
+ end
32
+ server.close
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RSpec
4
4
  module Interactive
5
- VERSION = "0.8.1"
5
+ VERSION = "0.9.0"
6
6
  end
7
7
  end
@@ -4,19 +4,22 @@ require 'pry'
4
4
  require 'readline'
5
5
  require 'rspec/core'
6
6
  require 'shellwords'
7
+ require 'socket'
8
+ require 'teamcity/spec/runner/formatter/teamcity/formatter'
7
9
 
8
- require 'rspec-interactive/runner'
9
10
  require 'rspec-interactive/config'
10
- require 'rspec-interactive/rspec_config_cache'
11
11
  require 'rspec-interactive/input_completer'
12
12
  require 'rspec-interactive/refresh_command'
13
13
  require 'rspec-interactive/rspec_command'
14
+ require 'rspec-interactive/rspec_config_cache'
14
15
  require 'rspec-interactive/rubo_cop_command'
16
+ require 'rspec-interactive/runner'
15
17
 
16
18
  module RSpec
17
19
  module Interactive
18
20
 
19
21
  DEFAULT_HISTORY_FILE = '.rspec_interactive_history'.freeze
22
+ DEFAULT_PORT = 5678
20
23
 
21
24
  class << self
22
25
  attr_accessor :configuration
@@ -26,11 +29,20 @@ module RSpec
26
29
  block.call(@configuration)
27
30
  end
28
31
 
29
- def self.start(config_file: nil, initial_rspec_args: nil, history_file: DEFAULT_HISTORY_FILE, input_stream: STDIN, output_stream: STDOUT, error_stream: STDERR)
32
+ def self.start(
33
+ config_file: nil,
34
+ server: false,
35
+ port: DEFAULT_PORT,
36
+ history_file: DEFAULT_HISTORY_FILE,
37
+ input_stream: STDIN,
38
+ output_stream: STDOUT,
39
+ error_stream: STDERR)
40
+
30
41
  @history_file = history_file
31
42
  @updated_files = []
32
43
  @stty_save = %x`stty -g`.chomp
33
- @mutex = Mutex.new
44
+ @file_change_mutex = Mutex.new
45
+ @rspec_mutex = Mutex.new
34
46
  @output_stream = output_stream
35
47
  @input_stream = input_stream
36
48
  @error_stream = error_stream
@@ -43,18 +55,25 @@ module RSpec
43
55
  trap_interrupt
44
56
  configure_pry
45
57
 
46
- @init_thread = Thread.start {
47
- @config_cache.record_configuration { @configuration.configure_rspec.call }
48
- start_file_watcher
49
- }
58
+ @config_cache.record_configuration { @configuration.configure_rspec.call }
59
+ start_file_watcher
60
+
61
+ if server
62
+ server_thread = Thread.start do
63
+ server = TCPServer.new 5678
50
64
 
51
- if initial_rspec_args
52
- open(@history_file, 'a') { |f| f.puts "rspec #{initial_rspec_args.strip}" }
53
- rspec Shellwords.split(initial_rspec_args)
65
+ while client = server.accept
66
+ request = client.gets
67
+ args = Shellwords.split(request)
68
+ rspec_for_server(client, args)
69
+ client.close
70
+ end
71
+ end
54
72
  end
55
73
 
56
74
  Pry.start
57
75
  @listener.stop if @listener
76
+ server_thread.exit if server_thread
58
77
  0
59
78
  end
60
79
 
@@ -66,10 +85,11 @@ module RSpec
66
85
  end
67
86
  end
68
87
 
69
- def self.configure_rspec
88
+ def self.configure_rspec(error_stream: @error_stream, output_stream: @output_stream)
70
89
  RSpec.configure do |config|
71
- config.error_stream = @error_stream
72
- config.output_stream = @output_stream
90
+ config.error_stream = error_stream
91
+ config.output_stream = output_stream
92
+ config.start_time = RSpec::Core::Time.now
73
93
  end
74
94
  end
75
95
 
@@ -79,9 +99,7 @@ module RSpec
79
99
  # We are on a different thread. There is a race here. Ignore nil.
80
100
  @runner&.quit
81
101
  else
82
- @output_stream.puts
83
- system "stty", @stty_save
84
- exit!(0)
102
+ raise Interrupt
85
103
  end
86
104
  end
87
105
  end
@@ -91,7 +109,7 @@ module RSpec
91
109
 
92
110
  # Only polling seems to work in Docker.
93
111
  @listener = Listen.to(*@configuration.watch_dirs, only: /\.rb$/, force_polling: true) do |modified, added|
94
- @mutex.synchronize do
112
+ @file_change_mutex.synchronize do
95
113
  @updated_files.concat(added + modified)
96
114
  end
97
115
  end
@@ -115,7 +133,7 @@ module RSpec
115
133
  end
116
134
 
117
135
  def self.refresh
118
- @mutex.synchronize do
136
+ @file_change_mutex.synchronize do
119
137
  @updated_files.uniq.each do |filename|
120
138
  @output_stream.puts "changed: #{filename}"
121
139
  trace = TracePoint.new(:class) do |tp|
@@ -131,8 +149,8 @@ module RSpec
131
149
  @configuration.refresh.call
132
150
  end
133
151
 
134
- def self.rspec(args)
135
- parsed_args = args.flat_map do |arg|
152
+ def self.parse_args(args)
153
+ args.flat_map do |arg|
136
154
  if arg.match(/[\*\?\[]/)
137
155
  glob = Dir.glob(arg)
138
156
  glob.empty? ? [arg] : glob
@@ -140,50 +158,71 @@ module RSpec
140
158
  [arg]
141
159
  end
142
160
  end
161
+ end
162
+
163
+ def self.rspec(args)
164
+ @rspec_mutex.synchronize do
165
+
166
+ @runner = RSpec::Interactive::Runner.new(parse_args(args))
167
+
168
+ refresh
169
+
170
+ # Stop saving history in case a new Pry session is started for debugging.
171
+ Pry.config.history_save = false
172
+
173
+ # RSpec::Interactive-specific RSpec configuration
174
+ configure_rspec
175
+
176
+ # Run.
177
+ exit_code = @runner.run
178
+ @runner = nil
143
179
 
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.
146
- @runner = RSpec::Interactive::Runner.new(parsed_args)
180
+ # Reenable history
181
+ Pry.config.history_save = true
147
182
 
148
- if @init_thread&.alive?
149
- @init_thread.join
150
- @init_thread = nil
183
+ # Reset
184
+ RSpec.clear_examples
185
+ RSpec.reset
186
+ @config_cache.replay_configuration
187
+ ensure
188
+ @runner = nil
151
189
  end
190
+ end
152
191
 
153
- refresh
192
+ def self.rspec_for_server(client, args)
193
+ @rspec_mutex.synchronize do
194
+ # Set the client so that logs are written to the client rathe than STDOUT.
195
+ Spec::Runner::Formatter::TeamcityFormatter.client = client
154
196
 
155
- # Stop saving history in case a new Pry session is started for debugging.
156
- Pry.config.history_save = false
197
+ @runner = RSpec::Interactive::Runner.new(parse_args(args))
157
198
 
158
- # RSpec::Interactive-specific RSpec configuration
159
- configure_rspec
199
+ refresh
160
200
 
161
- # Run.
162
- exit_code = @runner.run
163
- @runner = nil
201
+ # Stop saving history in case a new Pry session is started for debugging.
202
+ Pry.config.history_save = false
164
203
 
165
- # Reenable history
166
- Pry.config.history_save = true
204
+ # RSpec::Interactive-specific RSpec configuration
205
+ configure_rspec
206
+ RSpec.configuration.formatter = Spec::Runner::Formatter::TeamcityFormatter
167
207
 
168
- # Reset
169
- RSpec.clear_examples
170
- RSpec.reset
171
- @config_cache.replay_configuration
172
- ensure
173
- @runner = nil
174
- end
208
+ # Run.
209
+ exit_code = @runner.run
175
210
 
176
- def self.rubo_cop(args)
177
- if @init_thread&.alive?
178
- @init_thread.join
179
- @init_thread = nil
211
+ # Reset
212
+ Spec::Runner::Formatter::TeamcityFormatter.client = nil
213
+ RSpec.clear_examples
214
+ RSpec.reset
215
+ @config_cache.replay_configuration
180
216
  end
217
+ end
181
218
 
219
+ def self.rubo_cop(args)
182
220
  if defined?(RuboCop)
183
221
  RuboCop::CLI.new.run args
184
222
  else
185
223
  @error_stream.puts "fatal: RuboCop not found. Is the gem installed in this project?"
186
224
  end
187
225
  end
226
+
188
227
  end
189
228
  end
@@ -0,0 +1,18 @@
1
+ require 'rspec/teamcity'
2
+
3
+ module Spec
4
+ module Runner
5
+ module Formatter
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
+ end
16
+ end
17
+ end
18
+ end
@@ -23,9 +23,11 @@ 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'
26
27
  spec.require_paths = ["lib"]
27
28
 
28
29
  spec.add_dependency 'rspec-core'
30
+ spec.add_dependency 'rspec-teamcity', '1.0.0'
29
31
  spec.add_dependency 'listen'
30
32
  spec.add_dependency 'pry'
31
33
  end
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.8.1
4
+ version: 0.9.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-28 00:00:00.000000000 Z
11
+ date: 2022-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec-core
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec-teamcity
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 1.0.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: listen
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -57,6 +71,7 @@ email:
57
71
  - nicholasdower@gmail.com
58
72
  executables:
59
73
  - rspec-interactive
74
+ - rspec-interactive-run
60
75
  extensions: []
61
76
  extra_rdoc_files: []
62
77
  files:
@@ -68,6 +83,7 @@ files:
68
83
  - Rakefile
69
84
  - bin/console
70
85
  - bin/rspec-interactive
86
+ - bin/rspec-interactive-run
71
87
  - bin/setup
72
88
  - bin/test
73
89
  - examples/debugged_spec.rb
@@ -84,6 +100,7 @@ files:
84
100
  - lib/rspec-interactive/rubo_cop_command.rb
85
101
  - lib/rspec-interactive/runner.rb
86
102
  - lib/rspec-interactive/version.rb
103
+ - lib/teamcity/spec/runner/formatter/teamcity/formatter.rb
87
104
  - rspec-interactive.gemspec
88
105
  - scripts/release.sh
89
106
  - scripts/run-with-local-dep.sh