rspec-interactive 0.7.2 → 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: 4e56b91e4f1d28feae7da156d8e4f3ddec5aeffe5847f0ecf6c28150f9f2ac1d
4
- data.tar.gz: 9b88b87a123b207b1478413b0e963bee0a25255163977cd2982cd8d9a0d21742
3
+ metadata.gz: 987faf5573f9ae7554f4983ee350beaf7ad9ef832544cea3b6f92114cf554788
4
+ data.tar.gz: 29e0c2b195497e1d2af2f7e8565ee64ae6039870f3bb685dc86e750c11342a71
5
5
  SHA512:
6
- metadata.gz: a5acd4df05e27db03f66f66f96f9cc43692485abbfe04ee5e680589689c274bde396f07c893b2138cea6db745a4fcc2b9a127caaf7a8c0ccb7c5a2acedd60b6e
7
- data.tar.gz: 534a6ba41f06820271a60a5844fc72e19bb92730067bda01d84ad791fd5c99ce35b4f94b60badb862a7f5de183dbc5a799bfb8280f07162660e99a1b186d74d1
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.7.1)
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
@@ -1,23 +1,27 @@
1
1
  module RSpec::Interactive
2
2
  class InputCompleter < Pry::InputCompleter
3
3
 
4
- def rspec_completions(string)
4
+ def cli_completions(command, string)
5
5
  line = Readline.line_buffer
6
6
  before_current = Readline.point == string.length ? '' : line[0..(Readline.point - string.length)]
7
7
  before_cursor = line[0..(Readline.point - 1)]
8
8
 
