thor 0.18.1 → 0.19.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/README.md +13 -7
- data/Thorfile +4 -5
- data/bin/thor +1 -1
- data/lib/thor.rb +78 -67
- data/lib/thor/actions.rb +57 -56
- data/lib/thor/actions/create_file.rb +33 -35
- data/lib/thor/actions/create_link.rb +2 -3
- data/lib/thor/actions/directory.rb +37 -38
- data/lib/thor/actions/empty_directory.rb +67 -69
- data/lib/thor/actions/file_manipulation.rb +17 -15
- data/lib/thor/actions/inject_into_file.rb +27 -29
- data/lib/thor/base.rb +193 -189
- data/lib/thor/command.rb +20 -23
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +21 -24
- data/lib/thor/core_ext/io_binary_read.rb +2 -4
- data/lib/thor/core_ext/ordered_hash.rb +9 -11
- data/lib/thor/error.rb +5 -1
- data/lib/thor/group.rb +53 -54
- data/lib/thor/invocation.rb +44 -38
- data/lib/thor/line_editor.rb +17 -0
- data/lib/thor/line_editor/basic.rb +35 -0
- data/lib/thor/line_editor/readline.rb +88 -0
- data/lib/thor/parser.rb +4 -4
- data/lib/thor/parser/argument.rb +28 -29
- data/lib/thor/parser/arguments.rb +102 -98
- data/lib/thor/parser/option.rb +26 -22
- data/lib/thor/parser/options.rb +86 -86
- data/lib/thor/rake_compat.rb +9 -10
- data/lib/thor/runner.rb +141 -141
- data/lib/thor/shell.rb +27 -34
- data/lib/thor/shell/basic.rb +91 -63
- data/lib/thor/shell/color.rb +44 -43
- data/lib/thor/shell/html.rb +59 -60
- data/lib/thor/util.rb +24 -27
- data/lib/thor/version.rb +1 -1
- data/spec/actions/create_file_spec.rb +25 -27
- data/spec/actions/create_link_spec.rb +19 -18
- data/spec/actions/directory_spec.rb +31 -31
- data/spec/actions/empty_directory_spec.rb +18 -18
- data/spec/actions/file_manipulation_spec.rb +38 -28
- data/spec/actions/inject_into_file_spec.rb +13 -13
- data/spec/actions_spec.rb +43 -43
- data/spec/base_spec.rb +45 -38
- data/spec/command_spec.rb +13 -14
- data/spec/core_ext/hash_with_indifferent_access_spec.rb +19 -19
- data/spec/core_ext/ordered_hash_spec.rb +6 -6
- data/spec/exit_condition_spec.rb +4 -4
- data/spec/fixtures/invoke.thor +19 -0
- data/spec/fixtures/script.thor +1 -1
- data/spec/group_spec.rb +30 -24
- data/spec/helper.rb +28 -15
- data/spec/invocation_spec.rb +39 -19
- data/spec/line_editor/basic_spec.rb +28 -0
- data/spec/line_editor/readline_spec.rb +69 -0
- data/spec/line_editor_spec.rb +43 -0
- data/spec/parser/argument_spec.rb +12 -12
- data/spec/parser/arguments_spec.rb +11 -11
- data/spec/parser/option_spec.rb +33 -25
- data/spec/parser/options_spec.rb +66 -52
- data/spec/quality_spec.rb +75 -0
- data/spec/rake_compat_spec.rb +10 -10
- data/spec/register_spec.rb +60 -30
- data/spec/runner_spec.rb +67 -62
- data/spec/sandbox/application.rb +2 -0
- data/spec/sandbox/app{1}/README +3 -0
- data/spec/sandbox/bundle/execute.rb +6 -0
- data/spec/sandbox/bundle/main.thor +1 -0
- data/spec/sandbox/command.thor +10 -0
- data/spec/sandbox/doc/%file_name%.rb.tt +1 -0
- data/spec/sandbox/doc/COMMENTER +11 -0
- data/spec/sandbox/doc/README +3 -0
- data/spec/sandbox/doc/block_helper.rb +3 -0
- data/spec/sandbox/doc/config.rb +1 -0
- data/spec/sandbox/doc/config.yaml.tt +1 -0
- data/spec/sandbox/doc/excluding/%file_name%.rb.tt +1 -0
- data/spec/sandbox/enum.thor +10 -0
- data/spec/sandbox/group.thor +128 -0
- data/spec/sandbox/invoke.thor +131 -0
- data/spec/sandbox/path with spaces b/data/spec/sandbox/path with → spaces +0 -0
- data/spec/sandbox/preserve/script.sh +3 -0
- data/spec/sandbox/script.thor +220 -0
- data/spec/sandbox/subcommand.thor +17 -0
- data/spec/shell/basic_spec.rb +107 -86
- data/spec/shell/color_spec.rb +32 -8
- data/spec/shell/html_spec.rb +3 -4
- data/spec/shell_spec.rb +7 -7
- data/spec/subcommand_spec.rb +20 -2
- data/spec/thor_spec.rb +111 -97
- data/spec/util_spec.rb +30 -30
- data/thor.gemspec +14 -14
- metadata +69 -25
@@ -0,0 +1,75 @@
|
|
1
|
+
if defined?(Encoding) && Encoding.default_external != "UTF-8"
|
2
|
+
Encoding.default_external = "UTF-8"
|
3
|
+
end
|
4
|
+
|
5
|
+
describe "The library itself" do
|
6
|
+
def check_for_spec_defs_with_single_quotes(filename)
|
7
|
+
failing_lines = []
|
8
|
+
|
9
|
+
File.readlines(filename).each_with_index do |line,number|
|
10
|
+
failing_lines << number + 1 if line =~ /^ *(describe|it|context) {1}'{1}/
|
11
|
+
end
|
12
|
+
|
13
|
+
unless failing_lines.empty?
|
14
|
+
"#{filename} uses inconsistent single quotes on lines #{failing_lines.join(', ')}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def check_for_tab_characters(filename)
|
19
|
+
failing_lines = []
|
20
|
+
File.readlines(filename).each_with_index do |line,number|
|
21
|
+
failing_lines << number + 1 if line =~ /\t/
|
22
|
+
end
|
23
|
+
|
24
|
+
unless failing_lines.empty?
|
25
|
+
"#{filename} has tab characters on lines #{failing_lines.join(', ')}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def check_for_extra_spaces(filename)
|
30
|
+
failing_lines = []
|
31
|
+
File.readlines(filename).each_with_index do |line,number|
|
32
|
+
next if line =~ /^\s+#.*\s+\n$/
|
33
|
+
failing_lines << number + 1 if line =~ /\s+\n$/
|
34
|
+
end
|
35
|
+
|
36
|
+
unless failing_lines.empty?
|
37
|
+
"#{filename} has spaces on the EOL on lines #{failing_lines.join(', ')}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
RSpec::Matchers.define :be_well_formed do
|
42
|
+
failure_message_for_should do |actual|
|
43
|
+
actual.join("\n")
|
44
|
+
end
|
45
|
+
|
46
|
+
match do |actual|
|
47
|
+
actual.empty?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "has no malformed whitespace" do
|
52
|
+
exempt = /\.gitmodules|\.marshal|fixtures|vendor|spec|ssl_certs|LICENSE/
|
53
|
+
error_messages = []
|
54
|
+
Dir.chdir(File.expand_path("../..", __FILE__)) do
|
55
|
+
`git ls-files`.split("\n").each do |filename|
|
56
|
+
next if filename =~ exempt
|
57
|
+
error_messages << check_for_tab_characters(filename)
|
58
|
+
error_messages << check_for_extra_spaces(filename)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
expect(error_messages.compact).to be_well_formed
|
62
|
+
end
|
63
|
+
|
64
|
+
it "uses double-quotes consistently in specs" do
|
65
|
+
included = /spec/
|
66
|
+
error_messages = []
|
67
|
+
Dir.chdir(File.expand_path("../", __FILE__)) do
|
68
|
+
`git ls-files`.split("\n").each do |filename|
|
69
|
+
next unless filename =~ included
|
70
|
+
error_messages << check_for_spec_defs_with_single_quotes(filename)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
expect(error_messages.compact).to be_well_formed
|
74
|
+
end
|
75
|
+
end
|
data/spec/rake_compat_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "helper"
|
2
|
+
require "thor/rake_compat"
|
3
|
+
require "rake/tasklib"
|
4
4
|
|
5
5
|
$main = self
|
6
6
|
|
@@ -32,7 +32,7 @@ end
|
|
32
32
|
|
33
33
|
describe Thor::RakeCompat do
|
34
34
|
it "sets the rakefile application" do
|
35
|
-
expect([
|
35
|
+
expect(%w[rake_compat_spec.rb Thorfile]).to include(Rake.application.rakefile)
|
36
36
|
end
|
37
37
|
|
38
38
|
it "adds rake tasks to thor classes too" do
|
@@ -61,12 +61,12 @@ describe Thor::RakeCompat do
|
|
61
61
|
end
|
62
62
|
|
63
63
|
it "invoking the thor task invokes the rake task" do
|
64
|
-
expect(capture(:stdout)
|
65
|
-
ThorTask.start [
|
66
|
-
|
64
|
+
expect(capture(:stdout) do
|
65
|
+
ThorTask.start %w[cool]
|
66
|
+
end).to eq("COOL\n")
|
67
67
|
|
68
|
-
expect(capture(:stdout)
|
69
|
-
ThorTask::HiperMega.start [
|
70
|
-
|
68
|
+
expect(capture(:stdout) do
|
69
|
+
ThorTask::HiperMega.start %w[super]
|
70
|
+
end).to eq("HIPER MEGA SUPER\n")
|
71
71
|
end
|
72
72
|
end
|
data/spec/register_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "helper"
|
2
2
|
|
3
3
|
class BoringVendorProvidedCLI < Thor
|
4
4
|
desc "boring", "do boring stuff"
|
@@ -42,9 +42,9 @@ end
|
|
42
42
|
|
43
43
|
class ClassOptionGroupPlugin < Thor::Group
|
44
44
|
class_option :who,
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
:type => :string,
|
46
|
+
:aliases => "-w",
|
47
|
+
:default => "zebra"
|
48
48
|
end
|
49
49
|
|
50
50
|
class CompatibleWith19Plugin < ClassOptionGroupPlugin
|
@@ -82,6 +82,20 @@ class PluginWithDefaultcommandAndDeclaredArgument < Thor
|
|
82
82
|
default_command :say
|
83
83
|
end
|
84
84
|
|
85
|
+
class SubcommandWithDefault < Thor
|
86
|
+
default_command :default
|
87
|
+
|
88
|
+
desc "default", "default subcommand"
|
89
|
+
def default
|
90
|
+
puts "default"
|
91
|
+
end
|
92
|
+
|
93
|
+
desc "with_args", "subcommand with arguments"
|
94
|
+
def with_args(*args)
|
95
|
+
puts "received arguments: " + args.join(",")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
85
99
|
BoringVendorProvidedCLI.register(
|
86
100
|
ExcitingPluginCLI,
|
87
101
|
"exciting",
|
@@ -97,33 +111,36 @@ BoringVendorProvidedCLI.register(
|
|
97
111
|
|
98
112
|
BoringVendorProvidedCLI.register(
|
99
113
|
GroupPlugin,
|
100
|
-
|
114
|
+
"groupwork",
|
101
115
|
"Do a bunch of things in a row",
|
102
116
|
"purple monkey dishwasher")
|
103
117
|
|
104
118
|
BoringVendorProvidedCLI.register(
|
105
119
|
CompatibleWith19Plugin,
|
106
|
-
|
120
|
+
"zoo",
|
107
121
|
"zoo [-w animal]",
|
108
122
|
"Shows a provided animal or just zebra")
|
109
123
|
|
110
124
|
BoringVendorProvidedCLI.register(
|
111
125
|
PluginWithDefault,
|
112
|
-
|
113
|
-
|
114
|
-
|
126
|
+
"say",
|
127
|
+
"say message",
|
128
|
+
"subcommands ftw")
|
115
129
|
|
116
130
|
BoringVendorProvidedCLI.register(
|
117
131
|
PluginWithDefaultMultipleArguments,
|
118
|
-
|
119
|
-
|
120
|
-
|
132
|
+
"say_multiple",
|
133
|
+
"say message",
|
134
|
+
"subcommands ftw")
|
121
135
|
|
122
136
|
BoringVendorProvidedCLI.register(
|
123
137
|
PluginWithDefaultcommandAndDeclaredArgument,
|
124
|
-
|
125
|
-
|
126
|
-
|
138
|
+
"say_argument",
|
139
|
+
"say message",
|
140
|
+
"subcommands ftw")
|
141
|
+
|
142
|
+
BoringVendorProvidedCLI.register(SubcommandWithDefault,
|
143
|
+
"subcommand", "subcommand", "Run subcommands")
|
127
144
|
|
128
145
|
describe ".register-ing a Thor subclass" do
|
129
146
|
it "registers the plugin as a subcommand" do
|
@@ -133,23 +150,36 @@ describe ".register-ing a Thor subclass" do
|
|
133
150
|
|
134
151
|
it "includes the plugin's usage in the help" do
|
135
152
|
help_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[help]) }
|
136
|
-
expect(help_output).to include(
|
153
|
+
expect(help_output).to include("do exciting things")
|
137
154
|
end
|
138
155
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
156
|
+
context "with a default command," do
|
157
|
+
it "invokes the default command correctly" do
|
158
|
+
output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say hello]) }
|
159
|
+
expect(output).to include("hello")
|
160
|
+
end
|
143
161
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
162
|
+
it "invokes the default command correctly with multiple args" do
|
163
|
+
output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say_multiple hello adam]) }
|
164
|
+
expect(output).to include("hello")
|
165
|
+
expect(output).to include("adam")
|
166
|
+
end
|
167
|
+
|
168
|
+
it "invokes the default command correctly with a declared argument" do
|
169
|
+
output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say_argument hello]) }
|
170
|
+
expect(output).to include("hello")
|
171
|
+
end
|
172
|
+
|
173
|
+
it "displays the subcommand's help message" do
|
174
|
+
output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[subcommand help]) }
|
175
|
+
expect(output).to include("default subcommand")
|
176
|
+
expect(output).to include("subcommand with argument")
|
177
|
+
end
|
149
178
|
|
150
|
-
|
151
|
-
|
152
|
-
|
179
|
+
it "invokes commands with their actual args" do
|
180
|
+
output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[subcommand with_args actual_argument]) }
|
181
|
+
expect(output.strip).to eql("received arguments: actual_argument")
|
182
|
+
end
|
153
183
|
end
|
154
184
|
|
155
185
|
context "when $thor_runner is false" do
|
@@ -157,7 +187,7 @@ describe ".register-ing a Thor subclass" do
|
|
157
187
|
begin
|
158
188
|
$thor_runner = false
|
159
189
|
help_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[exciting]) }
|
160
|
-
expect(help_output).to include(
|
190
|
+
expect(help_output).to include("thor exciting_plugin_c_l_i fireworks")
|
161
191
|
ensure
|
162
192
|
$thor_runner = true
|
163
193
|
end
|
@@ -167,7 +197,7 @@ describe ".register-ing a Thor subclass" do
|
|
167
197
|
context "when hidden" do
|
168
198
|
it "omits the hidden plugin's usage from the help" do
|
169
199
|
help_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[help]) }
|
170
|
-
expect(help_output).not_to include(
|
200
|
+
expect(help_output).not_to include("secret stuff")
|
171
201
|
end
|
172
202
|
|
173
203
|
it "registers the plugin as a subcommand" do
|
data/spec/runner_spec.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "helper"
|
2
|
+
require "thor/runner"
|
3
3
|
|
4
4
|
describe Thor::Runner do
|
5
5
|
def when_no_thorfiles_exist
|
6
6
|
old_dir = Dir.pwd
|
7
|
-
Dir.chdir
|
8
|
-
delete = Thor::Base.subclasses.select {|e| e.namespace ==
|
9
|
-
delete.each {|e| Thor::Base.subclasses.delete e }
|
7
|
+
Dir.chdir ".."
|
8
|
+
delete = Thor::Base.subclasses.select { |e| e.namespace == "default" }
|
9
|
+
delete.each { |e| Thor::Base.subclasses.delete e }
|
10
10
|
yield
|
11
11
|
Thor::Base.subclasses.concat delete
|
12
12
|
Dir.chdir old_dir
|
@@ -14,40 +14,40 @@ describe Thor::Runner do
|
|
14
14
|
|
15
15
|
describe "#help" do
|
16
16
|
it "shows information about Thor::Runner itself" do
|
17
|
-
expect(capture(:stdout) { Thor::Runner.start([
|
17
|
+
expect(capture(:stdout) { Thor::Runner.start(%w[help]) }).to match(/List the available thor commands/)
|
18
18
|
end
|
19
19
|
|
20
20
|
it "shows information about a specific Thor::Runner command" do
|
21
|
-
content = capture(:stdout) { Thor::Runner.start([
|
21
|
+
content = capture(:stdout) { Thor::Runner.start(%w[help list]) }
|
22
22
|
expect(content).to match(/List the available thor commands/)
|
23
23
|
expect(content).not_to match(/help \[COMMAND\]/)
|
24
24
|
end
|
25
25
|
|
26
26
|
it "shows information about a specific Thor class" do
|
27
|
-
content = capture(:stdout) { Thor::Runner.start([
|
27
|
+
content = capture(:stdout) { Thor::Runner.start(%w[help my_script]) }
|
28
28
|
expect(content).to match(/zoo\s+# zoo around/m)
|
29
29
|
end
|
30
30
|
|
31
|
-
it "shows information about
|
32
|
-
content = capture(:stdout) { Thor::Runner.start([
|
31
|
+
it "shows information about a specific command from a specific Thor class" do
|
32
|
+
content = capture(:stdout) { Thor::Runner.start(%w[help my_script:zoo]) }
|
33
33
|
expect(content).to match(/zoo around/)
|
34
34
|
expect(content).not_to match(/help \[COMMAND\]/)
|
35
35
|
end
|
36
36
|
|
37
37
|
it "shows information about a specific Thor group class" do
|
38
|
-
content = capture(:stdout) { Thor::Runner.start([
|
38
|
+
content = capture(:stdout) { Thor::Runner.start(%w[help my_counter]) }
|
39
39
|
expect(content).to match(/my_counter N/)
|
40
40
|
end
|
41
41
|
|
42
42
|
it "raises error if a class/command cannot be found" do
|
43
|
-
content = capture(:stderr){ Thor::Runner.start([
|
43
|
+
content = capture(:stderr) { Thor::Runner.start(%w[help unknown]) }
|
44
44
|
expect(content.strip).to eq('Could not find command "unknown" in "default" namespace.')
|
45
45
|
end
|
46
46
|
|
47
47
|
it "raises error if a class/command cannot be found for a setup without thorfiles" do
|
48
48
|
when_no_thorfiles_exist do
|
49
|
-
Thor::Runner.
|
50
|
-
content = capture(:stderr){ Thor::Runner.start([
|
49
|
+
expect(Thor::Runner).to receive :exit
|
50
|
+
content = capture(:stderr) { Thor::Runner.start(%w[help unknown]) }
|
51
51
|
expect(content.strip).to eq('Could not find command "unknown".')
|
52
52
|
end
|
53
53
|
end
|
@@ -55,64 +55,65 @@ describe Thor::Runner do
|
|
55
55
|
|
56
56
|
describe "#start" do
|
57
57
|
it "invokes a command from Thor::Runner" do
|
58
|
-
ARGV.replace [
|
58
|
+
ARGV.replace %w[list]
|
59
59
|
expect(capture(:stdout) { Thor::Runner.start }).to match(/my_counter N/)
|
60
60
|
end
|
61
61
|
|
62
62
|
it "invokes a command from a specific Thor class" do
|
63
|
-
ARGV.replace [
|
64
|
-
expect(Thor::Runner.start).to
|
63
|
+
ARGV.replace %w[my_script:zoo]
|
64
|
+
expect(Thor::Runner.start).to be true
|
65
65
|
end
|
66
66
|
|
67
67
|
it "invokes the default command from a specific Thor class if none is specified" do
|
68
|
-
ARGV.replace [
|
68
|
+
ARGV.replace %w[my_script]
|
69
69
|
expect(Thor::Runner.start).to eq("default command")
|
70
70
|
end
|
71
71
|
|
72
|
-
it "
|
73
|
-
ARGV.replace [
|
74
|
-
expect(Thor::Runner.start).to eq([
|
72
|
+
it "forwards arguments to the invoked command" do
|
73
|
+
ARGV.replace %w[my_script:animal horse]
|
74
|
+
expect(Thor::Runner.start).to eq(%w[horse])
|
75
75
|
end
|
76
76
|
|
77
77
|
it "invokes commands through shortcuts" do
|
78
|
-
ARGV.replace [
|
79
|
-
expect(Thor::Runner.start).to eq([
|
78
|
+
ARGV.replace %w[my_script -T horse]
|
79
|
+
expect(Thor::Runner.start).to eq(%w[horse])
|
80
80
|
end
|
81
81
|
|
82
82
|
it "invokes a Thor::Group" do
|
83
|
-
ARGV.replace [
|
83
|
+
ARGV.replace %w[my_counter 1 2 --third 3]
|
84
84
|
expect(Thor::Runner.start).to eq([1, 2, 3, nil, nil, nil])
|
85
85
|
end
|
86
86
|
|
87
87
|
it "raises an error if class/command can't be found" do
|
88
|
-
ARGV.replace [
|
89
|
-
content = capture(:stderr){ Thor::Runner.start }
|
88
|
+
ARGV.replace %w[unknown]
|
89
|
+
content = capture(:stderr) { Thor::Runner.start }
|
90
90
|
expect(content.strip).to eq('Could not find command "unknown" in "default" namespace.')
|
91
91
|
end
|
92
92
|
|
93
93
|
it "raises an error if class/command can't be found in a setup without thorfiles" do
|
94
94
|
when_no_thorfiles_exist do
|
95
|
-
ARGV.replace [
|
96
|
-
Thor::Runner.
|
97
|
-
content = capture(:stderr){ Thor::Runner.start }
|
95
|
+
ARGV.replace %w[unknown]
|
96
|
+
expect(Thor::Runner).to receive :exit
|
97
|
+
content = capture(:stderr) { Thor::Runner.start }
|
98
98
|
expect(content.strip).to eq('Could not find command "unknown".')
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
102
|
it "does not swallow NoMethodErrors that occur inside the called method" do
|
103
|
-
ARGV.replace [
|
104
|
-
expect{ Thor::Runner.start }.to raise_error(NoMethodError)
|
103
|
+
ARGV.replace %w[my_script:call_unexistent_method]
|
104
|
+
expect { Thor::Runner.start }.to raise_error(NoMethodError)
|
105
105
|
end
|
106
106
|
|
107
107
|
it "does not swallow Thor::Group InvocationError" do
|
108
|
-
ARGV.replace [
|
109
|
-
expect{ Thor::Runner.start }.to raise_error(ArgumentError, /thor wrong_arity takes 1 argument, but it should not/)
|
108
|
+
ARGV.replace %w[whiny_generator]
|
109
|
+
expect { Thor::Runner.start }.to raise_error(ArgumentError, /thor wrong_arity takes 1 argument, but it should not/)
|
110
110
|
end
|
111
111
|
|
112
112
|
it "does not swallow Thor InvocationError" do
|
113
|
-
ARGV.replace [
|
113
|
+
ARGV.replace %w[my_script:animal]
|
114
114
|
content = capture(:stderr) { Thor::Runner.start }
|
115
|
-
expect(content.strip).to eq(%Q
|
115
|
+
expect(content.strip).to eq(%Q(ERROR: "thor animal" was called with no arguments
|
116
|
+
Usage: "thor my_script:animal TYPE"))
|
116
117
|
end
|
117
118
|
end
|
118
119
|
|
@@ -123,68 +124,68 @@ describe Thor::Runner do
|
|
123
124
|
"random" => {
|
124
125
|
:location => @location,
|
125
126
|
:filename => "4a33b894ffce85d7b412fc1b36f88fe0",
|
126
|
-
:namespaces => [
|
127
|
+
:namespaces => %w[amazing]
|
127
128
|
}
|
128
129
|
}
|
129
130
|
|
130
131
|
root_file = File.join(Thor::Util.thor_root, "thor.yml")
|
131
132
|
|
132
133
|
# Stub load and save to avoid thor.yaml from being overwritten
|
133
|
-
YAML.
|
134
|
-
File.
|
135
|
-
File.
|
134
|
+
allow(YAML).to receive(:load_file).and_return(@original_yaml)
|
135
|
+
allow(File).to receive(:exist?).with(root_file).and_return(true)
|
136
|
+
allow(File).to receive(:open).with(root_file, "w")
|
136
137
|
end
|
137
138
|
|
138
139
|
describe "list" do
|
139
140
|
it "gives a list of the available commands" do
|
140
|
-
ARGV.replace [
|
141
|
+
ARGV.replace %w[list]
|
141
142
|
content = capture(:stdout) { Thor::Runner.start }
|
142
143
|
expect(content).to match(/amazing:describe NAME\s+# say that someone is amazing/m)
|
143
144
|
end
|
144
145
|
|
145
146
|
it "gives a list of the available Thor::Group classes" do
|
146
|
-
ARGV.replace [
|
147
|
+
ARGV.replace %w[list]
|
147
148
|
expect(capture(:stdout) { Thor::Runner.start }).to match(/my_counter N/)
|
148
149
|
end
|
149
150
|
|
150
151
|
it "can filter a list of the available commands by --group" do
|
151
|
-
ARGV.replace [
|
152
|
+
ARGV.replace %w[list --group standard]
|
152
153
|
expect(capture(:stdout) { Thor::Runner.start }).to match(/amazing:describe NAME/)
|
153
154
|
ARGV.replace []
|
154
155
|
expect(capture(:stdout) { Thor::Runner.start }).not_to match(/my_script:animal TYPE/)
|
155
|
-
ARGV.replace [
|
156
|
+
ARGV.replace %w[list --group script]
|
156
157
|
expect(capture(:stdout) { Thor::Runner.start }).to match(/my_script:animal TYPE/)
|
157
158
|
end
|
158
159
|
|
159
160
|
it "can skip all filters to show all commands using --all" do
|
160
|
-
ARGV.replace [
|
161
|
+
ARGV.replace %w[list --all]
|
161
162
|
content = capture(:stdout) { Thor::Runner.start }
|
162
163
|
expect(content).to match(/amazing:describe NAME/)
|
163
164
|
expect(content).to match(/my_script:animal TYPE/)
|
164
165
|
end
|
165
166
|
|
166
167
|
it "doesn't list superclass commands in the subclass" do
|
167
|
-
ARGV.replace [
|
168
|
+
ARGV.replace %w[list]
|
168
169
|
expect(capture(:stdout) { Thor::Runner.start }).not_to match(/amazing:help/)
|
169
170
|
end
|
170
171
|
|
171
172
|
it "presents commands in the default namespace with an empty namespace" do
|
172
|
-
ARGV.replace [
|
173
|
+
ARGV.replace %w[list]
|
173
174
|
expect(capture(:stdout) { Thor::Runner.start }).to match(/^thor :cow\s+# prints 'moo'/m)
|
174
175
|
end
|
175
176
|
|
176
177
|
it "runs commands with an empty namespace from the default namespace" do
|
177
|
-
ARGV.replace [
|
178
|
+
ARGV.replace %w[:command_conflict]
|
178
179
|
expect(capture(:stdout) { Thor::Runner.start }).to eq("command\n")
|
179
180
|
end
|
180
181
|
|
181
182
|
it "runs groups even when there is a command with the same name" do
|
182
|
-
ARGV.replace [
|
183
|
+
ARGV.replace %w[command_conflict]
|
183
184
|
expect(capture(:stdout) { Thor::Runner.start }).to eq("group\n")
|
184
185
|
end
|
185
186
|
|
186
187
|
it "runs commands with no colon in the default namespace" do
|
187
|
-
ARGV.replace [
|
188
|
+
ARGV.replace %w[cow]
|
188
189
|
expect(capture(:stdout) { Thor::Runner.start }).to eq("moo\n")
|
189
190
|
end
|
190
191
|
end
|
@@ -192,21 +193,21 @@ describe Thor::Runner do
|
|
192
193
|
describe "uninstall" do
|
193
194
|
before do
|
194
195
|
path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
|
195
|
-
FileUtils.
|
196
|
+
expect(FileUtils).to receive(:rm_rf).with(path)
|
196
197
|
end
|
197
198
|
|
198
199
|
it "uninstalls existing thor modules" do
|
199
|
-
silence(:stdout) { Thor::Runner.start([
|
200
|
+
silence(:stdout) { Thor::Runner.start(%w[uninstall random]) }
|
200
201
|
end
|
201
202
|
end
|
202
203
|
|
203
204
|
describe "installed" do
|
204
205
|
before do
|
205
|
-
Dir.
|
206
|
+
expect(Dir).to receive(:[]).and_return([])
|
206
207
|
end
|
207
208
|
|
208
209
|
it "displays the modules installed in a pretty way" do
|
209
|
-
stdout = capture(:stdout) { Thor::Runner.start([
|
210
|
+
stdout = capture(:stdout) { Thor::Runner.start(%w[installed]) }
|
210
211
|
expect(stdout).to match(/random\s*amazing/)
|
211
212
|
expect(stdout).to match(/amazing:describe NAME\s+# say that someone is amazing/m)
|
212
213
|
end
|
@@ -214,27 +215,31 @@ describe Thor::Runner do
|
|
214
215
|
|
215
216
|
describe "install/update" do
|
216
217
|
before do
|
217
|
-
FileUtils.
|
218
|
-
FileUtils.
|
219
|
-
|
218
|
+
allow(FileUtils).to receive(:mkdir_p)
|
219
|
+
allow(FileUtils).to receive(:touch)
|
220
|
+
allow(Thor::LineEditor).to receive(:readline).and_return("Y")
|
220
221
|
|
221
222
|
path = File.join(Thor::Util.thor_root, Digest::MD5.hexdigest(@location + "random"))
|
222
|
-
File.
|
223
|
+
expect(File).to receive(:open).with(path, "w")
|
223
224
|
end
|
224
225
|
|
225
226
|
it "updates existing thor files" do
|
226
227
|
path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
|
227
228
|
if File.directory? path
|
228
|
-
FileUtils.
|
229
|
+
expect(FileUtils).to receive(:rm_rf).with(path)
|
229
230
|
else
|
230
|
-
File.
|
231
|
+
expect(File).to receive(:delete).with(path)
|
232
|
+
end
|
233
|
+
silence_warnings do
|
234
|
+
silence(:stdout) { Thor::Runner.start(%w[update random]) }
|
231
235
|
end
|
232
|
-
silence(:stdout) { Thor::Runner.start(["update", "random"]) }
|
233
236
|
end
|
234
237
|
|
235
238
|
it "installs thor files" do
|
236
|
-
ARGV.replace [
|
237
|
-
|
239
|
+
ARGV.replace %W[install #{@location}]
|
240
|
+
silence_warnings do
|
241
|
+
silence(:stdout) { Thor::Runner.start }
|
242
|
+
end
|
238
243
|
end
|
239
244
|
end
|
240
245
|
end
|