thor 0.16.0 → 0.17.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/.travis.yml +2 -1
- data/CHANGELOG.rdoc +8 -0
- data/Gemfile +12 -8
- data/lib/thor.rb +79 -10
- data/lib/thor/actions.rb +13 -13
- data/lib/thor/actions/directory.rb +29 -10
- data/lib/thor/actions/file_manipulation.rb +8 -2
- data/lib/thor/base.rb +24 -11
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +5 -0
- data/lib/thor/group.rb +5 -5
- data/lib/thor/parser/options.rb +63 -25
- data/lib/thor/rake_compat.rb +3 -2
- data/lib/thor/runner.rb +1 -1
- data/lib/thor/shell/basic.rb +16 -16
- data/lib/thor/shell/color.rb +9 -9
- data/lib/thor/shell/html.rb +9 -9
- data/lib/thor/task.rb +2 -2
- data/lib/thor/version.rb +1 -1
- data/spec/actions/create_file_spec.rb +30 -30
- data/spec/actions/create_link_spec.rb +12 -12
- data/spec/actions/directory_spec.rb +34 -27
- data/spec/actions/empty_directory_spec.rb +16 -16
- data/spec/actions/file_manipulation_spec.rb +62 -50
- data/spec/actions/inject_into_file_spec.rb +18 -18
- data/spec/actions_spec.rb +56 -56
- data/spec/base_spec.rb +69 -69
- data/spec/core_ext/hash_with_indifferent_access_spec.rb +19 -14
- data/spec/core_ext/ordered_hash_spec.rb +29 -29
- data/spec/exit_condition_spec.rb +3 -3
- data/spec/fixtures/preserve/script.sh +3 -0
- data/spec/fixtures/script.thor +5 -0
- data/spec/group_spec.rb +55 -55
- data/spec/invocation_spec.rb +26 -26
- data/spec/parser/argument_spec.rb +12 -12
- data/spec/parser/arguments_spec.rb +12 -12
- data/spec/parser/option_spec.rb +47 -47
- data/spec/parser/options_spec.rb +137 -72
- data/spec/rake_compat_spec.rb +11 -11
- data/spec/register_spec.rb +70 -8
- data/spec/runner_spec.rb +38 -38
- data/spec/shell/basic_spec.rb +49 -37
- data/spec/shell/color_spec.rb +13 -13
- data/spec/shell/html_spec.rb +3 -3
- data/spec/shell_spec.rb +7 -7
- data/spec/spec_helper.rb +4 -0
- data/spec/task_spec.rb +11 -11
- data/spec/thor_spec.rb +161 -91
- data/spec/util_spec.rb +42 -42
- data/thor.gemspec +1 -7
- metadata +8 -118
- data/lib/thor/core_ext/dir_escape.rb +0 -0
data/spec/shell/color_spec.rb
CHANGED
@@ -11,7 +11,7 @@ describe Thor::Shell::Color do
|
|
11
11
|
shell.say "Wow! Now we have colors!", :green
|
12
12
|
end
|
13
13
|
|
14
|
-
out.chomp.
|
14
|
+
expect(out.chomp).to eq("\e[32mWow! Now we have colors!\e[0m")
|
15
15
|
end
|
16
16
|
|
17
17
|
it "does not use a new line even with colors" do
|
@@ -19,7 +19,7 @@ describe Thor::Shell::Color do
|
|
19
19
|
shell.say "Wow! Now we have colors! ", :green
|
20
20
|
end
|
21
21
|
|
22
|
-
out.chomp.
|
22
|
+
expect(out.chomp).to eq("\e[32mWow! Now we have colors! \e[0m")
|
23
23
|
end
|
24
24
|
|
25
25
|
it "handles an Array of colors" do
|
@@ -27,7 +27,7 @@ describe Thor::Shell::Color do
|
|
27
27
|
shell.say "Wow! Now we have colors *and* background colors", [:green, :on_red, :bold]
|
28
28
|
end
|
29
29
|
|
30
|
-
out.chomp.
|
30
|
+
expect(out.chomp).to eq("\e[32m\e[41m\e[1mWow! Now we have colors *and* background colors\e[0m")
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -37,30 +37,30 @@ describe Thor::Shell::Color do
|
|
37
37
|
shell.say_status :conflict, "README", :red
|
38
38
|
end
|
39
39
|
|
40
|
-
out.chomp.
|
40
|
+
expect(out.chomp).to eq("\e[1m\e[31m conflict\e[0m README")
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
44
|
describe "#set_color" do
|
45
45
|
it "colors a string with a foreground color" do
|
46
46
|
red = shell.set_color "hi!", :red
|
47
|
-
red.
|
47
|
+
expect(red).to eq("\e[31mhi!\e[0m")
|
48
48
|
end
|
49
49
|
|
50
50
|
it "colors a string with a background color" do
|
51
51
|
on_red = shell.set_color "hi!", :white, :on_red
|
52
|
-
on_red.
|
52
|
+
expect(on_red).to eq("\e[37m\e[41mhi!\e[0m")
|
53
53
|
end
|
54
54
|
|
55
55
|
it "colors a string with a bold color" do
|
56
56
|
bold = shell.set_color "hi!", :white, true
|
57
|
-
bold.
|
57
|
+
expect(bold).to eq("\e[1m\e[37mhi!\e[0m")
|
58
58
|
|
59
59
|
bold = shell.set_color "hi!", :white, :bold
|
60
|
-
bold.
|
60
|
+
expect(bold).to eq("\e[37m\e[1mhi!\e[0m")
|
61
61
|
|
62
62
|
bold = shell.set_color "hi!", :white, :on_red, :bold
|
63
|
-
bold.
|
63
|
+
expect(bold).to eq("\e[37m\e[41m\e[1mhi!\e[0m")
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
@@ -71,10 +71,10 @@ describe Thor::Shell::Color do
|
|
71
71
|
$stdin.should_receive(:gets).and_return('d')
|
72
72
|
$stdin.should_receive(:gets).and_return('n')
|
73
73
|
|
74
|
-
output = capture(:stdout){ shell.file_collision('spec/fixtures/doc/README'){ "README\nEND\n" } }
|
75
|
-
output.
|
76
|
-
output.
|
77
|
-
output.
|
74
|
+
output = capture(:stdout) { shell.file_collision('spec/fixtures/doc/README'){ "README\nEND\n" } }
|
75
|
+
expect(output).to match(/\e\[31m\- __start__\e\[0m/)
|
76
|
+
expect(output).to match(/^ README/)
|
77
|
+
expect(output).to match(/\e\[32m\+ END\e\[0m/)
|
78
78
|
end
|
79
79
|
end
|
80
80
|
end
|
data/spec/shell/html_spec.rb
CHANGED
@@ -8,17 +8,17 @@ describe Thor::Shell::HTML do
|
|
8
8
|
describe "#say" do
|
9
9
|
it "set the color if specified" do
|
10
10
|
out = capture(:stdout) { shell.say "Wow! Now we have colors!", :green }
|
11
|
-
out.chomp.
|
11
|
+
expect(out.chomp).to eq('<span style="color: green;">Wow! Now we have colors!</span>')
|
12
12
|
end
|
13
13
|
|
14
14
|
it "sets bold if specified" do
|
15
15
|
out = capture(:stdout) { shell.say "Wow! Now we have colors *and* bold!", [:green, :bold] }
|
16
|
-
out.chomp.
|
16
|
+
expect(out.chomp).to eq('<span style="color: green; font-weight: bold;">Wow! Now we have colors *and* bold!</span>')
|
17
17
|
end
|
18
18
|
|
19
19
|
it "does not use a new line even with colors" do
|
20
20
|
out = capture(:stdout) { shell.say "Wow! Now we have colors! ", :green }
|
21
|
-
out.chomp.
|
21
|
+
expect(out.chomp).to eq('<span style="color: green;">Wow! Now we have colors! </span>')
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
data/spec/shell_spec.rb
CHANGED
@@ -8,30 +8,30 @@ describe Thor::Shell do
|
|
8
8
|
describe "#initialize" do
|
9
9
|
it "sets shell value" do
|
10
10
|
base = MyCounter.new [1, 2], { }, :shell => shell
|
11
|
-
base.shell.
|
11
|
+
expect(base.shell).to eq(shell)
|
12
12
|
end
|
13
13
|
|
14
14
|
it "sets the base value on the shell if an accessor is available" do
|
15
15
|
base = MyCounter.new [1, 2], { }, :shell => shell
|
16
|
-
shell.base.
|
16
|
+
expect(shell.base).to eq(base)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
describe "#shell" do
|
21
21
|
it "returns the shell in use" do
|
22
|
-
MyCounter.new([1,2]).shell.
|
22
|
+
expect(MyCounter.new([1,2]).shell).to be_kind_of(Thor::Base.shell)
|
23
23
|
end
|
24
24
|
|
25
25
|
it "uses $THOR_SHELL" do
|
26
26
|
class Thor::Shell::TestShell < Thor::Shell::Basic; end
|
27
27
|
|
28
|
-
Thor::Base.shell.
|
28
|
+
expect(Thor::Base.shell).to eq(shell.class)
|
29
29
|
ENV['THOR_SHELL'] = 'TestShell'
|
30
30
|
Thor::Base.shell = nil
|
31
|
-
Thor::Base.shell.
|
31
|
+
expect(Thor::Base.shell).to eq(Thor::Shell::TestShell)
|
32
32
|
ENV['THOR_SHELL'] = ''
|
33
33
|
Thor::Base.shell = shell.class
|
34
|
-
Thor::Base.shell.
|
34
|
+
expect(Thor::Base.shell).to eq(shell.class)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -39,7 +39,7 @@ describe Thor::Shell do
|
|
39
39
|
it "uses padding for inside block outputs" do
|
40
40
|
base = MyCounter.new([1,2])
|
41
41
|
base.with_padding do
|
42
|
-
capture(:stdout){ base.say_status :padding, "cool" }.strip.
|
42
|
+
expect(capture(:stdout) { base.say_status :padding, "cool" }.strip).to eq("padding cool")
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/task_spec.rb
CHANGED
@@ -12,32 +12,32 @@ describe Thor::Task do
|
|
12
12
|
describe "#formatted_usage" do
|
13
13
|
it "includes namespace within usage" do
|
14
14
|
object = Struct.new(:namespace, :arguments).new("foo", [])
|
15
|
-
task(:bar => :required).formatted_usage(object).
|
15
|
+
expect(task(:bar => :required).formatted_usage(object)).to eq("foo:can_has --bar=BAR")
|
16
16
|
end
|
17
17
|
|
18
18
|
it "includes subcommand name within subcommand usage" do
|
19
19
|
object = Struct.new(:namespace, :arguments).new("main:foo", [])
|
20
|
-
task(:bar => :required).formatted_usage(object, false, true).
|
20
|
+
expect(task(:bar => :required).formatted_usage(object, false, true)).to eq("foo can_has --bar=BAR")
|
21
21
|
end
|
22
22
|
|
23
23
|
it "removes default from namespace" do
|
24
24
|
object = Struct.new(:namespace, :arguments).new("default:foo", [])
|
25
|
-
task(:bar => :required).formatted_usage(object).
|
25
|
+
expect(task(:bar => :required).formatted_usage(object)).to eq(":foo:can_has --bar=BAR")
|
26
26
|
end
|
27
27
|
|
28
28
|
it "injects arguments into usage" do
|
29
29
|
options = {:required => true, :type => :string}
|
30
30
|
object = Struct.new(:namespace, :arguments).new("foo", [Thor::Argument.new(:bar, options)])
|
31
|
-
task(:foo => :required).formatted_usage(object).
|
31
|
+
expect(task(:foo => :required).formatted_usage(object)).to eq("foo:can_has BAR --foo=FOO")
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
describe "#dynamic" do
|
36
36
|
it "creates a dynamic task with the given name" do
|
37
|
-
Thor::DynamicTask.new('task').name.
|
38
|
-
Thor::DynamicTask.new('task').description.
|
39
|
-
Thor::DynamicTask.new('task').usage.
|
40
|
-
Thor::DynamicTask.new('task').options.
|
37
|
+
expect(Thor::DynamicTask.new('task').name).to eq('task')
|
38
|
+
expect(Thor::DynamicTask.new('task').description).to eq('A dynamically-generated task')
|
39
|
+
expect(Thor::DynamicTask.new('task').usage).to eq('task')
|
40
|
+
expect(Thor::DynamicTask.new('task').options).to eq({})
|
41
41
|
end
|
42
42
|
|
43
43
|
it "does not invoke an existing method" do
|
@@ -51,7 +51,7 @@ describe Thor::Task do
|
|
51
51
|
it "dup options hash" do
|
52
52
|
task = Thor::Task.new("can_has", nil, nil, nil, :foo => true, :bar => :required)
|
53
53
|
task.dup.options.delete(:foo)
|
54
|
-
task.options[:foo].
|
54
|
+
expect(task.options[:foo]).to be
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
@@ -59,7 +59,7 @@ describe Thor::Task do
|
|
59
59
|
it "runs a task by calling a method in the given instance" do
|
60
60
|
mock = mock()
|
61
61
|
mock.should_receive(:can_has).and_return {|*args| args }
|
62
|
-
task.run(mock, [1, 2, 3]).
|
62
|
+
expect(task.run(mock, [1, 2, 3])).to eq([1, 2, 3])
|
63
63
|
end
|
64
64
|
|
65
65
|
it "raises an error if the method to be invoked is private" do
|
@@ -74,7 +74,7 @@ describe Thor::Task do
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
task.run(klass.new).
|
77
|
+
expect(task.run(klass.new)).to eq("can_has")
|
78
78
|
end
|
79
79
|
end
|
80
80
|
end
|
data/spec/thor_spec.rb
CHANGED
@@ -5,67 +5,67 @@ describe Thor do
|
|
5
5
|
it "sets options to the next method to be invoked" do
|
6
6
|
args = ["foo", "bar", "--force"]
|
7
7
|
arg, options = MyScript.start(args)
|
8
|
-
options.
|
8
|
+
expect(options).to eq({ "force" => true })
|
9
9
|
end
|
10
10
|
|
11
11
|
describe ":lazy_default" do
|
12
12
|
it "is absent when option is not specified" do
|
13
13
|
arg, options = MyScript.start(["with_optional"])
|
14
|
-
options.
|
14
|
+
expect(options).to eq({})
|
15
15
|
end
|
16
16
|
|
17
17
|
it "sets a default that can be overridden for strings" do
|
18
18
|
arg, options = MyScript.start(["with_optional", "--lazy"])
|
19
|
-
options.
|
19
|
+
expect(options).to eq({ "lazy" => "yes" })
|
20
20
|
|
21
21
|
arg, options = MyScript.start(["with_optional", "--lazy", "yesyes!"])
|
22
|
-
options.
|
22
|
+
expect(options).to eq({ "lazy" => "yesyes!" })
|
23
23
|
end
|
24
24
|
|
25
25
|
it "sets a default that can be overridden for numerics" do
|
26
26
|
arg, options = MyScript.start(["with_optional", "--lazy-numeric"])
|
27
|
-
options.
|
27
|
+
expect(options).to eq({ "lazy_numeric" => 42 })
|
28
28
|
|
29
29
|
arg, options = MyScript.start(["with_optional", "--lazy-numeric", 20000])
|
30
|
-
options.
|
30
|
+
expect(options).to eq({ "lazy_numeric" => 20000 })
|
31
31
|
end
|
32
32
|
|
33
33
|
it "sets a default that can be overridden for arrays" do
|
34
34
|
arg, options = MyScript.start(["with_optional", "--lazy-array"])
|
35
|
-
options.
|
35
|
+
expect(options).to eq({ "lazy_array" => %w[eat at joes] })
|
36
36
|
|
37
37
|
arg, options = MyScript.start(["with_optional", "--lazy-array", "hello", "there"])
|
38
|
-
options.
|
38
|
+
expect(options).to eq({ "lazy_array" => %w[hello there] })
|
39
39
|
end
|
40
40
|
|
41
41
|
it "sets a default that can be overridden for hashes" do
|
42
42
|
arg, options = MyScript.start(["with_optional", "--lazy-hash"])
|
43
|
-
options.
|
43
|
+
expect(options).to eq({ "lazy_hash" => {'swedish' => 'meatballs'} })
|
44
44
|
|
45
45
|
arg, options = MyScript.start(["with_optional", "--lazy-hash", "polish:sausage"])
|
46
|
-
options.
|
46
|
+
expect(options).to eq({ "lazy_hash" => {'polish' => 'sausage'} })
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
50
|
describe "when :for is supplied" do
|
51
51
|
it "updates an already defined task" do
|
52
52
|
args, options = MyChildScript.start(["animal", "horse", "--other=fish"])
|
53
|
-
options[:other].
|
53
|
+
expect(options[:other]).to eq("fish")
|
54
54
|
end
|
55
55
|
|
56
56
|
describe "and the target is on the parent class" do
|
57
57
|
it "updates an already defined task" do
|
58
58
|
args = ["example_default_task", "my_param", "--new-option=verified"]
|
59
59
|
options = Scripts::MyScript.start(args)
|
60
|
-
options[:new_option].
|
60
|
+
expect(options[:new_option]).to eq("verified")
|
61
61
|
end
|
62
62
|
|
63
63
|
it "adds a task to the tasks list if the updated task is on the parent class" do
|
64
|
-
Scripts::MyScript.tasks["example_default_task"].
|
64
|
+
expect(Scripts::MyScript.tasks["example_default_task"]).to be
|
65
65
|
end
|
66
66
|
|
67
67
|
it "clones the parent task" do
|
68
|
-
Scripts::MyScript.tasks["example_default_task"].
|
68
|
+
expect(Scripts::MyScript.tasks["example_default_task"]).not_to eq(MyChildScript.tasks["example_default_task"])
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
@@ -73,48 +73,114 @@ describe Thor do
|
|
73
73
|
|
74
74
|
describe "#default_task" do
|
75
75
|
it "sets a default task" do
|
76
|
-
MyScript.default_task.
|
76
|
+
expect(MyScript.default_task).to eq("example_default_task")
|
77
77
|
end
|
78
78
|
|
79
79
|
it "invokes the default task if no command is specified" do
|
80
|
-
MyScript.start([]).
|
80
|
+
expect(MyScript.start([])).to eq("default task")
|
81
81
|
end
|
82
82
|
|
83
83
|
it "invokes the default task if no command is specified even if switches are given" do
|
84
|
-
MyScript.start(["--with", "option"]).
|
84
|
+
expect(MyScript.start(["--with", "option"])).to eq({"with"=>"option"})
|
85
85
|
end
|
86
86
|
|
87
87
|
it "inherits the default task from parent" do
|
88
|
-
MyChildScript.default_task.
|
88
|
+
expect(MyChildScript.default_task).to eq("example_default_task")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "#stop_on_unknown_option!" do
|
93
|
+
my_script = Class.new(Thor) do
|
94
|
+
class_option "verbose", :type => :boolean
|
95
|
+
class_option "mode", :type => :string
|
96
|
+
|
97
|
+
stop_on_unknown_option! :exec
|
98
|
+
|
99
|
+
desc "exec", "Run a command"
|
100
|
+
def exec(*args)
|
101
|
+
return options, args
|
102
|
+
end
|
103
|
+
|
104
|
+
desc "boring", "An ordinary task"
|
105
|
+
def boring(*args)
|
106
|
+
return options, args
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
it "passes remaining args to task when it encounters a non-option" do
|
111
|
+
expect(my_script.start(%w[exec command --verbose])).to eq [{}, ["command", "--verbose"]]
|
112
|
+
end
|
113
|
+
|
114
|
+
it "passes remaining args to task when it encounters an unknown option" do
|
115
|
+
expect(my_script.start(%w[exec --foo command --bar])).to eq [{}, ["--foo", "command", "--bar"]]
|
116
|
+
end
|
117
|
+
|
118
|
+
it "still accepts options that are given before non-options" do
|
119
|
+
expect(my_script.start(%w[exec --verbose command --foo])).to eq [{"verbose" => true}, ["command", "--foo"]]
|
120
|
+
end
|
121
|
+
|
122
|
+
it "still accepts options that require a value" do
|
123
|
+
expect(my_script.start(%w[exec --mode rashly command])).to eq [{"mode" => "rashly"}, ["command"]]
|
124
|
+
end
|
125
|
+
|
126
|
+
it "still passes everything after -- to task" do
|
127
|
+
expect(my_script.start(%w[exec -- --verbose])).to eq [{}, ["--verbose"]]
|
128
|
+
end
|
129
|
+
|
130
|
+
it "does not affect ordinary tasks" do
|
131
|
+
expect(my_script.start(%w[boring command --verbose])).to eq [{"verbose" => true}, ["command"]]
|
132
|
+
end
|
133
|
+
|
134
|
+
context "when provided with multiple task names" do
|
135
|
+
klass = Class.new(Thor) do
|
136
|
+
stop_on_unknown_option! :foo, :bar
|
137
|
+
end
|
138
|
+
it "affects all specified tasks" do
|
139
|
+
expect(klass.stop_on_unknown_option?(mock :name => "foo")).to be_true
|
140
|
+
expect(klass.stop_on_unknown_option?(mock :name => "bar")).to be_true
|
141
|
+
expect(klass.stop_on_unknown_option?(mock :name => "baz")).to be_false
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context "when invoked several times" do
|
146
|
+
klass = Class.new(Thor) do
|
147
|
+
stop_on_unknown_option! :foo
|
148
|
+
stop_on_unknown_option! :bar
|
149
|
+
end
|
150
|
+
it "affects all specified tasks" do
|
151
|
+
expect(klass.stop_on_unknown_option?(mock :name => "foo")).to be_true
|
152
|
+
expect(klass.stop_on_unknown_option?(mock :name => "bar")).to be_true
|
153
|
+
expect(klass.stop_on_unknown_option?(mock :name => "baz")).to be_false
|
154
|
+
end
|
89
155
|
end
|
90
156
|
end
|
91
157
|
|
92
158
|
describe "#map" do
|
93
159
|
it "calls the alias of a method if one is provided" do
|
94
|
-
MyScript.start(["-T", "fish"]).
|
160
|
+
expect(MyScript.start(["-T", "fish"])).to eq(["fish"])
|
95
161
|
end
|
96
162
|
|
97
163
|
it "calls the alias of a method if several are provided via .map" do
|
98
|
-
MyScript.start(["-f", "fish"]).
|
99
|
-
MyScript.start(["--foo", "fish"]).
|
164
|
+
expect(MyScript.start(["-f", "fish"])).to eq(["fish", {}])
|
165
|
+
expect(MyScript.start(["--foo", "fish"])).to eq(["fish", {}])
|
100
166
|
end
|
101
167
|
|
102
168
|
it "inherits all mappings from parent" do
|
103
|
-
MyChildScript.default_task.
|
169
|
+
expect(MyChildScript.default_task).to eq("example_default_task")
|
104
170
|
end
|
105
171
|
end
|
106
172
|
|
107
173
|
describe "#desc" do
|
108
174
|
it "provides description for a task" do
|
109
175
|
content = capture(:stdout) { MyScript.start(["help"]) }
|
110
|
-
content.
|
176
|
+
expect(content).to match(/thor my_script:zoo\s+# zoo around/m)
|
111
177
|
end
|
112
178
|
|
113
179
|
it "provides no namespace if $thor_runner is false" do
|
114
180
|
begin
|
115
181
|
$thor_runner = false
|
116
182
|
content = capture(:stdout) { MyScript.start(["help"]) }
|
117
|
-
content.
|
183
|
+
expect(content).to match(/thor zoo\s+# zoo around/m)
|
118
184
|
ensure
|
119
185
|
$thor_runner = true
|
120
186
|
end
|
@@ -122,17 +188,17 @@ describe Thor do
|
|
122
188
|
|
123
189
|
describe "when :for is supplied" do
|
124
190
|
it "overwrites a previous defined task" do
|
125
|
-
capture(:stdout) { MyChildScript.start(["help"]) }.
|
191
|
+
expect(capture(:stdout) { MyChildScript.start(["help"]) }).to match(/animal KIND \s+# fish around/m)
|
126
192
|
end
|
127
193
|
end
|
128
194
|
|
129
195
|
describe "when :hide is supplied" do
|
130
196
|
it "does not show the task in help" do
|
131
|
-
capture(:stdout) { MyScript.start(["help"]) }.
|
197
|
+
expect(capture(:stdout) { MyScript.start(["help"]) }).not_to match(/this is hidden/m)
|
132
198
|
end
|
133
199
|
|
134
200
|
it "but the task is still invokcable not show the task in help" do
|
135
|
-
MyScript.start(["hidden", "yesyes"]).
|
201
|
+
expect(MyScript.start(["hidden", "yesyes"])).to eq(["yesyes"])
|
136
202
|
end
|
137
203
|
end
|
138
204
|
end
|
@@ -140,83 +206,83 @@ describe Thor do
|
|
140
206
|
describe "#method_options" do
|
141
207
|
it "sets default options if called before an initializer" do
|
142
208
|
options = MyChildScript.class_options
|
143
|
-
options[:force].type.
|
144
|
-
options[:param].type.
|
209
|
+
expect(options[:force].type).to eq(:boolean)
|
210
|
+
expect(options[:param].type).to eq(:numeric)
|
145
211
|
end
|
146
212
|
|
147
213
|
it "overwrites default options if called on the method scope" do
|
148
214
|
args = ["zoo", "--force", "--param", "feathers"]
|
149
215
|
options = MyChildScript.start(args)
|
150
|
-
options.
|
216
|
+
expect(options).to eq({ "force" => true, "param" => "feathers" })
|
151
217
|
end
|
152
218
|
|
153
219
|
it "allows default options to be merged with method options" do
|
154
220
|
args = ["animal", "bird", "--force", "--param", "1.0", "--other", "tweets"]
|
155
221
|
arg, options = MyChildScript.start(args)
|
156
|
-
arg.
|
157
|
-
options.
|
222
|
+
expect(arg).to eq('bird')
|
223
|
+
expect(options).to eq({ "force"=>true, "param"=>1.0, "other"=>"tweets" })
|
158
224
|
end
|
159
225
|
end
|
160
226
|
|
161
227
|
describe "#start" do
|
162
228
|
it "calls a no-param method when no params are passed" do
|
163
|
-
MyScript.start(["zoo"]).
|
229
|
+
expect(MyScript.start(["zoo"])).to eq(true)
|
164
230
|
end
|
165
231
|
|
166
232
|
it "calls a single-param method when a single param is passed" do
|
167
|
-
MyScript.start(["animal", "fish"]).
|
233
|
+
expect(MyScript.start(["animal", "fish"])).to eq(["fish"])
|
168
234
|
end
|
169
235
|
|
170
236
|
it "does not set options in attributes" do
|
171
|
-
MyScript.start(["with_optional", "--all"]).
|
237
|
+
expect(MyScript.start(["with_optional", "--all"])).to eq([nil, { "all" => true }, []])
|
172
238
|
end
|
173
239
|
|
174
240
|
it "raises an error if a required param is not provided" do
|
175
|
-
capture(:stderr) { MyScript.start(["animal"]) }.strip.
|
241
|
+
expect(capture(:stderr) { MyScript.start(["animal"]) }.strip).to eq('thor animal requires at least 1 argument: "thor my_script:animal TYPE".')
|
176
242
|
end
|
177
243
|
|
178
244
|
it "raises an error if the invoked task does not exist" do
|
179
|
-
capture(:stderr) { Amazing.start(["animal"]) }.strip.
|
245
|
+
expect(capture(:stderr) { Amazing.start(["animal"]) }.strip).to eq('Could not find task "animal" in "amazing" namespace.')
|
180
246
|
end
|
181
247
|
|
182
248
|
it "calls method_missing if an unknown method is passed in" do
|
183
|
-
MyScript.start(["unk", "hello"]).
|
249
|
+
expect(MyScript.start(["unk", "hello"])).to eq([:unk, ["hello"]])
|
184
250
|
end
|
185
251
|
|
186
252
|
it "does not call a private method no matter what" do
|
187
|
-
capture(:stderr) { MyScript.start(["what"]) }.strip.
|
253
|
+
expect(capture(:stderr) { MyScript.start(["what"]) }.strip).to eq('Could not find task "what" in "my_script" namespace.')
|
188
254
|
end
|
189
255
|
|
190
256
|
it "uses task default options" do
|
191
257
|
options = MyChildScript.start(["animal", "fish"]).last
|
192
|
-
options.
|
258
|
+
expect(options).to eq({ "other" => "method default" })
|
193
259
|
end
|
194
260
|
|
195
261
|
it "raises when an exception happens within the task call" do
|
196
|
-
|
262
|
+
expect{ MyScript.start(["call_myself_with_wrong_arity"]) }.to raise_error(ArgumentError)
|
197
263
|
end
|
198
264
|
|
199
265
|
context "when the user enters an unambiguous substring of a command" do
|
200
|
-
it "
|
201
|
-
MyScript.start(["z"]).
|
266
|
+
it "invokes a command" do
|
267
|
+
expect(MyScript.start(["z"])).to eq(MyScript.start(["zoo"]))
|
202
268
|
end
|
203
269
|
|
204
|
-
it "
|
205
|
-
MyScript.start(["hi"]).
|
270
|
+
it "invokes a command, even when there's an alias the resolves to the same command" do
|
271
|
+
expect(MyScript.start(["hi"])).to eq(MyScript.start(["hidden"]))
|
206
272
|
end
|
207
273
|
|
208
|
-
it "
|
209
|
-
MyScript.start(["animal_pri"]).
|
274
|
+
it "invokes an alias" do
|
275
|
+
expect(MyScript.start(["animal_pri"])).to eq(MyScript.start(["zoo"]))
|
210
276
|
end
|
211
277
|
end
|
212
278
|
|
213
279
|
context "when the user enters an ambiguous substring of a command" do
|
214
|
-
it "
|
215
|
-
|
280
|
+
it "raises an exception that explains the ambiguity" do
|
281
|
+
expect{ MyScript.start(["call"]) }.to raise_error(ArgumentError, 'Ambiguous task call matches [call_myself_with_wrong_arity, call_unexistent_method]')
|
216
282
|
end
|
217
283
|
|
218
|
-
it "
|
219
|
-
|
284
|
+
it "raises an exception when there is an alias" do
|
285
|
+
expect{ MyScript.start(["f"]) }.to raise_error(ArgumentError, 'Ambiguous task f matches [foo, fu]')
|
220
286
|
end
|
221
287
|
end
|
222
288
|
|
@@ -224,20 +290,20 @@ describe Thor do
|
|
224
290
|
|
225
291
|
describe "#subcommand" do
|
226
292
|
it "maps a given subcommand to another Thor subclass" do
|
227
|
-
barn_help = capture(:stdout){ Scripts::MyDefaults.start(["barn"]) }
|
228
|
-
barn_help.
|
293
|
+
barn_help = capture(:stdout) { Scripts::MyDefaults.start(["barn"]) }
|
294
|
+
expect(barn_help).to include("barn help [COMMAND] # Describe subcommands or one specific subcommand")
|
229
295
|
end
|
230
296
|
|
231
297
|
it "passes commands to subcommand classes" do
|
232
|
-
capture(:stdout){ Scripts::MyDefaults.start(["barn", "open"]) }.strip.
|
298
|
+
expect(capture(:stdout) { Scripts::MyDefaults.start(["barn", "open"]) }.strip).to eq("Open sesame!")
|
233
299
|
end
|
234
300
|
|
235
301
|
it "passes arguments to subcommand classes" do
|
236
|
-
capture(:stdout){ Scripts::MyDefaults.start(["barn", "open", "shotgun"]) }.strip.
|
302
|
+
expect(capture(:stdout) { Scripts::MyDefaults.start(["barn", "open", "shotgun"]) }.strip).to eq("That's going to leave a mark.")
|
237
303
|
end
|
238
304
|
|
239
305
|
it "ignores unknown options (the subcommand class will handle them)" do
|
240
|
-
capture(:stdout){ Scripts::MyDefaults.start(["barn", "paint", "blue", "--coats", "4"])}.strip.
|
306
|
+
expect(capture(:stdout) { Scripts::MyDefaults.start(["barn", "paint", "blue", "--coats", "4"])}.strip).to eq("4 coats of blue paint")
|
241
307
|
end
|
242
308
|
end
|
243
309
|
|
@@ -248,47 +314,47 @@ describe Thor do
|
|
248
314
|
|
249
315
|
describe "on general" do
|
250
316
|
before do
|
251
|
-
@content = capture(:stdout){ MyScript.help(shell) }
|
317
|
+
@content = capture(:stdout) { MyScript.help(shell) }
|
252
318
|
end
|
253
319
|
|
254
320
|
it "provides useful help info for the help method itself" do
|
255
|
-
@content.
|
321
|
+
expect(@content).to match(/help \[TASK\]\s+# Describe available tasks/)
|
256
322
|
end
|
257
323
|
|
258
324
|
it "provides useful help info for a method with params" do
|
259
|
-
@content.
|
325
|
+
expect(@content).to match(/animal TYPE\s+# horse around/)
|
260
326
|
end
|
261
327
|
|
262
328
|
it "uses the maximum terminal size to show tasks" do
|
263
329
|
@shell.should_receive(:terminal_width).and_return(80)
|
264
|
-
content = capture(:stdout){ MyScript.help(shell) }
|
265
|
-
content.
|
330
|
+
content = capture(:stdout) { MyScript.help(shell) }
|
331
|
+
expect(content).to match(/aaa\.\.\.$/)
|
266
332
|
end
|
267
333
|
|
268
334
|
it "provides description for tasks from classes in the same namespace" do
|
269
|
-
@content.
|
335
|
+
expect(@content).to match(/baz\s+# do some bazing/)
|
270
336
|
end
|
271
337
|
|
272
338
|
it "shows superclass tasks" do
|
273
|
-
content = capture(:stdout){ MyChildScript.help(shell) }
|
274
|
-
content.
|
339
|
+
content = capture(:stdout) { MyChildScript.help(shell) }
|
340
|
+
expect(content).to match(/foo BAR \s+# do some fooing/)
|
275
341
|
end
|
276
342
|
|
277
343
|
it "shows class options information" do
|
278
|
-
content = capture(:stdout){ MyChildScript.help(shell) }
|
279
|
-
content.
|
280
|
-
content.
|
344
|
+
content = capture(:stdout) { MyChildScript.help(shell) }
|
345
|
+
expect(content).to match(/Options\:/)
|
346
|
+
expect(content).to match(/\[\-\-param=N\]/)
|
281
347
|
end
|
282
348
|
|
283
349
|
it "injects class arguments into default usage" do
|
284
|
-
content = capture(:stdout){ Scripts::MyScript.help(shell) }
|
285
|
-
content.
|
350
|
+
content = capture(:stdout) { Scripts::MyScript.help(shell) }
|
351
|
+
expect(content).to match(/zoo ACCESSOR \-\-param\=PARAM/)
|
286
352
|
end
|
287
353
|
end
|
288
354
|
|
289
355
|
describe "for a specific task" do
|
290
356
|
it "provides full help info when talking about a specific task" do
|
291
|
-
capture(:stdout) { MyScript.task_help(shell, "foo") }.
|
357
|
+
expect(capture(:stdout) { MyScript.task_help(shell, "foo") }).to eq(<<-END)
|
292
358
|
Usage:
|
293
359
|
thor my_script:foo BAR
|
294
360
|
|
@@ -302,17 +368,17 @@ END
|
|
302
368
|
end
|
303
369
|
|
304
370
|
it "raises an error if the task can't be found" do
|
305
|
-
|
371
|
+
expect {
|
306
372
|
MyScript.task_help(shell, "unknown")
|
307
|
-
}.
|
373
|
+
}.to raise_error(Thor::UndefinedTaskError, 'Could not find task "unknown" in "my_script" namespace.')
|
308
374
|
end
|
309
375
|
|
310
376
|
it "normalizes names before claiming they don't exist" do
|
311
|
-
capture(:stdout) { MyScript.task_help(shell, "name-with-dashes") }.
|
377
|
+
expect(capture(:stdout) { MyScript.task_help(shell, "name-with-dashes") }).to match(/thor my_script:name-with-dashes/)
|
312
378
|
end
|
313
379
|
|
314
380
|
it "uses the long description if it exists" do
|
315
|
-
capture(:stdout) { MyScript.task_help(shell, "long_description") }.
|
381
|
+
expect(capture(:stdout) { MyScript.task_help(shell, "long_description") }).to eq(<<-HELP)
|
316
382
|
Usage:
|
317
383
|
thor my_script:long_description
|
318
384
|
|
@@ -324,36 +390,36 @@ HELP
|
|
324
390
|
end
|
325
391
|
|
326
392
|
it "doesn't assign the long description to the next task without one" do
|
327
|
-
capture(:stdout)
|
393
|
+
expect(capture(:stdout) {
|
328
394
|
MyScript.task_help(shell, "name_with_dashes")
|
329
|
-
|
395
|
+
}).not_to match(/so very long/i)
|
330
396
|
end
|
331
397
|
end
|
332
398
|
|
333
399
|
describe "instance method" do
|
334
400
|
it "calls the class method" do
|
335
|
-
capture(:stdout){ MyScript.start(["help"]) }.
|
401
|
+
expect(capture(:stdout) { MyScript.start(["help"]) }).to match(/Tasks:/)
|
336
402
|
end
|
337
403
|
|
338
404
|
it "calls the class method" do
|
339
|
-
capture(:stdout){ MyScript.start(["help", "foo"]) }.
|
405
|
+
expect(capture(:stdout) { MyScript.start(["help", "foo"]) }).to match(/Usage:/)
|
340
406
|
end
|
341
407
|
end
|
342
408
|
end
|
343
409
|
|
344
410
|
describe "when creating tasks" do
|
345
411
|
it "prints a warning if a public method is created without description or usage" do
|
346
|
-
capture(:stdout) {
|
412
|
+
expect(capture(:stdout) {
|
347
413
|
klass = Class.new(Thor)
|
348
414
|
klass.class_eval "def hello_from_thor; end"
|
349
|
-
}.
|
415
|
+
}).to match(/\[WARNING\] Attempted to create task "hello_from_thor" without usage or description/)
|
350
416
|
end
|
351
417
|
|
352
418
|
it "does not print if overwriting a previous task" do
|
353
|
-
capture(:stdout) {
|
419
|
+
expect(capture(:stdout) {
|
354
420
|
klass = Class.new(Thor)
|
355
421
|
klass.class_eval "def help; end"
|
356
|
-
}.
|
422
|
+
}).to be_empty
|
357
423
|
end
|
358
424
|
end
|
359
425
|
|
@@ -368,9 +434,9 @@ HELP
|
|
368
434
|
end
|
369
435
|
end
|
370
436
|
|
371
|
-
klass.start(["hi", "jose"]).
|
372
|
-
klass.start(["hi", "jose", "--loud"]).
|
373
|
-
klass.start(["hi", "--loud", "jose"]).
|
437
|
+
expect(klass.start(["hi", "jose"])).to eq("Hi jose")
|
438
|
+
expect(klass.start(["hi", "jose", "--loud"])).to eq("Hi JOSE")
|
439
|
+
expect(klass.start(["hi", "--loud", "jose"])).to eq("Hi JOSE")
|
374
440
|
end
|
375
441
|
|
376
442
|
it "passes through unknown options" do
|
@@ -381,8 +447,8 @@ HELP
|
|
381
447
|
end
|
382
448
|
end
|
383
449
|
|
384
|
-
klass.start(["unknown", "foo", "--bar", "baz", "bat", "--bam"]).
|
385
|
-
klass.start(["unknown", "--bar", "baz"]).
|
450
|
+
expect(klass.start(["unknown", "foo", "--bar", "baz", "bat", "--bam"])).to eq(["foo", "--bar", "baz", "bat", "--bam"])
|
451
|
+
expect(klass.start(["unknown", "--bar", "baz"])).to eq(["--bar", "baz"])
|
386
452
|
end
|
387
453
|
|
388
454
|
it "does not pass through unknown options with strict args" do
|
@@ -395,8 +461,8 @@ HELP
|
|
395
461
|
end
|
396
462
|
end
|
397
463
|
|
398
|
-
klass.start(["unknown", "--bar", "baz"]).
|
399
|
-
klass.start(["unknown", "foo", "--bar", "baz"]).
|
464
|
+
expect(klass.start(["unknown", "--bar", "baz"])).to eq([])
|
465
|
+
expect(klass.start(["unknown", "foo", "--bar", "baz"])).to eq(["foo"])
|
400
466
|
end
|
401
467
|
|
402
468
|
it "strict args works in the inheritance chain" do
|
@@ -411,8 +477,12 @@ HELP
|
|
411
477
|
end
|
412
478
|
end
|
413
479
|
|
414
|
-
klass.start(["unknown", "--bar", "baz"]).
|
415
|
-
klass.start(["unknown", "foo", "--bar", "baz"]).
|
480
|
+
expect(klass.start(["unknown", "--bar", "baz"])).to eq([])
|
481
|
+
expect(klass.start(["unknown", "foo", "--bar", "baz"])).to eq(["foo"])
|
482
|
+
end
|
483
|
+
|
484
|
+
it "send as a task name" do
|
485
|
+
expect(MyScript.start(["send"])).to eq(true)
|
416
486
|
end
|
417
487
|
end
|
418
488
|
end
|