rjspotter-innate 2009.06.29

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 (128) hide show
  1. data/AUTHORS +10 -0
  2. data/CHANGELOG +3261 -0
  3. data/COPYING +18 -0
  4. data/MANIFEST +127 -0
  5. data/README.md +563 -0
  6. data/Rakefile +39 -0
  7. data/example/app/retro_games.rb +60 -0
  8. data/example/app/todo/layout/default.xhtml +11 -0
  9. data/example/app/todo/spec/todo.rb +63 -0
  10. data/example/app/todo/start.rb +51 -0
  11. data/example/app/todo/view/index.xhtml +39 -0
  12. data/example/app/whywiki_erb/layout/wiki.html.erb +15 -0
  13. data/example/app/whywiki_erb/spec/wiki.rb +19 -0
  14. data/example/app/whywiki_erb/start.rb +42 -0
  15. data/example/app/whywiki_erb/view/edit.erb +6 -0
  16. data/example/app/whywiki_erb/view/index.erb +12 -0
  17. data/example/custom_middleware.rb +35 -0
  18. data/example/hello.rb +11 -0
  19. data/example/howto_spec.rb +35 -0
  20. data/example/link.rb +27 -0
  21. data/example/provides.rb +31 -0
  22. data/example/session.rb +38 -0
  23. data/innate.gemspec +41 -0
  24. data/lib/innate.rb +269 -0
  25. data/lib/innate/action.rb +137 -0
  26. data/lib/innate/adapter.rb +76 -0
  27. data/lib/innate/cache.rb +134 -0
  28. data/lib/innate/cache/api.rb +128 -0
  29. data/lib/innate/cache/drb.rb +58 -0
  30. data/lib/innate/cache/file_based.rb +44 -0
  31. data/lib/innate/cache/marshal.rb +20 -0
  32. data/lib/innate/cache/memory.rb +21 -0
  33. data/lib/innate/cache/yaml.rb +20 -0
  34. data/lib/innate/current.rb +35 -0
  35. data/lib/innate/dynamap.rb +96 -0
  36. data/lib/innate/helper.rb +185 -0
  37. data/lib/innate/helper/aspect.rb +124 -0
  38. data/lib/innate/helper/cgi.rb +54 -0
  39. data/lib/innate/helper/flash.rb +36 -0
  40. data/lib/innate/helper/link.rb +94 -0
  41. data/lib/innate/helper/redirect.rb +85 -0
  42. data/lib/innate/helper/render.rb +152 -0
  43. data/lib/innate/helper/send_file.rb +26 -0
  44. data/lib/innate/log.rb +20 -0
  45. data/lib/innate/log/color_formatter.rb +49 -0
  46. data/lib/innate/log/hub.rb +77 -0
  47. data/lib/innate/middleware_compiler.rb +65 -0
  48. data/lib/innate/mock.rb +49 -0
  49. data/lib/innate/node.rb +1029 -0
  50. data/lib/innate/options.rb +37 -0
  51. data/lib/innate/options/dsl.rb +205 -0
  52. data/lib/innate/options/stub.rb +7 -0
  53. data/lib/innate/request.rb +141 -0
  54. data/lib/innate/response.rb +24 -0
  55. data/lib/innate/route.rb +114 -0
  56. data/lib/innate/session.rb +133 -0
  57. data/lib/innate/session/flash.rb +94 -0
  58. data/lib/innate/spec.rb +1 -0
  59. data/lib/innate/spec/bacon.rb +28 -0
  60. data/lib/innate/state.rb +26 -0
  61. data/lib/innate/state/accessor.rb +130 -0
  62. data/lib/innate/traited.rb +90 -0
  63. data/lib/innate/trinity.rb +18 -0
  64. data/lib/innate/version.rb +3 -0
  65. data/lib/innate/view.rb +97 -0
  66. data/lib/innate/view/erb.rb +14 -0
  67. data/lib/innate/view/etanni.rb +33 -0
  68. data/lib/innate/view/none.rb +9 -0
  69. data/spec/example/app/retro_games.rb +30 -0
  70. data/spec/example/hello.rb +13 -0
  71. data/spec/example/link.rb +25 -0
  72. data/spec/example/provides.rb +16 -0
  73. data/spec/example/session.rb +22 -0
  74. data/spec/helper.rb +10 -0
  75. data/spec/innate/action/layout.rb +121 -0
  76. data/spec/innate/action/layout/file_layout.xhtml +1 -0
  77. data/spec/innate/cache/common.rb +47 -0
  78. data/spec/innate/cache/marshal.rb +5 -0
  79. data/spec/innate/cache/memory.rb +5 -0
  80. data/spec/innate/cache/yaml.rb +5 -0
  81. data/spec/innate/dynamap.rb +22 -0
  82. data/spec/innate/helper.rb +86 -0
  83. data/spec/innate/helper/aspect.rb +75 -0
  84. data/spec/innate/helper/cgi.rb +37 -0
  85. data/spec/innate/helper/flash.rb +115 -0
  86. data/spec/innate/helper/link.rb +139 -0
  87. data/spec/innate/helper/redirect.rb +171 -0
  88. data/spec/innate/helper/render.rb +165 -0
  89. data/spec/innate/helper/send_file.rb +21 -0
  90. data/spec/innate/helper/view/aspect_hello.xhtml +1 -0
  91. data/spec/innate/helper/view/locals.xhtml +1 -0
  92. data/spec/innate/helper/view/loop.xhtml +4 -0
  93. data/spec/innate/helper/view/num.xhtml +1 -0
  94. data/spec/innate/helper/view/partial.xhtml +1 -0
  95. data/spec/innate/helper/view/recursive.xhtml +7 -0
  96. data/spec/innate/mock.rb +84 -0
  97. data/spec/innate/modes.rb +61 -0
  98. data/spec/innate/node/mapping.rb +37 -0
  99. data/spec/innate/node/node.rb +135 -0
  100. data/spec/innate/node/resolve.rb +82 -0
  101. data/spec/innate/node/view/another_layout/another_layout.xhtml +3 -0
  102. data/spec/innate/node/view/bar.xhtml +1 -0
  103. data/spec/innate/node/view/foo.html.xhtml +1 -0
  104. data/spec/innate/node/view/only_view.xhtml +1 -0
  105. data/spec/innate/node/view/with_layout.xhtml +1 -0
  106. data/spec/innate/node/wrap_action_call.rb +83 -0
  107. data/spec/innate/options.rb +123 -0
  108. data/spec/innate/parameter.rb +154 -0
  109. data/spec/innate/provides.rb +99 -0
  110. data/spec/innate/provides/list.html.xhtml +1 -0
  111. data/spec/innate/provides/list.txt.xhtml +1 -0
  112. data/spec/innate/request.rb +79 -0
  113. data/spec/innate/route.rb +135 -0
  114. data/spec/innate/session.rb +58 -0
  115. data/spec/innate/traited.rb +55 -0
  116. data/tasks/authors.rake +30 -0
  117. data/tasks/bacon.rake +66 -0
  118. data/tasks/changelog.rake +18 -0
  119. data/tasks/gem.rake +22 -0
  120. data/tasks/gem_setup.rake +99 -0
  121. data/tasks/grancher.rake +12 -0
  122. data/tasks/manifest.rake +4 -0
  123. data/tasks/rcov.rake +19 -0
  124. data/tasks/release.rake +53 -0
  125. data/tasks/reversion.rake +8 -0
  126. data/tasks/setup.rake +6 -0
  127. data/tasks/ycov.rake +84 -0
  128. metadata +218 -0
