rspec-interactive 0.8.1 → 0.9.0

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