rspec-interactive 0.1.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 +7 -0
- data/.gitignore +1 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +29 -0
- data/LICENSE.txt +21 -0
- data/Rakefile +4 -0
- data/bin/console +15 -0
- data/bin/rspec-interactive +5 -0
- data/bin/setup +8 -0
- data/lib/repo.rb +8 -0
- data/lib/rspec-interactive.rb +205 -0
- data/lib/rspec-interactive/runner.rb +46 -0
- data/lib/rspec-interactive/version.rb +5 -0
- data/rspec-console-0.1.0.gem +0 -0
- data/rspec-interactive.gemspec +29 -0
- metadata +75 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9cc41d7480a29852c93f700e92b70314e0b6e8fc70f73089ca419eae750f32bc
|
4
|
+
data.tar.gz: b7b3357dbf44d8dc21beef28a684950f148eac98aa40b4de53e2eb7faa9eb2e9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f6413fa767a8c4dd85e6f63129d35b9b341a264ae82183696d5c160f63cada92fe96b17972913246bea85b9fb5217b19d0bfd72c4dc1a0a3152a38861cb011de
|
7
|
+
data.tar.gz: 9a42fc226690f04ea027d5cf42403164cbd0cd7f3dae80a9eec4383ef1d3c5f36d40e4f9291432366f449e0651b19b91d1b54c88b6b455cd906b73ae2bad2c08
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rspec-interactive-*.gem
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rspec-console (0.1.0)
|
5
|
+
listen
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
ffi (1.15.0)
|
11
|
+
listen (3.5.1)
|
12
|
+
rb-fsevent (~> 0.10, >= 0.10.3)
|
13
|
+
rb-inotify (~> 0.9, >= 0.9.10)
|
14
|
+
rb-fsevent (0.11.0)
|
15
|
+
rb-inotify (0.10.1)
|
16
|
+
ffi (~> 1.0)
|
17
|
+
rspec-core (3.10.1)
|
18
|
+
rspec-support (~> 3.10.0)
|
19
|
+
rspec-support (3.10.2)
|
20
|
+
|
21
|
+
PLATFORMS
|
22
|
+
x86_64-darwin-20
|
23
|
+
|
24
|
+
DEPENDENCIES
|
25
|
+
rspec-console!
|
26
|
+
rspec-core
|
27
|
+
|
28
|
+
BUNDLED WITH
|
29
|
+
2.2.17
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2021 TODO: Write your name
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "repo"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require "irb"
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/repo.rb
ADDED
@@ -0,0 +1,205 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'listen'
|
5
|
+
require 'readline'
|
6
|
+
require 'rspec/core'
|
7
|
+
require 'shellwords'
|
8
|
+
|
9
|
+
require_relative 'rspec-interactive/runner.rb'
|
10
|
+
|
11
|
+
module RSpecInteractive
|
12
|
+
class Console
|
13
|
+
|
14
|
+
HISTORY_FILE = '.rspec_interactive_history'.freeze
|
15
|
+
CONFIG_FILE = '.rspec_interactive_config'.freeze
|
16
|
+
MAX_HISTORY_ITEMS = 100
|
17
|
+
COMMANDS = ['help', 'rspec']
|
18
|
+
|
19
|
+
def initialize(args)
|
20
|
+
if args.size > 1
|
21
|
+
STDERR.puts "expected 0 or 1 argument, got: #{args.join(', ')}"
|
22
|
+
exit!(1)
|
23
|
+
end
|
24
|
+
|
25
|
+
@stty_save = %x`stty -g`.chomp
|
26
|
+
@mutex = Mutex.new
|
27
|
+
@runner = nil
|
28
|
+
load_config(args[0])
|
29
|
+
end
|
30
|
+
|
31
|
+
def start()
|
32
|
+
start_file_watcher
|
33
|
+
load_history
|
34
|
+
configure_auto_complete
|
35
|
+
trap_interrupt
|
36
|
+
start_console
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def load_config(name = nil)
|
42
|
+
@config = get_config(name)
|
43
|
+
load @config["init_script"]
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_config(name = nil)
|
47
|
+
if !File.exists? CONFIG_FILE
|
48
|
+
STDERR.puts "file not found: #{CONFIG_FILE}"
|
49
|
+
exit!(1)
|
50
|
+
end
|
51
|
+
|
52
|
+
configs = JSON.parse(File.read(CONFIG_FILE))["configs"]
|
53
|
+
if configs.empty?
|
54
|
+
STDERR.puts "no configs found in: #{CONFIG_FILE}"
|
55
|
+
exit!(1)
|
56
|
+
end
|
57
|
+
|
58
|
+
# If a specific config was specified, use it.
|
59
|
+
if name
|
60
|
+
config = configs.find { |e| e["name"] == name }
|
61
|
+
return config if config
|
62
|
+
STDERR.puts "invalid config: #{name}"
|
63
|
+
exit!(1)
|
64
|
+
end
|
65
|
+
|
66
|
+
# If there is only one, use it.
|
67
|
+
if configs.size == 1
|
68
|
+
return configs[0]
|
69
|
+
end
|
70
|
+
|
71
|
+
# Ask the user which to use.
|
72
|
+
loop do
|
73
|
+
names = configs.map { |e| e["name"] }
|
74
|
+
names[0] = "#{names[0]} (default)"
|
75
|
+
print "Multiple simultaneous configs not yet supported. Please choose a config. #{names.join(', ')}: "
|
76
|
+
answer = STDIN.gets.chomp
|
77
|
+
if answer.strip.empty?
|
78
|
+
return configs[0]
|
79
|
+
end
|
80
|
+
config = configs.find { |e| e["name"] == answer }
|
81
|
+
return config if config
|
82
|
+
STDERR.puts "invalid config: #{answer}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def trap_interrupt
|
87
|
+
trap('INT') do
|
88
|
+
@mutex.synchronize do
|
89
|
+
if @runner
|
90
|
+
@runner.quit
|
91
|
+
else
|
92
|
+
puts
|
93
|
+
system "stty", @stty_save
|
94
|
+
exit!(0)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def start_file_watcher
|
101
|
+
# Only polling seems to work in Docker.
|
102
|
+
listener = Listen.to(*@config["watch_dirs"], only: /\.rb$/, force_polling: true) do |modified, added, removed|
|
103
|
+
(added + modified).each { |filename| load filename }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def load_history
|
108
|
+
if File.exists? HISTORY_FILE
|
109
|
+
lines = File.readlines(HISTORY_FILE)
|
110
|
+
lines.each do |line|
|
111
|
+
Readline::HISTORY << line.strip
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def configure_auto_complete
|
117
|
+
Readline.completion_append_character = ""
|
118
|
+
end
|
119
|
+
|
120
|
+
def start_console
|
121
|
+
loop do
|
122
|
+
buffer = Readline.readline('> ', true)&.strip
|
123
|
+
|
124
|
+
# Exit on ctrl-D.
|
125
|
+
if !buffer
|
126
|
+
puts
|
127
|
+
system "stty", @stty_save
|
128
|
+
exit!(0)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Ignore blank lines.
|
132
|
+
if buffer.empty?
|
133
|
+
Readline::HISTORY.pop
|
134
|
+
next
|
135
|
+
end
|
136
|
+
|
137
|
+
# Write history to file.
|
138
|
+
if Readline::HISTORY.size > 0
|
139
|
+
file = File.open(HISTORY_FILE, 'w')
|
140
|
+
lines = Readline::HISTORY.to_a
|
141
|
+
lines[-[MAX_HISTORY_ITEMS, lines.size].min..-1].each do |line|
|
142
|
+
file.write(line.strip + "\n")
|
143
|
+
end
|
144
|
+
file.close
|
145
|
+
end
|
146
|
+
|
147
|
+
# Handle quoting, etc.
|
148
|
+
args = Shellwords.shellsplit(buffer)
|
149
|
+
next if args.empty?
|
150
|
+
|
151
|
+
command = args[0].strip
|
152
|
+
if COMMANDS.include?(command)
|
153
|
+
send command.to_sym, args[1..-1]
|
154
|
+
else
|
155
|
+
STDERR.puts "command not found: #{args[0]}"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def help(args)
|
161
|
+
if !args.empty?
|
162
|
+
STDERR.puts "invalid argument(s): #{args}"
|
163
|
+
return
|
164
|
+
end
|
165
|
+
|
166
|
+
print "commands:\n\n"
|
167
|
+
print "help - print this message\n"
|
168
|
+
print "rspec - execute the specified spec file(s), wildcards allowed\n"
|
169
|
+
end
|
170
|
+
|
171
|
+
def rspec(args)
|
172
|
+
if args.empty?
|
173
|
+
STDERR.puts "you must specify one or more spec files"
|
174
|
+
return
|
175
|
+
end
|
176
|
+
|
177
|
+
# Allow wildcards.
|
178
|
+
filenames = args.flat_map { |filename| Dir.glob(filename) }
|
179
|
+
|
180
|
+
# Store formatters, if any, set by the init script. They will be cleared by RSpec below.
|
181
|
+
formatters = RSpec.configuration.formatters || []
|
182
|
+
|
183
|
+
# Initialize the runner. Also accessed by the signal handler above.
|
184
|
+
# RSpecInteractive::Runner sets RSpec.world.wants_to_quit to false. The signal
|
185
|
+
# handler sets it to true.
|
186
|
+
@mutex.synchronize { @runner = RSpecInteractive::Runner.new(filenames) }
|
187
|
+
|
188
|
+
# Run the specs.
|
189
|
+
@runner.run
|
190
|
+
|
191
|
+
# Clear the runner.
|
192
|
+
@mutex.synchronize { @runner = nil }
|
193
|
+
|
194
|
+
# Clear data from previous run.
|
195
|
+
RSpec.clear_examples
|
196
|
+
|
197
|
+
# Formatters get cleared by clear_examples. I don't understand why but the actual run
|
198
|
+
# also modifies the list of formatters. Reset them to whatever the init script set.
|
199
|
+
if !RSpec.configuration.formatters.empty?
|
200
|
+
raise "internal error. expected formatters to be cleared."
|
201
|
+
end
|
202
|
+
formatters.each { |f| RSpec.configuration.add_formatter(f) }
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rspec/core'
|
2
|
+
|
3
|
+
module RSpecInteractive
|
4
|
+
class Runner
|
5
|
+
def initialize(args)
|
6
|
+
RSpec.world.wants_to_quit = false
|
7
|
+
@options = RSpec::Core::ConfigurationOptions.new(args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def run()
|
11
|
+
begin
|
12
|
+
@options.configure(RSpec.configuration)
|
13
|
+
return if RSpec.world.wants_to_quit
|
14
|
+
|
15
|
+
RSpec.configuration.load_spec_files
|
16
|
+
ensure
|
17
|
+
RSpec.world.announce_filters
|
18
|
+
end
|
19
|
+
|
20
|
+
return RSpec.configuration.reporter.exit_early(RSpec.configuration.failure_exit_code) if RSpec.world.wants_to_quit
|
21
|
+
|
22
|
+
example_groups = RSpec.world.ordered_example_groups
|
23
|
+
examples_count = RSpec.world.example_count(example_groups)
|
24
|
+
|
25
|
+
success = RSpec.configuration.reporter.report(examples_count) do |reporter|
|
26
|
+
RSpec.configuration.with_suite_hooks do
|
27
|
+
if examples_count == 0 && RSpec.configuration.fail_if_no_examples
|
28
|
+
return RSpec.configuration.failure_exit_code
|
29
|
+
end
|
30
|
+
|
31
|
+
result = example_groups.map do |example_group|
|
32
|
+
example_group.run(reporter)
|
33
|
+
end
|
34
|
+
|
35
|
+
result.all?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
success && !RSpec.world.non_example_failure ? 0 : RSpec.configuration.failure_exit_code
|
40
|
+
end
|
41
|
+
|
42
|
+
def quit
|
43
|
+
RSpec.world.wants_to_quit = true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
Binary file
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/rspec-interactive/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "rspec-interactive"
|
7
|
+
spec.version = RSpecInteractive::VERSION
|
8
|
+
spec.authors = ["Nick Dower"]
|
9
|
+
spec.email = ["nicholasdower@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "An interactive console for running specs."
|
12
|
+
spec.description = "An interactive console for running specs."
|
13
|
+
spec.homepage = "https://github.com/nicholasdower/rspec-interactive"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = "https://github.com/nicholasdower/rspec-interactive"
|
19
|
+
spec.metadata["changelog_uri"] = "https://github.com/nicholasdower/rspec-interactive"
|
20
|
+
|
21
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
22
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
23
|
+
end
|
24
|
+
spec.bindir = 'bin'
|
25
|
+
spec.executables << 'rspec-interactive'
|
26
|
+
spec.require_paths = ["lib"]
|
27
|
+
|
28
|
+
spec.add_dependency "listen"
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rspec-interactive
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nick Dower
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-05-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: listen
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: An interactive console for running specs.
|
28
|
+
email:
|
29
|
+
- nicholasdower@gmail.com
|
30
|
+
executables:
|
31
|
+
- rspec-interactive
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- ".gitignore"
|
36
|
+
- Gemfile
|
37
|
+
- Gemfile.lock
|
38
|
+
- LICENSE.txt
|
39
|
+
- Rakefile
|
40
|
+
- bin/console
|
41
|
+
- bin/rspec-interactive
|
42
|
+
- bin/setup
|
43
|
+
- lib/repo.rb
|
44
|
+
- lib/rspec-interactive.rb
|
45
|
+
- lib/rspec-interactive/runner.rb
|
46
|
+
- lib/rspec-interactive/version.rb
|
47
|
+
- rspec-console-0.1.0.gem
|
48
|
+
- rspec-interactive.gemspec
|
49
|
+
homepage: https://github.com/nicholasdower/rspec-interactive
|
50
|
+
licenses:
|
51
|
+
- MIT
|
52
|
+
metadata:
|
53
|
+
homepage_uri: https://github.com/nicholasdower/rspec-interactive
|
54
|
+
source_code_uri: https://github.com/nicholasdower/rspec-interactive
|
55
|
+
changelog_uri: https://github.com/nicholasdower/rspec-interactive
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 2.4.0
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubygems_version: 3.2.3
|
72
|
+
signing_key:
|
73
|
+
specification_version: 4
|
74
|
+
summary: An interactive console for running specs.
|
75
|
+
test_files: []
|