adamwiggins-sinatra 0.8.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/AUTHORS +40 -0
  2. data/CHANGES +167 -0
  3. data/LICENSE +22 -0
  4. data/README.rdoc +529 -0
  5. data/Rakefile +180 -0
  6. data/compat/app_test.rb +300 -0
  7. data/compat/application_test.rb +334 -0
  8. data/compat/builder_test.rb +101 -0
  9. data/compat/custom_error_test.rb +62 -0
  10. data/compat/erb_test.rb +136 -0
  11. data/compat/events_test.rb +75 -0
  12. data/compat/filter_test.rb +30 -0
  13. data/compat/haml_test.rb +233 -0
  14. data/compat/helper.rb +21 -0
  15. data/compat/mapped_error_test.rb +72 -0
  16. data/compat/pipeline_test.rb +71 -0
  17. data/compat/public/foo.xml +1 -0
  18. data/compat/sass_test.rb +57 -0
  19. data/compat/sessions_test.rb +39 -0
  20. data/compat/streaming_test.rb +121 -0
  21. data/compat/sym_params_test.rb +19 -0
  22. data/compat/template_test.rb +30 -0
  23. data/compat/use_in_file_templates_test.rb +47 -0
  24. data/compat/views/foo.builder +1 -0
  25. data/compat/views/foo.erb +1 -0
  26. data/compat/views/foo.haml +1 -0
  27. data/compat/views/foo.sass +2 -0
  28. data/compat/views/foo_layout.erb +2 -0
  29. data/compat/views/foo_layout.haml +2 -0
  30. data/compat/views/layout_test/foo.builder +1 -0
  31. data/compat/views/layout_test/foo.erb +1 -0
  32. data/compat/views/layout_test/foo.haml +1 -0
  33. data/compat/views/layout_test/foo.sass +2 -0
  34. data/compat/views/layout_test/layout.builder +3 -0
  35. data/compat/views/layout_test/layout.erb +1 -0
  36. data/compat/views/layout_test/layout.haml +1 -0
  37. data/compat/views/layout_test/layout.sass +2 -0
  38. data/compat/views/no_layout/no_layout.builder +1 -0
  39. data/compat/views/no_layout/no_layout.haml +1 -0
  40. data/lib/sinatra/base.rb +818 -0
  41. data/lib/sinatra/compat.rb +239 -0
  42. data/lib/sinatra/images/404.png +0 -0
  43. data/lib/sinatra/images/500.png +0 -0
  44. data/lib/sinatra/main.rb +48 -0
  45. data/lib/sinatra/test/rspec.rb +2 -0
  46. data/lib/sinatra/test/spec.rb +2 -0
  47. data/lib/sinatra/test/unit.rb +11 -0
  48. data/lib/sinatra/test.rb +112 -0
  49. data/lib/sinatra.rb +3 -0
  50. data/sinatra.gemspec +107 -0
  51. data/test/base_test.rb +72 -0
  52. data/test/builder_test.rb +68 -0
  53. data/test/data/reload_app_file.rb +3 -0
  54. data/test/erb_test.rb +55 -0
  55. data/test/filter_test.rb +39 -0
  56. data/test/haml_test.rb +72 -0
  57. data/test/helpers_test.rb +368 -0
  58. data/test/mapped_error_test.rb +164 -0
  59. data/test/middleware_test.rb +63 -0
  60. data/test/options_test.rb +103 -0
  61. data/test/reload_test.rb +65 -0
  62. data/test/request_test.rb +11 -0
  63. data/test/result_test.rb +92 -0
  64. data/test/routing_test.rb +338 -0
  65. data/test/sass_test.rb +40 -0
  66. data/test/sinatra_test.rb +15 -0
  67. data/test/static_test.rb +60 -0
  68. data/test/templates_test.rb +92 -0
  69. data/test/views/hello.builder +1 -0
  70. data/test/views/hello.erb +1 -0
  71. data/test/views/hello.haml +1 -0
  72. data/test/views/hello.sass +2 -0
  73. data/test/views/hello.test +1 -0
  74. data/test/views/layout2.builder +3 -0
  75. data/test/views/layout2.erb +2 -0
  76. data/test/views/layout2.haml +2 -0
  77. data/test/views/layout2.test +1 -0
  78. metadata +159 -0
