boson 0.4.0 → 1.0.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 (64) hide show
  1. data/.gemspec +6 -7
  2. data/.rspec +2 -0
  3. data/.travis.yml +7 -0
  4. data/CHANGELOG.rdoc +1 -1
  5. data/README.md +144 -0
  6. data/README.rdoc +2 -2
  7. data/Upgrading.md +23 -0
  8. data/bin/boson +2 -2
  9. data/lib/boson.rb +44 -52
  10. data/lib/boson/bare_runner.rb +83 -0
  11. data/lib/boson/bin_runner.rb +114 -0
  12. data/lib/boson/command.rb +92 -132
  13. data/lib/boson/inspector.rb +49 -48
  14. data/lib/boson/library.rb +71 -120
  15. data/lib/boson/loader.rb +73 -84
  16. data/lib/boson/manager.rb +131 -135
  17. data/lib/boson/method_inspector.rb +112 -0
  18. data/lib/boson/option_command.rb +71 -154
  19. data/lib/boson/option_parser.rb +178 -173
  20. data/lib/boson/options.rb +46 -32
  21. data/lib/boson/runner.rb +58 -66
  22. data/lib/boson/runner_library.rb +31 -0
  23. data/lib/boson/scientist.rb +48 -81
  24. data/lib/boson/util.rb +46 -61
  25. data/lib/boson/version.rb +1 -1
  26. data/test/bin_runner_test.rb +53 -191
  27. data/test/command_test.rb +5 -9
  28. data/test/deps.rip +2 -2
  29. data/test/loader_test.rb +18 -216
  30. data/test/manager_test.rb +69 -79
  31. data/test/method_inspector_test.rb +12 -36
  32. data/test/option_parser_test.rb +45 -32
  33. data/test/runner_library_test.rb +10 -0
  34. data/test/runner_test.rb +158 -28
  35. data/test/scientist_test.rb +9 -147
  36. data/test/test_helper.rb +87 -52
  37. metadata +30 -72
  38. data/deps.rip +0 -2
  39. data/lib/boson/commands.rb +0 -7
  40. data/lib/boson/commands/core.rb +0 -77
  41. data/lib/boson/commands/web_core.rb +0 -153
  42. data/lib/boson/index.rb +0 -48
  43. data/lib/boson/inspectors/argument_inspector.rb +0 -97
  44. data/lib/boson/inspectors/comment_inspector.rb +0 -100
  45. data/lib/boson/inspectors/method_inspector.rb +0 -98
  46. data/lib/boson/libraries/file_library.rb +0 -144
  47. data/lib/boson/libraries/gem_library.rb +0 -30
  48. data/lib/boson/libraries/local_file_library.rb +0 -30
  49. data/lib/boson/libraries/module_library.rb +0 -37
  50. data/lib/boson/libraries/require_library.rb +0 -23
  51. data/lib/boson/namespace.rb +0 -31
  52. data/lib/boson/pipe.rb +0 -147
  53. data/lib/boson/pipes.rb +0 -75
  54. data/lib/boson/repo.rb +0 -107
  55. data/lib/boson/runners/bin_runner.rb +0 -208
  56. data/lib/boson/runners/console_runner.rb +0 -58
  57. data/lib/boson/view.rb +0 -95
  58. data/test/argument_inspector_test.rb +0 -62
  59. data/test/commands_test.rb +0 -22
  60. data/test/comment_inspector_test.rb +0 -126
  61. data/test/file_library_test.rb +0 -42
  62. data/test/pipes_test.rb +0 -65
  63. data/test/repo_index_test.rb +0 -122
  64. data/test/repo_test.rb +0 -23
