boson-more 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. data/.gemspec +22 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +97 -0
  4. data/Rakefile +35 -0
  5. data/deps.rip +1 -0
  6. data/lib/boson/alias.rb +75 -0
  7. data/lib/boson/argument_inspector.rb +90 -0
  8. data/lib/boson/commands/core.rb +67 -0
  9. data/lib/boson/commands/view_core.rb +19 -0
  10. data/lib/boson/commands/web_core.rb +153 -0
  11. data/lib/boson/comment_inspector.rb +100 -0
  12. data/lib/boson/console.rb +40 -0
  13. data/lib/boson/console_runner.rb +60 -0
  14. data/lib/boson/index.rb +48 -0
  15. data/lib/boson/libraries/file_library.rb +144 -0
  16. data/lib/boson/libraries/gem_library.rb +30 -0
  17. data/lib/boson/libraries/local_file_library.rb +30 -0
  18. data/lib/boson/libraries/module_library.rb +37 -0
  19. data/lib/boson/libraries/require_library.rb +23 -0
  20. data/lib/boson/libraries.rb +183 -0
  21. data/lib/boson/more/version.rb +5 -0
  22. data/lib/boson/more.rb +18 -0
  23. data/lib/boson/more_commands.rb +14 -0
  24. data/lib/boson/more_inspector.rb +42 -0
  25. data/lib/boson/more_manager.rb +34 -0
  26. data/lib/boson/more_method_inspector.rb +74 -0
  27. data/lib/boson/more_option_parser.rb +28 -0
  28. data/lib/boson/more_scientist.rb +68 -0
  29. data/lib/boson/more_util.rb +30 -0
  30. data/lib/boson/namespace.rb +31 -0
  31. data/lib/boson/namespacer.rb +117 -0
  32. data/lib/boson/pipe.rb +156 -0
  33. data/lib/boson/pipe_runner.rb +44 -0
  34. data/lib/boson/pipes.rb +75 -0
  35. data/lib/boson/repo.rb +96 -0
  36. data/lib/boson/repo_index.rb +135 -0
  37. data/lib/boson/runner_options.rb +88 -0
  38. data/lib/boson/save.rb +198 -0
  39. data/lib/boson/science.rb +273 -0
  40. data/lib/boson/view.rb +98 -0
  41. data/lib/boson/viewable.rb +48 -0
  42. data/test/alias_test.rb +55 -0
  43. data/test/argument_inspector_test.rb +40 -0
  44. data/test/command_test.rb +22 -0
  45. data/test/commands_test.rb +53 -0
  46. data/test/comment_inspector_test.rb +126 -0
  47. data/test/console_runner_test.rb +58 -0
  48. data/test/deps.rip +4 -0
  49. data/test/file_library_test.rb +41 -0
  50. data/test/gem_library_test.rb +40 -0
  51. data/test/libraries_test.rb +55 -0
  52. data/test/loader_test.rb +38 -0
  53. data/test/module_library_test.rb +30 -0
  54. data/test/more_manager_test.rb +29 -0
  55. data/test/more_method_inspector_test.rb +42 -0
  56. data/test/more_scientist_test.rb +10 -0
  57. data/test/namespacer_test.rb +61 -0
  58. data/test/pipes_test.rb +65 -0
  59. data/test/repo_index_test.rb +123 -0
  60. data/test/repo_test.rb +23 -0
  61. data/test/runner_options_test.rb +29 -0
  62. data/test/save_test.rb +86 -0
  63. data/test/science_test.rb +58 -0
  64. data/test/scientist_test.rb +195 -0
  65. data/test/test_helper.rb +165 -0
  66. data/test/web_test.rb +22 -0
  67. metadata +169 -0
