innate 2009.04

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/CHANGELOG +2981 -0
  2. data/COPYING +18 -0
  3. data/MANIFEST +127 -0
  4. data/README.md +563 -0
  5. data/Rakefile +35 -0
  6. data/example/app/retro_games.rb +60 -0
  7. data/example/app/todo/layout/default.xhtml +11 -0
  8. data/example/app/todo/spec/todo.rb +63 -0
  9. data/example/app/todo/start.rb +51 -0
  10. data/example/app/todo/view/index.xhtml +39 -0
  11. data/example/app/whywiki_erb/layout/wiki.html.erb +15 -0
  12. data/example/app/whywiki_erb/spec/wiki.rb +19 -0
  13. data/example/app/whywiki_erb/start.rb +42 -0
  14. data/example/app/whywiki_erb/view/edit.erb +6 -0
  15. data/example/app/whywiki_erb/view/index.erb +12 -0
  16. data/example/custom_middleware.rb +35 -0
  17. data/example/hello.rb +11 -0
  18. data/example/howto_spec.rb +35 -0
  19. data/example/link.rb +27 -0
  20. data/example/provides.rb +31 -0
  21. data/example/session.rb +38 -0
  22. data/innate.gemspec +29 -0
  23. data/lib/innate.rb +269 -0
  24. data/lib/innate/action.rb +150 -0
  25. data/lib/innate/adapter.rb +76 -0
  26. data/lib/innate/cache.rb +134 -0
  27. data/lib/innate/cache/api.rb +128 -0
  28. data/lib/innate/cache/drb.rb +58 -0
  29. data/lib/innate/cache/file_based.rb +41 -0
  30. data/lib/innate/cache/marshal.rb +17 -0
  31. data/lib/innate/cache/memory.rb +22 -0
  32. data/lib/innate/cache/yaml.rb +17 -0
  33. data/lib/innate/current.rb +37 -0
  34. data/lib/innate/dynamap.rb +96 -0
  35. data/lib/innate/helper.rb +183 -0
  36. data/lib/innate/helper/aspect.rb +124 -0
  37. data/lib/innate/helper/cgi.rb +54 -0
  38. data/lib/innate/helper/flash.rb +36 -0
  39. data/lib/innate/helper/link.rb +94 -0
  40. data/lib/innate/helper/redirect.rb +85 -0
  41. data/lib/innate/helper/render.rb +87 -0
  42. data/lib/innate/helper/send_file.rb +26 -0
  43. data/lib/innate/log.rb +20 -0
  44. data/lib/innate/log/color_formatter.rb +43 -0
  45. data/lib/innate/log/hub.rb +73 -0
  46. data/lib/innate/middleware_compiler.rb +65 -0
  47. data/lib/innate/mock.rb +49 -0
  48. data/lib/innate/node.rb +1025 -0
  49. data/lib/innate/options.rb +37 -0
  50. data/lib/innate/options/dsl.rb +202 -0
  51. data/lib/innate/options/stub.rb +7 -0
  52. data/lib/innate/request.rb +141 -0
  53. data/lib/innate/response.rb +23 -0
  54. data/lib/innate/route.rb +110 -0
  55. data/lib/innate/session.rb +121 -0
  56. data/lib/innate/session/flash.rb +94 -0
  57. data/lib/innate/spec.rb +23 -0
  58. data/lib/innate/state.rb +27 -0
  59. data/lib/innate/state/accessor.rb +130 -0
  60. data/lib/innate/state/fiber.rb +74 -0
  61. data/lib/innate/state/thread.rb +47 -0
  62. data/lib/innate/traited.rb +85 -0
  63. data/lib/innate/trinity.rb +18 -0
  64. data/lib/innate/version.rb +3 -0
  65. data/lib/innate/view.rb +60 -0
  66. data/lib/innate/view/erb.rb +15 -0
  67. data/lib/innate/view/etanni.rb +36 -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 +107 -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 +118 -0
  86. data/spec/innate/helper/link.rb +139 -0
  87. data/spec/innate/helper/redirect.rb +160 -0
  88. data/spec/innate/helper/render.rb +133 -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/node/mapping.rb +37 -0
  98. data/spec/innate/node/node.rb +134 -0
  99. data/spec/innate/node/resolve.rb +82 -0
  100. data/spec/innate/node/view/another_layout/another_layout.xhtml +3 -0
  101. data/spec/innate/node/view/bar.xhtml +1 -0
  102. data/spec/innate/node/view/foo.html.xhtml +1 -0
  103. data/spec/innate/node/view/only_view.xhtml +1 -0
  104. data/spec/innate/node/view/with_layout.xhtml +1 -0
  105. data/spec/innate/node/wrap_action_call.rb +83 -0
  106. data/spec/innate/options.rb +115 -0
  107. data/spec/innate/parameter.rb +154 -0
  108. data/spec/innate/provides.rb +99 -0
  109. data/spec/innate/provides/list.html.xhtml +1 -0
  110. data/spec/innate/provides/list.txt.xhtml +1 -0
  111. data/spec/innate/request.rb +77 -0
  112. data/spec/innate/route.rb +135 -0
  113. data/spec/innate/session.rb +54 -0
  114. data/spec/innate/state/fiber.rb +58 -0
  115. data/spec/innate/state/thread.rb +40 -0
  116. data/spec/innate/traited.rb +55 -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_installer.rake +76 -0
  121. data/tasks/grancher.rake +12 -0
  122. data/tasks/install_dependencies.rake +4 -0
  123. data/tasks/manifest.rake +4 -0
  124. data/tasks/rcov.rake +19 -0
  125. data/tasks/release.rake +51 -0
  126. data/tasks/reversion.rake +8 -0
  127. data/tasks/setup.rake +28 -0
  128. metadata +181 -0
