boson-more 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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