@@ -0,0 +1,65 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ describe "Pipes" do
4
+ before_all { ::Ab = Struct.new(:a, :b) }
5
+ describe "query_pipe" do
6
+ before_all {
7
+ @hashes = [{:a=>'some', :b=>'thing'}, {:a=>:more, :b=>:yep}]
8
+ @objects = [Ab.new('some', 'thing'), Ab.new(:more, :yep)]
9
+ }
10
+
11
+ it "searches one query" do
12
+ [@hashes, @objects].each {|e|
13
+ Pipes.query_pipe(e, :a=>'some').should == e[0,1]
14
+ }
15
+ end
16
+
17
+ it "searches non-string values" do
18
+ [@hashes, @objects].each {|e|
19
+ Pipes.query_pipe(e, :a=>'more').should == e[1,1]
20
+ }
21
+ end
22
+
23
+ it "searches multiple search terms" do
24
+ [@hashes, @objects].each {|e|
25
+ Pipes.query_pipe(e, :a=>'some', :b=>'yep').size.should == 2
26
+ }
27
+ end
28
+
29
+ it "prints error for invalid search field" do
30
+ capture_stderr { Pipes.query_pipe(@objects, :blah=>'blah') }.should =~ /failed.*'blah'/
31
+ end
32
+ end
33
+
34
+ describe "sort_pipe" do
35
+ before_all {
36
+ @hashes = [{:a=>'some', :b=>'thing'}, {:a=>:more, :b=>:yep}]
37
+ @objects = [Ab.new('some', 'thing'), Ab.new(:more, :yep)]
38
+ }
39
+ it "sorts objects with values of different types" do
40
+ Pipes.sort_pipe(@objects, :a).should == @objects.reverse
41
+ end
42
+
43
+ it "sorts hashes with values of different types" do
44
+ Pipes.sort_pipe(@hashes, :a).should == @hashes.reverse
45
+ end
46
+
47
+ it "sorts numeric values" do
48
+ hashes = [{:a=>10, :b=>4}, {:a=>5, :b=>3}]
49
+ Pipes.sort_pipe(hashes, :a).should == hashes.reverse
50
+ end
51
+
52
+ it "sorts numeric hash keys by string" do
53
+ hashes = [{2=>'thing'}, {2=>'some'}]
54
+ Pipes.sort_pipe(hashes, '2').should == hashes.reverse
55
+ end
56
+
57
+ it "sorts numeric hash keys by string" do
58
+ Pipes.sort_pipe(@hashes, 'a').should == @hashes.reverse
59
+ end
60
+
61
+ it "prints error for invalid sort field" do
62
+ capture_stderr { Pipes.sort_pipe(@objects, :blah)}.should =~ /failed.*'blah'/
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,123 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ describe "RepoIndex" do
4
+ # since we're defining our own @commands, @libraries, @lib_hashes
5
+ def index
6
+ @index ||= begin
7
+ ind = RepoIndex.new(Boson.repo)
8
+ ind.instance_variable_set "@read", true
9
+ ind
10
+ end
11
+ end
12
+
13
+ describe "read_and_transfer" do
14
+ before { reset_boson; index.instance_eval "@libraries = @commands = nil" }
15
+
16
+ def transfers(options={})
17
+ index.instance_variable_set "@libraries", [Library.new(:name=>'blah', :commands=>['blurb']),
18
+ Library.new(:name=>'bling')]
19
+ index.instance_variable_set "@commands", [Command.new(:name=>'blurb', :lib=>'blah')]
20
+ index.read_and_transfer options[:ignored] || []
21
+ Boson.libraries.map {|e| e.name}.should == options[:libraries]
22
+ Boson.commands.map {|e| e.name}.should == options[:commands]
23
+ end
24
+
25
+ it "transfers libraries with no libraries to ignore" do
26
+ transfers :libraries=>%w{blah bling}, :commands=>%w{blurb}, :ignored=>[]
27
+ end
28
+
29
+ it "transfers libraries and commands except for ignored libraries and its commands" do
30
+ transfers :libraries=>%w{bling}, :commands=>[], :ignored=>%w{blah}
31
+ end
32
+
33
+ it "doesn't replace existing libraries" do
34
+ lib = Library.new(:name=>'blah')
35
+ cmd = Command.new(:name=>'blurb', :lib=>'blah')
36
+ Boson.libraries << lib
37
+ Boson.commands << cmd
38
+ transfers :libraries=>%w{blah bling}, :commands=>%w{blurb}
39
+ Boson.libraries.include?(lib).should == true
40
+ Boson.commands.include?(cmd).should == true
41
+ end
42
+ end
43
+
44
+ describe "find_library" do
45
+ before_all {
46
+ reset_boson
47
+ commands = [Command.new(:name=>'blurb', :lib=>'blah', :alias=>'bb'),
48
+ Command.new(:name=>'sub', :lib=>'bling', :alias=>'s')
49
+ ]
50
+ index.instance_variable_set "@commands", commands
51
+ index.instance_variable_set "@libraries", [Library.new(:name=>'blah'), Library.new(:name=>'bling', :namespace=>'bling')]
52
+ }
53
+
54
+ it "finds command aliased or not" do
55
+ index.find_library('blurb').should == 'blah'
56
+ index.find_library('bb').should == 'blah'
57
+ end
58
+
59
+ it "doesn't find command" do
60
+ index.find_library('blah').should == nil
61
+ end
62
+
63
+ it "finds a subcommand aliased or not" do
64
+ index.find_library('bling.sub').should == 'bling'
65
+ # @index.find_library('bl.s').should == 'bling'
66
+ end
67
+
68
+ it "finds namespace command aliased or not without a subcommand" do
69
+ index.find_library('bling').should == 'bling'
70
+ # @index.find_library('bl').should == 'bling'
71
+ end
72
+
73
+ it "doesn't find a subcommand" do
74
+ index.find_library('d.d').should == nil
75
+ end
76
+ end
77
+
78
+ # enable once this is moved
79
+ xdescribe "changed_libraries" do
80
+ before_all { index.instance_eval "@lib_hashes = nil" }
81
+
82
+ def changed(string, all_libs=['file1'])
83
+ index.repo.expects(:all_libraries).returns(all_libs)
84
+ index.instance_variable_set "@lib_hashes", {"file1"=>Digest::MD5.hexdigest("state1")}
85
+ File.stubs(:exists?).returns(true)
86
+ File.expects(:read).returns(string)
87
+ index.changed_libraries
88
+ end
89
+
90
+ it "detects changed libraries" do
91
+ changed("state2").should == %w{file1}
92
+ end
93
+
94
+ it "detects new libraries" do
95
+ changed("state1", ['file2']).should == %w{file2}
96
+ end
97
+
98
+ it "detects no changed libraries" do
99
+ changed("state1").should == []
100
+ end
101
+ end
102
+
103
+ describe "write" do
104
+ before_all {
105
+ reset_boson
106
+ Boson.commands << Command.new(:name=>'blah', :lib=>'blah', :args=>[['arg1', {}], ['arg2', self.class]])
107
+ Boson.libraries << Library.new(:name=>'blah', :module=>self.class)
108
+ index.expects(:latest_hashes)
109
+ libraries = commands = []
110
+ index.expects(:save_marshal_index).with {|str| libraries, commands, hashes = Marshal.load(str) ; true}
111
+ index.write
112
+ @index_hash = {:libraries=>libraries, :commands=>commands}
113
+ }
114
+
115
+ it "saves library module constants as strings" do
116
+ @index_hash[:libraries][0].module.class.should == String
117
+ end
118
+
119
+ it "save commands with arg values as strings" do
120
+ @index_hash[:commands][0].args.each {|e| e[1].class.should == String}
121
+ end
122
+ end
123
+ end
data/test/repo_test.rb ADDED
@@ -0,0 +1,23 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ describe "config" do
4
+ before_all { reset }
5
+ before { @repo = Repo.new(File.dirname(__FILE__)) }
6
+
7
+ it "reloads config when passed true" do
8
+ @repo.config.object_id.should.not == @repo.config(true).object_id
9
+ end
10
+
11
+ it "reads existing config correctly" do
12
+ expected_hash = {:commands=>{'c1'=>{}}, :libraries=>{}}
13
+ File.expects(:exists?).returns(true)
14
+ YAML.expects(:load_file).returns(expected_hash)
15
+ @repo.config[:commands]['c1'].should == {}
16
+ end
17
+
18
+ it "ignores nonexistent file and sets config defaults" do
19
+ @repo.config[:command_aliases].class.should == Hash
20
+ @repo.config[:libraries].class.should == Hash
21
+ end
22
+ after_all { FileUtils.rm_r File.dirname(__FILE__)+'/config', :force=>true }
23
+ end
@@ -0,0 +1,29 @@
1
+ describe "BinRunner" do
2
+ describe "at commandline" do
3
+ def start(*args)
4
+ Hirb.stubs(:enable)
5
+ BinRunner.start(args)
6
+ end
7
+
8
+ before {|e|
9
+ BinRunner.instance_variables.each {|e| BinRunner.instance_variable_set(e, nil)}
10
+ }
11
+
12
+ before_all { reset }
13
+
14
+ it "invalid option value prints error" do
15
+ aborts_with(/Error: no value/) { start("-l") }
16
+ end
17
+
18
+ it "load option loads libraries" do
19
+ Manager.expects(:load).with {|*args| args[0][0].is_a?(Module) ? true : args[0][0] == 'blah'}.times(2)
20
+ BinRunner.stubs(:execute_command)
21
+ start('-l', 'blah', 'libraries')
22
+ end
23
+
24
+ it "with backtrace option prints backtrace" do
25
+ BinRunner.expects(:autoload_command).returns(false)
26
+ aborts_with(/not found\nOriginal.*runner\.rb:/m) { start("--backtrace", "blah") }
27
+ end
28
+ end
29
+ end
data/test/save_test.rb ADDED
@@ -0,0 +1,86 @@
1
+ describe "BinRunner" do
2
+ # TODO: moar acceptance tests
3
+ xit "basic command executes" do
4
+ BinRunner.expects(:init).returns(true)
5
+ BinRunner.stubs(:render_output)
6
+ Boson.main_object.expects(:send).with('kick','it')
7
+ start 'kick','it'
8
+ end
9
+ xit "bin_defaults config loads by default"
10
+
11
+ def start(*args)
12
+ BinRunner.start(args)
13
+ end
14
+
15
+ before {|e|
16
+ BinRunner.instance_variables.each {|e| BinRunner.instance_variable_set(e, nil)}
17
+ }
18
+
19
+ # TODO: fix missing libraries command
20
+ xdescribe "autoload_command" do
21
+ def index(options={})
22
+ Manager.expects(:load).with {|*args| args[0][0].is_a?(Module) ? true : args[0] == options[:load]
23
+ }.at_least(1).returns(!options[:fails])
24
+ Index.indexes[0].expects(:write)
25
+ end
26
+
27
+ it "with index option, no existing index and core command updates index and prints index message" do
28
+ index :load=>BareRunner.all_libraries
29
+ Index.indexes[0].stubs(:exists?).returns(false)
30
+ capture_stdout { start("--index", "libraries") }.should =~ /Generating index/
31
+ end
32
+
33
+ it "with index option, existing index and core command updates incremental index" do
34
+ index :load=>['changed']
35
+ Index.indexes[0].stubs(:exists?).returns(true)
36
+ capture_stdout { start("--index=changed", "libraries")}.should =~ /Indexing.*changed/
37
+ end
38
+
39
+ it "with index option, failed indexing prints error" do
40
+ index :load=>['changed'], :fails=>true
41
+ Index.indexes[0].stubs(:exists?).returns(true)
42
+ Manager.stubs(:failed_libraries).returns(['changed'])
43
+ capture_stderr {
44
+ capture_stdout { start("--index=changed", "libraries")}.should =~ /Indexing.*changed/
45
+ }.should =~ /Error:.*failed.*changed/
46
+ end
47
+
48
+ it "with core command updates index and doesn't print index message" do
49
+ Index.indexes[0].expects(:write)
50
+ Boson.main_object.expects(:send).with('libraries')
51
+ capture_stdout { start 'libraries'}.should.not =~ /index/i
52
+ end
53
+
54
+ it "with non-core command not finding library, does update index" do
55
+ Index.expects(:find_library).returns(nil, 'sweet_lib')
56
+ Manager.expects(:load).with {|*args| args[0].is_a?(String) ? args[0] == 'sweet_lib' : true}.at_least(1)
57
+ Index.indexes[0].expects(:update).returns(true)
58
+ aborts_with(/sweet/) { start 'sweet' }
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ __END__
65
+ describe "BinRunner" do
66
+ describe "at commandline" do
67
+ before_all { reset }
68
+
69
+ it "failed subcommand prints error and not command not found" do
70
+ BinRunner.expects(:execute_command).raises("bling")
71
+ aborts_with(/Error: bling/) { start("commands.to_s") }
72
+ end
73
+
74
+ it "nonexistant subcommand prints command not found" do
75
+ aborts_with(/'to_s.bling' not found/) { start("to_s.bling") }
76
+ end
77
+
78
+ it "sub command executes" do
79
+ obj = Object.new
80
+ Boson.main_object.extend Module.new { def phone; Struct.new(:home).new('done'); end }
81
+ BinRunner.expects(:init).returns(true)
82
+ start 'phone.home'
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,58 @@
1
+ describe "BinRunner" do
2
+ it "help option and command prints help" do
3
+ capture_stdout { start('-h', 'commands') }.should =~ /^commands/
4
+ end
5
+
6
+ it "global option takes value with whitespace" do
7
+ View.expects(:render).with {|*args| args[1][:fields] = %w{f1 f2} }
8
+ start('commands', '-f', 'f1, f2')
9
+ end
10
+
11
+ describe "render_output" do
12
+ before { Scientist.rendered = false; BinRunner.instance_eval "@options = {}" }
13
+
14
+ it "doesn't render when nil, false or true" do
15
+ View.expects(:render).never
16
+ [nil, false, true].each do |e|
17
+ BinRunner.render_output e
18
+ end
19
+ end
20
+
21
+ it "doesn't render when rendered with Scientist" do
22
+ Scientist.rendered = true
23
+ View.expects(:render).never
24
+ BinRunner.render_output 'blah'
25
+ end
26
+
27
+ it "render with puts when non-string" do
28
+ View.expects(:render).with('dude', {:method => 'puts'})
29
+ BinRunner.render_output 'dude'
30
+ end
31
+
32
+ it "renders with inspect when non-array and non-string" do
33
+ [{:a=>true}, :ok].each do |e|
34
+ View.expects(:puts).with(e.inspect)
35
+ BinRunner.render_output e
36
+ end
37
+ end
38
+
39
+ it "renders with inspect when Scientist rendering toggled off with :render" do
40
+ Scientist.global_options = {:render=>true}
41
+ View.expects(:puts).with([1,2].inspect)
42
+ BinRunner.render_output [1,2]
43
+ Scientist.global_options = nil
44
+ end
45
+
46
+ it "renders with hirb when array" do
47
+ View.expects(:render_object)
48
+ BinRunner.render_output [1,2,3]
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ describe "MethodInspector" do
55
+ it "render_options sets render_options" do
56
+ parse("render_options :z=>true; def zee; end")[:render_options].should == {"zee"=>{:z=>true}}
57
+ end
58
+ end
@@ -0,0 +1,195 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ # Now in science.rb
4
+ describe "Scientist" do
5
+ before_all {
6
+ Boson.in_shell = nil
7
+ eval <<-EOF
8
+ module Blah
9
+ def blah(arg1, options={})
10
+ [arg1, options]
11
+ end
12
+ def splat_blah(*args)
13
+ args
14
+ end
15
+ def default_blah(arg1, arg2=default, options={})
16
+ [arg1, arg2, options]
17
+ end
18
+ def default; 'some default'; end
19
+ def default_option(options={})
20
+ options
21
+ end
22
+ end
23
+ EOF
24
+ @opt_cmd = Object.new.extend Blah
25
+ }
26
+
27
+ def command(hash, args)
28
+ hash = {:name=>'blah', :lib=>'bling', :options=>{:force=>:boolean, :level=>2}}.merge(hash)
29
+ @cmd = Command.new hash
30
+ @cmd.instance_variable_set("@file_parsed_args", true) if hash[:file_parsed_args]
31
+ Scientist.redefine_command(@opt_cmd, @cmd)
32
+ @opt_cmd.send(hash[:name], *args)
33
+ end
34
+
35
+ def command_with_arg_size(*args)
36
+ command({:args=>2}, args)
37
+ end
38
+
39
+ def command_with_args(*args)
40
+ command({:args=>[['arg1'],['options', {}]]}, args)
41
+ end
42
+
43
+ def basic_command(hash, args)
44
+ command({:name=>'splat_blah', :args=>'*'}.merge(hash), args)
45
+ end
46
+
47
+ def command_with_splat_args(*args)
48
+ command({:name=>'splat_blah', :args=>'*'}, args)
49
+ end
50
+
51
+ def command_with_arg_defaults(*args)
52
+ arg_defaults = [%w{arg1}, %w{arg2 default}, %w{options {}}]
53
+ command({:name=>'default_blah', :file_parsed_args=>true, :args=>arg_defaults}, args)
54
+ end
55
+
56
+ def args_are_equal(args, array)
57
+ command_with_args(*args).should == array
58
+ command_with_arg_size(*args).should == array
59
+ command_with_splat_args(*args).should == array
60
+ end
61
+
62
+ def all_commands
63
+ [:command_with_args, :command_with_arg_size, :command_with_splat_args]
64
+ end
65
+
66
+ describe "command" do
67
+ describe "prints error" do
68
+ it "with unexpected error in render" do
69
+ Scientist.expects(:can_render?).raises("unexpected")
70
+ capture_stderr { command_with_args('a1') }.should =~ /Error.*unexpected/
71
+ end
72
+ end
73
+ end
74
+
75
+ def command_with_render(*args)
76
+ basic_command({:render_options=>{:fields=>{:values=>['f1', 'f2']}} }, args)
77
+ end
78
+
79
+ def render_expected(options=nil)
80
+ View.expects(:render).with(anything, options || anything, false)
81
+ end
82
+
83
+ describe "render" do
84
+ it "called for command with render_options" do
85
+ render_expected
86
+ command_with_render('1')
87
+ end
88
+
89
+ it "called for command without render_options and --render" do
90
+ render_expected
91
+ command_with_args('--render 1')
92
+ end
93
+
94
+ it "not called for command with render_options and --render" do
95
+ Boson.expects(:invoke).never
96
+ command_with_render('--render 1')
97
+ end
98
+
99
+ it "not called for command without render_options" do
100
+ Boson.expects(:invoke).never
101
+ command_with_args('1')
102
+ end
103
+ end
104
+
105
+ describe "command renders" do
106
+ it "with basic render options" do
107
+ render_expected :fields => ['f1', 'f2']
108
+ command_with_render("--fields f1,f2 ab")
109
+ end
110
+
111
+ it "without non-render options" do
112
+ render_expected :fields=>['f1']
113
+ Scientist.expects(:can_render?).returns(true)
114
+ args = ["--render --fields f1 ab"]
115
+ basic_command({:render_options=>{:fields=>{:values=>['f1', 'f2']}} }, args)
116
+ end
117
+
118
+ it "with user-defined render options" do
119
+ render_expected :fields=>['f1'], :foo=>true
120
+ args = ["--foo --fields f1 ab"]
121
+ basic_command({:render_options=>{:foo=>:boolean, :fields=>{:values=>['f1', 'f2']}} }, args)
122
+ end
123
+
124
+ it "with non-hash user-defined render options" do
125
+ render_expected :fields=>['f1'], :foo=>true
126
+ args = ["--foo --fields f1 ab"]
127
+ basic_command({:render_options=>{:foo=>:boolean, :fields=>%w{f1 f2 f3}} }, args)
128
+ end
129
+ end
130
+
131
+ it "optionless command renders" do
132
+ render_expected :fields=>['f1']
133
+ command({:args=>2, :options=>nil, :render_options=>{:fields=>:array}}, ["--fields f1 ab ok"])
134
+ end
135
+
136
+ describe "global options:" do
137
+ def local_and_global(*args)
138
+ Scientist.stubs(:can_render?).returns(false) # turn off rendering caused by :render_options
139
+ @non_opts = basic_command(@command_options, args)
140
+ @non_opts.slice!(-1,1) << Scientist.global_options
141
+ end
142
+
143
+ before_all {
144
+ @command_options = {:options=>{:do=>:boolean, :foo=>:boolean},
145
+ :render_options=>{:dude=>:boolean}}
146
+ @expected_non_opts = [[], ['doh'], ['doh'], [:doh]]
147
+ }
148
+
149
+ it "local option overrides global one" do
150
+ ['-d', 'doh -d','-d doh', [:doh, '-d']].each_with_index do |args, i|
151
+ local_and_global(*args).should == [{:do=>true}, {}]
152
+ @non_opts.should == @expected_non_opts[i]
153
+ end
154
+ end
155
+
156
+ it "global option before local one is valid" do
157
+ args_arr = ['--dude -f', '--dude doh -f', '--dude -f doh', [:doh, '--dude -f']]
158
+ args_arr.each_with_index do |args, i|
159
+ local_and_global(*args).should == [{:foo=>true}, {:dude=>true}]
160
+ @non_opts.should == @expected_non_opts[i]
161
+ end
162
+ end
163
+
164
+ it "delete_options deletes global options" do
165
+ local_and_global('--delete_options=r,p -rp -f').should ==
166
+ [{:foo=>true}, {:delete_options=>["r", "p"]}]
167
+ end
168
+
169
+ it "global option after local one is invalid" do
170
+ args_arr = ['-f --dude', '-f doh --dude', '-f --dude doh', [:doh, '-f --dude'] ]
171
+ args_arr.each_with_index do |args, i|
172
+ capture_stderr {
173
+ local_and_global(*args).should == [{:foo=>true}, {}]
174
+ @non_opts.should == @expected_non_opts[i]
175
+ }.should =~ /invalid.*dude/
176
+ end
177
+ end
178
+
179
+ it "global option after local one and -" do
180
+ local_and_global("doh -r -f - --dude").should == [{:foo=>true}, {:dude=>true, :render=>true}]
181
+ end
182
+
183
+ it "conflicting global option after -" do
184
+ local_and_global('doh - -f=1,2').should == [{}, {:fields=>["1", "2"]}]
185
+ end
186
+
187
+ it "no options parsed after --" do
188
+ local_and_global('doh -f -- -r').should == [{:foo=>true}, {}]
189
+ local_and_global('doh -- -r -f').should == [{}, {}]
190
+ local_and_global('-- -r -f').should == [{}, {}]
191
+ local_and_global('doh -r -- -f').should == [{}, {:render=>true}]
192
+ end
193
+ end
194
+ after_all { Boson.in_shell = false }
195
+ end