@@ -0,0 +1,134 @@
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
+ end
53
+
54
+ class SpecNodeWithLayoutMethod < SpecNodeProvide
55
+ map '/layout_method'
56
+ layout 'layout_method'
57
+
58
+ def layout_method
59
+ '<div class="content">#{@content}</div>'
60
+ end
61
+ end
62
+
63
+ class SpecNodeIndex
64
+ Innate.node('/spec_index')
65
+
66
+ def index
67
+ "I have no parameters"
68
+ end
69
+ end
70
+
71
+ class SpecNodeAliasView < SpecNodeProvideTemplate
72
+ map '/alias_view'
73
+ map_views '/'
74
+
75
+ alias_view :aliased, :bar
76
+ end
77
+
78
+ describe 'Innate::Node' do
79
+ behaves_like :mock
80
+
81
+ should 'respond with 404 if no action was found' do
82
+ got = Innate::Mock.get('/does_not_exist')
83
+ got.status.should == 404
84
+ got.body.should == 'No action found at: "/does_not_exist"'
85
+ got['Content-Type'].should == 'text/plain'
86
+ end
87
+
88
+ should 'wrap with layout' do
89
+ got = Innate::Mock.get('/layout/bar')
90
+ got.status.should == 200
91
+ got.body.should == %(<div class="content">42</div>)
92
+ got['Content-Type'].should == 'text/html'
93
+ end
94
+
95
+ should 'find layout with view_root' do
96
+ got = Innate::Mock.get('/another_layout/bar')
97
+ got.status.should == 200
98
+ got.body.should == %(<div class="content">\n 42\n</div>)
99
+ got['Content-Type'].should == 'text/html'
100
+ end
101
+
102
+ should 'find layout from method' do
103
+ got = Innate::Mock.get('/layout_method/bar')
104
+ got.status.should == 200
105
+ got.body.should == %(<div class="content">42</div>)
106
+ got['Content-Type'].should == 'text/html'
107
+ end
108
+
109
+ should 'not get an action with wrong parameters' do
110
+ got = Innate::Mock.get('/spec_index/bar')
111
+ got.status.should == 404
112
+ got.body.should == 'No action found at: "/bar"'
113
+ end
114
+
115
+ should 'get an action view if there is no method' do
116
+ got = Innate::Mock.get('/provide_template/only_view')
117
+ got.status.should == 200
118
+ got.body.strip.should == "Only template"
119
+ got['Content-Type'].should == 'text/html'
120
+ end
121
+
122
+ should 'not get an action view with params if there is no method' do
123
+ got = Innate::Mock.get('/provide_template/only_view/param')
124
+ got.status.should == 404
125
+ got.body.strip.should == 'No action found at: "/only_view/param"'
126
+ end
127
+
128
+ should 'use alias_view' do
129
+ got = get('/alias_view/aliased')
130
+ got.status.should == 200
131
+ got.body.strip.should == "<h1>Hello, World!</h1>"
132
+ got['Content-Type'].should == 'text/html'
133
+ end
134
+ 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 :mock
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,115 @@
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', :trigger=> nil}
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 'pretty_print' do
102
+ require 'pp'
103
+ p = PP.new
104
+ @options.pretty_print(p)
105
+ p.output.should =~ /:value=>:mom/
106
+ end
107
+
108
+ should 'trigger block when option is changed' do
109
+ set = nil
110
+ @options.trigger(:port){|value| set = value }
111
+ set.should.be.nil
112
+ @options.port = 300
113
+ set.should == 300
114
+ end
115
+ end
@@ -0,0 +1,154 @@
1
+ require 'spec/helper'
2
+
3
+ class SpecParameter
4
+ include Innate::Node
5
+ map '/'
6
+
7
+ def index
8
+ "index"
9
+ end
10
+
11
+ def no_params
12
+ "no params"
13
+ end
14
+
15
+ def single_param param
16
+ "single param (#{param})"
17
+ end
18
+
19
+ def double_param param1, param2
20
+ "double param (#{param1}, #{param2})"
21
+ end
22
+
23
+ def all_params *params
24
+ "all params (#{params.join(', ')})"
25
+ end
26
+
27
+ def at_least_one param, *params
28
+ "at least one (#{param}, #{params.join(', ')})"
29
+ end
30
+
31
+ def one_default param = 'default'
32
+ "one_default (#{param})"
33
+ end
34
+
35
+ def cat1__cat11
36
+ 'cat1: cat11'
37
+ end
38
+
39
+ def cat1__cat11__cat111
40
+ 'cat1: cat11: cat111'
41
+ end
42
+ end
43
+
44
+ class SpecParameter2
45
+ include Innate::Node
46
+ map '/jo'
47
+
48
+ def add(one, two = nil, three = nil)
49
+ "#{one}:#{two}:#{three}"
50
+ end
51
+
52
+ def keys
53
+ request.params.keys.inspect
54
+ end
55
+ end
56
+
57
+ class SpecParameter3
58
+ include Innate::Node
59
+ map '/ma'
60
+
61
+ def index(*args)
62
+ request.params['foo'].to_s.dump
63
+ end
64
+ end
65
+
66
+ describe "Simple Parameters" do
67
+ def handle(*url)
68
+ response = Innate::Mock.get(*url)
69
+ response.status.should == 200
70
+ response.body
71
+ end
72
+
73
+ it "Should respond to no parameters given" do
74
+ handle('/no_params').should == "no params"
75
+ end
76
+
77
+ it "Should respond to only / with the index" do
78
+ handle('/').should == "index"
79
+ end
80
+
81
+ it "call /bar though index doesn't take params" do
82
+ lambda{ handle('/bar') }.should.raise
83
+ end
84
+
85
+ it "action that takes a single param" do
86
+ handle('/single_param/foo').should == "single param (foo)"
87
+ end
88
+
89
+ it "action that takes two params" do
90
+ handle('/double_param/foo/bar').should == "double param (foo, bar)"
91
+ end
92
+
93
+ it "action that takes two params but we give only one" do
94
+ lambda{ handle('/double_param/foo') }.should.raise
95
+ end
96
+
97
+ it "action that takes all params" do
98
+ handle('/all_params/foo/bar/foobar').should == "all params (foo, bar, foobar)"
99
+ end
100
+
101
+ it "action that takes all params but needs at least one" do
102
+ handle('/at_least_one/foo/bar/foobar').should == "at least one (foo, bar, foobar)"
103
+ end
104
+
105
+ it "action that takes all params but needs at least one (not given here)" do
106
+ lambda{ handle('/at_least_one') }.
107
+ should.raise(ArgumentError)
108
+ end
109
+
110
+ it "one default" do
111
+ handle('/one_default').should == "one_default (default)"
112
+ end
113
+
114
+ it "one default" do
115
+ handle('/one_default/my_default').should == "one_default (my_default)"
116
+ end
117
+
118
+ it "double underscore lookup" do
119
+ handle('/cat1/cat11').should == 'cat1: cat11'
120
+ end
121
+
122
+ it "double double underscore lookup" do
123
+ handle('/cat1/cat11/cat111').should == 'cat1: cat11: cat111'
124
+ end
125
+
126
+
127
+ it "jo/add should raise with 0 parameters" do
128
+ lambda{ handle('/jo/add') }.
129
+ should.raise(ArgumentError)
130
+ end
131
+
132
+ it "add should raise with 4 parameters" do
133
+ lambda{ handle('/jo/add/1/2/3/4') }.
134
+ should.raise(ArgumentError)
135
+ end
136
+
137
+ it "add should not raise with 1-3 parameters" do
138
+ handle('/jo/add/1').should == '1::'
139
+ handle('/jo/add/1/2').should == '1:2:'
140
+ handle('/jo/add/1/2/3').should == '1:2:3'
141
+ end
142
+
143
+ it 'params should have no content without params' do
144
+ handle('/ma').should == '""'
145
+ end
146
+
147
+ it 'should have a parameter via QUERY_PARAMS' do
148
+ handle('/ma?foo=bar').should == '"bar"'
149
+ end
150
+
151
+ it 'should handle valueless params' do
152
+ handle('/jo/keys?foo').should == '["foo"]'
153
+ end
154
+ end