rspec-interactive 0.3.1 → 0.4.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: 44ae79866c1c58455a4c3002cd84f80b5a81ee65ff2256edee608179e8f0b4e1
4
- data.tar.gz: 189c67764a53a77ce517fbfe23f33a4a17fd368ce369a7ceb9bf423ce2cca3b1
3
+ metadata.gz: 04ebab7c57c976985c21b46ab99658f923f4c5b3550616db7c72f66d744b1e47
4
+ data.tar.gz: 56d0ca7636fa0efae3931708c88daaf226e766b098f743f7f888c6bb6d92f33b
5
5
  SHA512:
6
- metadata.gz: 5e8c797fc2481ce1380d4f4056883b39479d6519be4f40af235979fd63dd23040eb7b62e1e80234156b805dead002837afb09ca4fb569f30c134cc97a6f5c6e3
7
- data.tar.gz: a49843eff84cb74c5a3de6da1758de16a947b9ce16e741253354d69b4082c871184ce7e8dd346cb51576e2484e44ca3950d5079d581cc211915d3f600e7b01fd
6
+ metadata.gz: 0eea269e2f1a8f9a222baf3c707a8a7d418ddc6d2ea39c87da55c07490112e8909efd6f7c71d0ca01630cc6d894e397940c78406c3e206df0010ee90f52c8f75
7
+ data.tar.gz: d9080323163091dea28a8977d4b72c505e08e7f14b9c1f973ddf2086abb9d5f852f38e9760e20a6228e07480d99fac63508359a0f61d945452a93b063aa491ff
data/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  # RSpec Interactive
2
2
 
3
- **WARNING: New (or maybe old by now), experimental, untested and poorly documented. Use at your own risk.**
4
-
5
3
  An Pry console capable of running specs.
6
4
 
7
5
  ## Installation & Configuration
@@ -2,4 +2,13 @@
2
2
 
3
3
  require 'rspec-interactive'
4
4
 
5
- RSpec::Interactive.start(ARGV)
5
+ if ARGV.size == 0
6
+ RSpec::Interactive.start
7
+ elsif ARGV.size == 1
8
+ RSpec::Interactive.start(config_file: ARGV[0])
9
+ else
10
+ STDERR.puts "expected 0 or 1 argument, got: #{args.join(', ')}"
11
+ STDERR.puts ''
12
+ STDOUT.puts 'usage: rspec-interactive [config-file]'
13
+ exit 1
14
+ end
@@ -0,0 +1,11 @@
1
+ require 'rspec/core'
2
+
3
+ describe "other example spec" do
4
+ it "succeeds" do
5
+ expect(true).to eq(true)
6
+ end
7
+
8
+ it "succeeds again" do
9
+ expect(true).to eq(true)
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ require 'rspec/core'
2
+
3
+ describe "spec with syntax error" do
4
+ it "succeeds
5
+ end
@@ -5,7 +5,8 @@ require 'readline'
5
5
  require 'rspec/core'
6
6
 
7
7
  require 'rspec-interactive/runner'
8
- require 'rspec-interactive/config_cache'
8
+ require 'rspec-interactive/config'
9
+ require 'rspec-interactive/rspec_config_cache'
9
10
  require 'rspec-interactive/input_completer'
10
11
  require 'rspec-interactive/rspec_command'
11
12
 
@@ -13,23 +14,18 @@ module RSpec
13
14
  module Interactive
14
15
 
15
16
  DEFAULT_HISTORY_FILE = '.rspec_interactive_history'.freeze
16
- DEFAULT_CONFIG_FILE = '.rspec_interactive_config'.freeze
17
17
 
18
- class <<self
19
- attr_accessor :readline, :input_stream, :output_stream, :error_stream
20
- attr_accessor :config, :mutex, :config_cache, :runner, :results, :result, :updated_files
18
+ class << self
19
+ attr_accessor :configuration
21
20
  end
22
21
 