@@ -0,0 +1,300 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ context "Sinatra" do
4
+
5
+ setup do
6
+ Sinatra.application = nil
7
+ end
8
+
9
+ specify "should put all DSL methods on (main)" do
10
+ object = Object.new
11
+ Sinatra::Application::FORWARD_METHODS.each do |method|
12
+ object.private_methods.should.include(method)
13
+ end
14
+ end
15
+
16
+ specify "should handle result of nil" do
17
+ get '/' do
18
+ nil
19
+ end
20
+
21
+ get_it '/'
22
+ should.be.ok
23
+ body.should == ''
24
+ end
25
+
26
+ specify "handles events" do
27
+ get '/:name' do
28
+ 'Hello ' + params["name"]
29
+ end
30
+
31
+ get_it '/Blake'
32
+
33
+ should.be.ok
34
+ body.should.equal 'Hello Blake'
35
+ end
36
+
37
+
38
+ specify "handles splats" do
39
+ get '/hi/*' do
40
+ params["splat"].kind_of?(Array).should.equal true
41
+ params["splat"].first
42
+ end
43
+
44
+ get_it '/hi/Blake'
45
+
46
+ should.be.ok
47
+ body.should.equal 'Blake'
48
+ end
49
+
50
+ specify "handles multiple splats" do
51
+ get '/say/*/to/*' do
52
+ params["splat"].join(' ')
53
+ end
54
+
55
+ get_it '/say/hello/to/world'
56
+
57
+ should.be.ok
58
+ body.should.equal 'hello world'
59
+ end
60
+
61
+ specify "allow empty splats" do
62
+ get '/say/*/to*/*' do
63
+ params["splat"].join(' ')
64
+ end
65
+
66
+ get_it '/say/hello/to/world'
67
+
68
+ should.be.ok
69
+ body.should.equal 'hello world' # second splat is empty
70
+
71
+ get_it '/say/hello/tomy/world'
72
+
73
+ should.be.ok
74
+ body.should.equal 'hello my world'
75
+ end
76
+
77
+ specify "gives access to underlying response header Hash" do
78
+ get '/' do
79
+ header['X-Test'] = 'Is this thing on?'
80
+ headers 'X-Test2' => 'Foo', 'X-Test3' => 'Bar'
81
+ ''
82
+ end
83
+
84
+ get_it '/'
85
+ should.be.ok
86
+ headers.should.include 'X-Test'
87
+ headers['X-Test'].should.equal 'Is this thing on?'
88
+ headers.should.include 'X-Test3'
89
+ headers['X-Test3'].should.equal 'Bar'
90
+ end
91
+
92
+ specify "follows redirects" do
93
+ get '/' do
94
+ redirect '/blake'
95
+ end
96
+
97
+ get '/blake' do
98
+ 'Mizerany'
99
+ end
100
+
101
+ get_it '/'
102
+ should.be.redirection
103
+ body.should.equal ''
104
+
105
+ follow!
106
+ should.be.ok
107
+ body.should.equal 'Mizerany'
108
+ end
109
+
110
+ specify "renders a body with a redirect" do
111
+ helpers do
112
+ def foo ; 'blah' ; end
113
+ end
114
+ get "/" do
115
+ redirect 'foo', :foo
116
+ end
117
+ get_it '/'
118
+ should.be.redirection
119
+ headers['Location'].should.equal 'foo'
120
+ body.should.equal 'blah'
121
+ end
122
+
123
+ specify "redirects permanently with 301 status code" do
124
+ get "/" do
125
+ redirect 'foo', 301
126
+ end
127
+ get_it '/'
128
+ should.be.redirection
129
+ headers['Location'].should.equal 'foo'
130
+ status.should.equal 301
131
+ body.should.be.empty
132
+ end
133
+
134
+ specify "stop sets content and ends event" do
135
+ get '/set_body' do
136
+ stop 'Hello!'
137
+ stop 'World!'
138
+ fail 'stop should have halted'
139
+ end
140
+
141
+ get_it '/set_body'
142
+
143
+ should.be.ok
144
+ body.should.equal 'Hello!'
145
+
146
+ end
147
+
148
+ # Deprecated. WTF was going on here? What's the 1 in [:foo, 1] do?
149
+ xspecify "should set status then call helper with a var" do
150
+ helpers do
151
+ def foo
152
+ 'bah!'
153
+ end
154
+ end
155
+
156
+ get '/set_body' do
157
+ stop [404, [:foo, 1]]
158
+ end
159
+
160
+ get_it '/set_body'
161
+
162
+ should.be.not_found
163
+ body.should.equal 'bah!'
164
+
165
+ end
166
+
167
+ specify "should easily set response Content-Type" do
168
+ get '/foo.html' do
169
+ content_type 'text/html', :charset => 'utf-8'
170
+ "<h1>Hello, World</h1>"
171
+ end
172
+
173
+ get_it '/foo.html'
174
+ should.be.ok
175
+ headers['Content-Type'].should.equal 'text/html;charset=utf-8'
176
+ body.should.equal '<h1>Hello, World</h1>'
177
+
178
+ get '/foo_test.xml' do
179
+ content_type :xml
180
+ "<feed></feed>"
181
+ end
182
+
183
+ get_it '/foo_test.xml'
184
+ should.be.ok
185
+ headers['Content-Type'].should.equal 'application/xml'
186
+ body.should.equal '<feed></feed>'
187
+ end
188
+
189
+ specify "supports conditional GETs with last_modified" do
190
+ modified_at = Time.now
191
+ get '/maybe' do
192
+ last_modified modified_at
193
+ 'response body, maybe'
194
+ end
195
+
196
+ get_it '/maybe'
197
+ should.be.ok
198
+ body.should.equal 'response body, maybe'
199
+
200
+ get_it '/maybe', :env => { 'HTTP_IF_MODIFIED_SINCE' => modified_at.httpdate }
201
+ status.should.equal 304
202
+ body.should.equal ''
203
+ end
204
+
205
+ specify "supports conditional GETs with entity_tag" do
206
+ get '/strong' do
207
+ entity_tag 'FOO'
208
+ 'foo response'
209
+ end
210
+
211
+ get_it '/strong'
212
+ should.be.ok
213
+ body.should.equal 'foo response'
214
+
215
+ get_it '/strong', {},
216
+ 'HTTP_IF_NONE_MATCH' => '"BAR"'
217
+ should.be.ok
218
+ body.should.equal 'foo response'
219
+
220
+ get_it '/strong', {},
221
+ 'HTTP_IF_NONE_MATCH' => '"FOO"'
222
+ status.should.equal 304
223
+ body.should.equal ''
224
+
225
+ get_it '/strong', {},
226
+ 'HTTP_IF_NONE_MATCH' => '"BAR", *'
227
+ status.should.equal 304
228
+ body.should.equal ''
229
+ end
230
+
231
+ specify "delegates HEAD requests to GET handlers" do
232
+ get '/invisible' do
233
+ "I am invisible to the world"
234
+ end
235
+
236
+ head_it '/invisible'
237
+ should.be.ok
238
+ body.should.not.equal "I am invisible to the world"
239
+ body.should.equal ''
240
+ end
241
+
242
+
243
+ specify "supports PUT" do
244
+ put '/' do
245
+ 'puted'
246
+ end
247
+ put_it '/'
248
+ assert_equal 'puted', body
249
+ end
250
+
251
+ specify "rewrites POSTs with _method param to PUT" do
252
+ put '/' do
253
+ 'puted'
254
+ end
255
+ post_it '/', :_method => 'PUT'
256
+ assert_equal 'puted', body
257
+ end
258
+
259
+ specify "rewrites POSTs with lowercase _method param to PUT" do
260
+ put '/' do
261
+ 'puted'
262
+ end
263
+ post_it '/', :_method => 'put'
264
+ body.should.equal 'puted'
265
+ end
266
+
267
+ specify "does not rewrite GETs with _method param to PUT" do
268
+ get '/' do
269
+ 'getted'
270
+ end
271
+ get_it '/', :_method => 'put'
272
+ should.be.ok
273
+ body.should.equal 'getted'
274
+ end
275
+
276
+ specify "ignores _method query string parameter on non-POST requests" do
277
+ post '/' do
278
+ 'posted'
279
+ end
280
+ put '/' do
281
+ 'booo'
282
+ end
283
+ post_it "/?_method=PUT"
284
+ should.be.ok
285
+ body.should.equal 'posted'
286
+ end
287
+
288
+ specify "does not read body if content type is not url encoded" do
289
+ post '/foo.xml' do
290
+ request.env['CONTENT_TYPE'].should.be == 'application/xml'
291
+ request.content_type.should.be == 'application/xml'
292
+ request.body.read
293
+ end
294
+
295
+ post_it '/foo.xml', '<foo></foo>', :content_type => 'application/xml'
296
+ @response.should.be.ok
297
+ @response.body.should.be == '<foo></foo>'
298
+ end
299
+
300
+ end
@@ -0,0 +1,334 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ require 'uri'
4
+
5
+ class TesterWithEach
6
+ def each
7
+ yield 'foo'
8
+ yield 'bar'
9
+ yield 'baz'
10
+ end
11
+ end
12
+
13
+ context "Looking up a request" do
14
+
15
+ setup do
16
+ Sinatra.application = nil
17
+ end
18
+
19
+ # Deprecated. The lookup method is no longer used.
20
+ xspecify "returns what's at the end" do
21
+ block = Proc.new { 'Hello' }
22
+ get '/', &block
23
+
24
+ result = Sinatra.application.lookup(
25
+ Rack::Request.new(
26
+ 'REQUEST_METHOD' => 'GET',
27
+ 'PATH_INFO' => '/'
28
+ )
29
+ )
30
+
31
+ result.should.not.be.nil
32
+ result.block.should.be block
33
+ end
34
+
35
+ # Deprecated. The lookup method is no longer used.
36
+ xspecify "takes params in path" do
37
+ block = Proc.new { 'Hello' }
38
+ get '/:foo', &block
39
+
40
+ result = Sinatra.application.lookup(
41
+ Rack::Request.new(
42
+ 'REQUEST_METHOD' => 'GET',
43
+ 'PATH_INFO' => '/bar'
44
+ )
45
+ )
46
+
47
+ result.should.not.be.nil
48
+ result.block.should.be block
49
+ result.params.should.equal "foo" => 'bar'
50
+ end
51
+
52
+ end
53
+
54
+ context "An app returns" do
55
+
56
+ setup do
57
+ Sinatra.application = nil
58
+ end
59
+
60
+ specify "404 if no events found" do
61
+ request = Rack::MockRequest.new(@app)
62
+ get_it '/'
63
+ should.be.not_found
64
+ body.should.equal '<h1>Not Found</h1>'
65
+ end
66
+
67
+ specify "200 if success" do
68
+ get '/' do
69
+ 'Hello World'
70
+ end
71
+ get_it '/'
72
+ should.be.ok
73
+ body.should.equal 'Hello World'
74
+ end
75
+
76
+ specify "an objects result from each if it has it" do
77
+
78
+ get '/' do
79
+ TesterWithEach.new
80
+ end
81
+
82
+ get_it '/'
83
+ should.be.ok
84
+ body.should.equal 'foobarbaz'
85
+
86
+ end
87
+
88
+ # Deprecated. The body method no longer halts.
89
+ xspecify "the body set if set before the last" do
90
+
91
+ get '/' do
92
+ body 'Blake'
93
+ 'Mizerany'
94
+ end
95
+
96
+ get_it '/'
97
+ should.be.ok
98
+ body.should.equal 'Blake'
99
+
100
+ end
101
+
102
+ specify "404 if NotFound is raised" do
103
+
104
+ get '/' do
105
+ raise Sinatra::NotFound
106
+ end
107
+
108
+ get_it '/'
109
+ should.be.not_found
110
+
111
+ end
112
+
113
+ end
114
+
115
+ context "Application#configure blocks" do
116
+
117
+ setup do
118
+ Sinatra.application = nil
119
+ end
120
+
121
+ specify "run when no environment specified" do
122
+ ref = false
123
+ configure { ref = true }
124
+ ref.should.equal true
125
+ end
126
+
127
+ specify "run when matching environment specified" do
128
+ ref = false
129
+ configure(:test) { ref = true }
130
+ ref.should.equal true
131
+ end
132
+
133
+ specify "do not run when no matching environment specified" do
134
+ configure(:foo) { flunk "block should not have been executed" }
135
+ configure(:development, :production, :foo) { flunk "block should not have been executed" }
136
+ end
137
+
138
+ specify "accept multiple environments" do
139
+ ref = false
140
+ configure(:foo, :test, :bar) { ref = true }
141
+ ref.should.equal true
142
+ end
143
+
144
+ end
145
+
146
+ context "Default Application Configuration" do
147
+
148
+ # Sinatra::ServerError is no longer used
149
+ xspecify "includes 404 and 500 error handlers" do
150
+ Sinatra.application.errors.should.include(Sinatra::ServerError)
151
+ Sinatra.application.errors[Sinatra::ServerError].should.not.be.nil
152
+ Sinatra.application.errors.should.include(Sinatra::NotFound)
153
+ Sinatra.application.errors[Sinatra::NotFound].should.not.be.nil
154
+ end
155
+
156
+ # Deprecated. No such thing as a Static event anymore.
157
+ xspecify "includes Static event" do
158
+ assert Sinatra.application.events[:get].any? { |e| Sinatra::Static === e }
159
+ end
160
+
161
+ end
162
+
163
+ context "Events in an app" do
164
+
165
+ setup do
166
+ Sinatra.application = nil
167
+ end
168
+
169
+ specify "evaluate in a clean context" do
170
+ helpers do
171
+ def foo
172
+ 'foo'
173
+ end
174
+ end
175
+
176
+ get '/foo' do
177
+ foo
178
+ end
179
+
180
+ get_it '/foo'
181
+ should.be.ok
182
+ body.should.equal 'foo'
183
+ end
184
+
185
+ specify "get access to request, response, and params" do
186
+ get '/:foo' do
187
+ params["foo"] + params["bar"]
188
+ end
189
+
190
+ get_it '/foo?bar=baz'
191
+ should.be.ok
192
+ body.should.equal 'foobaz'
193
+ end
194
+
195
+ specify "can filters by agent" do
196
+
197
+ get '/', :agent => /Windows/ do
198
+ request.env['HTTP_USER_AGENT']
199
+ end
200
+
201
+ get_it '/', :env => { :agent => 'Windows' }
202
+ should.be.ok
203
+ body.should.equal 'Windows'
204
+
205
+ get_it '/', :env => { :agent => 'Mac' }
206
+ should.not.be.ok
207
+
208
+ end
209
+
210
+ specify "can use regex to get parts of user-agent" do
211
+
212
+ get '/', :agent => /Windows (NT)/ do
213
+ params[:agent].first
214
+ end
215
+
216
+ get_it '/', :env => { :agent => 'Windows NT' }
217
+
218
+ body.should.equal 'NT'
219
+
220
+ end
221
+
222
+ specify "can deal with spaces in paths" do
223
+
224
+ path = '/path with spaces'
225
+
226
+ get path do
227
+ "Look ma, a path with spaces!"
228
+ end
229
+
230
+ get_it URI.encode(path)
231
+
232
+ body.should.equal "Look ma, a path with spaces!"
233
+ end
234
+
235
+ specify "route based on host" do
236
+
237
+ get '/' do
238
+ 'asdf'
239
+ end
240
+
241
+ get_it '/'
242
+ assert ok?
243
+ assert_equal('asdf', body)
244
+
245
+ get '/foo', :host => 'foo.sinatrarb.com' do
246
+ 'in foo!'
247
+ end
248
+
249
+ get '/foo', :host => 'bar.sinatrarb.com' do
250
+ 'in bar!'
251
+ end
252
+
253
+ get_it '/foo', {}, 'HTTP_HOST' => 'foo.sinatrarb.com'
254
+ assert ok?
255
+ assert_equal 'in foo!', body
256
+
257
+ get_it '/foo', {}, 'HTTP_HOST' => 'bar.sinatrarb.com'
258
+ assert ok?
259
+ assert_equal 'in bar!', body
260
+
261
+ get_it '/foo'
262
+ assert not_found?
263
+
264
+ end
265
+
266
+ end
267
+
268
+
269
+ context "Options in an app" do
270
+
271
+ setup do
272
+ Sinatra.application = nil
273
+ @app = Sinatra::application
274
+ end
275
+
276
+ specify "can be set singly on app" do
277
+ @app.set :foo, 1234
278
+ @app.options.foo.should.equal 1234
279
+ end
280
+
281
+ specify "can be set singly from top-level" do
282
+ set_option :foo, 1234
283
+ @app.options.foo.should.equal 1234
284
+ end
285
+
286
+ specify "can be set multiply on app" do
287
+ @app.options.foo.should.be.nil
288
+ @app.set :foo => 1234,
289
+ :bar => 'hello, world'
290
+ @app.options.foo.should.equal 1234
291
+ @app.options.bar.should.equal 'hello, world'
292
+ end
293
+
294
+ specify "can be set multiply from top-level" do
295
+ @app.options.foo.should.be.nil
296
+ set_options :foo => 1234,
297
+ :bar => 'hello, world'
298
+ @app.options.foo.should.equal 1234
299
+ @app.options.bar.should.equal 'hello, world'
300
+ end
301
+
302
+ specify "can be enabled on app" do
303
+ @app.options.foo.should.be.nil
304
+ @app.enable :sessions, :foo, :bar
305
+ @app.options.sessions.should.equal true
306
+ @app.options.foo.should.equal true
307
+ @app.options.bar.should.equal true
308
+ end
309
+
310
+ specify "can be enabled from top-level" do
311
+ @app.options.foo.should.be.nil
312
+ enable :sessions, :foo, :bar
313
+ @app.options.sessions.should.equal true
314
+ @app.options.foo.should.equal true
315
+ @app.options.bar.should.equal true
316
+ end
317
+
318
+ specify "can be disabled on app" do
319
+ @app.options.foo.should.be.nil
320
+ @app.disable :sessions, :foo, :bar
321
+ @app.options.sessions.should.equal false
322
+ @app.options.foo.should.equal false
323
+ @app.options.bar.should.equal false
324
+ end
325
+
326
+ specify "can be enabled from top-level" do
327
+ @app.options.foo.should.be.nil
328
+ disable :sessions, :foo, :bar
329
+ @app.options.sessions.should.equal false
330
+ @app.options.foo.should.equal false
331
+ @app.options.bar.should.equal false
332
+ end
333
+
334
+ end