sinatra-sinatra 0.8.9

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 (80) hide show
  1. data/AUTHORS +40 -0
  2. data/CHANGES +174 -0
  3. data/LICENSE +22 -0
  4. data/README.rdoc +545 -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 +78 -0
  12. data/compat/filter_test.rb +30 -0
  13. data/compat/haml_test.rb +233 -0
  14. data/compat/helper.rb +30 -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/bacon.rb +17 -0
  46. data/lib/sinatra/test/rspec.rb +9 -0
  47. data/lib/sinatra/test/spec.rb +9 -0
  48. data/lib/sinatra/test/unit.rb +11 -0
  49. data/lib/sinatra/test.rb +109 -0
  50. data/lib/sinatra.rb +4 -0
  51. data/sinatra.gemspec +109 -0
  52. data/test/base_test.rb +68 -0
  53. data/test/builder_test.rb +64 -0
  54. data/test/data/reload_app_file.rb +3 -0
  55. data/test/erb_test.rb +50 -0
  56. data/test/filter_test.rb +35 -0
  57. data/test/haml_test.rb +68 -0
  58. data/test/helper.rb +20 -0
  59. data/test/helpers_test.rb +361 -0
  60. data/test/mapped_error_test.rb +160 -0
  61. data/test/middleware_test.rb +58 -0
  62. data/test/options_test.rb +97 -0
  63. data/test/reload_test.rb +61 -0
  64. data/test/request_test.rb +9 -0
  65. data/test/result_test.rb +88 -0
  66. data/test/routing_test.rb +334 -0
  67. data/test/sass_test.rb +36 -0
  68. data/test/sinatra_test.rb +13 -0
  69. data/test/static_test.rb +57 -0
  70. data/test/templates_test.rb +88 -0
  71. data/test/views/hello.builder +1 -0
  72. data/test/views/hello.erb +1 -0
  73. data/test/views/hello.haml +1 -0
  74. data/test/views/hello.sass +2 -0
  75. data/test/views/hello.test +1 -0
  76. data/test/views/layout2.builder +3 -0
  77. data/test/views/layout2.erb +2 -0
  78. data/test/views/layout2.haml +2 -0
  79. data/test/views/layout2.test +1 -0
  80. metadata +161 -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