bosonson 0.304.1

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 (61) hide show
  1. data/CHANGELOG.rdoc +108 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.rdoc +181 -0
  4. data/bin/bss +6 -0
  5. data/bosonson.gemspec +24 -0
  6. data/deps.rip +2 -0
  7. data/lib/boson.rb +96 -0
  8. data/lib/boson/command.rb +196 -0
  9. data/lib/boson/commands.rb +7 -0
  10. data/lib/boson/commands/core.rb +77 -0
  11. data/lib/boson/commands/web_core.rb +153 -0
  12. data/lib/boson/index.rb +48 -0
  13. data/lib/boson/inspector.rb +120 -0
  14. data/lib/boson/inspectors/argument_inspector.rb +97 -0
  15. data/lib/boson/inspectors/comment_inspector.rb +100 -0
  16. data/lib/boson/inspectors/method_inspector.rb +98 -0
  17. data/lib/boson/libraries/file_library.rb +144 -0
  18. data/lib/boson/libraries/gem_library.rb +30 -0
  19. data/lib/boson/libraries/local_file_library.rb +30 -0
  20. data/lib/boson/libraries/module_library.rb +37 -0
  21. data/lib/boson/libraries/require_library.rb +23 -0
  22. data/lib/boson/library.rb +179 -0
  23. data/lib/boson/loader.rb +118 -0
  24. data/lib/boson/manager.rb +169 -0
  25. data/lib/boson/namespace.rb +31 -0
  26. data/lib/boson/option_command.rb +222 -0
  27. data/lib/boson/option_parser.rb +475 -0
  28. data/lib/boson/options.rb +146 -0
  29. data/lib/boson/pipe.rb +147 -0
  30. data/lib/boson/pipes.rb +75 -0
  31. data/lib/boson/repo.rb +107 -0
  32. data/lib/boson/repo_index.rb +124 -0
  33. data/lib/boson/runner.rb +81 -0
  34. data/lib/boson/runners/bin_runner.rb +208 -0
  35. data/lib/boson/runners/console_runner.rb +58 -0
  36. data/lib/boson/scientist.rb +182 -0
  37. data/lib/boson/util.rb +129 -0
  38. data/lib/boson/version.rb +3 -0
  39. data/lib/boson/view.rb +95 -0
  40. data/test/argument_inspector_test.rb +62 -0
  41. data/test/bin_runner_test.rb +223 -0
  42. data/test/command_test.rb +22 -0
  43. data/test/commands_test.rb +22 -0
  44. data/test/comment_inspector_test.rb +126 -0
  45. data/test/deps.rip +4 -0
  46. data/test/file_library_test.rb +42 -0
  47. data/test/loader_test.rb +235 -0
  48. data/test/manager_test.rb +114 -0
  49. data/test/method_inspector_test.rb +90 -0
  50. data/test/option_parser_test.rb +367 -0
  51. data/test/options_test.rb +189 -0
  52. data/test/pipes_test.rb +65 -0
  53. data/test/repo_index_test.rb +122 -0
  54. data/test/repo_test.rb +23 -0
  55. data/test/runner_test.rb +40 -0
  56. data/test/scientist_test.rb +341 -0
  57. data/test/test_helper.rb +130 -0
  58. data/test/util_test.rb +56 -0
  59. data/vendor/bundle/gems/bacon-bits-0.1.0/deps.rip +1 -0
  60. data/vendor/bundle/gems/hirb-0.6.0/test/deps.rip +4 -0
  61. metadata +217 -0
