rspec-interactive 0.8.0 → 0.9.1

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: 44b14e54786342da3629408fcbaa937173a3965eb3913da0c852a1e7300ac710
4
- data.tar.gz: 729af533ef4f4aa26201704430c7dd99c1902d3cd6ab7e924a258340f77a7664
3
+ metadata.gz: dbc1f295bcf16bf85e5d6a6281de27ea2b51aa08f373272fb7d9e472ec13f3e9
4
+ data.tar.gz: 36d80a0af500094c129970d522b2a3a3e6bbfc117549b9453f8a5f07ccbcbe33
5
5
  SHA512:
6
- metadata.gz: d83fa6a30f885189a65de0a24cb639ff0e62e6e089378403f5698e75dea8761ab8e74dfd1fd05fe533f37070dd89f683ea9e95eac9ca4b9b0daa33e7b8d4cdf1
7
- data.tar.gz: e2cd51ef90235dacf57a47feb4f8b4cdca4e8191c437c57acc73fe0990d055f98d4db6e0e38a84aae4e07fd342a60d34c75a3035ff2a4b86d0f88187cdb45d90
6
+ metadata.gz: 11ba7e2f1e90ddc985f6154b7fec1b738b2477481eb40efe92a822d11a39970799ed147a4ae5da4736b226d1fcb25fe372083fbb7a2346754f5a771456a9a01f
7
+ data.tar.gz: e10376660d90bace5ea870d3b9f046780157c65e3ec489ca21aa409ae0dcbdacf60cfa11e49d9ba2ab947b06b71e9e3fd5d35b976346ee370b552e8fd07e0bb6
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,33 +1,43 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rspec-interactive (0.7.2)
4
+ rspec-interactive (0.9.0)
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/
11
12
  specs:
12
13
  coderay (1.1.3)
13
14
  diff-lcs (1.4.4)
14
- ffi (1.15.3)
15
- listen (3.5.1)
15
+ ffi (1.15.5)
16
+ listen (3.7.1)
16
17
  rb-fsevent (~> 0.10, >= 0.10.3)
17
18
  rb-inotify (~> 0.9, >= 0.9.10)
18
19
  method_source (1.0.0)
19
20
  pry (0.14.1)
20
21
  coderay (~> 1.1)
21
22
  method_source (~> 1.0)
22
- rb-fsevent (0.11.0)
23
+ rb-fsevent (0.11.1)
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: 5678
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 5678.") 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.0"
5
+ VERSION = "0.9.1"
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
@@ -40,21 +52,27 @@ module RSpec
40
52
  load config_file if config_file
41
53
 
42
54
  check_rails
43
- trap_interrupt
44
55
  configure_pry
45
56
 
46
- @init_thread = Thread.start {
47
- @config_cache.record_configuration { @configuration.configure_rspec.call }
48
- start_file_watcher
49
- }
57
+ @config_cache.record_configuration { @configuration.configure_rspec.call }
58
+ start_file_watcher
59
+
60
+ if server
61
+ server_thread = Thread.start do
62
+ server = TCPServer.new 5678
50
63
 
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)
64
+ while client = server.accept
65
+ request = client.gets
66
+ args = Shellwords.split(request)
67
+ rspec_for_server(client, args)
68
+ client.close
69
+ end
70
+ end
54
71
  end
55
72
 
56
73
  Pry.start
57
74
  @listener.stop if @listener
75
+ server_thread.exit if server_thread
58
76
  0
59
77
  end
60
78
 
@@ -66,23 +84,11 @@ module RSpec
66
84
  end
67
85
  end
68
86
 
69
- def self.configure_rspec
87
+ def self.configure_rspec(error_stream: @error_stream, output_stream: @output_stream)
70
88
  RSpec.configure do |config|
71
- config.error_stream = @error_stream
72
- config.output_stream = @output_stream
73
- end
74
- end
75
-
76
- def self.trap_interrupt
77
- trap('INT') do
78
- if @runner
79
- # We are on a different thread. There is a race here. Ignore nil.
80
- @runner&.quit
81
- else
82
- @output_stream.puts
83
- system "stty", @stty_save
84
- exit!(0)
85
- end
89
+ config.error_stream = error_stream
90
+ config.output_stream = output_stream
91
+ config.start_time = RSpec::Core::Time.now
86
92
  end
