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,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
@@ -0,0 +1,99 @@
1
+ begin
2
+ require 'json'
3
+ rescue LoadError
4
+ exit
5
+ end
6
+
7
+ require 'spec/helper'
8
+ require 'yaml'
9
+
10
+ Innate.options.merge!(:views => 'provides', :layouts => 'provides')
11
+
12
+ class SpecNodeProvides
13
+ Innate.node '/'
14
+
15
+ provide(:html, :engine => :None)
16
+ provide(:yaml, :type => 'text/yaml'){|a,s| s.to_yaml }
17
+ provide(:json, :type => 'application/json'){|a,s| s.to_json }
18
+
19
+ def object
20
+ {'intro' => 'Hello, World!'}
21
+ end
22
+
23
+ def string
24
+ 'Just 42'
25
+ end
26
+ end
27
+
28
+ class SpecNodeProvidesTemplates
29
+ Innate.node '/template'
30
+ map_views '/'
31
+
32
+ provide(:yaml, :type => 'text/yaml'){|a,s| s.to_yaml }
33
+ provide(:json, :type => 'application/json'){|a,s| s.to_json }
34
+ provide(:txt, :engine => :Etanni, :type => 'text/plain')
35
+
36
+ def list
37
+ @users = %w[starbucks apollo athena]
38
+ end
39
+ end
40
+
41
+ shared :assert_wish do
42
+ def assert_wish(uri, body, content_type)
43
+ got = get(uri)
44
+ got.status.should == 200
45
+ got.body.strip.should == body.strip
46
+ got['Content-Type'].should == content_type
47
+ end
48
+ end
49
+
50
+ describe 'Content representation' do
51
+ describe 'without template' do
52
+ behaves_like :rack_test, :assert_wish
53
+
54
+ it 'provides yaml for an object' do
55
+ assert_wish('/object.yaml', {'intro' => 'Hello, World!'}.to_yaml, 'text/yaml')
56
+ end
57
+
58
+ it 'provides json for an object' do
59
+ assert_wish('/object.json', {'intro' => 'Hello, World!'}.to_json, 'application/json')
60
+ end
61
+
62
+ it 'provides html for an object' do
63
+ assert_wish('/string.html', 'Just 42', 'text/html')
64
+ end
65
+
66
+ it 'defaults to html presentation' do
67
+ assert_wish('/string', 'Just 42', 'text/html')
68
+ end
69
+ end
70
+
71
+ describe 'with templates' do
72
+ behaves_like :rack_test, :assert_wish
73
+
74
+ it 'defaults to <name>.html.<engine>' do
75
+ body = '<ul><li>starbucks</li><li>apollo</li><li>athena</li></ul>'
76
+ assert_wish('/template/list', body, 'text/html')
77
+ end
78
+
79
+ it 'uses explicit wish for <name>.html.<engine>' do
80
+ body = '<ul><li>starbucks</li><li>apollo</li><li>athena</li></ul>'
81
+ assert_wish('/template/list.html', body, 'text/html')
82
+ end
83
+
84
+ it 'fails when the wish cannot be satisfied' do
85
+ got = get('/template/list.svg')
86
+ got.status.should == 404
87
+ end
88
+
89
+ it 'uses the object returned from the action method for block provides' do
90
+ body = %w[starbucks apollo athena].to_yaml
91
+ assert_wish('/template/list.yaml', body, 'text/yaml')
92
+ end
93
+
94
+ it 'uses explicit wish for <name>.txt.<engine>' do
95
+ body = "starbucks\napollo\nathena"
96
+ assert_wish('/template/list.txt', body, 'text/plain')
97
+ end
98
+ end
99
+ end
@@ -0,0 +1 @@
1
+ <ul><?r @users.each do |user| ?><li>#{user}</li><?r end ?></ul>
@@ -0,0 +1 @@
1
+ <?r @users.each do |user| ?>#{"#{user}\n"}<?r end ?>
@@ -0,0 +1,79 @@
1
+ require 'spec/helper'
2
+
3
+ describe Innate::Request do
4
+ def request(env = {})
5
+ Innate::Request.new(@env.merge(env))
6
+ end
7
+
8
+ @env = {
9
+ "GATEWAY_INTERFACE" => "CGI/1.1",
10
+ "HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
11
+ "HTTP_ACCEPT_CHARSET" => "UTF-8,*",
12
+ "HTTP_ACCEPT_ENCODING" => "gzip,deflate",
13
+ "HTTP_ACCEPT_LANGUAGE" => "en-us,en;q=0.8,de-at;q=0.5,de;q=0.3",
14
+ "HTTP_CACHE_CONTROL" => "max-age=0",
15
+ "HTTP_CONNECTION" => "keep-alive",
16
+ "HTTP_HOST" => "localhost:7000",
17
+ "HTTP_KEEP_ALIVE" => "300",
18
+ "HTTP_USER_AGENT" => "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008123017 Firefox/3.0.4 Ubiquity/0.1.4",
19
+ "HTTP_VERSION" => "HTTP/1.1",
20
+ "PATH_INFO" => "/",
21
+ "QUERY_STRING" => "a=b",
22
+ "REMOTE_ADDR" => "127.0.0.1",
23
+ "REMOTE_HOST" => "delta.local",
24
+ "REQUEST_METHOD" => "GET",
25
+ "REQUEST_PATH" => "/",
26
+ "REQUEST_URI" => "http://localhost:7000/",
27
+ "SCRIPT_NAME" => "",
28
+ "SERVER_NAME" => "localhost",
29
+ "SERVER_PORT" => "7000",
30
+ "SERVER_PROTOCOL" => "HTTP/1.1",
31
+ }
32
+
33
+ should 'provide #request_uri' do
34
+ request('REQUEST_URI' => '/?a=b').request_uri.should == '/?a=b'
35
+ request('REQUEST_URI' => '/').request_uri.should == '/'
36
+ end
37
+
38
+ should 'provide #local_net?' do
39
+ request.local_net?('192.168.0.1').to_s.should == '192.168.0.0'
40
+ request.local_net?('252.168.0.1').should == nil
41
+ request.local_net?('unknown').should == nil
42
+ request('REMOTE_ADDR' => '211.3.129.47, 66.249.85.131').local_net?.should == nil
43
+ request('REMOTE_ADDR' => '211.3.129.47').local_net?.should == nil
44
+ end
45
+
46
+ should 'provide #subset' do
47
+ require 'stringio'
48
+
49
+ query = {'a' => 'b', 'c' => 'd', 'e' => 'f'}
50
+ params = StringIO.new(Rack::Utils.build_query(query))
51
+ req = request('rack.request.form_hash' => params, 'rack.input' => params)
52
+
53
+ req.params.should == query
54
+ req.subset(:a).should == {'a' => 'b'}
55
+ req.subset(:a, :c).should == {'a' => 'b', 'c' => 'd'}
56
+ end
57
+
58
+ should 'provide #domain on http' do
59
+ request('rack.url_scheme' => 'http').domain.
60
+ should == URI('http://localhost:7000/')
61
+
62
+ request('rack.url_scheme' => 'http').domain('/foo').
63
+ should == URI('http://localhost:7000/foo')
64
+
65
+ request('rack.url_scheme' => 'http').domain('/foo', :keep_query => true).
66
+ should == URI('http://localhost:7000/foo?a=b')
67
+ end
68
+
69
+ should 'provide #domain on https' do
70
+ request('rack.url_scheme' => 'https').domain.
71
+ should == URI('https://localhost:7000/')
72
+
73
+ request('rack.url_scheme' => 'https').domain('/foo').
74
+ should == URI('https://localhost:7000/foo')
75
+
76
+ request('rack.url_scheme' => 'https').domain('/foo', :keep_query => true).
77
+ should == URI('https://localhost:7000/foo?a=b')
78
+ end
79
+ end
@@ -0,0 +1,135 @@
1
+ require 'spec/helper'
2
+
3
+ class SpecRouter
4
+ Innate.node('/').provide(:html, :None)
5
+
6
+ def float(flt)
7
+ "Float: %3.3f" % flt
8
+ end
9
+
10
+ def string(str)
11
+ "String: #{str}"
12
+ end
13
+
14
+ def price(p)
15
+ "Price: \$#{p}"
16
+ end
17
+
18
+ def sum(a, b)
19
+ a.to_i + b.to_i
20
+ end
21
+
22
+ def bar
23
+ 'this is bar'
24
+ end
25
+ end
26
+
27
+ Route, Rewrite = Innate::Route, Innate::Rewrite
28
+
29
+ describe Innate::Route do
30
+ def check(uri, status, body = nil)
31
+ got = Innate::Mock.get(uri)
32
+ got.status.should == status
33
+ got.body.should == body if body
34
+ end
35
+
36
+ should 'take lambda routers' do
37
+ Route['string'] = lambda{|path, req|
38
+ path if path =~ %r!^/string!
39
+ }
40
+ Route['string'].class.should == Proc
41
+
42
+ Route['calc sum'] = lambda{|path, req|
43
+ if req[:do_calc]
44
+ lval, rval = req[:a, :b]
45
+ rval = rval.to_i * 10
46
+ "/sum/#{lval}/#{rval}"
47
+ end
48
+ }
49
+
50
+ Innate::Route('foo') do |path, req|
51
+ '/bar' if req[:bar]
52
+ end
53
+ end
54
+
55
+ should 'define string routes' do
56
+ Route['/foobar'] = '/bar'
57
+ Route['/foobar'].should == '/bar'
58
+ end
59
+
60
+ should 'define regex routes' do
61
+ Route[%r!^/(\d+\.\d{2})$!] = "/price/%.2f"
62
+ Route[%r!^/(\d+\.\d{2})$!].should == "/price/%.2f"
63
+
64
+ Route[%r!^/(\d+\.\d+)!] = "/float/%.3f"
65
+ Route[%r!^/(\d+\.\d+)!].should == "/float/%.3f"
66
+
67
+ Route[%r!^/(\w+)!] = "/string/%s"
68
+ Route[%r!^/(\w+)!].should == "/string/%s"
69
+ end
70
+
71
+ should 'be used at /float' do
72
+ check('/123.123', 200, 'Float: 123.123')
73
+ end
74
+
75
+ should 'be used at /string' do
76
+ check('/foo', 200, 'String: foo')
77
+ end
78
+
79
+ should 'use %.3f' do
80
+ check('/123.123456', 200, 'Float: 123.123')
81
+ end
82
+
83
+ should 'resolve in the order added' do
84
+ check('/12.84', 200, 'Price: $12.84')
85
+ end
86
+
87
+ should 'use lambda routers' do
88
+ check('/string/abc', 200, 'String: abc')
89
+
90
+ check('/?do_calc=1&a=2&b=6', 200, '62')
91
+ end
92
+
93
+ it 'should support Route() with blocks' do
94
+ check('/foo?bar=1', 200, 'this is bar')
95
+ end
96
+
97
+ it 'should support string route translations' do
98
+ check('/foobar', 200, 'this is bar')
99
+ end
100
+
101
+ it 'should clear routes' do
102
+ Route::ROUTES.size.should > 0
103
+ Route.clear
104
+ Route::ROUTES.size.should == 0
105
+ end
106
+
107
+ it 'should not recurse given a bad route' do
108
+ Innate::Route[ %r!^/good/(.+)$! ] = "/bad/%s"
109
+ check('/good/hi', 404)
110
+ end
111
+ end
112
+
113
+ describe Innate::Rewrite do
114
+ Innate::Rewrite[ %r!^/(.+)$! ] = "/string/%s"
115
+
116
+ it 'should rewrite on non-existent actions' do
117
+ got = Innate::Mock.get('/hello')
118
+ got.status.should == 200
119
+ got.body.should == 'String: hello'
120
+ end
121
+
122
+ it 'should exclude existing actions' do
123
+ got = Innate::Mock.get('/bar')
124
+ got.status.should == 200
125
+ got.body.should == 'this is bar'
126
+ end
127
+
128
+ it 'should rewite with (key, val)' do
129
+ Innate::Rewrite[ %r!^/(.+)$! ] = nil
130
+ Innate::Rewrite(%r!^/(.+)$!, "/string/%s")
131
+ got = Innate::Mock.get('/hello')
132
+ got.status.should == 200
133
+ got.body.should == 'String: hello'
134
+ end
135
+ end