rspec-interactive 0.3.1 → 0.4.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 +4 -4
- data/README.md +0 -2
- data/bin/rspec-interactive +10 -1
- data/examples/other_passing_spec.rb +11 -0
- data/examples/spec_with_syntax_error.rb +5 -0
- data/lib/rspec-interactive.rb +59 -77
- data/lib/rspec-interactive/config.rb +17 -0
- data/lib/rspec-interactive/rspec_command.rb +1 -46
- data/lib/rspec-interactive/{config_cache.rb → rspec_config_cache.rb} +0 -0
- data/lib/rspec-interactive/runner.rb +12 -30
- data/lib/rspec-interactive/version.rb +1 -1
- data/run-with-local-dep.sh +36 -0
- data/tests/debugged_spec_test.rb +37 -0
- data/tests/eof_test.rb +10 -0
- data/tests/example_file_test.rb +54 -0
- data/tests/glob_test.rb +18 -0
- data/tests/line_number_test.rb +19 -0
- data/tests/rerun_failed_specs_test.rb +90 -0
- data/tests/spec_with_syntax_error_test.rb +30 -0
- data/tests/support/test_helper.rb +33 -17
- metadata +13 -4
- data/tests/invalid_config_test.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04ebab7c57c976985c21b46ab99658f923f4c5b3550616db7c72f66d744b1e47
|
4
|
+
data.tar.gz: 56d0ca7636fa0efae3931708c88daaf226e766b098f743f7f888c6bb6d92f33b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0eea269e2f1a8f9a222baf3c707a8a7d418ddc6d2ea39c87da55c07490112e8909efd6f7c71d0ca01630cc6d894e397940c78406c3e206df0010ee90f52c8f75
|
7
|
+
data.tar.gz: d9080323163091dea28a8977d4b72c505e08e7f14b9c1f973ddf2086abb9d5f852f38e9760e20a6228e07480d99fac63508359a0f61d945452a93b063aa491ff
|
data/README.md
CHANGED
data/bin/rspec-interactive
CHANGED
@@ -2,4 +2,13 @@
|
|
2
2
|
|
3
3
|
require 'rspec-interactive'
|
4
4
|
|
5
|
-
|
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
|
data/lib/rspec-interactive.rb
CHANGED
@@ -5,7 +5,8 @@ require 'readline'
|
|
5
5
|
require 'rspec/core'
|
6
6
|
|
7
7
|
require 'rspec-interactive/runner'
|
8
|
-
require 'rspec-interactive/
|
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 :
|
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.
|
24
|
-
|
25
|
-
|
26
|
-
return 1
|
27
|
-
end
|
22
|
+
def self.configure(&block)
|
23
|
+
block.call(@configuration)
|
24
|
+
end
|
28
25
|
|
29
|
-
|
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
|
-
@
|
41
|
-
|
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
|
78
|
+
return if @configuration.watch_dirs.empty?
|
142
79
|
|
143
80
|
# Only polling seems to work in Docker.
|
144
|
-
listener = Listen.to(*@
|
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
|
-
|
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)
|
File without changes
|
@@ -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
|
-
|
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
|
-
|
57
|
-
ExampleGroupResult.new(example_group, group_success)
|
33
|
+
example_group.run(reporter)
|
58
34
|
end
|
59
35
|
|
60
|
-
success = group_results.all?
|
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
|
-
|
43
|
+
exit_code
|
68
44
|
end
|
69
45
|
end
|
70
|
-
|
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
|
65
|
+
::RSpec.configuration.error_stream.puts "warning: failed to write results to #{path}"
|
84
66
|
end
|
85
67
|
end
|
86
68
|
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
|
data/tests/debugged_spec_test.rb
CHANGED
@@ -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
|
data/tests/glob_test.rb
ADDED
@@ -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
|
-
|
114
|
-
|
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
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
267
|
-
|
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.
|
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-
|
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/
|
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/
|
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
|