23
- def self.start(args, config_file: DEFAULT_CONFIG_FILE, history_file: DEFAULT_HISTORY_FILE, input_stream: STDIN, output_stream: STDOUT, error_stream: STDERR)
24
- if args.size > 1
25
- @error_stream.puts "expected 0 or 1 argument, got: #{args.join(', ')}"
26
- return 1
27
- end
22
+ def self.configure(&block)
23
+ block.call(@configuration)
24
+ end
28
25
 
29
- @config_file = config_file
26
+ def self.start(config_file: nil, history_file: DEFAULT_HISTORY_FILE, input_stream: STDIN, output_stream: STDOUT, error_stream: STDERR)
30
27
  @history_file = history_file
31
28
  @updated_files = []
32
- @results = []
33
29
  @stty_save = %x`stty -g`.chomp
34
30
  @mutex = Mutex.new
35
31
  @output_stream = output_stream
@@ -37,16 +33,16 @@ module RSpec
37
33
  @error_stream = error_stream
38
34
  @config_cache = RSpec::Interactive::ConfigCache.new
39
35
 
40
- @config = get_config(args[0])
41
- return 1 unless @config
36
+ @configuration = Configuration.new
37
+ @config_cache.record_configuration { load config_file if config_file }
42
38
 
43
- load_rspec_config
44
39
  check_rails
45
40
  start_file_watcher
46
41
  trap_interrupt
47
42
  configure_pry
48
43
 
49
44
  Pry.start
45
+ @listener.stop if @listener
50
46
  0
51
47
  end
52
48
 
@@ -58,10 +54,6 @@ module RSpec
58
54
  end
59
55
  end
60
56
 
61
- def self.load_rspec_config
62
- @config_cache.record_configuration(&rspec_configuration)
63
- end
64
-
65
57
  def self.configure_rspec
66
58
  RSpec.configure do |config|
67
59
  config.error_stream = @error_stream
@@ -69,61 +61,6 @@ module RSpec
69
61
  end
70
62
  end
71
63
 
72
- def self.rspec_configuration
73
- proc do
74
- if @config["init_script"]
75
- $LOAD_PATH << '.'
76
- require @config["init_script"]
77
- end
78
- end
79
- end
80
-
81
- def self.get_config(name = nil)
82
- unless @config_file && File.exists?(@config_file)
83
- @error_stream.puts "warning: config file not found, using default config" if @config_file
84
- return {}
85
- end
86
-
87
- begin
88
- configs = JSON.parse(File.read(@config_file))["configs"] || []
89
- rescue JSON::ParserError => e
90
- @error_stream.puts "failed to parse config file"
91
- return nil
92
- end
93
-
94
- if configs.empty?
95
- @error_stream.puts "no configs found in config file"
96
- return nil
97
- end
98
-
99
- # If a specific config was specified, use it.
100
- if name
101
- config = configs.find { |e| e["name"] == name }
102
- return config if config
103
- @error_stream.puts "invalid config: #{name}"
104
- return nil
105
- end
106
-
107
- # If there is only one, use it.
108
- if configs.size == 1
109
- return configs[0]
110
- end
111
-
112
- # Ask the user which to use.
113
- loop do
114
- names = configs.map { |e| e["name"] }
115
- names[0] = "#{names[0]} (default)"
116
- print "Multiple simultaneous configs not yet supported. Please choose a config. #{names.join(', ')}: "
117
- answer = @input_stream.gets.chomp
118
- if answer.strip.empty?
119
- return configs[0]
120
- end
121
- config = configs.find { |e| e["name"] == answer }
122
- return config if config
123
- @error_stream.puts "invalid config: #{answer}"
124
- end
125
- end
126
-
127
64
  def self.trap_interrupt
128
65
  trap('INT') do
129
66
  if @runner
@@ -138,15 +75,15 @@ module RSpec
138
75
  end
139
76
 
140
77
  def self.start_file_watcher
141
- return unless @config["watch_dirs"]
78
+ return if @configuration.watch_dirs.empty?
142
79
 
143
80
  # Only polling seems to work in Docker.
144
- listener = Listen.to(*@config["watch_dirs"], only: /\.rb$/, force_polling: true) do |modified, added, removed|
81
+ @listener = Listen.to(*@configuration.watch_dirs, only: /\.rb$/, force_polling: true) do |modified, added, removed|
145
82
  @mutex.synchronize do