@@ -0,0 +1,61 @@
1
+ require 'spec/helper'
2
+
3
+ class SpecModeDummy
4
+ Innate.node '/'
5
+
6
+ def index
7
+ 'Hello, World!'
8
+ end
9
+
10
+ def random
11
+ rand.to_s
12
+ end
13
+ end
14
+
15
+ describe 'Innate modes' do
16
+ describe 'dev' do
17
+ behaves_like :rack_test
18
+ Innate.options.mode = :dev
19
+
20
+ should 'handle GET request' do
21
+ get('/').status.
22
+ should == 200
23
+ last_response.headers.
24
+ should == {'Content-Length' => '13', 'Content-Type' => 'text/html'}
25
+ last_response.body.
26
+ should == 'Hello, World!'
27
+ end
28
+
29
+ should 'handle HEAD requests by omitting body' do
30
+ head('/').status.
31
+ should == 200
32
+ last_response.headers.
33
+ should == {'Content-Length' => '13', 'Content-Type' => 'text/html'}
34
+ last_response.body.
35
+ should == ''
36
+ end
37
+ end
38
+
39
+ describe 'live' do
40
+ behaves_like :rack_test
41
+ Innate.options.mode = :live
42
+
43
+ should 'handle GET request' do
44
+ get('/').status.
45
+ should == 200
46
+ last_response.headers.
47
+ should == {'Content-Length' => '13', 'Content-Type' => 'text/html'}
48
+ last_response.body.
49
+ should == 'Hello, World!'
50
+ end
51
+
52
+ should 'handle HEAD requests by omitting body' do
53
+ head('/').status.
54
+ should == 200
55
+ last_response.headers.
56
+ should == {'Content-Length' => '13', 'Content-Type' => 'text/html'}
57
+ last_response.body.
58
+ should == ''
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec/helper'
2
+
3
+ describe 'Node::generate_mapping' do
4
+ def gen(const)
5
+ Innate::Node.generate_mapping(const)
6
+ end
7
+
8
+ should 'transform class names into snake_case locations' do
9
+ gen( 'O').should == '/o'
10
+ gen( 'Oo').should == '/oo'
11
+ gen( 'Ooo').should == '/ooo'
12
+ gen( 'OooO').should == '/oooo'
13
+ gen( 'OooOo').should == '/ooo_oo'
14
+ gen('OooOoo').should == '/ooo_ooo'
15
+ gen('OOOooo').should == '/oooooo'
16
+ gen('OooOOO').should == '/oooooo'
17
+ gen('OoOoOo').should == '/oo_oo_oo'
18
+ end
19
+
20
+ should 'transform namespaces into leading parts of the location' do
21
+ gen('O::O').should == '/o/o'
22
+ gen('O::O::O').should == '/o/o/o'
23
+ gen('O::O::O::O').should == '/o/o/o/o'
24
+ end
25
+
26
+ should 'transform leading parts just like standalone part' do
27
+ gen( 'O::O').should == '/o/o'
28
+ gen( 'Oo::O').should == '/oo/o'
29
+ gen( 'Ooo::O').should == '/ooo/o'
30
+ gen( 'OooO::O').should == '/oooo/o'
31
+ gen( 'OooOo::O').should == '/ooo_oo/o'
32
+ gen('OooOoo::O').should == '/ooo_ooo/o'
33
+ gen('OOOooo::O').should == '/oooooo/o'
34
+ gen('OooOOO::O').should == '/oooooo/o'
35
+ gen('OoOoOo::O').should == '/oo_oo_oo/o'
36
+ end
37
+ end
@@ -0,0 +1,135 @@
1
+ require 'spec/helper'
2
+
3
+ Innate.options.merge!(:views => 'view', :layouts => 'view')
4
+
5
+ class SpecNode
6
+ Innate.node('/')
7
+
8
+ def foo; end
9
+ def bar; end
10
+ def one(arg) end
11
+ def two(arg1, arg2) end
12
+ def more(*args) end
13
+ def default(arg = nil) end
14
+ end
15
+
16
+ class SpecNodeProvide
17
+ Innate.node('/provide')
18
+
19
+ def foo
20
+ '#{21 * 2}'
21
+ end
22
+
23
+ def bar
24
+ '#{84 / 2}'
25
+ end
26
+ end
27
+
28
+ class SpecNodeProvideTemplate
29
+ Innate.node('/provide_template')
30
+
31
+ map_views '/'
32
+ end
33
+
34
+ class SpecNodeSub < SpecNode
35
+ map '/sub'
36
+
37
+ def bar(arg) end
38
+ end
39
+
40
+ class SpecNodeWithLayout < SpecNodeProvide
41
+ map '/layout'
42
+ layout 'with_layout'
43
+
44
+ map_layouts '/'
45
+ end
46
+
47
+ class SpecNodeWithLayoutView < SpecNodeProvide
48
+ map '/another_layout'
49
+ layout 'another_layout'
50
+
51
+ map_views 'node/another_layout'
52
+ map_layouts 'another_layout'
53
+ end
54
+
55
+ class SpecNodeWithLayoutMethod < SpecNodeProvide
56
+ map '/layout_method'
57
+ layout 'layout_method'
58
+
59
+ def layout_method
60
+ '<div class="content">#{@content}</div>'
61
+ end
62
+ end
63
+
64
+ class SpecNodeIndex
65
+ Innate.node('/spec_index')
66
+
67
+ def index
68
+ "I have no parameters"
69
+ end
70
+ end
71
+
72
+ class SpecNodeAliasView < SpecNodeProvideTemplate
73
+ map '/alias_view'
74
+ map_views '/'
75
+
76
+ alias_view :aliased, :bar
77
+ end
78
+
79
+ describe 'Innate::Node' do
80
+ behaves_like :rack_test
81
+
82
+ should 'respond with 404 if no action was found' do
83
+ got = Innate::Mock.get('/does_not_exist')
84
+ got.status.should == 404
85
+ got.body.should == 'No action found at: "/does_not_exist"'
86
+ got['Content-Type'].should == 'text/plain'
87
+ end
88
+
89
+ should 'wrap with layout' do
90
+ got = Innate::Mock.get('/layout/bar')
91
+ got.status.should == 200
92
+ got.body.should == %(<div class="content">42</div>)
93
+ got['Content-Type'].should == 'text/html'
94
+ end
95
+
96
+ should 'find layout with view_root' do
97
+ got = Innate::Mock.get('/another_layout/bar')
98
+ got.status.should == 200
99
+ got.body.should == %(<div class="content">\n 42\n</div>)
100
+ got['Content-Type'].should == 'text/html'
101
+ end
102
+
103
+ should 'find layout from method' do
104
+ got = Innate::Mock.get('/layout_method/bar')
105
+ got.status.should == 200
106
+ got.body.should == %(<div class="content">42</div>)
107
+ got['Content-Type'].should == 'text/html'
108
+ end
109
+
110
+ should 'not get an action with wrong parameters' do
111
+ got = Innate::Mock.get('/spec_index/bar')
112
+ got.status.should == 404
113
+ got.body.should == 'No action found at: "/bar"'
114
+ end
115
+
116
+ should 'get an action view if there is no method' do
117
+ got = Innate::Mock.get('/provide_template/only_view')
118
+ got.status.should == 200
119
+ got.body.strip.should == "Only template"
120
+ got['Content-Type'].should == 'text/html'
121
+ end
122
+
123
+ should 'not get an action view with params if there is no method' do
124
+ got = Innate::Mock.get('/provide_template/only_view/param')
125
+ got.status.should == 404
126
+ got.body.strip.should == 'No action found at: "/only_view/param"'
127
+ end
128
+
129
+ should 'use alias_view' do
130
+ got = get('/alias_view/aliased')
131
+ got.status.should == 200
132
+ got.body.strip.should == "<h1>Hello, World!</h1>"
133
+ got['Content-Type'].should == 'text/html'
134
+ end
135
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec/helper'
2
+
3
+ class SpecNodeResolve
4
+ Innate.node('/')
5
+
6
+ def foo; end
7
+ def bar; end
8
+ def one(arg) end
9
+ def two(arg1, arg2) end
10
+ def more(*args) end
11
+ def default(arg = nil) end
12
+ end
13
+
14
+ class SpecNodeResolveSub < SpecNodeResolve
15
+ map '/sub'
16
+
17
+ def bar(arg) end
18
+ end
19
+
20
+ class SpecNodeResolveIndex
21
+ Innate.node('/arg')
22
+
23
+ def index(arg) end
24
+ end
25
+
26
+ describe 'Node.resolve' do
27
+ def compare(url, hash)
28
+ result = SpecNodeResolve.resolve(url)
29
+ result.should.not.be.nil
30
+ hash.each do |key, value|
31
+ result[key.to_s].should == value
32
+ end
33
+ end
34
+
35
+ should 'resolve actions with methods' do
36
+ SpecNodeResolve.resolve('/').should.be.nil
37
+ SpecNodeResolve.resolve('/index').should.be.nil
38
+
39
+ compare '/foo', :method => 'foo', :params => []
40
+ SpecNodeResolve.resolve('/foo/one/two').should.be.nil
41
+
42
+ compare '/bar', :method => 'bar', :params => []
43
+ SpecNodeResolve.resolve('/bar/one').should.be.nil
44
+
45
+ SpecNodeResolve.resolve('/one').should.be.nil
46
+ compare '/one/1', :method => 'one', :params => ['1']
47
+ SpecNodeResolve.resolve('/one/1/2').should.be.nil
48
+ SpecNodeResolve.resolve('/one/1/2/3').should.be.nil
49
+
50
+ SpecNodeResolve.resolve('/two').should.be.nil
51
+ SpecNodeResolve.resolve('/two/1').should.be.nil
52
+ compare '/two/1/2', :method => 'two', :params => %w[1 2]
53
+ SpecNodeResolve.resolve('/two/1/2/3').should.be.nil
54
+
55
+ compare '/more', :method => 'more', :params => []
56
+ compare '/more/1', :method => 'more', :params => %w[1]
57
+ compare '/more/1/2', :method => 'more', :params => %w[1 2]
58
+ compare '/more/1/2/3', :method => 'more', :params => %w[1 2 3]
59
+
60
+ compare '/default', :method => 'default', :params => []
61
+ compare '/default/1', :method => 'default', :params => %w[1]
62
+
63
+ # NOTE: these are actually bound to fail when called, but we cannot
64
+ # introspect enough to anticipate this failure
65
+ compare '/default/1/2', :method => 'default', :params => %w[1 2]
66
+ compare '/default/1/2/3', :method => 'default', :params => %w[1 2 3]
67
+ end
68
+
69
+ should 'inherit action methods from superclasses' do
70
+ SpecNodeResolveSub.resolve('/foo').should.not.be.nil
71
+ SpecNodeResolveSub.resolve('/foo/one/two').should.be.nil
72
+ end
73
+
74
+ should 'select correct method from subclasses' do
75
+ SpecNodeResolveSub.resolve('/bar/one').should.not.be.nil
76
+ SpecNodeResolveSub.resolve('/bar').should.be.nil
77
+ end
78
+
79
+ it "doesn't select index as action with index parameter if arity is 1" do
80
+ SpecNodeResolveIndex.resolve('/index').should.be.nil
81
+ end
82
+ end
@@ -0,0 +1,3 @@
1
+ <div class="content">
2
+ #{@content}
3
+ </div>
@@ -0,0 +1 @@
1
+ <h1>Hello, World!</h1>
@@ -0,0 +1 @@
1
+ <?r 10.times do |n| ?>#{n}<?r end ?>
@@ -0,0 +1 @@
1
+ Only template
@@ -0,0 +1 @@
1
+ <div class="content">#{@content}</div>
@@ -0,0 +1,83 @@
1
+ require 'spec/helper'
2
+
3
+ SPEC_WRAP_LOG = []
4
+
5
+ class SpecWrapActionCall
6
+ Innate.node '/'
7
+
8
+ def first; end
9
+ def second; end
10
+ def third; end
11
+
12
+ private
13
+
14
+ def wrap_before(action)
15
+ SPEC_WRAP_LOG << [:before, action.name]
16
+ yield
17
+ end
18
+
19
+ def wrap_after(action)
20
+ SPEC_WRAP_LOG << [:after, action.name]
21
+ yield
22
+ end
23
+ end
24
+
25
+ class SpecWrapActionCallStop
26
+ Innate.node '/stop'
27
+
28
+ def index; 'Hello'; end
29
+
30
+ def wrap_pass(action)
31
+ yield
32
+ end
33
+
34
+ def wrap_stop(action)
35
+ 'No Hello'
36
+ end
37
+ end
38
+
39
+
40
+ describe 'Node#wrap_action_call' do
41
+ behaves_like :rack_test
42
+
43
+ it 'executes our wrapper' do
44
+ SPEC_WRAP_LOG.clear
45
+ SpecWrapActionCall.add_action_wrapper(2.0, :wrap_after)
46
+
47
+ get('/first')
48
+ SPEC_WRAP_LOG.should == [[:after, 'first']]
49
+
50
+ get('/second')
51
+ SPEC_WRAP_LOG.should == [[:after, 'first'], [:after, 'second']]
52
+
53
+ get('/third')
54
+ SPEC_WRAP_LOG.should == [[:after, 'first'], [:after, 'second'], [:after, 'third']]
55
+ end
56
+
57
+ it 'executes wrappers in correct order' do
58
+ SPEC_WRAP_LOG.clear
59
+ SpecWrapActionCall.add_action_wrapper(1.0, :wrap_before)
60
+
61
+ get('/first')
62
+ SPEC_WRAP_LOG.should == [[:before, 'first'], [:after, 'first']]
63
+
64
+ get('/second')
65
+ SPEC_WRAP_LOG.should == [
66
+ [:before, 'first'], [:after, 'first'],
67
+ [:before, 'second'], [:after, 'second']]
68
+
69
+ get('/third')
70
+ SPEC_WRAP_LOG.should == [
71
+ [:before, 'first'], [:after, 'first'],
72
+ [:before, 'second'], [:after, 'second'],
73
+ [:before, 'third'], [:after, 'third']]
74
+ end
75
+
76
+ it 'stops in the chain when not yielded' do
77
+ SpecWrapActionCallStop.add_action_wrapper(1.0, :wrap_pass)
78
+ get('/stop').body.should == 'Hello'
79
+
80
+ SpecWrapActionCallStop.add_action_wrapper(2.0, :wrap_stop)
81
+ get('/stop').body.should == 'No Hello'
82
+ end
83
+ end
@@ -0,0 +1,123 @@
1
+ require 'spec/helper'
2
+
3
+ Options = Innate::Options
4
+
5
+ describe Options do
6
+ @options = Innate::Options.new(:spec)
7
+
8
+ should 'create option' do
9
+ @options.o('my name', :name, 'manveru')
10
+ @options.name.should == 'manveru'
11
+ end
12
+
13
+ should 'create options with meta hash' do
14
+ @options.o('the port', :port, 7000, :cli => '-p')
15
+ @options.port.should == 7000
16
+ end
17
+
18
+ should 'get complete hash via #get' do
19
+ @options.get(:port)[:cli].should == '-p'
20
+ @options.get(:port)[:doc].should == 'the port'
21
+ end
22
+
23
+ should 'get value via []' do
24
+ @options[:port].should == 7000
25
+ end
26
+
27
+ should 'create scope' do
28
+ @options.sub(:deep)
29
+ @options.deep.should.not.be.nil
30
+ end
31
+
32
+ should 'create option in scope' do
33
+ @options.deep.o('the browser', :browser, :firefox)
34
+ @options.deep.browser.should == :firefox
35
+ end
36
+
37
+ should 'append to scope via dsl' do
38
+ @options.sub(:deep).o('hi mom', :greeting, :mom)
39
+ @options.deep.greeting.should == :mom
40
+ end
41
+
42
+ should 'sub in subscope' do
43
+ @options.sub(:deep).sub(:down).o('deep down', :me, :too)
44
+ @options.deep.down.me.should == :too
45
+ end
46
+
47
+ should 'get sub-sub option' do
48
+ @options.get(:deep, :down, :me).
49
+ should == {:value => :too, :doc => 'deep down'}
50
+ end
51
+
52
+ should 'respond with nil on getting missing option' do
53
+ @options.get(:deep, :down, :you).should.be.nil
54
+ end
55
+
56
+ should 'search in higher scope if key not found' do
57
+ @options.deep.port.should == 7000
58
+ end
59
+
60
+ should '#set_value to set a nested value directly' do
61
+ @options.set_value([:deep, :down, :me], 'me deep down')
62
+ @options.deep.down.me.should == 'me deep down'
63
+ end
64
+
65
+ should 'merge! existing options with other Enumerable' do
66
+ @options.merge!(:port => 4000, :name => 'feagliir')
67
+ @options.port.should == 4000
68
+ @options.name.should == 'feagliir'
69
+ end
70
+
71
+ should 'iterate via #each_pair' do
72
+ given_keys = [:deep, :name, :port]
73
+ given_values = [@options[:deep], @options[:name], @options[:port]]
74
+
75
+ @options.each_pair do |key, value|
76
+ given_keys.delete(key)
77
+ given_values.delete(value)
78
+ end
79
+
80
+ given_keys.should.be.empty
81
+ given_values.should.be.empty
82
+ end
83
+
84
+ should 'iterate via #each_option' do
85
+ given_keys = [:deep, :name, :port]
86
+ given_values = [@options.get(:deep), @options.get(:name), @options.get(:port)]
87
+
88
+ @options.each_option do |key, option|
89
+ given_keys.delete(key)
90
+ given_values.delete(option)
91
+ end
92
+
93
+ given_keys.should.be.empty
94
+ given_values.should.be.empty
95
+ end
96
+
97
+ should "raise when trying to assign to key that doesn't exist" do
98
+ lambda{ @options[:foo] = :bar }.should.raise(ArgumentError)
99
+ end
100
+
101
+ should "raise when trying to assign to an option that doesn't exist" do
102
+ lambda{ @options.merge!(:foo => :bar) }.should.raise(IndexError)
103
+ end
104
+
105
+ should 'pretty_print' do
106
+ require 'pp'
107
+ p = PP.new
108
+ @options.pretty_print(p)
109
+ lines = p.output.split(/\n/)
110
+ lines.find_all{|l|
111
+ /:doc/ === l &&
112
+ /:value/ === l
113
+ }.size.should > 3
114
+ end
115
+
116
+ should 'trigger block when option is changed' do
117
+ set = nil
118
+ @options.trigger(:port){|value| set = value }
119
+ set.should.be.nil
120
+ @options.port = 300
121
+ set.should == 300
122
+ end
123
+ end