thor-exclude_pattern 0.18.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/.document +5 -0
- data/CHANGELOG.md +130 -0
- data/LICENSE.md +20 -0
- data/README.md +34 -0
- data/Thorfile +30 -0
- data/bin/rake2thor +86 -0
- data/bin/thor +6 -0
- data/lib/thor.rb +458 -0
- data/lib/thor/actions.rb +318 -0
- data/lib/thor/actions/create_file.rb +105 -0
- data/lib/thor/actions/create_link.rb +60 -0
- data/lib/thor/actions/directory.rb +119 -0
- data/lib/thor/actions/empty_directory.rb +153 -0
- data/lib/thor/actions/file_manipulation.rb +314 -0
- data/lib/thor/actions/inject_into_file.rb +109 -0
- data/lib/thor/base.rb +649 -0
- data/lib/thor/command.rb +136 -0
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +80 -0
- data/lib/thor/core_ext/io_binary_read.rb +12 -0
- data/lib/thor/core_ext/ordered_hash.rb +100 -0
- data/lib/thor/error.rb +32 -0
- data/lib/thor/exclude_pattern/version.rb +5 -0
- data/lib/thor/group.rb +287 -0
- data/lib/thor/invocation.rb +172 -0
- data/lib/thor/parser.rb +4 -0
- data/lib/thor/parser/argument.rb +74 -0
- data/lib/thor/parser/arguments.rb +171 -0
- data/lib/thor/parser/option.rb +121 -0
- data/lib/thor/parser/options.rb +218 -0
- data/lib/thor/rake_compat.rb +72 -0
- data/lib/thor/runner.rb +322 -0
- data/lib/thor/shell.rb +88 -0
- data/lib/thor/shell/basic.rb +393 -0
- data/lib/thor/shell/color.rb +148 -0
- data/lib/thor/shell/html.rb +127 -0
- data/lib/thor/util.rb +270 -0
- data/lib/thor/version.rb +3 -0
- data/spec/actions/create_file_spec.rb +170 -0
- data/spec/actions/create_link_spec.rb +95 -0
- data/spec/actions/directory_spec.rb +169 -0
- data/spec/actions/empty_directory_spec.rb +130 -0
- data/spec/actions/file_manipulation_spec.rb +382 -0
- data/spec/actions/inject_into_file_spec.rb +135 -0
- data/spec/actions_spec.rb +331 -0
- data/spec/base_spec.rb +294 -0
- data/spec/command_spec.rb +80 -0
- data/spec/core_ext/hash_with_indifferent_access_spec.rb +48 -0
- data/spec/core_ext/ordered_hash_spec.rb +115 -0
- data/spec/exit_condition_spec.rb +19 -0
- data/spec/fixtures/application.rb +2 -0
- data/spec/fixtures/app{1}/README +3 -0
- data/spec/fixtures/bundle/execute.rb +6 -0
- data/spec/fixtures/bundle/main.thor +1 -0
- data/spec/fixtures/command.thor +10 -0
- data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
- data/spec/fixtures/doc/COMMENTER +11 -0
- data/spec/fixtures/doc/README +3 -0
- data/spec/fixtures/doc/block_helper.rb +3 -0
- data/spec/fixtures/doc/config.rb +1 -0
- data/spec/fixtures/doc/config.yaml.tt +1 -0
- data/spec/fixtures/doc/excluding/%file_name%.rb.tt +1 -0
- data/spec/fixtures/enum.thor +10 -0
- data/spec/fixtures/group.thor +128 -0
- data/spec/fixtures/invoke.thor +112 -0
- data/spec/fixtures/path with spaces b/data/spec/fixtures/path with → spaces +0 -0
- data/spec/fixtures/preserve/script.sh +3 -0
- data/spec/fixtures/script.thor +199 -0
- data/spec/fixtures/subcommand.thor +17 -0
- data/spec/group_spec.rb +216 -0
- data/spec/helper.rb +67 -0
- data/spec/invocation_spec.rb +100 -0
- data/spec/parser/argument_spec.rb +53 -0
- data/spec/parser/arguments_spec.rb +66 -0
- data/spec/parser/option_spec.rb +202 -0
- data/spec/parser/options_spec.rb +400 -0
- data/spec/rake_compat_spec.rb +72 -0
- data/spec/register_spec.rb +197 -0
- data/spec/runner_spec.rb +241 -0
- 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 +4 -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 +112 -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 +199 -0
- data/spec/sandbox/subcommand.thor +17 -0
- data/spec/shell/basic_spec.rb +311 -0
- data/spec/shell/color_spec.rb +95 -0
- data/spec/shell/html_spec.rb +32 -0
- data/spec/shell_spec.rb +47 -0
- data/spec/subcommand_spec.rb +30 -0
- data/spec/thor_spec.rb +469 -0
- data/spec/util_spec.rb +196 -0
- data/thor.gemspec +24 -0
- metadata +232 -0
@@ -0,0 +1,331 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Thor::Actions do
|
4
|
+
def runner(options={})
|
5
|
+
@runner ||= MyCounter.new([1], options, { :destination_root => destination_root })
|
6
|
+
end
|
7
|
+
|
8
|
+
def action(*args, &block)
|
9
|
+
capture(:stdout) { runner.send(*args, &block) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def file
|
13
|
+
File.join(destination_root, "foo")
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "on include" do
|
17
|
+
it "adds runtime options to the base class" do
|
18
|
+
expect(MyCounter.class_options.keys).to include(:pretend)
|
19
|
+
expect(MyCounter.class_options.keys).to include(:force)
|
20
|
+
expect(MyCounter.class_options.keys).to include(:quiet)
|
21
|
+
expect(MyCounter.class_options.keys).to include(:skip)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#initialize" do
|
26
|
+
it "has default behavior invoke" do
|
27
|
+
expect(runner.behavior).to eq(:invoke)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "can have behavior revoke" do
|
31
|
+
expect(MyCounter.new([1], {}, :behavior => :revoke).behavior).to eq(:revoke)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "when behavior is set to force, overwrite options" do
|
35
|
+
runner = MyCounter.new([1], { :force => false, :skip => true }, :behavior => :force)
|
36
|
+
expect(runner.behavior).to eq(:invoke)
|
37
|
+
expect(runner.options.force).to be_true
|
38
|
+
expect(runner.options.skip).not_to be_true
|
39
|
+
end
|
40
|
+
|
41
|
+
it "when behavior is set to skip, overwrite options" do
|
42
|
+
runner = MyCounter.new([1], ["--force"], :behavior => :skip)
|
43
|
+
expect(runner.behavior).to eq(:invoke)
|
44
|
+
expect(runner.options.force).not_to be_true
|
45
|
+
expect(runner.options.skip).to be_true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "accessors" do
|
50
|
+
describe "#destination_root=" do
|
51
|
+
it "gets the current directory and expands the path to set the root" do
|
52
|
+
base = MyCounter.new([1])
|
53
|
+
base.destination_root = "here"
|
54
|
+
expect(base.destination_root).to eq(File.expand_path(File.join(File.dirname(__FILE__), "..", "here")))
|
55
|
+
end
|
56
|
+
|
57
|
+
it "does not use the current directory if one is given" do
|
58
|
+
root = File.expand_path("/")
|
59
|
+
base = MyCounter.new([1])
|
60
|
+
base.destination_root = root
|
61
|
+
expect(base.destination_root).to eq(root)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "uses the current directory if none is given" do
|
65
|
+
base = MyCounter.new([1])
|
66
|
+
expect(base.destination_root).to eq(File.expand_path(File.join(File.dirname(__FILE__), "..")))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#relative_to_original_destination_root" do
|
71
|
+
it "returns the path relative to the absolute root" do
|
72
|
+
expect(runner.relative_to_original_destination_root(file)).to eq("foo")
|
73
|
+
end
|
74
|
+
|
75
|
+
it "does not remove dot if required" do
|
76
|
+
expect(runner.relative_to_original_destination_root(file, false)).to eq("./foo")
|
77
|
+
end
|
78
|
+
|
79
|
+
it "always use the absolute root" do
|
80
|
+
runner.inside("foo") do
|
81
|
+
expect(runner.relative_to_original_destination_root(file)).to eq("foo")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "creates proper relative paths for absolute file location" do
|
86
|
+
expect(runner.relative_to_original_destination_root('/test/file')).to eq("/test/file")
|
87
|
+
end
|
88
|
+
|
89
|
+
it "does not fail with files constaining regexp characters" do
|
90
|
+
runner = MyCounter.new([1], {}, { :destination_root => File.join(destination_root, "fo[o-b]ar") })
|
91
|
+
expect(runner.relative_to_original_destination_root("bar")).to eq("bar")
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "#source_paths_for_search" do
|
95
|
+
it "add source_root to source_paths_for_search" do
|
96
|
+
expect(MyCounter.source_paths_for_search).to include(File.expand_path("fixtures", File.dirname(__FILE__)))
|
97
|
+
end
|
98
|
+
|
99
|
+
it "keeps only current source root in source paths" do
|
100
|
+
expect(ClearCounter.source_paths_for_search).to include(File.expand_path("fixtures/bundle", File.dirname(__FILE__)))
|
101
|
+
expect(ClearCounter.source_paths_for_search).not_to include(File.expand_path("fixtures", File.dirname(__FILE__)))
|
102
|
+
end
|
103
|
+
|
104
|
+
it "customized source paths should be before source roots" do
|
105
|
+
expect(ClearCounter.source_paths_for_search[0]).to eq(File.expand_path("fixtures/doc", File.dirname(__FILE__)))
|
106
|
+
expect(ClearCounter.source_paths_for_search[1]).to eq(File.expand_path("fixtures/bundle", File.dirname(__FILE__)))
|
107
|
+
end
|
108
|
+
|
109
|
+
it "keeps inherited source paths at the end" do
|
110
|
+
expect(ClearCounter.source_paths_for_search.last).to eq(File.expand_path("fixtures/broken", File.dirname(__FILE__)))
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "#find_in_source_paths" do
|
116
|
+
it "raises an error if source path is empty" do
|
117
|
+
expect {
|
118
|
+
A.new.find_in_source_paths("foo")
|
119
|
+
}.to raise_error(Thor::Error, /Currently you have no source paths/)
|
120
|
+
end
|
121
|
+
|
122
|
+
it "finds a template inside the source path" do
|
123
|
+
expect(runner.find_in_source_paths("doc")).to eq(File.expand_path("doc", source_root))
|
124
|
+
expect{ runner.find_in_source_paths("README") }.to raise_error
|
125
|
+
|
126
|
+
new_path = File.join(source_root, "doc")
|
127
|
+
runner.instance_variable_set(:@source_paths, nil)
|
128
|
+
runner.source_paths.unshift(new_path)
|
129
|
+
expect(runner.find_in_source_paths("README")).to eq(File.expand_path("README", new_path))
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "#inside" do
|
135
|
+
it "executes the block inside the given folder" do
|
136
|
+
runner.inside("foo") do
|
137
|
+
expect(Dir.pwd).to eq(file)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
it "changes the base root" do
|
142
|
+
runner.inside("foo") do
|
143
|
+
expect(runner.destination_root).to eq(file)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
it "creates the directory if it does not exist" do
|
148
|
+
runner.inside("foo") do
|
149
|
+
expect(File.exists?(file)).to be_true
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "when pretending" do
|
154
|
+
it "no directories should be created" do
|
155
|
+
runner.inside("bar", :pretend => true) {}
|
156
|
+
expect(File.exists?("bar")).to be_false
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
describe "when verbose" do
|
161
|
+
it "logs status" do
|
162
|
+
expect(capture(:stdout) {
|
163
|
+
runner.inside("foo", :verbose => true) {}
|
164
|
+
}).to match(/inside foo/)
|
165
|
+
end
|
166
|
+
|
167
|
+
it "uses padding in next status" do
|
168
|
+
expect(capture(:stdout) {
|
169
|
+
runner.inside("foo", :verbose => true) do
|
170
|
+
runner.say_status :cool, :padding
|
171
|
+
end
|
172
|
+
}).to match(/cool padding/)
|
173
|
+
end
|
174
|
+
|
175
|
+
it "removes padding after block" do
|
176
|
+
expect(capture(:stdout) {
|
177
|
+
runner.inside("foo", :verbose => true) {}
|
178
|
+
runner.say_status :no, :padding
|
179
|
+
}).to match(/no padding/)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "#in_root" do
|
185
|
+
it "executes the block in the root folder" do
|
186
|
+
runner.inside("foo") do
|
187
|
+
runner.in_root { expect(Dir.pwd).to eq(destination_root) }
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
it "changes the base root" do
|
192
|
+
runner.inside("foo") do
|
193
|
+
runner.in_root { expect(runner.destination_root).to eq(destination_root) }
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
it "returns to the previous state" do
|
198
|
+
runner.inside("foo") do
|
199
|
+
runner.in_root { }
|
200
|
+
expect(runner.destination_root).to eq(file)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "#apply" do
|
206
|
+
before do
|
207
|
+
@template = <<-TEMPLATE
|
208
|
+
@foo = "FOO"
|
209
|
+
say_status :cool, :padding
|
210
|
+
TEMPLATE
|
211
|
+
@template.stub(:read).and_return(@template)
|
212
|
+
|
213
|
+
@file = '/'
|
214
|
+
runner.stub(:open).and_return(@template)
|
215
|
+
end
|
216
|
+
|
217
|
+
it "accepts a URL as the path" do
|
218
|
+
@file = "http://gist.github.com/103208.txt"
|
219
|
+
runner.should_receive(:open).with(@file, "Accept" => "application/x-thor-template").and_return(@template)
|
220
|
+
action(:apply, @file)
|
221
|
+
end
|
222
|
+
|
223
|
+
it "accepts a secure URL as the path" do
|
224
|
+
@file = "https://gist.github.com/103208.txt"
|
225
|
+
runner.should_receive(:open).with(@file, "Accept" => "application/x-thor-template").and_return(@template)
|
226
|
+
action(:apply, @file)
|
227
|
+
end
|
228
|
+
|
229
|
+
it "accepts a local file path with spaces" do
|
230
|
+
@file = File.expand_path("fixtures/path with spaces", File.dirname(__FILE__))
|
231
|
+
runner.should_receive(:open).with(@file).and_return(@template)
|
232
|
+
action(:apply, @file)
|
233
|
+
end
|
234
|
+
|
235
|
+
it "opens a file and executes its content in the instance binding" do
|
236
|
+
action :apply, @file
|
237
|
+
expect(runner.instance_variable_get("@foo")).to eq("FOO")
|
238
|
+
end
|
239
|
+
|
240
|
+
it "applies padding to the content inside the file" do
|
241
|
+
expect(action(:apply, @file)).to match(/cool padding/)
|
242
|
+
end
|
243
|
+
|
244
|
+
it "logs its status" do
|
245
|
+
expect(action(:apply, @file)).to match(/ apply #{@file}\n/)
|
246
|
+
end
|
247
|
+
|
248
|
+
it "does not log status" do
|
249
|
+
content = action(:apply, @file, :verbose => false)
|
250
|
+
expect(content).to match(/cool padding/)
|
251
|
+
expect(content).not_to match(/apply http/)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
describe "#run" do
|
256
|
+
before do
|
257
|
+
runner.should_receive(:system).with("ls")
|
258
|
+
end
|
259
|
+
|
260
|
+
it "executes the command given" do
|
261
|
+
action :run, "ls"
|
262
|
+
end
|
263
|
+
|
264
|
+
it "logs status" do
|
265
|
+
expect(action(:run, "ls")).to eq(" run ls from \".\"\n")
|
266
|
+
end
|
267
|
+
|
268
|
+
it "does not log status if required" do
|
269
|
+
expect(action(:run, "ls", :verbose => false)).to be_empty
|
270
|
+
end
|
271
|
+
|
272
|
+
it "accepts a color as status" do
|
273
|
+
runner.shell.should_receive(:say_status).with(:run, 'ls from "."', :yellow)
|
274
|
+
action :run, "ls", :verbose => :yellow
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
describe "#run_ruby_script" do
|
279
|
+
before do
|
280
|
+
Thor::Util.stub!(:ruby_command).and_return("/opt/jruby")
|
281
|
+
runner.should_receive(:system).with("/opt/jruby script.rb")
|
282
|
+
end
|
283
|
+
|
284
|
+
it "executes the ruby script" do
|
285
|
+
action :run_ruby_script, "script.rb"
|
286
|
+
end
|
287
|
+
|
288
|
+
it "logs status" do
|
289
|
+
expect(action(:run_ruby_script, "script.rb")).to eq(" run jruby script.rb from \".\"\n")
|
290
|
+
end
|
291
|
+
|
292
|
+
it "does not log status if required" do
|
293
|
+
expect(action(:run_ruby_script, "script.rb", :verbose => false)).to be_empty
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
describe "#thor" do
|
298
|
+
it "executes the thor command" do
|
299
|
+
runner.should_receive(:system).with("thor list")
|
300
|
+
action :thor, :list, :verbose => true
|
301
|
+
end
|
302
|
+
|
303
|
+
it "converts extra arguments to command arguments" do
|
304
|
+
runner.should_receive(:system).with("thor list foo bar")
|
305
|
+
action :thor, :list, "foo", "bar"
|
306
|
+
end
|
307
|
+
|
308
|
+
it "converts options hash to switches" do
|
309
|
+
runner.should_receive(:system).with("thor list foo bar --foo")
|
310
|
+
action :thor, :list, "foo", "bar", :foo => true
|
311
|
+
|
312
|
+
runner.should_receive(:system).with("thor list --foo 1 2 3")
|
313
|
+
action :thor, :list, :foo => [1,2,3]
|
314
|
+
end
|
315
|
+
|
316
|
+
it "logs status" do
|
317
|
+
runner.should_receive(:system).with("thor list")
|
318
|
+
expect(action(:thor, :list)).to eq(" run thor list from \".\"\n")
|
319
|
+
end
|
320
|
+
|
321
|
+
it "does not log status if required" do
|
322
|
+
runner.should_receive(:system).with("thor list --foo 1 2 3")
|
323
|
+
expect(action(:thor, :list, :foo => [1,2,3], :verbose => false)).to be_empty
|
324
|
+
end
|
325
|
+
|
326
|
+
it "captures the output when :capture is given" do
|
327
|
+
runner.should_receive(:`).with("thor foo bar")
|
328
|
+
action(:thor, "foo", "bar", :capture => true)
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,294 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'thor/base'
|
3
|
+
|
4
|
+
class Amazing
|
5
|
+
desc "hello", "say hello"
|
6
|
+
def hello
|
7
|
+
puts "Hello"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Thor::Base do
|
12
|
+
describe "#initialize" do
|
13
|
+
it "sets arguments array" do
|
14
|
+
base = MyCounter.new [1, 2]
|
15
|
+
expect(base.first).to eq(1)
|
16
|
+
expect(base.second).to eq(2)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "sets arguments default values" do
|
20
|
+
base = MyCounter.new [1]
|
21
|
+
expect(base.second).to eq(2)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "sets options default values" do
|
25
|
+
base = MyCounter.new [1, 2]
|
26
|
+
expect(base.options[:third]).to eq(3)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "allows options to be given as symbols or strings" do
|
30
|
+
base = MyCounter.new [1, 2], :third => 4
|
31
|
+
expect(base.options[:third]).to eq(4)
|
32
|
+
|
33
|
+
base = MyCounter.new [1, 2], "third" => 4
|
34
|
+
expect(base.options[:third]).to eq(4)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "creates options with indifferent access" do
|
38
|
+
base = MyCounter.new [1, 2], :third => 3
|
39
|
+
expect(base.options['third']).to eq(3)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "creates options with magic predicates" do
|
43
|
+
base = MyCounter.new [1, 2], :third => 3
|
44
|
+
expect(base.options.third).to eq(3)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#no_commands" do
|
49
|
+
it "avoids methods being added as commands" do
|
50
|
+
expect(MyScript.commands.keys).to include("animal")
|
51
|
+
expect(MyScript.commands.keys).not_to include("this_is_not_a_command")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#argument" do
|
56
|
+
it "sets a value as required and creates an accessor for it" do
|
57
|
+
expect(MyCounter.start(["1", "2", "--third", "3"])[0]).to eq(1)
|
58
|
+
expect(Scripts::MyScript.start(["zoo", "my_special_param", "--param=normal_param"])).to eq("my_special_param")
|
59
|
+
end
|
60
|
+
|
61
|
+
it "does not set a value in the options hash" do
|
62
|
+
expect(BrokenCounter.start(["1", "2", "--third", "3"])[0]).to be_nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#arguments" do
|
67
|
+
it "returns the arguments for the class" do
|
68
|
+
expect(MyCounter.arguments).to have(2).items
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe ":aliases" do
|
73
|
+
it "supports string aliases without a dash prefix" do
|
74
|
+
expect(MyCounter.start(["1", "2", "-z", "3"])[4]).to eq(3)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "supports symbol aliases" do
|
78
|
+
expect(MyCounter.start(["1", "2", "-y", "3"])[5]).to eq(3)
|
79
|
+
expect(MyCounter.start(["1", "2", "-r", "3"])[5]).to eq(3)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "#class_option" do
|
84
|
+
it "sets options class wise" do
|
85
|
+
expect(MyCounter.start(["1", "2", "--third", "3"])[2]).to eq(3)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "does not create an accessor for it" do
|
89
|
+
expect(BrokenCounter.start(["1", "2", "--third", "3"])[3]).to be_false
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#class_options" do
|
94
|
+
it "sets default options overwriting superclass definitions" do
|
95
|
+
options = Scripts::MyScript.class_options
|
96
|
+
expect(options[:force]).not_to be_required
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "#remove_argument" do
|
101
|
+
it "removes previous defined arguments from class" do
|
102
|
+
expect(ClearCounter.arguments).to be_empty
|
103
|
+
end
|
104
|
+
|
105
|
+
it "undefine accessors if required" do
|
106
|
+
expect(ClearCounter.new).not_to respond_to(:first)
|
107
|
+
expect(ClearCounter.new).not_to respond_to(:second)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "#remove_class_option" do
|
112
|
+
it "removes previous defined class option" do
|
113
|
+
expect(ClearCounter.class_options[:third]).to be_nil
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#class_options_help" do
|
118
|
+
before do
|
119
|
+
@content = capture(:stdout) { MyCounter.help(Thor::Base.shell.new) }
|
120
|
+
end
|
121
|
+
|
122
|
+
it "shows options description" do
|
123
|
+
expect(@content).to match(/# The third argument/)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "shows usage with banner content" do
|
127
|
+
expect(@content).to match(/\[\-\-third=THREE\]/)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "shows default values below description" do
|
131
|
+
expect(@content).to match(/# Default: 3/)
|
132
|
+
end
|
133
|
+
|
134
|
+
it "shows options in different groups" do
|
135
|
+
expect(@content).to match(/Options\:/)
|
136
|
+
expect(@content).to match(/Runtime options\:/)
|
137
|
+
expect(@content).to match(/\-p, \[\-\-pretend\]/)
|
138
|
+
end
|
139
|
+
|
140
|
+
it "use padding in options that does not have aliases" do
|
141
|
+
expect(@content).to match(/^ -t, \[--third/)
|
142
|
+
expect(@content).to match(/^ \[--fourth/)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "allows extra options to be given" do
|
146
|
+
hash = { "Foo" => B.class_options.values }
|
147
|
+
|
148
|
+
content = capture(:stdout) { MyCounter.send(:class_options_help, Thor::Base.shell.new, hash) }
|
149
|
+
expect(content).to match(/Foo options\:/)
|
150
|
+
expect(content).to match(/--last-name=LAST_NAME/)
|
151
|
+
end
|
152
|
+
|
153
|
+
it "displays choices for enums" do
|
154
|
+
content = capture(:stdout) { Enum.help(Thor::Base.shell.new) }
|
155
|
+
expect(content).to match(/Possible values\: apple, banana/)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "#namespace" do
|
160
|
+
it "returns the default class namespace" do
|
161
|
+
expect(Scripts::MyScript.namespace).to eq("scripts:my_script")
|
162
|
+
end
|
163
|
+
|
164
|
+
it "sets a namespace to the class" do
|
165
|
+
expect(Scripts::MyDefaults.namespace).to eq("default")
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "#group" do
|
170
|
+
it "sets a group" do
|
171
|
+
expect(MyScript.group).to eq("script")
|
172
|
+
end
|
173
|
+
|
174
|
+
it "inherits the group from parent" do
|
175
|
+
expect(MyChildScript.group).to eq("script")
|
176
|
+
end
|
177
|
+
|
178
|
+
it "defaults to standard if no group is given" do
|
179
|
+
expect(Amazing.group).to eq("standard")
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "#subclasses" do
|
184
|
+
it "tracks its subclasses in an Array" do
|
185
|
+
expect(Thor::Base.subclasses).to include(MyScript)
|
186
|
+
expect(Thor::Base.subclasses).to include(MyChildScript)
|
187
|
+
expect(Thor::Base.subclasses).to include(Scripts::MyScript)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
describe "#subclass_files" do
|
192
|
+
it "returns tracked subclasses, grouped by the files they come from" do
|
193
|
+
thorfile = File.join(File.dirname(__FILE__), "fixtures", "script.thor")
|
194
|
+
expect(Thor::Base.subclass_files[File.expand_path(thorfile)]).to eq([
|
195
|
+
MyScript, MyScript::AnotherScript, MyChildScript, Barn,
|
196
|
+
Scripts::MyScript, Scripts::MyDefaults, Scripts::ChildDefault
|
197
|
+
])
|
198
|
+
end
|
199
|
+
|
200
|
+
it "tracks a single subclass across multiple files" do
|
201
|
+
thorfile = File.join(File.dirname(__FILE__), "fixtures", "command.thor")
|
202
|
+
expect(Thor::Base.subclass_files[File.expand_path(thorfile)]).to include(Amazing)
|
203
|
+
expect(Thor::Base.subclass_files[File.expand_path(__FILE__)]).to include(Amazing)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "#commands" do
|
208
|
+
it "returns a list with all commands defined in this class" do
|
209
|
+
expect(MyChildScript.new).to respond_to("animal")
|
210
|
+
expect(MyChildScript.commands.keys).to include("animal")
|
211
|
+
end
|
212
|
+
|
213
|
+
it "raises an error if a command with reserved word is defined" do
|
214
|
+
expect {
|
215
|
+
klass = Class.new(Thor::Group)
|
216
|
+
klass.class_eval "def shell; end"
|
217
|
+
}.to raise_error(RuntimeError, /"shell" is a Thor reserved word and cannot be defined as command/)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
describe "#all_commands" do
|
222
|
+
it "returns a list with all commands defined in this class plus superclasses" do
|
223
|
+
expect(MyChildScript.new).to respond_to("foo")
|
224
|
+
expect(MyChildScript.all_commands.keys).to include("foo")
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe "#remove_command" do
|
229
|
+
it "removes the command from its commands hash" do
|
230
|
+
expect(MyChildScript.commands.keys).not_to include("bar")
|
231
|
+
expect(MyChildScript.commands.keys).not_to include("boom")
|
232
|
+
end
|
233
|
+
|
234
|
+
it "undefines the method if desired" do
|
235
|
+
expect(MyChildScript.new).not_to respond_to("boom")
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe "#from_superclass" do
|
240
|
+
it "does not send a method to the superclass if the superclass does not respond to it" do
|
241
|
+
expect(MyCounter.get_from_super).to eq(13)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
describe "#start" do
|
246
|
+
it "raises an error instead of rescueing if THOR_DEBUG=1 is given" do
|
247
|
+
begin
|
248
|
+
ENV["THOR_DEBUG"] = 1
|
249
|
+
expect {
|
250
|
+
MyScript.start ["what", "--debug"]
|
251
|
+
}.to raise_error(Thor::UndefinedcommandError, 'Could not find command "what" in "my_script" namespace.')
|
252
|
+
rescue
|
253
|
+
ENV["THOR_DEBUG"] = nil
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
it "does not steal args" do
|
258
|
+
args = ["foo", "bar", "--force", "true"]
|
259
|
+
MyScript.start(args)
|
260
|
+
expect(args).to eq(["foo", "bar", "--force", "true"])
|
261
|
+
end
|
262
|
+
|
263
|
+
it "checks unknown options" do
|
264
|
+
expect(capture(:stderr) {
|
265
|
+
MyScript.start(["foo", "bar", "--force", "true", "--unknown", "baz"])
|
266
|
+
}.strip).to eq("Unknown switches '--unknown'")
|
267
|
+
end
|
268
|
+
|
269
|
+
it "checks unknown options except specified" do
|
270
|
+
expect(capture(:stderr) {
|
271
|
+
expect(MyScript.start(["with_optional", "NAME", "--omg", "--invalid"])).to eq(["NAME", {}, ["--omg", "--invalid"]])
|
272
|
+
}.strip).to be_empty
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
describe "attr_*" do
|
277
|
+
it "does not add attr_reader as a command" do
|
278
|
+
expect(capture(:stderr){ MyScript.start(["another_attribute"]) }).to match(/Could not find/)
|
279
|
+
end
|
280
|
+
|
281
|
+
it "does not add attr_writer as a command" do
|
282
|
+
expect(capture(:stderr){ MyScript.start(["another_attribute=", "foo"]) }).to match(/Could not find/)
|
283
|
+
end
|
284
|
+
|
285
|
+
it "does not add attr_accessor as a command" do
|
286
|
+
expect(capture(:stderr){ MyScript.start(["some_attribute"]) }).to match(/Could not find/)
|
287
|
+
expect(capture(:stderr){ MyScript.start(["some_attribute=", "foo"]) }).to match(/Could not find/)
|
288
|
+
end
|
289
|
+
|
290
|
+
it "respects visibility" do
|
291
|
+
expect(MyScript.public_instance_methods).to_not include(:private_attribute)
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|