87
93
  end
88
94
 
@@ -91,7 +97,7 @@ module RSpec
91
97
 
92
98
  # Only polling seems to work in Docker.
93
99
  @listener = Listen.to(*@configuration.watch_dirs, only: /\.rb$/, force_polling: true) do |modified, added|
94
- @mutex.synchronize do
100
+ @file_change_mutex.synchronize do
95
101
  @updated_files.concat(added + modified)
96
102
  end
97
103
  end
@@ -99,9 +105,6 @@ module RSpec
99
105
  end
100
106
 
101
107
  def self.configure_pry
102
- # Prevent Pry from trapping too. It will break ctrl-c handling.
103
- Pry.config.should_trap_interrupts = false
104
-
105
108
  # Set up IO.
106
109
  Pry.config.input = Readline
107
110
  Pry.config.output = @output_stream
@@ -115,7 +118,7 @@ module RSpec
115
118
  end
116
119
 
117
120
  def self.refresh
118
- @mutex.synchronize do
121
+ @file_change_mutex.synchronize do
119
122
  @updated_files.uniq.each do |filename|
120
123
  @output_stream.puts "changed: #{filename}"
121
124
  trace = TracePoint.new(:class) do |tp|
@@ -131,8 +134,8 @@ module RSpec
131
134
  @configuration.refresh.call
132
135
  end
133
136
 
134
- def self.rspec(args)
135
- parsed_args = args.flat_map do |arg|
137
+ def self.parse_args(args)
138
+ args.flat_map do |arg|
136
139
  if arg.match(/[\*\?\[]/)
137
140
  glob = Dir.glob(arg)
138
141
  glob.empty? ? [arg] : glob
@@ -140,37 +143,67 @@ module RSpec
140
143
  [arg]
141
144
  end
142
145
  end
146
+ end
147
+
148
+ def self.rspec(args)
149
+ @rspec_mutex.synchronize do
150
+
151
+ @runner = RSpec::Interactive::Runner.new(parse_args(args))
152
+
153
+ refresh
143
154
 
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)
155
+ # Stop saving history in case a new Pry session is started for debugging.
156
+ Pry.config.history_save = false
147
157
 
148
- if @init_thread&.alive?
149
- @init_thread.join
150
- @init_thread = nil
158
+ # RSpec::Interactive-specific RSpec configuration
159
+ configure_rspec
160
+
161
+ # Run.
162
+ exit_code = @runner.run
163
+ @runner = nil
164
+
165
+ # Reenable history
166
+ Pry.config.history_save = true
167
+
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
151
176
  end
177
+ end
152
178
 
153
- refresh
179
+ 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
154
183
 
155
- # Stop saving history in case a new Pry session is started for debugging.
156
- Pry.config.history_save = false
184
+ @runner = RSpec::Interactive::Runner.new(parse_args(args))
157
185
 
158
- # RSpec::Interactive-specific RSpec configuration
159
- configure_rspec
186
+ refresh
160
187
 
161
- # Run.
162
- exit_code = @runner.run
163
- @runner = nil
188
+ # Stop saving history in case a new Pry session is started for debugging.
189
+ Pry.config.history_save = false
164
190
 
165
- # Reenable history
166
- Pry.config.history_save = true
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
167
197
 
168
- # Reset
169
- RSpec.clear_examples
170
- RSpec.reset
171
- @config_cache.replay_configuration
172
- ensure
173
- @runner = nil
198
+ # Run.
199
+ exit_code = @runner.run
200
+
201
+ # Reset
202
+ Spec::Runner::Formatter::TeamcityFormatter.client = nil
203
+ RSpec.clear_examples
204
+ RSpec.reset
205
+ @config_cache.replay_configuration
206
+ end
174
207
  end
175
208
 
176
209
  def self.rubo_cop(args)
@@ -180,5 +213,6 @@ module RSpec
180
213
  @error_stream.puts "fatal: RuboCop not found. Is the gem installed in this project?"
181
214
  end
182
215
  end
216
+
183
217
  end
184
218
  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.0
4
+ version: 0.9.1
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-25 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