data/lib/boson/view.rb DELETED
@@ -1,95 +0,0 @@
1
- module Boson
2
- # This module generates views for a command by handing it to {Hirb}[http://tagaholic.me/hirb/]. Since Hirb can be customized
3
- # to generate any view, commands can have any views associated with them!
4
- #
5
- # === Views with Render Options
6
- # To pass rendering options to a Hirb helper as command options, a command has to define the options with
7
- # the render_options method attribute:
8
- #
9
- # # @render_options :fields=>[:a,:b]
10
- # def list(options={})
11
- # [{:a=>1, :b=>2}, {:a=>10,:b=>11}]
12
- # end
13
- #
14
- # # To see that the render_options method attribute actually passes the :fields option by default:
15
- # >> list '-p' # or list '--pretend'
16
- # Arguments: []
17
- # Global options: {:pretend=>true, :fields=>[:a, :b]}
18
- #
19
- # >> list
20
- # +----+----+
21
- # | a | b |
22
- # +----+----+
23
- # | 1 | 2 |
24
- # | 10 | 11 |
25
- # +----+----+
26
- # 2 rows in set
27
- #
28
- # # To create a vertical table, we can pass --vertical, one of the default global render options.
29
- # >> list '-V' # or list '--vertical'
30
- # *** 1. row ***
31
- # a: 1
32
- # b: 2
33
- # ...
34
- #
35
- # # To get the original return value use the global option --render
36
- # >> list '-r' # or list '--render'
37
- # => [{:a=>1, :b=>2}, {:a=>10,:b=>11}]
38
- #
39
- # === Boson and Hirb
40
- # Since Boson uses {Hirb's auto table helper}[http://tagaholic.me/hirb/doc/classes/Hirb/Helpers/AutoTable.html]
41
- # by default, you may want to read up on its many options. To use any of them in commands, define them locally
42
- # with render_options or globally by adding them under the :render_options key of the main config.
43
- # What if you want to use your own helper class? No problem. Simply pass it with the global :class option.
44
- #
45
- # When using the default helper, one of the most important options to define is :fields. Aside from controlling what fields
46
- # are displayed, it's used to set :values option attributes for related options i.e. :sort and :query. This provides handy option
47
- # value aliasing via OptionParser. If you don't set :fields, Boson will try to set its :values with field-related options i.e.
48
- # :change_fields, :filters and :headers.
49
- module View
50
- extend self
51
-
52
- # Enables hirb and reads a config file from the main repo's config/hirb.yml.
53
- def enable
54
- unless @enabled
55
- Hirb::View.enable(:config_file=>File.join(Boson.repo.config_dir, 'hirb.yml'))
56
- Hirb::Helpers::Table.filter_any = true
57
- end
58
- @enabled = true
59
- end
60
-
61
- # Renders any object via Hirb. Options are passed directly to
62
- # {Hirb::Console.render_output}[http://tagaholic.me/hirb/doc/classes/Hirb/Console.html#M000011].
63
- def render(object, options={}, return_obj=false)
64
- if options[:inspect]
65
- puts(object.inspect)
66
- else
67
- render_object(object, options, return_obj) unless silent_object?(object)
68
- end
69
- end
70
-
71
- #:stopdoc:
72
- def class_config(klass)
73
- opts = (Hirb::View.formatter_config[klass] || {}).dup
74
- opts.delete(:ancestor)
75
- opts.merge!((opts.delete(:options) || {}).dup)
76
- OptionParser.make_mergeable!(opts)
77
- opts
78
- end
79
-
80
- def toggle_pager
81
- Hirb::View.toggle_pager
82
- end
83
-
84
- def silent_object?(obj)
85
- [nil,false,true].include?(obj)
86
- end
87
-
88
- def render_object(object, options={}, return_obj=false)
89
- options[:class] ||= :auto_table
90
- render_result = Hirb::Console.render_output(object, options)
91
- return_obj ? object : render_result
92
- end
93
- #:startdoc:
94
- end
95
- end
@@ -1,62 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
2
-
3
- describe "scrape_with_text" do
4
- def args_from(file_string)
5
- ArgumentInspector.scrape_with_text(file_string, "blah")
6
- end
7
-
8
- it "parses arguments of class method" do
9
- args_from(" def YAML.blah( filepath )\n").should == [['filepath']]
10
- end
11
-
12
- it "parses arguments with no spacing" do
13
- args_from("def bong; end\ndef blah(arg1,arg2='val2')\nend").should == [["arg1"], ['arg2', "'val2'"]]
14
- end
15
-
16
- it "parses arguments with spacing" do
17
- args_from("\t def blah( arg1=val1, arg2 = val2)").should == [["arg1","val1"], ["arg2", "val2"]]
18
- end
19
-
20
- it "parses arguments without parenthesis" do
21
- args_from(" def blah arg1, arg2, arg3={}").should == [['arg1'], ['arg2'], ['arg3','{}']]
22
- end
23
- end
24
-
25
- describe "scrape_with_eval" do
26
- def args_from(string)
27
- # methods need options to have their args parsed with ArgumentInspector
28
- string.gsub!(/(def blah)/, 'options :a=>1; \1')
29
- Inspector.enable
30
- ::Boson::Commands::Aaa.module_eval(string)
31
- Inspector.disable
32
- MethodInspector.store[:args]['blah']
33
- end
34
-
35
- before_all { eval "module ::Boson::Commands::Aaa; end"; }
36
- before { MethodInspector.mod_store[::Boson::Commands::Aaa] = {} }
37
-
38
- it "determines arguments with literal defaults" do
39
- args_from("def blah(arg1,arg2='val2'); end").should == [['arg1'], ['arg2','val2']]
40
- end
41
-
42
- it "determines splat arguments" do
43
- args_from("def blah(arg1, *args); end").should == [['arg1'], ["*args"]]
44
- end
45
-
46
- it "determines arguments with local values before a method" do
47
- body = "AWESOME='awesome'; def sweet; 'ok'; end; def blah(arg1=AWESOME, arg2=sweet); end"
48
- args_from(body).should == [['arg1', 'awesome'], ['arg2', 'ok']]
49
- end
50
-
51
- it "doesn't get arguments with local values after a method" do
52
- args_from("def blah(arg1=nope) end; def nope; 'nope'; end").should == nil
53
- end
54
-
55
- it "doesn't determine arguments of a private method" do
56
- args_from("private; def blah(arg1,arg2); end").should == nil
57
- end
58
-
59
- it "doesn't determine arguments if an error occurs" do
60
- args_from("def blah(arg1,arg2=raise); end").should == nil
61
- end
62
- end
@@ -1,22 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
2
-
3
- describe "WebCore" do
4
- it "#get with no options" do
5
- request = mock { expects(:request).with({}) }
6
- Commands::WebCore::Get.expects(:new).with('blah.com').returns(request)
7
- Commands::WebCore.get 'blah.com'
8
- end
9
-
10
- it "#post with no options" do
11
- Net::HTTP.expects(:post_form).with(anything, {}).returns(nil)
12
- Commands::WebCore.post 'blah.com'
13
- end
14
-
15
- it "#build_url with string params" do
16
- Commands::WebCore.build_url('ababd.com', :q=>'search').should == 'ababd.com?q=search'
17
- end
18
-
19
- it "#build_url with array params" do
20
- Commands::WebCore.build_url('ababd.com', :q=>%w{multi word search}).should == 'ababd.com?q=multi+word+search'
21
- end
22
- end
@@ -1,126 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
2
-
3
- describe "CommentInspector" do
4
- before_all { eval "module ::Optional; def self.bling; {:a=>'bling'}; end; end" }
5
- describe "scrapes description" do
6
- before {
7
- @lines = ["module Foo", " # some comments yay", " def foo", " end", "end"]
8
- }
9
- def description(options={})
10
- CommentInspector.scrape(@lines.join("\n"), options[:line] || 3, Optional)[:desc]
11
- end
12
-
13
- it "directly above method returns desc" do
14
- description.should == "some comments yay"
15
- end
16
-
17
- it "with explicit @desc returns desc" do
18
- @lines[1] = '#@desc some comments yay'
19
- description.should == "some comments yay"
20
- end
21
-
22
- it "of multiple lines returns desc" do
23
- @lines.delete_at(1)
24
- @lines.insert(1, '#@options :b=>1', '#@desc here be', '# comments')
25
- description(:line=>5).should == "here be comments"
26
- end
27
-
28
- it "that is empty returns nil" do
29
- @lines[1] = ""
30
- description.should == nil
31
- end
32
-
33
- it "that is empty with options keyword returns nil" do
34
- @lines[1] = '#@options {:a=>1}'
35
- description.should == nil
36
- end
37
-
38
- it "not directly above returns nil" do
39
- @lines.insert(2, " ")
40
- description(:line=>4).should == nil
41
- end
42
- end
43
-
44
- describe "scrapes options" do
45
- before {
46
- @lines = ["module Foo", ' #@options {:a=>true}', " def foo", " end", "end"]
47
- }
48
- def options(opts={})
49
- @lines[1] = opts[:value] if opts[:value]
50
- args = [@lines.join("\n"), opts[:line] || 3, Optional]
51
- CommentInspector.scrape(*args)[:options]
52
- end
53
-
54
- it "that are basic" do
55
- options.should == {:a=>true}
56
- end
57
-
58
- it "that are hash-like" do
59
- options(:value=>'#@options :a => 2').should == {:a=>2}
60
- end
61
-
62
- it "that are whitespaced" do
63
- options(:value=>"\t"+ '# @options {:a=>1}').should == {:a=>1}
64
- end
65
-
66
- it "that have a local value" do
67
- options(:value=>'#@options bling').should == {:a=>'bling'}
68
- end
69
-
70
- it "that are multi-line" do
71
- @lines.delete_at(1)
72
- @lines.insert(1, '#@options {:a =>', " # 1}", "# some comments")
73
- options(:line=>5).should == {:a=>1}
74
- end
75
-
76
- it "with failed eval and returns nil" do
77
- options(:value=>'#@options !--').should == nil
78
- end
79
-
80
- it "that are empty and returns nil" do
81
- options(:value=>"# nada").should == nil
82
- end
83
-
84
- it "when @option overwrites @options" do
85
- @lines.insert(1, ' #@option :a, :boolean')
86
- options(:line=>4).should == {:a=>:boolean}
87
- end
88
-
89
- it "when set by @option and @options" do
90
- @lines.insert(1, ' #@option :b, :boolean')
91
- options(:line=>4).should == {:b=>:boolean, :a=>true}
92
- end
93
-
94
- it "when set by @option" do
95
- @lines.delete_at(1)
96
- @lines.insert(1, ' #@option :b, :string', ' #@option :a, 4')
97
- options(:line=>4).should == {:b=>:string, :a=>4}
98
- end
99
-
100
- it "when set by multi-line @option" do
101
- @lines.delete_at(1)
102
- @lines.insert(1, ' #@option :b, :type=>:string,', ' # :values=>%w{one two}', '# some comments')
103
- options(:line=>5).should == {:b=>{:type=>:string, :values=>%w{one two}}}
104
- end
105
-
106
- it "and ignores invalid @option's" do
107
- @lines.delete_at(1)
108
- @lines.insert(1, ' #@option :b=>:string', ' #@option :a, :string')
109
- options(:line=>4).should == {:a=>:string}
110
- end
111
- end
112
-
113
- it "scrapes all comment types with implicit desc" do
114
- @lines = ["module Foo", '# @config :a=>true', '# @render_options :b=>1', ' # @options {:a=>true}',
115
- '#blah', " def foo", " end", "end"]
116
- expected = {:desc=>"blah", :options=>{:a=>true}, :render_options=>{:b=>1}, :config=>{:a=>true}}
117
- CommentInspector.scrape(@lines.join("\n"), 6, Optional).should == expected
118
- end
119
-
120
- it "scrapes all comment types with explicit desc" do
121
- @lines = ["module Foo", '#@desc blah', '# @render_options :b=>1,', '# :c=>2',
122
- ' # @options {:a=>true}', ' # @config :a=>true', " def foo", " end", "end"]
123
- expected = {:desc=>"blah", :options=>{:a=>true}, :render_options=>{:b=>1, :c=>2}, :config=>{:a=>true}}
124
- CommentInspector.scrape(@lines.join("\n"), 7, Optional).should == expected
125
- end
126
- end
@@ -1,42 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'test_helper')
2
-
3
- describe "file library" do
4
- before { reset; FileLibrary.reset_file_cache }
5
- before { Gem.stubs(:loaded_specs).returns({}) } if RUBY_VERSION >= '1.9.2' && defined? Gem
6
-
7
- it "loads" do
8
- load :blah, :file_string=>"module Blah; def blah; end; end"
9
- library_has_module('blah', 'Boson::Commands::Blah')
10
- command_exists?('blah')
11
- end
12
-
13
- it "in a subdirectory loads" do
14
- load 'site/delicious', :file_string=>"module Delicious; def blah; end; end"
15
- library_has_module('site/delicious', "Boson::Commands::Site::Delicious")
16
- command_exists?('blah')
17
- end
18
-
19
- it "in a sub subdirectory loads" do
20
- load 'web/site/delicious', :file_string=>"module Delicious; def blah; end; end"
21
- library_has_module('web/site/delicious', "Boson::Commands::Web::Site::Delicious")
22
- command_exists?('blah')
23
- end
24
-
25
- it "loads by basename" do
26
- Dir.stubs(:[]).returns([RUBY_VERSION < '1.9.2' ? './test/commands/site/github.rb' :
27
- File.expand_path('./test/commands/site/github.rb')])
28
- load 'github', :file_string=>"module Github; def blah; end; end", :exists=>false
29
- library_has_module('site/github', "Boson::Commands::Site::Github")
30
- command_exists?('blah')
31
- end
32
-
33
- it "loads a plugin library by creating its module" do
34
- load(:blah, :file_string=>"def blah; end")
35
- library_has_module('blah', "Boson::Commands::Blah")
36
- command_exists?('blah', false)
37
- end
38
-
39
- it "prints error for file library with multiple modules" do
40
- capture_stderr { load(:blah, :file_string=>"module Doo; end; module Daa; end") }.should =~ /Can't.*config/
41
- end
42
- end
data/test/pipes_test.rb DELETED
@@ -1,65 +0,0 @@
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
@@ -1,122 +0,0 @@
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
- describe "changed_libraries" do
79
- before_all { index.instance_eval "@lib_hashes = nil" }
80
-
81
- def changed(string, all_libs=['file1'])
82
- index.repo.expects(:all_libraries).returns(all_libs)
83
- index.instance_variable_set "@lib_hashes", {"file1"=>Digest::MD5.hexdigest("state1")}
84
- File.stubs(:exists?).returns(true)
85
- File.expects(:read).returns(string)
86
- index.changed_libraries
87
- end
88
-
89
- it "detects changed libraries" do
90
- changed("state2").should == %w{file1}
91
- end
92
-
93
- it "detects new libraries" do
94
- changed("state1", ['file2']).should == %w{file2}
95
- end
96
-
97
- it "detects no changed libraries" do
98
- changed("state1").should == []
99
- end
100
- end
101
-
102
- describe "write" do
103
- before_all {
104
- reset_boson
105
- Boson.commands << Command.new(:name=>'blah', :lib=>'blah', :args=>[['arg1', {}], ['arg2', self.class]])
106
- Boson.libraries << Library.new(:name=>'blah', :module=>self.class)
107
- index.expects(:latest_hashes)
108
- libraries = commands = []
109
- index.expects(:save_marshal_index).with {|str| libraries, commands, hashes = Marshal.load(str) ; true}
110
- index.write
111
- @index_hash = {:libraries=>libraries, :commands=>commands}
112
- }
113
-
114
- it "saves library module constants as strings" do
115
- @index_hash[:libraries][0].module.class.should == String
116
- end
117
-
118
- it "save commands with arg values as strings" do
119
- @index_hash[:commands][0].args.each {|e| e[1].class.should == String}
120
- end
121
- end
122
- end