wijet-thor 0.14.6

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.
Files changed (75) hide show
  1. data/CHANGELOG.rdoc +103 -0
  2. data/LICENSE +20 -0
  3. data/README.md +307 -0
  4. data/Thorfile +24 -0
  5. data/bin/rake2thor +86 -0
  6. data/bin/thor +6 -0
  7. data/lib/thor.rb +334 -0
  8. data/lib/thor/actions.rb +314 -0
  9. data/lib/thor/actions/create_file.rb +105 -0
  10. data/lib/thor/actions/create_link.rb +57 -0
  11. data/lib/thor/actions/directory.rb +93 -0
  12. data/lib/thor/actions/empty_directory.rb +134 -0
  13. data/lib/thor/actions/file_manipulation.rb +270 -0
  14. data/lib/thor/actions/inject_into_file.rb +109 -0
  15. data/lib/thor/base.rb +579 -0
  16. data/lib/thor/core_ext/file_binary_read.rb +9 -0
  17. data/lib/thor/core_ext/hash_with_indifferent_access.rb +75 -0
  18. data/lib/thor/core_ext/ordered_hash.rb +100 -0
  19. data/lib/thor/error.rb +30 -0
  20. data/lib/thor/group.rb +273 -0
  21. data/lib/thor/invocation.rb +168 -0
  22. data/lib/thor/parser.rb +4 -0
  23. data/lib/thor/parser/argument.rb +67 -0
  24. data/lib/thor/parser/arguments.rb +161 -0
  25. data/lib/thor/parser/option.rb +120 -0
  26. data/lib/thor/parser/options.rb +173 -0
  27. data/lib/thor/rake_compat.rb +66 -0
  28. data/lib/thor/runner.rb +309 -0
  29. data/lib/thor/shell.rb +88 -0
  30. data/lib/thor/shell/basic.rb +290 -0
  31. data/lib/thor/shell/color.rb +108 -0
  32. data/lib/thor/shell/html.rb +121 -0
  33. data/lib/thor/task.rb +114 -0
  34. data/lib/thor/util.rb +229 -0
  35. data/lib/thor/version.rb +3 -0
  36. data/spec/actions/create_file_spec.rb +170 -0
  37. data/spec/actions/directory_spec.rb +136 -0
  38. data/spec/actions/empty_directory_spec.rb +98 -0
  39. data/spec/actions/file_manipulation_spec.rb +310 -0
  40. data/spec/actions/inject_into_file_spec.rb +135 -0
  41. data/spec/actions_spec.rb +322 -0
  42. data/spec/base_spec.rb +269 -0
  43. data/spec/core_ext/hash_with_indifferent_access_spec.rb +43 -0
  44. data/spec/core_ext/ordered_hash_spec.rb +115 -0
  45. data/spec/fixtures/application.rb +2 -0
  46. data/spec/fixtures/bundle/execute.rb +6 -0
  47. data/spec/fixtures/bundle/main.thor +1 -0
  48. data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
  49. data/spec/fixtures/doc/README +3 -0
  50. data/spec/fixtures/doc/block_helper.rb +3 -0
  51. data/spec/fixtures/doc/components/.empty_directory +0 -0
  52. data/spec/fixtures/doc/config.rb +1 -0
  53. data/spec/fixtures/group.thor +114 -0
  54. data/spec/fixtures/invoke.thor +112 -0
  55. data/spec/fixtures/path with spaces b/data/spec/fixtures/path with → spaces +0 -0
  56. data/spec/fixtures/script.thor +184 -0
  57. data/spec/fixtures/task.thor +10 -0
  58. data/spec/group_spec.rb +178 -0
  59. data/spec/invocation_spec.rb +100 -0
  60. data/spec/parser/argument_spec.rb +47 -0
  61. data/spec/parser/arguments_spec.rb +64 -0
  62. data/spec/parser/option_spec.rb +202 -0
  63. data/spec/parser/options_spec.rb +319 -0
  64. data/spec/rake_compat_spec.rb +68 -0
  65. data/spec/register_spec.rb +104 -0
  66. data/spec/runner_spec.rb +210 -0
  67. data/spec/shell/basic_spec.rb +223 -0
  68. data/spec/shell/color_spec.rb +41 -0
  69. data/spec/shell/html_spec.rb +27 -0
  70. data/spec/shell_spec.rb +47 -0
  71. data/spec/spec_helper.rb +54 -0
  72. data/spec/task_spec.rb +74 -0
  73. data/spec/thor_spec.rb +334 -0
  74. data/spec/util_spec.rb +163 -0
  75. metadata +193 -0