9
- if line.match(/^ *rspec +/)
9
+ if line.match(/^ *#{command} +/)
10
10
  Dir[string + '*'].map { |filename| File.directory?(filename) ? "#{filename}/" : filename }
11
- elsif before_current.strip.empty? && "rspec".match(/^#{Regexp.escape(string)}/)
12
- ["rspec "]
11
+ elsif before_current.strip.empty? && command.match(/^#{Regexp.escape(string)}/)
12
+ ["#{command} "]
13
13
  else
14
14
  nil
15
15
  end
16
16
  end
17
17
 
18
18
  def call(str, options = {})
19
- rspec_completions = rspec_completions(str)
19
+ rspec_completions = cli_completions('rspec', str)
20
20
  return rspec_completions if rspec_completions
21
+
22
+ rubocop_completions = cli_completions('rubocop', str)
23
+ return rubocop_completions if rubocop_completions
24
+
21
25
  super
22
26
  end
23
27
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RSpec::Interactive
4
+ class RuboCopCommand < Pry::ClassCommand
5
+ match 'rubocop'
6
+ description "Invoke RuboCop."
7
+
8
+ banner <<-BANNER
9
+ Usage: rubocop [arguments]
10
+
11
+ See https://docs.rubocop.org/rubocop/usage/basic_usage.html
12
+ BANNER
13
+
14
+ command_options(
15
+ :keep_retval => false
16
+ )
17
+
18
+ def process
19
+ RSpec::Interactive.rubo_cop(args)
20
+ end
21
+
22
+ Pry::Commands.add_command(::RSpec::Interactive::RuboCopCommand)
23
+ end
24
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RSpec
4
4
  module Interactive
5
- VERSION = "0.7.2"
5
+ VERSION = "0.9.0"
6
6
  end
7
7
  end
@@ -4,18 +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'
15
+ require 'rspec-interactive/rubo_cop_command'
16
+ require 'rspec-interactive/runner'
14
17
 
15
18
  module RSpec
16
19
  module Interactive
17
20
 
18
21
  DEFAULT_HISTORY_FILE = '.rspec_interactive_history'.freeze
22
+ DEFAULT_PORT = 5678
19
23
 
20
24
  class << self
21
25
  attr_accessor :configuration
@@ -25,11 +29,20 @@ module RSpec
25
29
  block.call(@configuration)
26
30
  end
27
31
 
28
- 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
+
29
41
  @history_file = history_file
30
42
  @updated_files = []
31
43
  @stty_save = %x`stty -g`.chomp
32
- @mutex = Mutex.new
44
+ @file_change_mutex = Mutex.new
45
+ @rspec_mutex = Mutex.new
33
46
  @output_stream = output_stream
34
47
  @input_stream = input_stream
35
48
  @error_stream = error_stream
@@ -42,18 +55,25 @@ module RSpec
42
55
  trap_interrupt
43
56
  configure_pry
44
57
 
45
- @init_thread = Thread.start {
46
- @config_cache.record_configuration { @configuration.configure_rspec.call }
47
- start_file_watcher
48
- }
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
49
64
 
50
- if initial_rspec_args
51
- open(@history_file, 'a') { |f| f.puts "rspec #{initial_rspec_args.strip}" }
52
- 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
53
72
  end
54
73
 
55
74
  Pry.start
56
75
  @listener.stop if @listener
76
+ server_thread.exit if server_thread
57
77
  0
58
78
  end
59
79
 
@@ -65,10 +85,11 @@ module RSpec
65
85
  end
66
86
  end
67
87
 
68
- def self.configure_rspec
88
+ def self.configure_rspec(error_stream: @error_stream, output_stream: @output_stream)
69
89
  RSpec.configure do |config|
70
- config.error_stream = @error_stream
71
- 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
72
93
  end
73
94
  end
74
95
 
@@ -78,9 +99,7 @@ module RSpec
78
99
  # We are on a different thread. There is a race here. Ignore nil.
79
100
  @runner&.quit
80
101
  else
81
- @output_stream.puts
82
- system "stty", @stty_save
83
- exit!(0)
102
+ raise Interrupt
84
103
  end
85
104
  end
86
105
  end
@@ -90,7 +109,7 @@ module RSpec
90
109
 
91
110
  # Only polling seems to work in Docker.
92
111
  @listener = Listen.to(*@configuration.watch_dirs, only: /\.rb$/, force_polling: true) do |modified, added|
93
- @mutex.synchronize do
112
+ @file_change_mutex.synchronize do
94
113
  @updated_files.concat(added + modified)
95
114
  end
96
115
  end
@@ -114,7 +133,7 @@ module RSpec
114
133
  end
115
134
 
116
135
  def self.refresh
117
- @mutex.synchronize do
136
+ @file_change_mutex.synchronize do
118
137
  @updated_files.uniq.each do |filename|
119
138
  @output_stream.puts "changed: #{filename}"
120
139
  trace = TracePoint.new(:class) do |tp|
@@ -130,8 +149,8 @@ module RSpec
130
149
  @configuration.refresh.call
131
150
  end
132
151
 
133
- def self.rspec(args)
134
- parsed_args = args.flat_map do |arg|
152
+ def self.parse_args(args)
153
+ args.flat_map do |arg|
135
154
  if arg.match(/[\*\?\[]/)
136
155
  glob = Dir.glob(arg)
137
156
  glob.empty? ? [arg] : glob
@@ -139,37 +158,71 @@ module RSpec
139
158
  [arg]
140
159
  end
141
160
  end
161
+ end
162
+
163
+ def self.rspec(args)
164
+ @rspec_mutex.synchronize do
142
165
 
143
- # Initialize the runner before waiting for the init thread so that the interrupt
144
- # handler will cancel the RSpec invocation rather than kill the app.
145
- @runner = RSpec::Interactive::Runner.new(parsed_args)
166
+ @runner = RSpec::Interactive::Runner.new(parse_args(args))
146
167
 
147
- if @init_thread&.alive?
148
- @init_thread.join
149
- @init_thread = nil
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
179
+
180
+ # Reenable history
181
+ Pry.config.history_save = true
182
+
183
+ # Reset
184
+ RSpec.clear_examples
185
+ RSpec.reset
186
+ @config_cache.replay_configuration
187
+ ensure
188
+ @runner = nil
150
189
  end
190
+ end
151
191
 
152
- 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
153
196
 
154
- # Stop saving history in case a new Pry session is started for debugging.
155
- Pry.config.history_save = false
197
+ @runner = RSpec::Interactive::Runner.new(parse_args(args))
156
198
 
157
- # RSpec::Interactive-specific RSpec configuration
158
- configure_rspec
199
+ refresh
159
200
 
160
- # Run.
161
- exit_code = @runner.run
162
- @runner = nil
201
+ # Stop saving history in case a new Pry session is started for debugging.
202
+ Pry.config.history_save = false
163
203
 
164
- # Reenable history
165
- Pry.config.history_save = true
204
+ # RSpec::Interactive-specific RSpec configuration
205
+ configure_rspec
206
+ RSpec.configuration.formatter = Spec::Runner::Formatter::TeamcityFormatter
166
207
 
167
- # Reset
168
- RSpec.clear_examples
169
- RSpec.reset
170
- @config_cache.replay_configuration
171
- ensure
172
- @runner = nil
208
+ # Run.
209
+ exit_code = @runner.run
210
+
211
+ # Reset
212
+ Spec::Runner::Formatter::TeamcityFormatter.client = nil
213
+ RSpec.clear_examples
214
+ RSpec.reset
215
+ @config_cache.replay_configuration
216
+ end
217
+ end
218
+
219
+ def self.rubo_cop(args)
220
+ if defined?(RuboCop)
221
+ RuboCop::CLI.new.run args
222
+ else
223
+ @error_stream.puts "fatal: RuboCop not found. Is the gem installed in this project?"
224
+ end
173
225
  end
226
+
174
227
  end
175
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.7.2
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-25 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
@@ -81,8 +97,10 @@ files:
81
97
  - lib/rspec-interactive/refresh_command.rb
82
98
  - lib/rspec-interactive/rspec_command.rb
83
99
  - lib/rspec-interactive/rspec_config_cache.rb
100
+ - lib/rspec-interactive/rubo_cop_command.rb
84
101
  - lib/rspec-interactive/runner.rb
85
102
  - lib/rspec-interactive/version.rb
103
+ - lib/teamcity/spec/runner/formatter/teamcity/formatter.rb
86
104
  - rspec-interactive.gemspec
87
105
  - scripts/release.sh
88
106
  - scripts/run-with-local-dep.sh