rspec-interactive 0.7.2 → 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: 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