146
83
  @updated_files.concat(added + modified)
147
84
  end
148
85
  end
149
- listener.start
86
+ @listener.start
150
87
  end
151
88
 
152
89
  def self.configure_pry
@@ -164,5 +101,50 @@ module RSpec
164
101
 
165
102
  Pry.config.history_file = @history_file
166
103
  end
104
+
105
+ def self.rspec(args)
106
+ parsed_args = args.flat_map do |arg|
107
+ if arg.match(/[\*\?\[]/)
108
+ glob = Dir.glob(arg)
109
+ glob.empty? ? [arg] : glob
110
+ else
111
+ [arg]
112
+ end
113
+ end
114
+
115
+ @mutex.synchronize do
116
+ @updated_files.uniq.each do |filename|
117
+ @output_stream.puts "modified: #{filename}"
118
+ trace = TracePoint.new(:class) do |tp|
119
+ @configuration.on_class_load.call(tp.self)
120
+ end
121
+ trace.enable
122
+ load filename
123
+ trace.disable
124
+ @output_stream.puts
125
+ end
126
+ @updated_files.clear
127
+ end
128
+
129
+ @runner = RSpec::Interactive::Runner.new(parsed_args)
130
+
131
+ # Stop saving history in case a new Pry session is started for debugging.
132
+ Pry.config.history_save = false
133
+
134
+ # RSpec::Interactive-specific RSpec configuration
135
+ configure_rspec
136
+
137
+ # Run.
138
+ exit_code = @runner.run
139
+ @runner = nil
140
+
141
+ # Reenable history
142
+ Pry.config.history_save = true
143
+
144
+ # Reset
145
+ RSpec.clear_examples
146
+ RSpec.reset
147
+ @config_cache.replay_configuration
148
+ end
167
149
  end
168
150
  end
@@ -0,0 +1,17 @@
1
+ module RSpec
2
+ module Interactive
3
+ class Configuration
4
+ attr_accessor :watch_dirs, :on_class_load
5
+
6
+ def initialize
7
+ @watch_dirs = []
8
+ @on_class_load = proc {}
9
+ end
10
+
11
+ def on_class_load(&block)
12
+ return @on_class_load unless block
13
+ @on_class_load = block
14
+ end
15
+ end
16
+ end
17
+ end
@@ -16,52 +16,7 @@ module RSpec::Interactive
16
16
  )
17
17
 
18
18
  def process
