millisami-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 (82) hide show
  1. data/.autotest +8 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +1 -0
  5. data/CHANGELOG.rdoc +103 -0
  6. data/Gemfile +11 -0
  7. data/LICENSE.md +20 -0
  8. data/README.md +26 -0
  9. data/Thorfile +13 -0
  10. data/bin/rake2thor +86 -0
  11. data/bin/thor +6 -0
  12. data/lib/thor/actions/create_file.rb +105 -0
  13. data/lib/thor/actions/create_link.rb +57 -0
  14. data/lib/thor/actions/directory.rb +93 -0
  15. data/lib/thor/actions/empty_directory.rb +134 -0
  16. data/lib/thor/actions/file_manipulation.rb +270 -0
  17. data/lib/thor/actions/inject_into_file.rb +109 -0
  18. data/lib/thor/actions.rb +314 -0
  19. data/lib/thor/base.rb +598 -0
  20. data/lib/thor/core_ext/file_binary_read.rb +9 -0
  21. data/lib/thor/core_ext/hash_with_indifferent_access.rb +75 -0
  22. data/lib/thor/core_ext/ordered_hash.rb +100 -0
  23. data/lib/thor/error.rb +30 -0
  24. data/lib/thor/group.rb +276 -0
  25. data/lib/thor/invocation.rb +168 -0
  26. data/lib/thor/parser/argument.rb +67 -0
  27. data/lib/thor/parser/arguments.rb +165 -0
  28. data/lib/thor/parser/option.rb +120 -0
  29. data/lib/thor/parser/options.rb +181 -0
  30. data/lib/thor/parser.rb +4 -0
  31. data/lib/thor/rake_compat.rb +70 -0
  32. data/lib/thor/runner.rb +309 -0
  33. data/lib/thor/shell/basic.rb +302 -0
  34. data/lib/thor/shell/color.rb +108 -0
  35. data/lib/thor/shell/html.rb +121 -0
  36. data/lib/thor/shell.rb +88 -0
  37. data/lib/thor/task.rb +129 -0
  38. data/lib/thor/util.rb +229 -0
  39. data/lib/thor/version.rb +3 -0
  40. data/lib/thor.rb +336 -0
  41. data/spec/actions/create_file_spec.rb +170 -0
  42. data/spec/actions/directory_spec.rb +136 -0
  43. data/spec/actions/empty_directory_spec.rb +98 -0
  44. data/spec/actions/file_manipulation_spec.rb +317 -0
  45. data/spec/actions/inject_into_file_spec.rb +135 -0
  46. data/spec/actions_spec.rb +322 -0
  47. data/spec/base_spec.rb +274 -0
  48. data/spec/core_ext/hash_with_indifferent_access_spec.rb +43 -0
  49. data/spec/core_ext/ordered_hash_spec.rb +115 -0
  50. data/spec/fixtures/application.rb +2 -0
  51. data/spec/fixtures/bundle/execute.rb +6 -0
  52. data/spec/fixtures/bundle/main.thor +1 -0
  53. data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
  54. data/spec/fixtures/doc/README +3 -0
  55. data/spec/fixtures/doc/block_helper.rb +3 -0
  56. data/spec/fixtures/doc/components/.empty_directory +0 -0
  57. data/spec/fixtures/doc/config.rb +1 -0
  58. data/spec/fixtures/doc/config.yaml.tt +1 -0
  59. data/spec/fixtures/group.thor +114 -0
  60. data/spec/fixtures/invoke.thor +112 -0
  61. data/spec/fixtures/path with spaces +0 -0
  62. data/spec/fixtures/script.thor +184 -0
  63. data/spec/fixtures/task.thor +10 -0
  64. data/spec/group_spec.rb +216 -0
  65. data/spec/invocation_spec.rb +100 -0
  66. data/spec/parser/argument_spec.rb +47 -0
  67. data/spec/parser/arguments_spec.rb +65 -0
  68. data/spec/parser/option_spec.rb +202 -0
  69. data/spec/parser/options_spec.rb +329 -0
  70. data/spec/rake_compat_spec.rb +72 -0
  71. data/spec/register_spec.rb +92 -0
  72. data/spec/runner_spec.rb +210 -0
  73. data/spec/shell/basic_spec.rb +223 -0
  74. data/spec/shell/color_spec.rb +41 -0
  75. data/spec/shell/html_spec.rb +27 -0
  76. data/spec/shell_spec.rb +47 -0
  77. data/spec/spec_helper.rb +54 -0
  78. data/spec/task_spec.rb +74 -0
  79. data/spec/thor_spec.rb +362 -0
  80. data/spec/util_spec.rb +163 -0
  81. data/thor.gemspec +25 -0
  82. metadata +241 -0
