rspec-interactive 0.8.0 → 0.9.1

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