19
- parsed_args = args.flat_map do |arg|
20
- if arg.match(/[\*\?\[]/)
21
- glob = Dir.glob(arg)
22
- glob.empty? ? [arg] : glob
23
- else
24
- [arg]
25
- end
26
- end
27
-
28
- RSpec::Interactive.mutex.synchronize do
29
- RSpec::Interactive.updated_files.uniq.each do |filename|
30
- load filename
31
- end
32
- RSpec::Interactive.updated_files.clear
33
- end
34
-
35
- RSpec::Interactive.runner = RSpec::Interactive::Runner.new(parsed_args)
36
-
37
- # Stop saving history in case a new Pry session is started for debugging.
38
- Pry.config.history_save = false
39
-
40
- # RSpec::Interactive-specific RSpec configuration
41
- RSpec::Interactive.configure_rspec
42
-
43
- # Run.
44
- result = RSpec::Interactive.runner.run
45
- RSpec::Interactive.runner = nil
46
-
47
- # Save results
48
- RSpec::Interactive.results << result
49
- RSpec::Interactive.result = result
50
-
51
- # Reenable history
52
- Pry.config.history_save = true
53
-
54
- # Reset
55
- RSpec.clear_examples
56
- RSpec.reset
57
- RSpec::Interactive.config_cache.replay_configuration
58
-
59
- if !RSpec::Interactive.result.success && ::RSpec.configuration.example_status_persistence_file_path
60
- RSpec::Interactive.output_stream.puts "Rerun failures by executing the previous command with --only-failures or --next-failure."
61
- RSpec::Interactive.output_stream.puts
62
- end
63
-
64
- result
19
+ RSpec::Interactive.rspec(args)
65
20
  end
66
21
 
67
22
  Pry::Commands.add_command(::RSpec::Interactive::RSpecCommand)
@@ -2,29 +2,6 @@ require 'rspec/core'
2
2
 
3
3
  module RSpec
4
4
  module Interactive
5
- class ExampleGroupResult
6
- attr_accessor :group, :success
7
-
8
- def initialize(group, success)
9
- @group = group
10
- @success = success
11
- end
12
- end
13
-
14
- class Result
15
- attr_accessor :group_results, :success, :exit_code
16
-
17
- def initialize(group_results, success, exit_code)
18
- @group_results = group_results
19
- @success = success
20
- @exit_code = exit_code
21
- end
22
-
23
- def inspect(original = false)
24
- original ? super() : "<RSpec::Interactive::Result @success=#{@success}, @group_results=[...]>"
25
- end
26
- end
27
-
28
5
  class Runner
29
6
  def initialize(args)
30
7
  ::RSpec.world.wants_to_quit = false
@@ -46,28 +23,33 @@ module RSpec
46
23
  example_groups = ::RSpec.world.ordered_example_groups
47
24
  examples_count = ::RSpec.world.example_count(example_groups)
48
25
 
49
- result = ::RSpec.configuration.reporter.report(examples_count) do |reporter|
26
+ exit_code = ::RSpec.configuration.reporter.report(examples_count) do |reporter|
50
27
  ::RSpec.configuration.with_suite_hooks do
51
28
  if examples_count == 0 && ::RSpec.configuration.fail_if_no_examples
52
29
  return ::RSpec.configuration.failure_exit_code
53
30
  end
54
31
 
55
32
  group_results = example_groups.map do |example_group|
56
- group_success = example_group.run(reporter)
57
- ExampleGroupResult.new(example_group, group_success)
33
+ example_group.run(reporter)
58
34
  end
59
35
 
60
- success = group_results.all?(&:success)
36
+ success = group_results.all?
61
37
  exit_code = success ? 0 : 1
62
38
  if ::RSpec.world.non_example_failure
63
39
  success = false
64
40
  exit_code = ::RSpec.configuration.failure_exit_code
65
41
  end
66
42
  persist_example_statuses
67
- Result.new(group_results, success, exit_code)
43
+ exit_code
68
44
  end
69
45
  end
70
- result
46
+
47
+ if exit_code != 0 && ::RSpec.configuration.example_status_persistence_file_path
48
+ ::RSpec.configuration.output_stream.puts "Rerun failures by executing the previous command with --only-failures or --next-failure."
49
+ ::RSpec.configuration.output_stream.puts
50
+ end
51
+
52
+ exit_code
71
53
  end
72
54
 
73
55
  def quit
@@ -80,7 +62,7 @@ module RSpec
80
62
 
81
63
  ::RSpec::Core::ExampleStatusPersister.persist(::RSpec.world.all_examples, path)
82
64
  rescue SystemCallError => e
83
- RSpec::Interactive.error_stream.puts "warning: failed to write results to #{path}"
65
+ ::RSpec.configuration.error_stream.puts "warning: failed to write results to #{path}"
84
66
  end
85
67
  end
86
68
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RSpec
4
4
  module Interactive
5
- VERSION = "0.3.1"
5
+ VERSION = "0.4.0"
6
6
  end
7
7
  end
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Used to quickly test a development version of a gem in the current
4
+ # directory. Adds a local copy of the specified gem, at the specified
5
+ # path, to the current directory's Gemfile and executes the specified
6
+ # command. Upon completion, the Gemfile will be returned to its
7
+ # previous state.
8
+
9
+ if [ $# -ne 3 ]; then
10
+ echo "usage: $0 <gem-name> <path> <command>" >&2
11
+ exit 1
12
+ fi
13
+
14
+ GEM_NAME=$1
15
+ GEM_PATH=$2
16
+ COMMAND=$3
17
+
18
+ if [ -d $GEM_NAME ]; then
19
+ echo "directory exists: $GEM_NAME" >&2
20
+ exit 1
21
+ fi
22
+
23
+ OLD_DEP=$(grep "'$GEM_NAME'" Gemfile)
24
+ if [ $? -ne 0 ]; then
25
+ echo "$GEM_NAME not found in Gemfile" >&2
26
+ exit 1
27
+ fi
28
+
29
+ cp Gemfile Gemfile.save
30
+ cp Gemfile.lock Gemfile.lock.save
31
+ cp -R $GEM_PATH $GEM_NAME
32
+ sed -i '' -E "s/^( *gem '$GEM_NAME').*/\1, path: '$GEM_NAME'/g" Gemfile
33
+ $COMMAND
34
+ rm -rf $GEM_NAME
35
+ mv Gemfile.lock.save Gemfile.lock
36
+ mv Gemfile.save Gemfile
@@ -31,6 +31,43 @@ Test.test "debugged spec" do
31
31
 
32
32
  [2] pry(main)> exit
33
33
  EOF
34
+ end
35
+
36
+ Test.test "debugger does not add to history" do
37
+ await_prompt
38
+ input "rspec examples/debugged_spec.rb"
39
+ await_prompt
40
+ input '"this should not show up in history"'
41
+ await_prompt
42
+ input "exit"
43
+ await_prompt
44
+ input "exit"
45
+ await_termination
46
+ expect_output <<~EOF
47
+ [1] pry(main)> rspec examples/debugged_spec.rb
48
+
49
+ From: /Users/nickdower/Development/rspec-interactive/examples/debugged_spec.rb:6 :
50
+
51
+ 1: require 'rspec/core'
52
+ 2: require 'pry'
53
+ 3:
54
+ 4: describe "example spec" do
55
+ 5: it "gets debugged" do
56
+ => 6: binding.pry
57
+ 7: expect(true).to eq(true)
58
+ 8: end
59
+ 9: end
60
+
61
+ [1] pry(#<RSpec::ExampleGroups::ExampleSpec>)> "this should not show up in history"
62
+ => "this should not show up in history"
63
+ [2] pry(#<RSpec::ExampleGroups::ExampleSpec>)> exit
64
+ .
65
+
66
+ Finished in 0 seconds (files took 0 seconds to load)
67
+ 1 example, 0 failures
68
+
69
+ [2] pry(main)> exit
70
+ EOF
34
71
 
35
72
  expect_history <<~EOF
36
73
  rspec examples/debugged_spec.rb
data/tests/eof_test.rb ADDED
@@ -0,0 +1,10 @@
1
+ require_relative 'support/test_helper'
2
+
3
+ Test.test "exiting via ctrl-d" do
4
+ await_prompt
5
+ ctrl_d
6
+ await_termination
7
+ # No newlines in tests because we return false from tty? in test_helper.rb.
8
+ # In the real app, Pry will add a newline because tty? is true.
9
+ expect_output '[1] pry(main)> '
10
+ end
@@ -0,0 +1,54 @@
1
+ require_relative 'support/test_helper'
2
+
3
+ RSpec.configuration.backtrace_exclusion_patterns = [ /.*/ ]
4
+ RSpec.configuration.backtrace_inclusion_patterns = [ /examples\/failing_spec.rb/ ]
5
+
6
+ examples = Tempfile.new('examples')
7
+
8
+ config = Tempfile.new('config')
9
+ config.write <<~EOF
10
+ RSpec.configuration.example_status_persistence_file_path = "#{examples.path}"
11
+ EOF
12
+ config.rewind
13
+
14
+ Test.test "failing spec with example file", config_path: config.path do
15
+ await_prompt
16
+ input "rspec examples/failing_spec.rb"
17
+ await_prompt
18
+ input "exit"
19
+ await_termination
20
+ expect_output <<~EOF
21
+ [1] pry(main)> rspec examples/failing_spec.rb
22
+ F
23
+
24
+ Failures:
25
+
26
+ 1) example spec fails
27
+ Failure/Error: expect(true).to eq(false)
28
+
29
+ expected: false
30
+ got: true
31
+
32
+ (compared using ==)
33
+
34
+ Diff:
35
+ @@ -1 +1 @@
36
+ -false
37
+ +true
38
+ # ./examples/failing_spec.rb:5:in `block (2 levels) in <top (required)>'
39
+
40
+ Finished in 0 seconds (files took 0 seconds to load)
41
+ 1 example, 1 failure
42
+
43
+ Failed examples:
44
+
45
+ rspec ./examples/failing_spec.rb:4 # example spec fails
46
+
47
+ Rerun failures by executing the previous command with --only-failures or --next-failure.
48
+
49
+ [2] pry(main)> exit
50
+ EOF
51
+ end
52
+
53
+ config.close
54
+ examples.close
@@ -0,0 +1,18 @@
1
+ require_relative 'support/test_helper'
2
+
3
+ Test.test "passing spec" do
4
+ await_prompt
5
+ input "rspec examples/*passing*_spec.rb"
6
+ await_prompt
7
+ input "exit"
8
+ await_termination
9
+ expect_output <<~EOF
10
+ [1] pry(main)> rspec examples/*passing*_spec.rb
11
+ ....
12
+
13
+ Finished in 0 seconds (files took 0 seconds to load)
14
+ 4 examples, 0 failures
15
+
16
+ [2] pry(main)> exit
17
+ EOF
18
+ end
@@ -0,0 +1,19 @@
1
+ require_relative 'support/test_helper'
2
+
3
+ Test.test "running example group at line number" do
4
+ await_prompt
5
+ input "rspec examples/passing_spec.rb:8"
6
+ await_prompt
7
+ input "exit"
8
+ await_termination
9
+ expect_output <<~EOF
10
+ [1] pry(main)> rspec examples/passing_spec.rb:8
11
+ Run options: include {:locations=>{"./examples/passing_spec.rb"=>[8]}}
12
+ .
13
+
14
+ Finished in 0 seconds (files took 0 seconds to load)
15
+ 1 example, 0 failures
16
+
17
+ [2] pry(main)> exit
18
+ EOF
19
+ end
@@ -0,0 +1,90 @@
1
+ require_relative 'support/test_helper'
2
+
3
+ examples = Tempfile.new('examples')
4
+
5
+ config = Tempfile.new('config')
6
+ config.write <<~EOF
7
+ RSpec.configuration.example_status_persistence_file_path = "#{examples.path}"
8
+ EOF
9
+ config.rewind
10
+
11
+ Test.test "failing spec with example file", config_path: config.path do
12
+ await_prompt
13
+
14
+ RSpec.configuration.backtrace_exclusion_patterns = [ /.*/ ]
15
+ RSpec.configuration.backtrace_inclusion_patterns = [ /examples\/failing_spec.rb/ ]
16
+
17
+ input "rspec examples/failing_spec.rb examples/passing_spec.rb"
18
+ await_prompt
19
+
20
+ RSpec.configuration.backtrace_exclusion_patterns = [ /.*/ ]
21
+ RSpec.configuration.backtrace_inclusion_patterns = [ /examples\/failing_spec.rb/ ]
22
+
23
+ input "rspec examples/failing_spec.rb examples/passing_spec.rb --only-failures"
24
+ await_prompt
25
+ input "exit"
26
+ await_termination
27
+ expect_output <<~EOF
28
+ [1] pry(main)> rspec examples/failing_spec.rb examples/passing_spec.rb
29
+ F..
30
+
31
+ Failures:
32
+
33
+ 1) example spec fails
34
+ Failure/Error: expect(true).to eq(false)
35
+
36
+ expected: false
37
+ got: true
38
+
39
+ (compared using ==)
40
+
41
+ Diff:
42
+ @@ -1 +1 @@
43
+ -false
44
+ +true
45
+ # ./examples/failing_spec.rb:5:in `block (2 levels) in <top (required)>'
46
+
47
+ Finished in 0 seconds (files took 0 seconds to load)
48
+ 3 examples, 1 failure
49
+
50
+ Failed examples:
51
+
52
+ rspec ./examples/failing_spec.rb:4 # example spec fails
53
+
54
+ Rerun failures by executing the previous command with --only-failures or --next-failure.
55
+
56
+ [2] pry(main)> rspec examples/failing_spec.rb examples/passing_spec.rb --only-failures
57
+ Run options: include {:last_run_status=>"failed"}
58
+ F
59
+
60
+ Failures:
61
+
62
+ 1) example spec fails
63
+ Failure/Error: expect(true).to eq(false)
64
+
65
+ expected: false
66
+ got: true
67
+
68
+ (compared using ==)
69
+
70
+ Diff:
71
+ @@ -1 +1 @@
72
+ -false
73
+ +true
74
+ # ./examples/failing_spec.rb:5:in `block (2 levels) in <top (required)>'
75
+
76
+ Finished in 0 seconds (files took 0 seconds to load)
77
+ 1 example, 1 failure
78
+
79
+ Failed examples:
80
+
81
+ rspec ./examples/failing_spec.rb:4 # example spec fails
82
+
83
+ Rerun failures by executing the previous command with --only-failures or --next-failure.
84
+
85
+ [3] pry(main)> exit
86
+ EOF
87
+ end
88
+
89
+ config.close
90
+ examples.close
@@ -0,0 +1,30 @@
1
+ require_relative 'support/test_helper'
2
+
3
+ RSpec.configuration.backtrace_exclusion_patterns = [ /.*/ ]
4
+ RSpec.configuration.backtrace_inclusion_patterns = [ /`load_spec_files'/ ]
5
+
6
+ Test.test "spec with syntax error" do
7
+ await_prompt
8
+ input "rspec examples/spec_with_syntax_error.rb"
9
+ await_prompt
10
+ input "exit"
11
+ await_termination
12
+ expect_equal "output", output.gsub(/.+(?=(\\|\/)[a-z_-]+[.]rb:[0-9]+:.*)/, ' [...]'), <<~EOF
13
+ [1] pry(main)> rspec examples/spec_with_syntax_error.rb
14
+
15
+ An error occurred while loading ./examples/spec_with_syntax_error.rb.
16
+ Failure/Error: ::RSpec.configuration.load_spec_files
17
+
18
+ SyntaxError:
19
+ [...]/spec_with_syntax_error.rb:5: unterminated string meets end of file
20
+ [...]/spec_with_syntax_error.rb:5: syntax error, unexpected end-of-input, expecting `end'
21
+ [...]/configuration.rb:1607:in `load_spec_files'
22
+ No examples found.
23
+
24
+
25
+ Finished in 0 seconds (files took 0 seconds to load)
26
+ 0 examples, 0 failures, 1 error occurred outside of examples
27
+
28
+ [2] pry(main)> exit
29
+ EOF
30
+ end
@@ -109,9 +109,16 @@ module Readline
109
109
  Thread.current.kill
110
110
  end
111
111
 
112
+ response = @next_response[0]
113
+ @next_response.clear
114
+
112
115
  temp = Tempfile.new('input')
113
- temp.write("#{@next_response[0]}\n")
114
- temp.rewind
116
+
117
+ unless response.nil?
118
+ temp.write("#{response}\n")
119
+ temp.rewind
120
+ end
121
+
115
122
  input_read = File.new(temp.path, 'r')
116
123
  Readline.input = input_read
117
124
 
@@ -172,13 +179,17 @@ class Test
172
179
  @history_temp_file = Tempfile.new('history')
173
180
 
174
181
  @interactive_thread = Thread.start do
175
- @result = RSpec::Interactive.start(
176
- ARGV,
177
- config_file: config_path,
178
- history_file: @history_temp_file.path,
179
- input_stream: STDIN,
180
- output_stream: @output_write,
181
- error_stream: @error_write)
182
+ begin
183
+ @result = RSpec::Interactive.start(
184
+ config_file: config_path,
185
+ history_file: @history_temp_file.path,
186
+ input_stream: STDIN,
187
+ output_stream: @output_write,
188
+ error_stream: @error_write)
189
+ ensure
190
+ RSpec.clear_examples
191
+ RSpec.reset
192
+ end
182
193
  end
183
194
 
184
195
  begin
@@ -212,6 +223,7 @@ class Test
212
223
  @history_temp_file.close
213
224
 
214
225
  Readline.reset
226
+ Pry.reset_defaults
215
227
  end
216
228
 
217
229
  def await_termination
@@ -231,6 +243,10 @@ class Test
231
243
  Readline.puts(string)
232
244
  end
233
245
 
246
+ def ctrl_d
247
+ Readline.ctrl_d
248
+ end
249
+
234
250
  def output
235
251
  @output_temp_file.rewind
236
252
  File.read(@output_temp_file.path).gsub("\e[0G", "")
@@ -251,20 +267,20 @@ class Test
251
267
  end
252
268
 
253
269
  def expect_output(expected)
254
- if expected != output
255
- raise "unexpected output:\n expected: #{expected.inspect}\n actual: #{output.inspect}"
256
- end
270
+ expect_equal("output", output, expected)
257
271
  end
258
272
 
259
273
  def expect_error_output(expected)
260
- if expected != error_output
261
- raise "unexpected error output:\n expected: #{expected.inspect}\n actual: #{error_output.inspect}"
262
- end
274
+ expect_equal("error output", error_output, expected)
263
275
  end
264
276
 
265
277
  def expect_result(expected)
266
- if expected != @result
267
- raise "unexpected result:\n expected: #{expected.inspect}\n actual: #{@result.inspect}"
278
+ expect_equal("result", @result, expected)
279
+ end
280
+
281
+ def expect_equal(name, actual, expected)
282
+ if expected != actual
283
+ raise "unexpected #{name}:\n expected: #{expected.inspect}\n actual: #{actual.inspect}"
268
284
  end
269
285
  end
270
286
  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.3.1
4
+ version: 0.4.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-05-18 00:00:00.000000000 Z
11
+ date: 2021-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec-core
@@ -72,18 +72,27 @@ files:
72
72
  - bin/test
73
73
  - examples/debugged_spec.rb
74
74
  - examples/failing_spec.rb
75
+ - examples/other_passing_spec.rb
75
76
  - examples/passing_spec.rb
77
+ - examples/spec_with_syntax_error.rb
76
78
  - lib/rspec-interactive.rb
77
- - lib/rspec-interactive/config_cache.rb
79
+ - lib/rspec-interactive/config.rb
78
80
  - lib/rspec-interactive/input_completer.rb
79
81
  - lib/rspec-interactive/rspec_command.rb
82
+ - lib/rspec-interactive/rspec_config_cache.rb
80
83
  - lib/rspec-interactive/runner.rb
81
84
  - lib/rspec-interactive/version.rb
82
85
  - rspec-interactive.gemspec
86
+ - run-with-local-dep.sh
83
87
  - tests/debugged_spec_test.rb
88
+ - tests/eof_test.rb
89
+ - tests/example_file_test.rb
84
90
  - tests/failing_spec_test.rb
85
- - tests/invalid_config_test.rb
91
+ - tests/glob_test.rb
92
+ - tests/line_number_test.rb
86
93
  - tests/passing_spec_test.rb
94
+ - tests/rerun_failed_specs_test.rb
95
+ - tests/spec_with_syntax_error_test.rb
87
96
  - tests/support/ansi.rb
88
97
  - tests/support/test_helper.rb
89
98
  homepage: https://github.com/nicholasdower/rspec-interactive
@@ -1,26 +0,0 @@
1
- require_relative 'support/test_helper'
2
-
3
- config = Tempfile.new('config')
4
- config.write '{'
5
- config.rewind
6
-
7
- Test.test "invalid config", config_path: config.path do
8
- await_termination
9
- expect_error_output <<~EOF
10
- failed to parse config file
11
- EOF
12
- expect_result 1
13
- end
14
- config.close
15
-
16
- config = Tempfile.new('config')
17
- config.write '{}'
18
- config.rewind
19
-
20
- Test.test "empty config", config_path: config.path do
21
- await_termination
22
- expect_error_output <<~EOF
23
- no configs found in config file
24
- EOF
25
- expect_result 1
26
- end