@@ -0,0 +1,41 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Thor::Shell::Color do
4
+ def shell
5
+ @shell ||= Thor::Shell::Color.new
6
+ end
7
+
8
+ describe "#say" do
9
+ it "set the color if specified" do
10
+ $stdout.should_receive(:puts).with("\e[32mWow! Now we have colors!\e[0m")
11
+ shell.say "Wow! Now we have colors!", :green
12
+ end
13
+
14
+ it "does not use a new line even with colors" do
15
+ $stdout.should_receive(:print).with("\e[32mWow! Now we have colors! \e[0m")
16
+ shell.say "Wow! Now we have colors! ", :green
17
+ end
18
+ end
19
+
20
+ describe "#say_status" do
21
+ it "uses color to say status" do
22
+ $stdout.should_receive(:puts).with("\e[1m\e[31m conflict\e[0m README")
23
+ shell.say_status :conflict, "README", :red
24
+ end
25
+ end
26
+
27
+ describe "#file_collision" do
28
+ describe "when a block is given" do
29
+ it "invokes the diff command" do
30
+ $stdout.stub!(:print)
31
+ $stdin.should_receive(:gets).and_return('d')
32
+ $stdin.should_receive(:gets).and_return('n')
33
+
34
+ output = capture(:stdout){ shell.file_collision('spec/fixtures/doc/README'){ "README\nEND\n" } }
35
+ output.should =~ /\e\[31m\- __start__\e\[0m/
36
+ output.should =~ /^ README/
37
+ output.should =~ /\e\[32m\+ END\e\[0m/
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Thor::Shell::HTML do
4
+ def shell
5
+ @shell ||= Thor::Shell::HTML.new
6
+ end
7
+
8
+ describe "#say" do
9
+ it "set the color if specified" do
10
+ $stdout.should_receive(:puts).with('<span style="color: green;">Wow! Now we have colors!</span>')
11
+ shell.say "Wow! Now we have colors!", :green
12
+ end
13
+
14
+ it "does not use a new line even with colors" do
15
+ $stdout.should_receive(:print).with('<span style="color: green;">Wow! Now we have colors! </span>')
16
+ shell.say "Wow! Now we have colors! ", :green
17
+ end
18
+ end
19
+
20
+ describe "#say_status" do
21
+ it "uses color to say status" do
22
+ $stdout.should_receive(:puts).with('<strong><span style="color: red;"> conflict</span></strong> README')
23
+ shell.say_status :conflict, "README", :red
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,47 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Thor::Shell do
4
+ def shell
5
+ @shell ||= Thor::Base.shell.new
6
+ end
7
+
8
+ describe "#initialize" do
9
+ it "sets shell value" do
10
+ base = MyCounter.new [1, 2], { }, :shell => shell
11
+ base.shell.should == shell
12
+ end
13
+
14
+ it "sets the base value on the shell if an accessor is available" do
15
+ base = MyCounter.new [1, 2], { }, :shell => shell
16
+ shell.base.should == base
17
+ end
18
+ end
19
+
20
+ describe "#shell" do
21
+ it "returns the shell in use" do
22
+ MyCounter.new([1,2]).shell.should be_kind_of(Thor::Base.shell)
23
+ end
24
+
25
+ it "uses $THOR_SHELL" do
26
+ class Thor::Shell::TestShell < Thor::Shell::Basic; end
27
+
28
+ Thor::Base.shell.should == shell.class
29
+ ENV['THOR_SHELL'] = 'TestShell'
30
+ Thor::Base.shell = nil
31
+ Thor::Base.shell.should == Thor::Shell::TestShell
32
+ ENV['THOR_SHELL'] = ''
33
+ Thor::Base.shell = shell.class
34
+ Thor::Base.shell.should == shell.class
35
+ end
36
+ end
37
+
38
+ describe "with_padding" do
39
+ it "uses padding for inside block outputs" do
40
+ base = MyCounter.new([1,2])
41
+ base.with_padding do
42
+ capture(:stdout){ base.say_status :padding, "cool" }.strip.should == "padding cool"
43
+ end
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,54 @@
1
+ $TESTING=true
2
+
3
+ require 'simplecov'
4
+ SimpleCov.start do
5
+ add_group 'Libraries', 'lib'
6
+ add_group 'Specs', 'spec'
7
+ end
8
+
9
+ $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
10
+ require 'thor'
11
+ require 'thor/group'
12
+ require 'stringio'
13
+
14
+ require 'rdoc'
15
+ require 'rspec'
16
+ require 'diff/lcs' # You need diff/lcs installed to run specs (but not to run Thor).
17
+ require 'fakeweb' # You need fakeweb installed to run specs (but not to run Thor).
18
+
19
+ # Set shell to basic
20
+ $0 = "thor"
21
+ $thor_runner = true
22
+ ARGV.clear
23
+ Thor::Base.shell = Thor::Shell::Basic
24
+
25
+ # Load fixtures
26
+ load File.join(File.dirname(__FILE__), "fixtures", "task.thor")
27
+ load File.join(File.dirname(__FILE__), "fixtures", "group.thor")
28
+ load File.join(File.dirname(__FILE__), "fixtures", "script.thor")
29
+ load File.join(File.dirname(__FILE__), "fixtures", "invoke.thor")
30
+
31
+ RSpec.configure do |config|
32
+ def capture(stream)
33
+ begin
34
+ stream = stream.to_s
35
+ eval "$#{stream} = StringIO.new"
36
+ yield
37
+ result = eval("$#{stream}").string
38
+ ensure
39
+ eval("$#{stream} = #{stream.upcase}")
40
+ end
41
+
42
+ result
43
+ end
44
+
45
+ def source_root
46
+ File.join(File.dirname(__FILE__), 'fixtures')
47
+ end
48
+
49
+ def destination_root
50
+ File.join(File.dirname(__FILE__), 'sandbox')
51
+ end
52
+
53
+ alias :silence :capture
54
+ end
@@ -0,0 +1,74 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Thor::Task do
4
+ def task(options={})
5
+ options.each do |key, value|
6
+ options[key] = Thor::Option.parse(key, value)
7
+ end
8
+
9
+ @task ||= Thor::Task.new(:can_has, "I can has cheezburger", "I can has cheezburger\nLots and lots of it", "can_has", options)
10
+ end
11
+
12
+ describe "#formatted_usage" do
13
+ it "includes namespace within usage" do
14
+ Object.stub!(:namespace).and_return("foo")
15
+ Object.stub!(:arguments).and_return([])
16
+ task(:bar => :required).formatted_usage(Object).should == "foo:can_has --bar=BAR"
17
+ end
18
+
19
+ it "includes subcommand name within subcommand usage" do
20
+ object = Struct.new(:namespace, :arguments).new("main:foo", [])
21
+ task(:bar => :required).formatted_usage(object, false, true).should == "foo can_has --bar=BAR"
22
+ end
23
+
24
+ it "removes default from namespace" do
25
+ Object.stub!(:namespace).and_return("default:foo")
26
+ Object.stub!(:arguments).and_return([])
27
+ task(:bar => :required).formatted_usage(Object).should == ":foo:can_has --bar=BAR"
28
+ end
29
+
30
+ it "injects arguments into usage" do
31
+ Object.stub!(:namespace).and_return("foo")
32
+ Object.stub!(:arguments).and_return([ Thor::Argument.new(:bar, nil, true, :string) ])
33
+ task(:foo => :required).formatted_usage(Object).should == "foo:can_has BAR --foo=FOO"
34
+ end
35
+ end
36
+
37
+ describe "#dynamic" do
38
+ it "creates a dynamic task with the given name" do
39
+ Thor::DynamicTask.new('task').name.should == 'task'
40
+ Thor::DynamicTask.new('task').description.should == 'A dynamically-generated task'
41
+ Thor::DynamicTask.new('task').usage.should == 'task'
42
+ Thor::DynamicTask.new('task').options.should == {}
43
+ end
44
+
45
+ it "does not invoke an existing method" do
46
+ mock = mock()
47
+ mock.class.should_receive(:handle_no_task_error).with("to_s")
48
+ Thor::DynamicTask.new('to_s').run(mock)
49
+ end
50
+ end
51
+
52
+ describe "#dup" do
53
+ it "dup options hash" do
54
+ task = Thor::Task.new("can_has", nil, nil, nil, :foo => true, :bar => :required)
55
+ task.dup.options.delete(:foo)
56
+ task.options[:foo].should_not be_nil
57
+ end
58
+ end
59
+
60
+ describe "#run" do
61
+ it "runs a task by calling a method in the given instance" do
62
+ mock = mock()
63
+ mock.should_receive(:send).with("can_has", 1, 2, 3)
64
+ task.run(mock, [1, 2, 3])
65
+ end
66
+
67
+ it "raises an error if the method to be invoked is private" do
68
+ mock = mock()
69
+ mock.should_receive(:private_methods).and_return(['can_has'])
70
+ mock.class.should_receive(:handle_no_task_error).with("can_has")
71
+ task.run(mock)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,334 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Thor do
4
+ describe "#method_option" do
5
+ it "sets options to the next method to be invoked" do
6
+ args = ["foo", "bar", "--force"]
7
+ arg, options = MyScript.start(args)
8
+ options.should == { "force" => true }
9
+ end
10
+
11
+ describe ":lazy_default" do
12
+ it "is absent when option is not specified" do
13
+ arg, options = MyScript.start(["with_optional"])
14
+ options.should == {}
15
+ end
16
+
17
+ it "sets a default that can be overridden for strings" do
18
+ arg, options = MyScript.start(["with_optional", "--lazy"])
19
+ options.should == { "lazy" => "yes" }
20
+
21
+ arg, options = MyScript.start(["with_optional", "--lazy", "yesyes!"])
22
+ options.should == { "lazy" => "yesyes!" }
23
+ end
24
+
25
+ it "sets a default that can be overridden for numerics" do
26
+ arg, options = MyScript.start(["with_optional", "--lazy-numeric"])
27
+ options.should == { "lazy_numeric" => 42 }
28
+
29
+ arg, options = MyScript.start(["with_optional", "--lazy-numeric", 20000])
30
+ options.should == { "lazy_numeric" => 20000 }
31
+ end
32
+
33
+ it "sets a default that can be overridden for arrays" do
34
+ arg, options = MyScript.start(["with_optional", "--lazy-array"])
35
+ options.should == { "lazy_array" => %w[eat at joes] }
36
+
37
+ arg, options = MyScript.start(["with_optional", "--lazy-array", "hello", "there"])
38
+ options.should == { "lazy_array" => %w[hello there] }
39
+ end
40
+
41
+ it "sets a default that can be overridden for hashes" do
42
+ arg, options = MyScript.start(["with_optional", "--lazy-hash"])
43
+ options.should == { "lazy_hash" => {'swedish' => 'meatballs'} }
44
+
45
+ arg, options = MyScript.start(["with_optional", "--lazy-hash", "polish:sausage"])
46
+ options.should == { "lazy_hash" => {'polish' => 'sausage'} }
47
+ end
48
+ end
49
+
50
+ describe "when :for is supplied" do
51
+ it "updates an already defined task" do
52
+ args, options = MyChildScript.start(["animal", "horse", "--other=fish"])
53
+ options[:other].should == "fish"
54
+ end
55
+
56
+ describe "and the target is on the parent class" do
57
+ it "updates an already defined task" do
58
+ args = ["example_default_task", "my_param", "--new-option=verified"]
59
+ options = Scripts::MyScript.start(args)
60
+ options[:new_option].should == "verified"
61
+ end
62
+
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"].should_not be_nil
65
+ end
66
+
67
+ it "clones the parent task" do
68
+ Scripts::MyScript.tasks["example_default_task"].should_not == MyChildScript.tasks["example_default_task"]
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ describe "#default_task" do
75
+ it "sets a default task" do
76
+ MyScript.default_task.should == "example_default_task"
77
+ end
78
+
79
+ it "invokes the default task if no command is specified" do
80
+ MyScript.start([]).should == "default task"
81
+ end
82
+
83
+ it "invokes the default task if no command is specified even if switches are given" do
84
+ MyScript.start(["--with", "option"]).should == {"with"=>"option"}
85
+ end
86
+
87
+ it "inherits the default task from parent" do
88
+ MyChildScript.default_task.should == "example_default_task"
89
+ end
90
+ end
91
+
92
+ describe "#map" do
93
+ it "calls the alias of a method if one is provided" do
94
+ MyScript.start(["-T", "fish"]).should == ["fish"]
95
+ end
96
+
97
+ it "calls the alias of a method if several are provided via .map" do
98
+ MyScript.start(["-f", "fish"]).should == ["fish", {}]
99
+ MyScript.start(["--foo", "fish"]).should == ["fish", {}]
100
+ end
101
+
102
+ it "inherits all mappings from parent" do
103
+ MyChildScript.default_task.should == "example_default_task"
104
+ end
105
+ end
106
+
107
+ describe "#desc" do
108
+ it "provides description for a task" do
109
+ content = capture(:stdout) { MyScript.start(["help"]) }
110
+ content.should =~ /thor my_script:zoo\s+# zoo around/m
111
+ end
112
+
113
+ it "provides no namespace if $thor_runner is false" do
114
+ begin
115
+ $thor_runner = false
116
+ content = capture(:stdout) { MyScript.start(["help"]) }
117
+ content.should =~ /thor zoo\s+# zoo around/m
118
+ ensure
119
+ $thor_runner = true
120
+ end
121
+ end
122
+
123
+ describe "when :for is supplied" do
124
+ it "overwrites a previous defined task" do
125
+ capture(:stdout) { MyChildScript.start(["help"]) }.should =~ /animal KIND \s+# fish around/m
126
+ end
127
+ end
128
+
129
+ describe "when :hide is supplied" do
130
+ it "does not show the task in help" do
131
+ capture(:stdout) { MyScript.start(["help"]) }.should_not =~ /this is hidden/m
132
+ end
133
+
134
+ it "but the task is still invokcable not show the task in help" do
135
+ MyScript.start(["hidden", "yesyes"]).should == ["yesyes"]
136
+ end
137
+ end
138
+ end
139
+
140
+ describe "#method_options" do
141
+ it "sets default options if called before an initializer" do
142
+ options = MyChildScript.class_options
143
+ options[:force].type.should == :boolean
144
+ options[:param].type.should == :numeric
145
+ end
146
+
147
+ it "overwrites default options if called on the method scope" do
148
+ args = ["zoo", "--force", "--param", "feathers"]
149
+ options = MyChildScript.start(args)
150
+ options.should == { "force" => true, "param" => "feathers" }
151
+ end
152
+
153
+ it "allows default options to be merged with method options" do
154
+ args = ["animal", "bird", "--force", "--param", "1.0", "--other", "tweets"]
155
+ arg, options = MyChildScript.start(args)
156
+ arg.should == 'bird'
157
+ options.should == { "force"=>true, "param"=>1.0, "other"=>"tweets" }
158
+ end
159
+ end
160
+
161
+ describe "#start" do
162
+ it "calls a no-param method when no params are passed" do
163
+ MyScript.start(["zoo"]).should == true
164
+ end
165
+
166
+ it "calls a single-param method when a single param is passed" do
167
+ MyScript.start(["animal", "fish"]).should == ["fish"]
168
+ end
169
+
170
+ it "does not set options in attributes" do
171
+ MyScript.start(["with_optional", "--all"]).should == [nil, { "all" => true }]
172
+ end
173
+
174
+ it "raises an error if a required param is not provided" do
175
+ capture(:stderr) { MyScript.start(["animal"]) }.strip.should == '"animal" was called incorrectly. Call as "thor my_script:animal TYPE".'
176
+ end
177
+
178
+ it "raises an error if the invoked task does not exist" do
179
+ capture(:stderr) { Amazing.start(["animal"]) }.strip.should == 'Could not find task "animal" in "amazing" namespace.'
180
+ end
181
+
182
+ it "calls method_missing if an unknown method is passed in" do
183
+ MyScript.start(["unk", "hello"]).should == [:unk, ["hello"]]
184
+ end
185
+
186
+ it "does not call a private method no matter what" do
187
+ capture(:stderr) { MyScript.start(["what"]) }.strip.should == 'Could not find task "what" in "my_script" namespace.'
188
+ end
189
+
190
+ it "uses task default options" do
191
+ options = MyChildScript.start(["animal", "fish"]).last
192
+ options.should == { "other" => "method default" }
193
+ end
194
+
195
+ it "raises when an exception happens within the task call" do
196
+ lambda { MyScript.start(["call_myself_with_wrong_arity"]) }.should raise_error(ArgumentError)
197
+ end
198
+ end
199
+
200
+ describe "#subcommand" do
201
+ it "maps a given subcommand to another Thor subclass" do
202
+ barn_help = capture(:stdout){ Scripts::MyDefaults.start(["barn"]) }
203
+ barn_help.should include("barn help [COMMAND] # Describe subcommands or one specific subcommand")
204
+ end
205
+
206
+ it "passes commands to subcommand classes" do
207
+ capture(:stdout){ Scripts::MyDefaults.start(["barn", "open"]) }.strip.should == "Open sesame!"
208
+ end
209
+
210
+ it "passes arguments to subcommand classes" do
211
+ capture(:stdout){ Scripts::MyDefaults.start(["barn", "open", "shotgun"]) }.strip.should == "That's going to leave a mark."
212
+ end
213
+
214
+ it "ignores unknown options (the subcommand class will handle them)" do
215
+ capture(:stdout){ Scripts::MyDefaults.start(["barn", "paint", "blue", "--coats", "4"])}.strip.should == "4 coats of blue paint"
216
+ end
217
+ end
218
+
219
+ describe "#help" do
220
+ def shell
221
+ @shell ||= Thor::Base.shell.new
222
+ end
223
+
224
+ describe "on general" do
225
+ before(:each) do
226
+ @content = capture(:stdout){ MyScript.help(shell) }
227
+ end
228
+
229
+ it "provides useful help info for the help method itself" do
230
+ @content.should =~ /help \[TASK\]\s+# Describe available tasks/
231
+ end
232
+
233
+ it "provides useful help info for a method with params" do
234
+ @content.should =~ /animal TYPE\s+# horse around/
235
+ end
236
+
237
+ it "uses the maximum terminal size to show tasks" do
238
+ @shell.should_receive(:terminal_width).and_return(80)
239
+ content = capture(:stdout){ MyScript.help(shell) }
240
+ content.should =~ /aaa\.\.\.$/
241
+ end
242
+
243
+ it "provides description for tasks from classes in the same namespace" do
244
+ @content.should =~ /baz\s+# do some bazing/
245
+ end
246
+
247
+ it "shows superclass tasks" do
248
+ content = capture(:stdout){ MyChildScript.help(shell) }
249
+ content.should =~ /foo BAR \s+# do some fooing/
250
+ end
251
+
252
+ it "shows class options information" do
253
+ content = capture(:stdout){ MyChildScript.help(shell) }
254
+ content.should =~ /Options\:/
255
+ content.should =~ /\[\-\-param=N\]/
256
+ end
257
+
258
+ it "injects class arguments into default usage" do
259
+ content = capture(:stdout){ Scripts::MyScript.help(shell) }
260
+ content.should =~ /zoo ACCESSOR \-\-param\=PARAM/
261
+ end
262
+ end
263
+
264
+ describe "for a specific task" do
265
+ it "provides full help info when talking about a specific task" do
266
+ capture(:stdout) { MyScript.task_help(shell, "foo") }.should == <<-END
267
+ Usage:
268
+ thor my_script:foo BAR
269
+
270
+ Options:
271
+ [--force] # Force to do some fooing
272
+
273
+ do some fooing
274
+ This is more info!
275
+ Everyone likes more info!
276
+ END
277
+ end
278
+
279
+ it "raises an error if the task can't be found" do
280
+ lambda {
281
+ MyScript.task_help(shell, "unknown")
282
+ }.should raise_error(Thor::UndefinedTaskError, 'Could not find task "unknown" in "my_script" namespace.')
283
+ end
284
+
285
+ it "normalizes names before claiming they don't exist" do
286
+ capture(:stdout) { MyScript.task_help(shell, "name-with-dashes") }.should =~ /thor my_script:name-with-dashes/
287
+ end
288
+
289
+ it "uses the long description if it exists" do
290
+ capture(:stdout) { MyScript.task_help(shell, "long_description") }.should == <<-HELP
291
+ Usage:
292
+ thor my_script:long_description
293
+
294
+ Description:
295
+ This is a really really really long description. Here you go. So very long.
296
+
297
+ It even has two paragraphs.
298
+ HELP
299
+ end
300
+
301
+ it "doesn't assign the long description to the next task without one" do
302
+ capture(:stdout) do
303
+ MyScript.task_help(shell, "name_with_dashes")
304
+ end.should_not =~ /so very long/i
305
+ end
306
+ end
307
+
308
+ describe "instance method" do
309
+ it "calls the class method" do
310
+ capture(:stdout){ MyScript.start(["help"]) }.should =~ /Tasks:/
311
+ end
312
+
313
+ it "calls the class method" do
314
+ capture(:stdout){ MyScript.start(["help", "foo"]) }.should =~ /Usage:/
315
+ end
316
+ end
317
+ end
318
+
319
+ describe "when creating tasks" do
320
+ it "prints a warning if a public method is created without description or usage" do
321
+ capture(:stdout) {
322
+ klass = Class.new(Thor)
323
+ klass.class_eval "def hello_from_thor; end"
324
+ }.should =~ /\[WARNING\] Attempted to create task "hello_from_thor" without usage or description/
325
+ end
326
+
327
+ it "does not print if overwriting a previous task" do
328
+ capture(:stdout) {
329
+ klass = Class.new(Thor)
330
+ klass.class_eval "def help; end"
331
+ }.should be_empty
332
+ end
333
+ end
334
+ end