@@ -0,0 +1,114 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ describe "Manager" do
4
+ describe ".after_load" do
5
+ def load_library(hash)
6
+ new_attributes = {:name=>hash[:name], :commands=>[], :created_dependencies=>[], :loaded=>true}
7
+ [:module, :commands].each {|e| new_attributes[e] = hash.delete(e) if hash[e] }
8
+ Manager.expects(:rescue_load_action).returns(Library.new(new_attributes))
9
+ Manager.load([hash[:name]])
10
+ end
11
+
12
+ before { reset_boson }
13
+
14
+ it "loads basic library" do
15
+ load_library :name=>'blah'
16
+ library_loaded? 'blah'
17
+ end
18
+
19
+ it "loads library with commands" do
20
+ load_library :name=>'blah', :commands=>['frylock','meatwad']
21
+ library_loaded? 'blah'
22
+ command_exists?('frylock')
23
+ command_exists?('meatwad')
24
+ end
25
+
26
+ it "prints error for library with SyntaxError" do
27
+ Manager.expects(:loader_create).raises(SyntaxError)
28
+ capture_stderr {
29
+ Manager.load 'blah'
30
+ }.should =~ /Unable to load library blah. Reason: SyntaxError/
31
+ end
32
+
33
+ it "prints error for library with LoadError" do
34
+ Manager.expects(:loader_create).raises(LoadError)
35
+ capture_stderr {
36
+ Manager.load 'blah'
37
+ }.should =~ /Unable to load library blah. Reason: LoadError/
38
+ end
39
+
40
+ describe "command aliases" do
41
+ before { eval %[module ::Aquateen; def frylock; end; end] }
42
+ after { Object.send(:remove_const, "Aquateen") }
43
+
44
+ it "created with command specific config" do
45
+ with_config(:command_aliases=>{'frylock'=>'fr'}) do
46
+ Manager.expects(:create_instance_aliases).with({"Aquateen"=>{"frylock"=>"fr"}})
47
+ load_library :name=>'aquateen', :commands=>['frylock'], :module=>Aquateen
48
+ library_loaded? 'aquateen'
49
+ end
50
+ end
51
+
52
+ it "created with config command_aliases" do
53
+ with_config(:command_aliases=>{"frylock"=>"fr"}) do
54
+ Manager.expects(:create_instance_aliases).with({"Aquateen"=>{"frylock"=>"fr"}})
55
+ load_library :name=>'aquateen', :commands=>['frylock'], :module=>Aquateen
56
+ library_loaded? 'aquateen'
57
+ end
58
+ end
59
+
60
+ it "not created and warns for commands with no module" do
61
+ with_config(:command_aliases=>{'frylock'=>'fr'}) do
62
+ capture_stderr {
63
+ load_library(:name=>'aquateen', :commands=>['frylock'])
64
+ }.should =~ /No aliases/
65
+ library_loaded? 'aquateen'
66
+ Aquateen.method_defined?(:fr).should == false
67
+ end
68
+ end
69
+ end
70
+
71
+ it "merges with existing created library" do
72
+ create_library('blah')
73
+ load_library :name=>'blah'
74
+ library_loaded? 'blah'
75
+ Boson.libraries.size.should == 1
76
+ end
77
+ end
78
+
79
+ describe "option commands without args" do
80
+ before_all {
81
+ reset_boson
82
+ @library = Library.new(:name=>'blah', :commands=>['foo', 'bar'])
83
+ Boson.libraries << @library
84
+ @foo = Command.new(:name=>'foo', :lib=>'blah', :options=>{:fool=>:string}, :args=>'*')
85
+ Boson.commands << @foo
86
+ Boson.commands << Command.new(:name=>'bar', :lib=>'blah', :options=>{:bah=>:string})
87
+ }
88
+
89
+ it "are deleted" do
90
+ Scientist.expects(:redefine_command).with(anything, @foo)
91
+ Manager.redefine_commands(@library, @library.commands)
92
+ end
93
+
94
+ it "are deleted and printed when verbose" do
95
+ Scientist.expects(:redefine_command).with(anything, @foo)
96
+ @library.instance_eval("@options = {:verbose=>true}")
97
+ capture_stdout { Manager.redefine_commands(@library, @library.commands) } =~ /options.*blah/
98
+ end
99
+ end
100
+
101
+ describe ".loaded?" do
102
+ before { reset_libraries }
103
+
104
+ it "returns false when library isn't loaded" do
105
+ create_library('blah')
106
+ Manager.loaded?('blah').should == false
107
+ end
108
+
109
+ it "returns true when library is loaded" do
110
+ create_library('blah', :loaded=>true)
111
+ Manager.loaded?('blah').should == true
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,90 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ describe "MethodInspector" do
4
+ it "non commands module can't set anything" do
5
+ eval "module Blah; end"
6
+ MethodInspector.current_module = Blah
7
+ Inspector.enable
8
+ Blah.module_eval("desc 'test'; def test; end; options :a=>1; def test2; end")
9
+ Inspector.disable
10
+ MethodInspector.store[:desc].empty?.should == true
11
+ MethodInspector.store[:options].empty?.should == true
12
+ end
13
+
14
+ it "handles anonymous classes" do
15
+ MethodInspector.mod_store = {}
16
+ Inspector.enable
17
+ Class.new.module_eval "def blah; end"
18
+ Inspector.disable
19
+ MethodInspector.store.should == nil
20
+ end
21
+
22
+ describe "commands module with" do
23
+ def parse(string)
24
+ Inspector.enable
25
+ ::Boson::Commands::Zzz.module_eval(string)
26
+ Inspector.disable
27
+ MethodInspector.store
28
+ end
29
+
30
+ before_all { eval "module ::Boson::Commands::Zzz; end" }
31
+ before { MethodInspector.mod_store.delete(::Boson::Commands::Zzz) }
32
+
33
+ it "desc sets descriptions" do
34
+ parsed = parse "desc 'test'; def m1; end; desc 'one'; desc 'more'; def m2; end"
35
+ parsed[:desc].should == {"m1"=>"test", "m2"=>"more"}
36
+ end
37
+
38
+ it "options sets options" do
39
+ parse("options :z=>'b'; def zee; end")[:options].should == {"zee"=>{:z=>'b'}}
40
+ end
41
+
42
+ it "option sets options" do
43
+ parse("option :z, 'b'; option :y, :boolean; def zee; end")[:options].should ==
44
+ {"zee"=>{:z=>'b', :y=>:boolean}}
45
+ end
46
+
47
+ it "option(s) sets options" do
48
+ parse("options :z=>'b'; option :y, :string; def zee; end")[:options].should ==
49
+ {"zee"=>{:z=>'b', :y=>:string}}
50
+ end
51
+
52
+ it "option(s) option overrides options" do
53
+ parse("options :z=>'b'; option :z, :string; def zee; end")[:options].should ==
54
+ {"zee"=>{:z=>:string}}
55
+ end
56
+
57
+ it "render_options sets render_options" do
58
+ parse("render_options :z=>true; def zee; end")[:render_options].should == {"zee"=>{:z=>true}}
59
+ end
60
+
61
+ it "config sets config" do
62
+ parse("config :z=>true; def zee; end")[:config].should == {"zee"=>{:z=>true}}
63
+ end
64
+
65
+ it "not all method attributes set causes method_locations to be set" do
66
+ MethodInspector.stubs(:find_method_locations).returns(["/some/path", 10])
67
+ parsed = parse "desc 'yo'; def yo; end; options :yep=>1; def yep; end; " +
68
+ "option :b, :boolean; render_options :a=>1; config :a=>1; desc 'z'; options :a=>1; def az; end"
69
+ parsed[:method_locations].key?('yo').should == true
70
+ parsed[:method_locations].key?('yep').should == true
71
+ parsed[:method_locations].key?('az').should == false
72
+ end
73
+
74
+ it "no find_method_locations doesn't set method_locations" do
75
+ MethodInspector.stubs(:find_method_locations).returns(nil)
76
+ parse("def bluh; end")[:method_locations].key?('bluh').should == false
77
+ end
78
+
79
+ it "options calls scrape_with_eval" do
80
+ ArgumentInspector.expects(:scrape_with_eval).returns([['arg1']])
81
+ parse("desc 'desc'; options :some=>:opts; def doy(arg1); end")[:args]['doy'].should == [['arg1']]
82
+ end
83
+
84
+ it "options in file calls scrape_with_eval" do
85
+ MethodInspector.expects(:inspector_in_file?).returns(true)
86
+ ArgumentInspector.expects(:scrape_with_eval).returns([['arg1']])
87
+ parse("desc 'desc'; def doz(arg1); end")[:args]['doz'].should == [['arg1']]
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,367 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ describe "OptionParser" do
4
+ def create(opts)
5
+ @opt = OptionParser.new(opts)
6
+ end
7
+
8
+ def opt; @opt; end
9
+
10
+ def parse(*args)
11
+ @non_opts = []
12
+ opt.parse(args.flatten)
13
+ end
14
+
15
+ describe "IndifferentAccessHash" do
16
+ before {
17
+ @hash = IndifferentAccessHash.new 'foo' => 'bar', 'baz' => 'bee'
18
+ }
19
+ it "can access values indifferently" do
20
+ @hash['foo'].should == 'bar'
21
+ @hash[:foo].should == 'bar'
22
+ @hash.values_at(:foo, :baz).should == ['bar', 'bee']
23
+ end
24
+
25
+ it "can be initialized with either strings or symbols and be equal" do
26
+ hash2 = IndifferentAccessHash.new :foo=>'bar', :baz=>'bee'
27
+ @hash.should == hash2
28
+ end
29
+
30
+ it "returns keys as symbols by default" do
31
+ @hash.should == {:foo=>'bar', :baz=>'bee'}
32
+ end
33
+
34
+ it "can set values indifferently" do
35
+ @hash['foo'] = 'duh'
36
+ @hash[:foo].should == 'duh'
37
+ @hash[:baz] = 'wasp'
38
+ @hash['baz'].should == 'wasp'
39
+ end
40
+ end
41
+
42
+ describe "naming" do
43
+ it "automatically aliases long options with their first letter" do
44
+ create "--foo" => true
45
+ parse("-f")["foo"].should == true
46
+ end
47
+
48
+ it "automatically aliases two options with same first letters by aliasing alphabetical first with lowercase and second with uppercase" do
49
+ create :verbose=>:boolean, :vertical=>:string, :verz=>:boolean
50
+ parse('-v', '-V','2').should == {:verbose=>true, :vertical=>'2'}
51
+ end
52
+
53
+ it "doesn't auto-alias options that have multiple names given" do
54
+ create ["--foo", "--bar"] => :boolean
55
+ parse("-f")["foo"].should == nil
56
+ end
57
+
58
+ it "allows aliases to be symbols or strings" do
59
+ create [:foo, :bar, 'baz'] =>:string
60
+ parse("--foo", "12")[:foo].should == "12"
61
+ parse("--bar", "12")[:foo].should == "12"
62
+ parse("--baz", "12")[:foo].should == "12"
63
+ end
64
+
65
+ it "allows multiple aliases for a given opt" do
66
+ create ["--foo", "--bar", "--baz"] => :string
67
+ parse("--foo", "12")["foo"].should == "12"
68
+ parse("--bar", "12")["foo"].should == "12"
69
+ parse("--baz", "12")["foo"].should == "12"
70
+ end
71
+
72
+ it "allows custom short names" do
73
+ create "-f" => :string
74
+ parse("-f", "12").should == {:f => "12"}
75
+ end
76
+
77
+ it "allows capital short names" do
78
+ create :A => :boolean
79
+ parse("-A")[:A].should == true
80
+ end
81
+
82
+ it "allows capital short aliases" do
83
+ create [:awesome, :A] => :string
84
+ parse("--awesome", "bar")[:awesome].should == 'bar'
85
+ parse("-A", "bar")[:awesome].should == 'bar'
86
+ end
87
+
88
+ it "allows custom short aliases" do
89
+ create ["--bar", "-f"] => :string
90
+ parse("-f", "12").should == {:bar => "12"}
91
+ end
92
+
93
+ it "allows humanized opt name" do
94
+ create 'foo' => :string, :bar => :string
95
+ parse("-f", "1", "-b", "2").should == {:foo => "1", :bar => "2"}
96
+ end
97
+
98
+ it "allows humanized symbol opt name" do
99
+ create :foo=>:string
100
+ parse('-f','1').should == {:foo=>'1'}
101
+ end
102
+
103
+ it "doesn't allow alias to override another option" do
104
+ create :foo=>:string, [:bar, :foo]=>:boolean
105
+ parse("--foo", "boo")[:foo].should == 'boo'
106
+ end
107
+
108
+ it "doesn't recognize long opt format for a opt that is originally short" do
109
+ create 'f' => :string
110
+ parse("-f", "1").should == {:f => "1"}
111
+ parse("--f", "1").should == {}
112
+ end
113
+
114
+ it "accepts --[no-]opt variant for booleans, setting false for value" do
115
+ create "--foo" => :boolean
116
+ parse("--no-foo")["foo"].should == false
117
+ parse("--no-f")["foo"].should == false
118
+ parse("--foo")["foo"].should == true
119
+ end
120
+
121
+ it "accepts --[no-]opt variant for single letter booleans" do
122
+ create :e=>true
123
+ parse("--no-e")[:e].should == false
124
+ end
125
+
126
+ it "will prefer 'no-opt' variant over inverting 'opt' if explicitly set" do
127
+ create "--no-foo" => true
128
+ parse("--no-foo")["no-foo"].should == true
129
+ end
130
+
131
+ end
132
+
133
+ describe "option values can be set with" do
134
+ it "a opt=<value> assignment" do
135
+ create :foo => :string
136
+ parse("--foo=12")["foo"].should == "12"
137
+ parse("-f=12")["foo"].should == "12"
138
+ parse("--foo=bar=baz")["foo"].should == "bar=baz"
139
+ parse("--foo=sentence with spaces")["foo"].should == "sentence with spaces"
140
+ end
141
+
142
+ it "a -nXY assignment" do
143
+ create "--num" => :numeric
144
+ parse("-n12")["num"].should == 12
145
+ end
146
+
147
+ it "conjoined short options" do
148
+ create "--foo" => true, "--bar" => true, "--app" => true
149
+ opts = parse "-fba"
150
+ opts["foo"].should == true
151
+ opts["bar"].should == true
152
+ opts["app"].should == true
153
+ end
154
+
155
+ it "conjoined short options with argument" do
156
+ create "--foo" => true, "--bar" => true, "--app" => :numeric
157
+ opts = parse "-fba", "12"
158
+ opts["foo"].should == true
159
+ opts["bar"].should == true
160
+ opts["app"].should == 12
161
+ end
162
+ end
163
+
164
+ describe "parse" do
165
+ it "extracts non-option arguments" do
166
+ create "--foo" => :string, "--bar" => true
167
+ parse("foo", "bar", "--baz", "--foo", "12", "--bar", "-T", "bang").should == {
168
+ :foo => "12", :bar => true
169
+ }
170
+ opt.leading_non_opts.should == ["foo", "bar", "--baz"]
171
+ opt.trailing_non_opts.should == ["-T", "bang"]
172
+ opt.non_opts.should == ["foo", "bar", "--baz", "-T", "bang"]
173
+ end
174
+
175
+ it "stopped by --" do
176
+ create :foo=>:boolean, :dude=>:boolean
177
+ parse("foo", "bar", "--", "-f").should == {}
178
+ opt.leading_non_opts.should == %w{foo bar}
179
+ opt.trailing_non_opts.should == %w{-- -f}
180
+ end
181
+
182
+ describe "with parse flag" do
183
+ it ":delete_invalid_opts deletes and warns of invalid options" do
184
+ create(:foo=>:boolean)
185
+ capture_stderr {
186
+ opt.parse(%w{-f -d ok}, :delete_invalid_opts=>true)
187
+ }.should =~ /Deleted invalid option '-d'/
188
+ opt.non_opts.should == ['ok']
189
+ end
190
+
191
+ it ":delete_invalid_opts deletes until - or --" do
192
+ create(:foo=>:boolean, :bar=>:boolean)
193
+ %w{- --}.each do |stop_char|
194
+ capture_stderr {
195
+ opt.parse(%w{ok -b -d} << stop_char << '-f', :delete_invalid_opts=>true)
196
+ }.should =~ /'-d'/
197
+ opt.non_opts.should == %w{ok -d} << stop_char << '-f'
198
+ end
199
+ end
200
+
201
+ it ":opts_before_args only allows options before args" do
202
+ create(:foo=>:boolean)
203
+ opt.parse(%w{ok -f}, :opts_before_args=>true).should == {}
204
+ opt.parse(%w{-f ok}, :opts_before_args=>true).should == {:foo=>true}
205
+ end
206
+ end
207
+
208
+ describe "with no arguments" do
209
+ it "and no options returns an empty hash" do
210
+ create({})
211
+ parse.should == {}
212
+ end
213
+
214
+ it "and several options returns an empty hash" do
215
+ create "--foo" => :boolean, "--bar" => :string
216
+ parse.should == {}
217
+ end
218
+ end
219
+ end
220
+
221
+ describe "option hashes" do
222
+ it "make hash keys available as symbols as well" do
223
+ create "--foo" => :string
224
+ parse("--foo", "12")[:foo].should == "12"
225
+ end
226
+
227
+ it "don't set nonexistant options" do
228
+ create "--foo" => :boolean
229
+ parse("--foo")["bar"].should == nil
230
+ opts = parse
231
+ opts["foo"].should == nil
232
+ end
233
+ end
234
+
235
+ describe ":required option attribute" do
236
+ before_all {
237
+ create "--foo" => {:type=>:string, :required=>true}, :bar => {:type=>:hash, :required=>true}
238
+ }
239
+
240
+ it "raises an error if string option isn't given" do
241
+ assert_error(OptionParser::Error, 'no value.*required.*foo') { parse("--bar", "str:ok") }
242
+ end
243
+
244
+ it "raises an error if non-string option isn't given" do
245
+ assert_error(OptionParser::Error, 'no value.*required.*bar') { parse("--foo", "yup") }
246
+ end
247
+
248
+ it "raises no error when given arguments" do
249
+ parse("--foo", "yup", "--bar","ok:dude").should == {:foo=>'yup', :bar=>{'ok'=>'dude'}}
250
+ end
251
+ end
252
+
253
+ describe ":bool_default option attribute" do
254
+ before_all {
255
+ create :foo=>{:type=>:string, :bool_default=>'whoop'}, :bar=>{:type=>:array, :bool_default=>'1'},
256
+ :verbose=>:boolean, :yep=>{:type=>:string, :bool_default=>true}
257
+ }
258
+
259
+ it "sets default boolean" do
260
+ parse('--foo', '--bar', '1')[:foo].should == 'whoop'
261
+ parse('--foo', 'ok', 'dokay')[:foo].should == 'whoop'
262
+ end
263
+
264
+ it "sets options normally" do
265
+ parse('--foo=boo', '--bar=har').should == {:foo=>'boo', :bar=>['har']}
266
+ end
267
+
268
+ it "sets default boolean for array" do
269
+ parse("--bar", '--foo', '2')[:bar].should == ['1']
270
+ end
271
+
272
+ it "sets default boolean for non-string value" do
273
+ parse('--yep', '--foo=2')[:yep].should == true
274
+ end
275
+
276
+ it "default booleans can be joined with boolean options" do
277
+ parse('-fbv').should == {:verbose=>true, :bar=>['1'], :foo=>'whoop'}
278
+ end
279
+ end
280
+
281
+ describe "option with attributes" do
282
+ it "can get type from :type" do
283
+ create :foo=>{:type=>:numeric}
284
+ parse("-f", '3')[:foo].should == 3
285
+ end
286
+
287
+ it "can get type and default from :default" do
288
+ create :foo=>{:default=>[]}
289
+ parse("-f", "1")[:foo].should == ['1']
290
+ parse[:foo].should == []
291
+ end
292
+
293
+ it "assumes :boolean type if no type found" do
294
+ create :foo=>{:some=>'params'}
295
+ parse('-f')[:foo].should == true
296
+ end
297
+ end
298
+
299
+ def usage
300
+ opt.formatted_usage.split(" ").sort
301
+ end
302
+
303
+ describe "#formatted_usage" do
304
+ it "outputs string args with sample values" do
305
+ create "--repo" => :string, "--branch" => "bugfix", "-n" => 6
306
+ usage.should == %w([--branch=bugfix] [--repo=REPO] [-n=6])
307
+ end
308
+
309
+ it "outputs numeric args with 'N' as sample value" do
310
+ create "--iter" => :numeric
311
+ usage.should == ["[--iter=N]"]
312
+ end
313
+
314
+ it "outputs array args with sample value" do
315
+ create "--libs" => :array
316
+ usage.should == ["[--libs=A,B,C]"]
317
+ end
318
+
319
+ it "outputs hash args with sample value" do
320
+ create '--paths' => :hash
321
+ usage.should == ["[--paths=A:B,C:D]"]
322
+ end
323
+ end
324
+
325
+ describe "user defined option class" do
326
+ before_all {
327
+ ::FooBoo = Struct.new(:name)
328
+ module Options::FooBoo
329
+ def create_foo_boo(value)
330
+ ::FooBoo.new(value)
331
+ end
332
+ def validate_foo_boo(value); end
333
+ end
334
+ ::OptionParser.send :include, Options::FooBoo
335
+ create :a=>:foo_boo, :b=>::FooBoo.new('blah'), :c=>:blah_blah,
336
+ :d=>{:type=>:foo_boo, :type=>::FooBoo.new('bling')}
337
+ }
338
+
339
+ it "created from symbol" do
340
+ (obj = parse('-a', 'whoop')[:a]).class.should == ::FooBoo
341
+ obj.name.should == 'whoop'
342
+ end
343
+
344
+ it "created from default" do
345
+ (obj = parse[:b]).class.should == ::FooBoo
346
+ obj.name.should == 'blah'
347
+ end
348
+
349
+ it "created from type attribute" do
350
+ (obj = parse('-d', 'whoop')[:d]).class.should == ::FooBoo
351
+ obj.name.should == 'whoop'
352
+ end
353
+
354
+ it "has its validation called" do
355
+ opt.expects(:validate_foo_boo)
356
+ parse("-a", 'blah')
357
+ end
358
+
359
+ it "has default usage" do
360
+ usage[0].should == "[-a=:foo_boo]"
361
+ end
362
+
363
+ it "when nonexistant raises error" do
364
+ assert_error(OptionParser::Error, "invalid.*:blah_blah") { parse("-c", 'ok') }
365
+ end
366
+ end
367
+ end