@@ -0,0 +1,216 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Thor::Group do
4
+ describe "task" do
5
+ it "allows to use private methods from parent class as tasks" do
6
+ ChildGroup.start.should == ["bar", "foo", "baz"]
7
+ ChildGroup.new.baz("bar").should == "bar"
8
+ end
9
+ end
10
+
11
+ describe "#start" do
12
+ it "invokes all the tasks under the Thor group" do
13
+ MyCounter.start(["1", "2", "--third", "3"]).should == [ 1, 2, 3 ]
14
+ end
15
+
16
+ it "uses argument default value" do
17
+ MyCounter.start(["1", "--third", "3"]).should == [ 1, 2, 3 ]
18
+ end
19
+
20
+ it "invokes all the tasks in the Thor group and his parents" do
21
+ BrokenCounter.start(["1", "2", "--third", "3"]).should == [ nil, 2, 3, false, 5 ]
22
+ end
23
+
24
+ it "raises an error if a required argument is added after a non-required" do
25
+ lambda {
26
+ MyCounter.argument(:foo, :type => :string)
27
+ }.should raise_error(ArgumentError, 'You cannot have "foo" as required argument after the non-required argument "second".')
28
+ end
29
+
30
+ it "raises when an exception happens within the task call" do
31
+ lambda { BrokenCounter.start(["1", "2", "--fail"]) }.should raise_error
32
+ end
33
+
34
+ it "raises an error when a Thor group task expects arguments" do
35
+ lambda { WhinyGenerator.start }.should raise_error(ArgumentError, /Are you sure it has arity equals to 0\?/)
36
+ end
37
+
38
+ it "invokes help message if any of the shortcuts is given" do
39
+ MyCounter.should_receive(:help)
40
+ MyCounter.start(["-h"])
41
+ end
42
+ end
43
+
44
+ describe "#desc" do
45
+ it "sets the description for a given class" do
46
+ MyCounter.desc.should == "Description:\n This generator runs three tasks: one, two and three.\n"
47
+ end
48
+
49
+ it "can be inherited" do
50
+ BrokenCounter.desc.should == "Description:\n This generator runs three tasks: one, two and three.\n"
51
+ end
52
+
53
+ it "can be nil" do
54
+ WhinyGenerator.desc.should be_nil
55
+ end
56
+ end
57
+
58
+ describe "#help" do
59
+ before(:each) do
60
+ @content = capture(:stdout){ MyCounter.help(Thor::Base.shell.new) }
61
+ end
62
+
63
+ it "provides usage information" do
64
+ @content.should =~ /my_counter N \[N\]/
65
+ end
66
+
67
+ it "shows description" do
68
+ @content.should =~ /Description:/
69
+ @content.should =~ /This generator runs three tasks: one, two and three./
70
+ end
71
+
72
+ it "shows options information" do
73
+ @content.should =~ /Options/
74
+ @content.should =~ /\[\-\-third=THREE\]/
75
+ end
76
+ end
77
+
78
+ describe "#invoke" do
79
+ before(:each) do
80
+ @content = capture(:stdout){ E.start }
81
+ end
82
+
83
+ it "allows to invoke a class from the class binding" do
84
+ @content.should =~ /1\n2\n3\n4\n5\n/
85
+ end
86
+
87
+ it "shows invocation information to the user" do
88
+ @content.should =~ /invoke Defined/
89
+ end
90
+
91
+ it "uses padding on status generated by the invoked class" do
92
+ @content.should =~ /finished counting/
93
+ end
94
+
95
+ it "allows invocation to be configured with blocks" do
96
+ capture(:stdout) do
97
+ F.start.should == ["Valim, Jose"]
98
+ end
99
+ end
100
+
101
+ it "shows invoked options on help" do
102
+ content = capture(:stdout){ E.help(Thor::Base.shell.new) }
103
+ content.should =~ /Defined options:/
104
+ content.should =~ /\[--unused\]/
105
+ content.should =~ /# This option has no use/
106
+ end
107
+ end
108
+
109
+ describe "#invoke_from_option" do
110
+ describe "with default type" do
111
+ before(:each) do
112
+ @content = capture(:stdout){ G.start }
113
+ end
114
+
115
+ it "allows to invoke a class from the class binding by a default option" do
116
+ @content.should =~ /1\n2\n3\n4\n5\n/
117
+ end
118
+
119
+ it "does not invoke if the option is nil" do
120
+ capture(:stdout){ G.start(["--skip-invoked"]) }.should_not =~ /invoke/
121
+ end
122
+
123
+ it "prints a message if invocation cannot be found" do
124
+ content = capture(:stdout){ G.start(["--invoked", "unknown"]) }
125
+ content.should =~ /error unknown \[not found\]/
126
+ end
127
+
128
+ it "allows to invoke a class from the class binding by the given option" do
129
+ content = capture(:stdout){ G.start(["--invoked", "e"]) }
130
+ content.should =~ /invoke e/
131
+ end
132
+
133
+ it "shows invocation information to the user" do
134
+ @content.should =~ /invoke defined/
135
+ end
136
+
137
+ it "uses padding on status generated by the invoked class" do
138
+ @content.should =~ /finished counting/
139
+ end
140
+
141
+ it "shows invoked options on help" do
142
+ content = capture(:stdout){ G.help(Thor::Base.shell.new) }
143
+ content.should =~ /defined options:/
144
+ content.should =~ /\[--unused\]/
145
+ content.should =~ /# This option has no use/
146
+ end
147
+ end
148
+
149
+ describe "with boolean type" do
150
+ before(:each) do
151
+ @content = capture(:stdout){ H.start }
152
+ end
153
+
154
+ it "allows to invoke a class from the class binding by a default option" do
155
+ @content.should =~ /1\n2\n3\n4\n5\n/
156
+ end
157
+
158
+ it "does not invoke if the option is false" do
159
+ capture(:stdout){ H.start(["--no-defined"]) }.should_not =~ /invoke/
160
+ end
161
+
162
+ it "shows invocation information to the user" do
163
+ @content.should =~ /invoke defined/
164
+ end
165
+
166
+ it "uses padding on status generated by the invoked class" do
167
+ @content.should =~ /finished counting/
168
+ end
169
+
170
+ it "shows invoked options on help" do
171
+ content = capture(:stdout){ H.help(Thor::Base.shell.new) }
172
+ content.should =~ /defined options:/
173
+ content.should =~ /\[--unused\]/
174
+ content.should =~ /# This option has no use/
175
+ end
176
+ end
177
+ end
178
+
179
+ describe "edge-cases" do
180
+ it "can handle boolean options followed by arguments" do
181
+ klass = Class.new(Thor::Group) do
182
+ desc "say hi to name"
183
+ argument :name, :type => :string
184
+ class_option :loud, :type => :boolean
185
+
186
+ def hi
187
+ name.upcase! if options[:loud]
188
+ "Hi #{name}"
189
+ end
190
+ end
191
+
192
+ klass.start(["jose"]).should == ["Hi jose"]
193
+ klass.start(["jose", "--loud"]).should == ["Hi JOSE"]
194
+ klass.start(["--loud", "jose"]).should == ["Hi JOSE"]
195
+ end
196
+
197
+ it "provides extra args as `args`" do
198
+ klass = Class.new(Thor::Group) do
199
+ desc "say hi to name"
200
+ argument :name, :type => :string
201
+ class_option :loud, :type => :boolean
202
+
203
+ def hi
204
+ name.upcase! if options[:loud]
205
+ out = "Hi #{name}"
206
+ out << ": " << args.join(", ") unless args.empty?
207
+ out
208
+ end
209
+ end
210
+
211
+ klass.start(["jose"]).should == ["Hi jose"]
212
+ klass.start(["jose", "--loud"]).should == ["Hi JOSE"]
213
+ klass.start(["--loud", "jose"]).should == ["Hi JOSE"]
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,100 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'thor/base'
3
+
4
+ describe Thor::Invocation do
5
+ describe "#invoke" do
6
+ it "invokes a task inside another task" do
7
+ capture(:stdout){ A.new.invoke(:two) }.should == "2\n3\n"
8
+ end
9
+
10
+ it "invokes a task just once" do
11
+ capture(:stdout){ A.new.invoke(:one) }.should == "1\n2\n3\n"
12
+ end
13
+
14
+ it "invokes a task just once even if they belongs to different classes" do
15
+ capture(:stdout){ Defined.new.invoke(:one) }.should == "1\n2\n3\n4\n5\n"
16
+ end
17
+
18
+ it "invokes a task with arguments" do
19
+ A.new.invoke(:five, [5]).should be_true
20
+ A.new.invoke(:five, [7]).should be_false
21
+ end
22
+
23
+ it "invokes the default task if none is given to a Thor class" do
24
+ content = capture(:stdout){ A.new.invoke("b") }
25
+ content.should =~ /Tasks/
26
+ content.should =~ /LAST_NAME/
27
+ end
28
+
29
+ it "accepts a class as argument without a task to invoke" do
30
+ content = capture(:stdout){ A.new.invoke(B) }
31
+ content.should =~ /Tasks/
32
+ content.should =~ /LAST_NAME/
33
+ end
34
+
35
+ it "accepts a class as argument with a task to invoke" do
36
+ base = A.new([], :last_name => "Valim")
37
+ base.invoke(B, :one, ["Jose"]).should == "Valim, Jose"
38
+ end
39
+
40
+ it "allows customized options to be given" do
41
+ base = A.new([], :last_name => "Wrong")
42
+ base.invoke(B, :one, ["Jose"], :last_name => "Valim").should == "Valim, Jose"
43
+ end
44
+
45
+ it "reparses options in the new class" do
46
+ A.start(["invoker", "--last-name", "Valim"]).should == "Valim, Jose"
47
+ end
48
+
49
+ it "shares initialize options with invoked class" do
50
+ A.new([], :foo => :bar).invoke("b:two").should == { "foo" => :bar }
51
+ end
52
+
53
+ it "dump configuration values to be used in the invoked class" do
54
+ base = A.new
55
+ base.invoke("b:three").shell.should == base.shell
56
+ end
57
+
58
+ it "allow extra configuration values to be given" do
59
+ base, shell = A.new, Thor::Base.shell.new
60
+ base.invoke("b:three", [], {}, :shell => shell).shell.should == shell
61
+ end
62
+
63
+ it "invokes a Thor::Group and all of its tasks" do
64
+ capture(:stdout){ A.new.invoke(:c) }.should == "1\n2\n3\n"
65
+ end
66
+
67
+ it "does not invoke a Thor::Group twice" do
68
+ base = A.new
69
+ silence(:stdout){ base.invoke(:c) }
70
+ capture(:stdout){ base.invoke(:c) }.should be_empty
71
+ end
72
+
73
+ it "does not invoke any of Thor::Group tasks twice" do
74
+ base = A.new
75
+ silence(:stdout){ base.invoke(:c) }
76
+ capture(:stdout){ base.invoke("c:one") }.should be_empty
77
+ end
78
+
79
+ it "raises Thor::UndefinedTaskError if the task can't be found" do
80
+ lambda do
81
+ A.new.invoke("foo:bar")
82
+ end.should raise_error(Thor::UndefinedTaskError)
83
+ end
84
+
85
+ it "raises Thor::UndefinedTaskError if the task can't be found even if all tasks where already executed" do
86
+ base = C.new
87
+ silence(:stdout){ base.invoke_all }
88
+
89
+ lambda do
90
+ base.invoke("foo:bar")
91
+ end.should raise_error(Thor::UndefinedTaskError)
92
+ end
93
+
94
+ it "raises an error if a non Thor class is given" do
95
+ lambda do
96
+ A.new.invoke(Object)
97
+ end.should raise_error(RuntimeError, "Expected Thor class, got Object")
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,47 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'thor/parser'
3
+
4
+ describe Thor::Argument do
5
+
6
+ def argument(name, type=:string, default=nil, required=nil)
7
+ @argument ||= Thor::Argument.new(name, nil, required || default.nil?, type, default)
8
+ end
9
+
10
+ describe "errors" do
11
+ it "raises an error if name is not supplied" do
12
+ lambda {
13
+ argument(nil)
14
+ }.should raise_error(ArgumentError, "Argument name can't be nil.")
15
+ end
16
+
17
+ it "raises an error if type is unknown" do
18
+ lambda {
19
+ argument(:task, :unknown)
20
+ }.should raise_error(ArgumentError, "Type :unknown is not valid for arguments.")
21
+ end
22
+
23
+ it "raises an error if argument is required and have default values" do
24
+ lambda {
25
+ argument(:task, :string, "bar", true)
26
+ }.should raise_error(ArgumentError, "An argument cannot be required and have default value.")
27
+ end
28
+ end
29
+
30
+ describe "#usage" do
31
+ it "returns usage for string types" do
32
+ argument(:foo, :string).usage.should == "FOO"
33
+ end
34
+
35
+ it "returns usage for numeric types" do
36
+ argument(:foo, :numeric).usage.should == "N"
37
+ end
38
+
39
+ it "returns usage for array types" do
40
+ argument(:foo, :array).usage.should == "one two three"
41
+ end
42
+
43
+ it "returns usage for hash types" do
44
+ argument(:foo, :hash).usage.should == "key:value"
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,65 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'thor/parser'
3
+
4
+ describe Thor::Arguments do
5
+ def create(opts={})
6
+ arguments = opts.map do |type, default|
7
+ Thor::Argument.new(type.to_s, nil, default.nil?, type, default)
8
+ end
9
+
10
+ arguments.sort!{ |a,b| b.name <=> a.name }
11
+ @opt = Thor::Arguments.new(arguments)
12
+ end
13
+
14
+ def parse(*args)
15
+ @opt.parse(args)
16
+ end
17
+
18
+ describe "#parse" do
19
+ it "parses arguments in the given order" do
20
+ create :string => nil, :numeric => nil
21
+ parse("name", "13")["string"].should == "name"
22
+ parse("name", "13")["numeric"].should == 13
23
+ end
24
+
25
+ it "accepts hashes" do
26
+ create :string => nil, :hash => nil
27
+ parse("product", "title:string", "age:integer")["string"].should == "product"
28
+ parse("product", "title:string", "age:integer")["hash"].should == { "title" => "string", "age" => "integer"}
29
+ parse("product", "url:http://www.amazon.com/gp/product/123")["hash"].should == { "url" => "http://www.amazon.com/gp/product/123" }
30
+ end
31
+
32
+ it "accepts arrays" do
33
+ create :string => nil, :array => nil
34
+ parse("product", "title", "age")["string"].should == "product"
35
+ parse("product", "title", "age")["array"].should == %w(title age)
36
+ end
37
+
38
+ describe "with no inputs" do
39
+ it "and no arguments returns an empty hash" do
40
+ create
41
+ parse.should == {}
42
+ end
43
+
44
+ it "and required arguments raises an error" do
45
+ create :string => nil, :numeric => nil
46
+ lambda { parse }.should raise_error(Thor::RequiredArgumentMissingError, "No value provided for required arguments 'string', 'numeric'")
47
+ end
48
+
49
+ it "and default arguments returns default values" do
50
+ create :string => "name", :numeric => 13
51
+ parse.should == { "string" => "name", "numeric" => 13 }
52
+ end
53
+ end
54
+
55
+ it "returns the input if it's already parsed" do
56
+ create :string => nil, :hash => nil, :array => nil, :numeric => nil
57
+ parse("", 0, {}, []).should == { "string" => "", "numeric" => 0, "hash" => {}, "array" => [] }
58
+ end
59
+
60
+ it "returns the default value if none is provided" do
61
+ create :string => "foo", :numeric => 3.0
62
+ parse("bar").should == { "string" => "bar", "numeric" => 3.0 }
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,202 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require 'thor/parser'
3
+
4
+ describe Thor::Option do
5
+ def parse(key, value)
6
+ Thor::Option.parse(key, value)
7
+ end
8
+
9
+ def option(name, *args)
10
+ @option ||= Thor::Option.new(name, *args)
11
+ end
12
+
13
+ describe "#parse" do
14
+
15
+ describe "with value as a symbol" do
16
+ describe "and symbol is a valid type" do
17
+ it "has type equals to the symbol" do
18
+ parse(:foo, :string).type.should == :string
19
+ parse(:foo, :numeric).type.should == :numeric
20
+ end
21
+
22
+ it "has not default value" do
23
+ parse(:foo, :string).default.should be_nil
24
+ parse(:foo, :numeric).default.should be_nil
25
+ end
26
+ end
27
+
28
+ describe "equals to :required" do
29
+ it "has type equals to :string" do
30
+ parse(:foo, :required).type.should == :string
31
+ end
32
+
33
+ it "has no default value" do
34
+ parse(:foo, :required).default.should be_nil
35
+ end
36
+ end
37
+
38
+ describe "and symbol is not a reserved key" do
39
+ it "has type equals to :string" do
40
+ parse(:foo, :bar).type.should == :string
41
+ end
42
+
43
+ it "has no default value" do
44
+ parse(:foo, :bar).default.should be_nil
45
+ end
46
+ end
47
+ end
48
+
49
+ describe "with value as hash" do
50
+ it "has default type :hash" do
51
+ parse(:foo, :a => :b).type.should == :hash
52
+ end
53
+
54
+ it "has default value equals to the hash" do
55
+ parse(:foo, :a => :b).default.should == { :a => :b }
56
+ end
57
+ end
58
+
59
+ describe "with value as array" do
60
+ it "has default type :array" do
61
+ parse(:foo, [:a, :b]).type.should == :array
62
+ end
63
+
64
+ it "has default value equals to the array" do
65
+ parse(:foo, [:a, :b]).default.should == [:a, :b]
66
+ end
67
+ end
68
+
69
+ describe "with value as string" do
70
+ it "has default type :string" do
71
+ parse(:foo, "bar").type.should == :string
72
+ end
73
+
74
+ it "has default value equals to the string" do
75
+ parse(:foo, "bar").default.should == "bar"
76
+ end
77
+ end
78
+
79
+ describe "with value as numeric" do
80
+ it "has default type :numeric" do
81
+ parse(:foo, 2.0).type.should == :numeric
82
+ end
83
+
84
+ it "has default value equals to the numeric" do
85
+ parse(:foo, 2.0).default.should == 2.0
86
+ end
87
+ end
88
+
89
+ describe "with value as boolean" do
90
+ it "has default type :boolean" do
91
+ parse(:foo, true).type.should == :boolean
92
+ parse(:foo, false).type.should == :boolean
93
+ end
94
+
95
+ it "has default value equals to the boolean" do
96
+ parse(:foo, true).default.should == true
97
+ parse(:foo, false).default.should == false
98
+ end
99
+ end
100
+
101
+ describe "with key as a symbol" do
102
+ it "sets the name equals to the key" do
103
+ parse(:foo, true).name.should == "foo"
104
+ end
105
+ end
106
+
107
+ describe "with key as an array" do
108
+ it "sets the first items in the array to the name" do
109
+ parse([:foo, :bar, :baz], true).name.should == "foo"
110
+ end
111
+
112
+ it "sets all other items as aliases" do
113
+ parse([:foo, :bar, :baz], true).aliases.should == [:bar, :baz]
114
+ end
115
+ end
116
+ end
117
+
118
+ it "returns the switch name" do
119
+ option("foo").switch_name.should == "--foo"
120
+ option("--foo").switch_name.should == "--foo"
121
+ end
122
+
123
+ it "returns the human name" do
124
+ option("foo").human_name.should == "foo"
125
+ option("--foo").human_name.should == "foo"
126
+ end
127
+
128
+ it "converts underscores to dashes" do
129
+ option("foo_bar").switch_name.should == "--foo-bar"
130
+ end
131
+
132
+ it "can be required and have default values" do
133
+ option = option("foo", nil, true, :string, "bar")
134
+ option.default.should == "bar"
135
+ option.should be_required
136
+ end
137
+
138
+ it "cannot be required and have type boolean" do
139
+ lambda {
140
+ option("foo", nil, true, :boolean)
141
+ }.should raise_error(ArgumentError, "An option cannot be boolean and required.")
142
+ end
143
+
144
+ it "allows type predicates" do
145
+ parse(:foo, :string).should be_string
146
+ parse(:foo, :boolean).should be_boolean
147
+ parse(:foo, :numeric).should be_numeric
148
+ end
149
+
150
+ it "raises an error on method missing" do
151
+ lambda {
152
+ parse(:foo, :string).unknown?
153
+ }.should raise_error(NoMethodError)
154
+ end
155
+
156
+ describe "#usage" do
157
+
158
+ it "returns usage for string types" do
159
+ parse(:foo, :string).usage.should == "[--foo=FOO]"
160
+ end
161
+
162
+ it "returns usage for numeric types" do
163
+ parse(:foo, :numeric).usage.should == "[--foo=N]"
164
+ end
165
+
166
+ it "returns usage for array types" do
167
+ parse(:foo, :array).usage.should == "[--foo=one two three]"
168
+ end
169
+
170
+ it "returns usage for hash types" do
171
+ parse(:foo, :hash).usage.should == "[--foo=key:value]"
172
+ end
173
+
174
+ it "returns usage for boolean types" do
175
+ parse(:foo, :boolean).usage.should == "[--foo]"
176
+ end
177
+
178
+ it "uses padding when no aliases is given" do
179
+ parse(:foo, :boolean).usage(4).should == " [--foo]"
180
+ end
181
+
182
+ it "uses banner when supplied" do
183
+ option(:foo, nil, false, :string, nil, "BAR").usage.should == "[--foo=BAR]"
184
+ end
185
+
186
+ it "checkes when banner is an empty string" do
187
+ option(:foo, nil, false, :string, nil, "").usage.should == "[--foo]"
188
+ end
189
+
190
+ describe "with required values" do
191
+ it "does not show the usage between brackets" do
192
+ parse(:foo, :required).usage.should == "--foo=FOO"
193
+ end
194
+ end
195
+
196
+ describe "with aliases" do
197
+ it "does not show the usage between brackets" do
198
+ parse([:foo, "-f", "-b"], :required).usage.should == "-f, -b, --foo=FOO"
199
+ end
200
+ end
201
+ end
202
+ end