sinatra 0.3.3 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sinatra might be problematic. Click here for more details.
- data/AUTHORS +40 -0
- data/CHANGES +189 -0
- data/README.rdoc +146 -117
- data/Rakefile +33 -10
- data/{test → compat}/app_test.rb +11 -10
- data/{test → compat}/application_test.rb +10 -5
- data/compat/builder_test.rb +101 -0
- data/{test → compat}/custom_error_test.rb +0 -0
- data/compat/erb_test.rb +136 -0
- data/{test → compat}/events_test.rb +16 -3
- data/compat/filter_test.rb +30 -0
- data/compat/haml_test.rb +233 -0
- data/compat/helper.rb +30 -0
- data/compat/mapped_error_test.rb +72 -0
- data/{test → compat}/pipeline_test.rb +9 -4
- data/{test → compat}/public/foo.xml +0 -0
- data/compat/sass_test.rb +57 -0
- data/{test → compat}/sessions_test.rb +0 -0
- data/{test → compat}/streaming_test.rb +4 -1
- data/{test → compat}/sym_params_test.rb +0 -0
- data/{test → compat}/template_test.rb +0 -0
- data/{test → compat}/use_in_file_templates_test.rb +0 -0
- data/{test → compat}/views/foo.builder +0 -0
- data/{test → compat}/views/foo.erb +0 -0
- data/{test → compat}/views/foo.haml +0 -0
- data/{test → compat}/views/foo.sass +0 -0
- data/{test → compat}/views/foo_layout.erb +0 -0
- data/{test → compat}/views/foo_layout.haml +0 -0
- data/{test → compat}/views/layout_test/foo.builder +0 -0
- data/{test → compat}/views/layout_test/foo.erb +0 -0
- data/{test → compat}/views/layout_test/foo.haml +0 -0
- data/{test → compat}/views/layout_test/foo.sass +0 -0
- data/{test → compat}/views/layout_test/layout.builder +0 -0
- data/{test → compat}/views/layout_test/layout.erb +0 -0
- data/{test → compat}/views/layout_test/layout.haml +0 -0
- data/{test → compat}/views/layout_test/layout.sass +0 -0
- data/{test → compat}/views/no_layout/no_layout.builder +0 -0
- data/{test → compat}/views/no_layout/no_layout.haml +0 -0
- data/lib/sinatra.rb +6 -1484
- data/lib/sinatra/base.rb +838 -0
- data/lib/sinatra/compat.rb +239 -0
- data/{images → lib/sinatra/images}/404.png +0 -0
- data/{images → lib/sinatra/images}/500.png +0 -0
- data/lib/sinatra/main.rb +48 -0
- data/lib/sinatra/test.rb +114 -0
- data/lib/sinatra/test/bacon.rb +17 -0
- data/lib/sinatra/test/rspec.rb +7 -8
- data/lib/sinatra/test/spec.rb +3 -4
- data/lib/sinatra/test/unit.rb +3 -5
- data/sinatra.gemspec +68 -35
- data/test/base_test.rb +68 -0
- data/test/builder_test.rb +50 -87
- data/test/data/reload_app_file.rb +3 -0
- data/test/erb_test.rb +38 -124
- data/test/filter_test.rb +27 -22
- data/test/haml_test.rb +51 -216
- data/test/helper.rb +22 -6
- data/test/helpers_test.rb +361 -0
- data/test/mapped_error_test.rb +137 -49
- data/test/middleware_test.rb +58 -0
- data/test/options_test.rb +97 -0
- data/test/reload_test.rb +61 -0
- data/test/request_test.rb +18 -0
- data/test/result_test.rb +88 -0
- data/test/routing_test.rb +391 -0
- data/test/sass_test.rb +27 -48
- data/test/sinatra_test.rb +13 -0
- data/test/static_test.rb +57 -0
- data/test/templates_test.rb +88 -0
- data/test/views/hello.builder +1 -0
- data/test/views/hello.erb +1 -0
- data/test/views/hello.haml +1 -0
- data/test/views/hello.sass +2 -0
- data/test/views/hello.test +1 -0
- data/test/views/layout2.builder +3 -0
- data/test/views/layout2.erb +2 -0
- data/test/views/layout2.haml +2 -0
- data/test/views/layout2.test +1 -0
- metadata +80 -48
- data/ChangeLog +0 -96
- data/lib/sinatra/test/methods.rb +0 -76
- data/test/event_context_test.rb +0 -15
@@ -0,0 +1,391 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
describe "Routing" do
|
4
|
+
%w[get put post delete head].each do |verb|
|
5
|
+
it "defines #{verb.upcase} request handlers with #{verb}" do
|
6
|
+
mock_app {
|
7
|
+
send verb, '/hello' do
|
8
|
+
'Hello World'
|
9
|
+
end
|
10
|
+
}
|
11
|
+
|
12
|
+
request = Rack::MockRequest.new(@app)
|
13
|
+
response = request.request(verb.upcase, '/hello', {})
|
14
|
+
assert response.ok?
|
15
|
+
assert_equal 'Hello World', response.body
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "404s when no route satisfies the request" do
|
20
|
+
mock_app {
|
21
|
+
get('/foo') { }
|
22
|
+
}
|
23
|
+
get '/bar'
|
24
|
+
assert_equal 404, status
|
25
|
+
end
|
26
|
+
|
27
|
+
it "exposes params with indifferent hash" do
|
28
|
+
mock_app {
|
29
|
+
get '/:foo' do
|
30
|
+
assert_equal 'bar', params['foo']
|
31
|
+
assert_equal 'bar', params[:foo]
|
32
|
+
'well, alright'
|
33
|
+
end
|
34
|
+
}
|
35
|
+
get '/bar'
|
36
|
+
assert_equal 'well, alright', body
|
37
|
+
end
|
38
|
+
|
39
|
+
it "merges named params and query string params in params" do
|
40
|
+
mock_app {
|
41
|
+
get '/:foo' do
|
42
|
+
assert_equal 'bar', params['foo']
|
43
|
+
assert_equal 'biz', params['baz']
|
44
|
+
end
|
45
|
+
}
|
46
|
+
get '/bar?baz=biz'
|
47
|
+
assert ok?
|
48
|
+
end
|
49
|
+
|
50
|
+
it "supports named params like /hello/:person" do
|
51
|
+
mock_app {
|
52
|
+
get '/hello/:person' do
|
53
|
+
"Hello #{params['person']}"
|
54
|
+
end
|
55
|
+
}
|
56
|
+
get '/hello/Frank'
|
57
|
+
assert_equal 'Hello Frank', body
|
58
|
+
end
|
59
|
+
|
60
|
+
it "supports optional named params like /?:foo?/?:bar?" do
|
61
|
+
mock_app {
|
62
|
+
get '/?:foo?/?:bar?' do
|
63
|
+
"foo=#{params[:foo]};bar=#{params[:bar]}"
|
64
|
+
end
|
65
|
+
}
|
66
|
+
|
67
|
+
get '/hello/world'
|
68
|
+
assert ok?
|
69
|
+
assert_equal "foo=hello;bar=world", body
|
70
|
+
|
71
|
+
get '/hello'
|
72
|
+
assert ok?
|
73
|
+
assert_equal "foo=hello;bar=", body
|
74
|
+
|
75
|
+
get '/'
|
76
|
+
assert ok?
|
77
|
+
assert_equal "foo=;bar=", body
|
78
|
+
end
|
79
|
+
|
80
|
+
it "supports single splat params like /*" do
|
81
|
+
mock_app {
|
82
|
+
get '/*' do
|
83
|
+
assert params['splat'].kind_of?(Array)
|
84
|
+
params['splat'].join "\n"
|
85
|
+
end
|
86
|
+
}
|
87
|
+
|
88
|
+
get '/foo'
|
89
|
+
assert_equal "foo", body
|
90
|
+
|
91
|
+
get '/foo/bar/baz'
|
92
|
+
assert_equal "foo/bar/baz", body
|
93
|
+
end
|
94
|
+
|
95
|
+
it "supports mixing multiple splat params like /*/foo/*/*" do
|
96
|
+
mock_app {
|
97
|
+
get '/*/foo/*/*' do
|
98
|
+
assert params['splat'].kind_of?(Array)
|
99
|
+
params['splat'].join "\n"
|
100
|
+
end
|
101
|
+
}
|
102
|
+
|
103
|
+
get '/bar/foo/bling/baz/boom'
|
104
|
+
assert_equal "bar\nbling\nbaz/boom", body
|
105
|
+
|
106
|
+
get '/bar/foo/baz'
|
107
|
+
assert not_found?
|
108
|
+
end
|
109
|
+
|
110
|
+
it "supports mixing named and splat params like /:foo/*" do
|
111
|
+
mock_app {
|
112
|
+
get '/:foo/*' do
|
113
|
+
assert_equal 'foo', params['foo']
|
114
|
+
assert_equal ['bar/baz'], params['splat']
|
115
|
+
end
|
116
|
+
}
|
117
|
+
|
118
|
+
get '/foo/bar/baz'
|
119
|
+
assert ok?
|
120
|
+
end
|
121
|
+
|
122
|
+
it "supports basic nested params" do
|
123
|
+
mock_app {
|
124
|
+
get '/hi' do
|
125
|
+
params["person"]["name"]
|
126
|
+
end
|
127
|
+
}
|
128
|
+
|
129
|
+
get "/hi?person[name]=John+Doe"
|
130
|
+
assert ok?
|
131
|
+
assert_equal "John Doe", body
|
132
|
+
end
|
133
|
+
|
134
|
+
it "exposes nested params with indifferent hash" do
|
135
|
+
mock_app {
|
136
|
+
get '/testme' do
|
137
|
+
assert_equal 'baz', params['bar']['foo']
|
138
|
+
assert_equal 'baz', params['bar'][:foo]
|
139
|
+
'well, alright'
|
140
|
+
end
|
141
|
+
}
|
142
|
+
get '/testme?bar[foo]=baz'
|
143
|
+
assert_equal 'well, alright', body
|
144
|
+
end
|
145
|
+
|
146
|
+
it "supports deeply nested params" do
|
147
|
+
input = {
|
148
|
+
'browser[chrome][engine][name]' => 'V8',
|
149
|
+
'browser[chrome][engine][version]' => '1.0',
|
150
|
+
'browser[firefox][engine][name]' => 'spidermonkey',
|
151
|
+
'browser[firefox][engine][version]' => '1.7.0',
|
152
|
+
'emacs[map][goto-line]' => 'M-g g',
|
153
|
+
'emacs[version]' => '22.3.1',
|
154
|
+
'paste[name]' => 'hello world',
|
155
|
+
'paste[syntax]' => 'ruby'
|
156
|
+
}
|
157
|
+
expected = {
|
158
|
+
"emacs" => {
|
159
|
+
"map" => { "goto-line" => "M-g g" },
|
160
|
+
"version" => "22.3.1"
|
161
|
+
},
|
162
|
+
"browser" => {
|
163
|
+
"firefox" => {"engine" => {"name"=>"spidermonkey", "version"=>"1.7.0"}},
|
164
|
+
"chrome" => {"engine" => {"name"=>"V8", "version"=>"1.0"}}
|
165
|
+
},
|
166
|
+
"paste" => {"name"=>"hello world", "syntax"=>"ruby"}
|
167
|
+
}
|
168
|
+
mock_app {
|
169
|
+
get '/foo' do
|
170
|
+
assert_equal expected, params
|
171
|
+
'looks good'
|
172
|
+
end
|
173
|
+
}
|
174
|
+
get "/foo?#{param_string(input)}"
|
175
|
+
assert ok?
|
176
|
+
assert_equal 'looks good', body
|
177
|
+
end
|
178
|
+
|
179
|
+
it "supports paths that include spaces" do
|
180
|
+
mock_app {
|
181
|
+
get '/path with spaces' do
|
182
|
+
'looks good'
|
183
|
+
end
|
184
|
+
}
|
185
|
+
|
186
|
+
get '/path%20with%20spaces'
|
187
|
+
assert ok?
|
188
|
+
assert_equal 'looks good', body
|
189
|
+
end
|
190
|
+
|
191
|
+
it "URL decodes named parameters and splats" do
|
192
|
+
mock_app {
|
193
|
+
get '/:foo/*' do
|
194
|
+
assert_equal 'hello world', params['foo']
|
195
|
+
assert_equal ['how are you'], params['splat']
|
196
|
+
nil
|
197
|
+
end
|
198
|
+
}
|
199
|
+
|
200
|
+
get '/hello%20world/how%20are%20you'
|
201
|
+
assert ok?
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'supports regular expressions' do
|
205
|
+
mock_app {
|
206
|
+
get(/^\/foo...\/bar$/) do
|
207
|
+
'Hello World'
|
208
|
+
end
|
209
|
+
}
|
210
|
+
|
211
|
+
get '/foooom/bar'
|
212
|
+
assert ok?
|
213
|
+
assert_equal 'Hello World', body
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'makes regular expression captures available in params[:captures]' do
|
217
|
+
mock_app {
|
218
|
+
get(/^\/fo(.*)\/ba(.*)/) do
|
219
|
+
assert_equal ['orooomma', 'f'], params[:captures]
|
220
|
+
'right on'
|
221
|
+
end
|
222
|
+
}
|
223
|
+
|
224
|
+
get '/foorooomma/baf'
|
225
|
+
assert ok?
|
226
|
+
assert_equal 'right on', body
|
227
|
+
end
|
228
|
+
|
229
|
+
it "returns response immediately on halt" do
|
230
|
+
mock_app {
|
231
|
+
get '/' do
|
232
|
+
halt 'Hello World'
|
233
|
+
'Boo-hoo World'
|
234
|
+
end
|
235
|
+
}
|
236
|
+
|
237
|
+
get '/'
|
238
|
+
assert ok?
|
239
|
+
assert_equal 'Hello World', body
|
240
|
+
end
|
241
|
+
|
242
|
+
it "transitions to the next matching route on pass" do
|
243
|
+
mock_app {
|
244
|
+
get '/:foo' do
|
245
|
+
pass
|
246
|
+
'Hello Foo'
|
247
|
+
end
|
248
|
+
|
249
|
+
get '/*' do
|
250
|
+
assert !params.include?('foo')
|
251
|
+
'Hello World'
|
252
|
+
end
|
253
|
+
}
|
254
|
+
|
255
|
+
get '/bar'
|
256
|
+
assert ok?
|
257
|
+
assert_equal 'Hello World', body
|
258
|
+
end
|
259
|
+
|
260
|
+
it "transitions to 404 when passed and no subsequent route matches" do
|
261
|
+
mock_app {
|
262
|
+
get '/:foo' do
|
263
|
+
pass
|
264
|
+
'Hello Foo'
|
265
|
+
end
|
266
|
+
}
|
267
|
+
|
268
|
+
get '/bar'
|
269
|
+
assert not_found?
|
270
|
+
end
|
271
|
+
|
272
|
+
it "passes when matching condition returns false" do
|
273
|
+
mock_app {
|
274
|
+
condition { params[:foo] == 'bar' }
|
275
|
+
get '/:foo' do
|
276
|
+
'Hello World'
|
277
|
+
end
|
278
|
+
}
|
279
|
+
|
280
|
+
get '/bar'
|
281
|
+
assert ok?
|
282
|
+
assert_equal 'Hello World', body
|
283
|
+
|
284
|
+
get '/foo'
|
285
|
+
assert not_found?
|
286
|
+
end
|
287
|
+
|
288
|
+
it "does not pass when matching condition returns nil" do
|
289
|
+
mock_app {
|
290
|
+
condition { nil }
|
291
|
+
get '/:foo' do
|
292
|
+
'Hello World'
|
293
|
+
end
|
294
|
+
}
|
295
|
+
|
296
|
+
get '/bar'
|
297
|
+
assert ok?
|
298
|
+
assert_equal 'Hello World', body
|
299
|
+
end
|
300
|
+
|
301
|
+
it "passes to next route when condition calls pass explicitly" do
|
302
|
+
mock_app {
|
303
|
+
condition { pass unless params[:foo] == 'bar' }
|
304
|
+
get '/:foo' do
|
305
|
+
'Hello World'
|
306
|
+
end
|
307
|
+
}
|
308
|
+
|
309
|
+
get '/bar'
|
310
|
+
assert ok?
|
311
|
+
assert_equal 'Hello World', body
|
312
|
+
|
313
|
+
get '/foo'
|
314
|
+
assert not_found?
|
315
|
+
end
|
316
|
+
|
317
|
+
it "passes to the next route when host_name does not match" do
|
318
|
+
mock_app {
|
319
|
+
host_name 'example.com'
|
320
|
+
get '/foo' do
|
321
|
+
'Hello World'
|
322
|
+
end
|
323
|
+
}
|
324
|
+
get '/foo'
|
325
|
+
assert not_found?
|
326
|
+
|
327
|
+
get '/foo', :env => { 'HTTP_HOST' => 'example.com' }
|
328
|
+
assert_equal 200, status
|
329
|
+
assert_equal 'Hello World', body
|
330
|
+
end
|
331
|
+
|
332
|
+
it "passes to the next route when user_agent does not match" do
|
333
|
+
mock_app {
|
334
|
+
user_agent(/Foo/)
|
335
|
+
get '/foo' do
|
336
|
+
'Hello World'
|
337
|
+
end
|
338
|
+
}
|
339
|
+
get '/foo'
|
340
|
+
assert not_found?
|
341
|
+
|
342
|
+
get '/foo', :env => { 'HTTP_USER_AGENT' => 'Foo Bar' }
|
343
|
+
assert_equal 200, status
|
344
|
+
assert_equal 'Hello World', body
|
345
|
+
end
|
346
|
+
|
347
|
+
it "makes captures in user agent pattern available in params[:agent]" do
|
348
|
+
mock_app {
|
349
|
+
user_agent(/Foo (.*)/)
|
350
|
+
get '/foo' do
|
351
|
+
'Hello ' + params[:agent].first
|
352
|
+
end
|
353
|
+
}
|
354
|
+
get '/foo', :env => { 'HTTP_USER_AGENT' => 'Foo Bar' }
|
355
|
+
assert_equal 200, status
|
356
|
+
assert_equal 'Hello Bar', body
|
357
|
+
end
|
358
|
+
|
359
|
+
it "filters by accept header" do
|
360
|
+
mock_app {
|
361
|
+
get '/', :provides => :xml do
|
362
|
+
request.env['HTTP_ACCEPT']
|
363
|
+
end
|
364
|
+
}
|
365
|
+
|
366
|
+
get '/', :env => { :accept => 'application/xml' }
|
367
|
+
assert ok?
|
368
|
+
assert_equal 'application/xml', body
|
369
|
+
assert_equal 'application/xml', response.headers['Content-Type']
|
370
|
+
|
371
|
+
get '/', :env => { :accept => 'text/html' }
|
372
|
+
assert !ok?
|
373
|
+
end
|
374
|
+
|
375
|
+
it "allows multiple mime types for accept header" do
|
376
|
+
types = ['image/jpeg', 'image/pjpeg']
|
377
|
+
|
378
|
+
mock_app {
|
379
|
+
get '/', :provides => types do
|
380
|
+
request.env['HTTP_ACCEPT']
|
381
|
+
end
|
382
|
+
}
|
383
|
+
|
384
|
+
types.each do |type|
|
385
|
+
get '/', :env => { :accept => type }
|
386
|
+
assert ok?
|
387
|
+
assert_equal type, body
|
388
|
+
assert_equal type, response.headers['Content-Type']
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
data/test/sass_test.rb
CHANGED
@@ -1,57 +1,36 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
describe "Sass Templates" do
|
4
|
+
def sass_app(&block)
|
5
|
+
mock_app {
|
6
|
+
set :views, File.dirname(__FILE__) + '/views'
|
7
|
+
get '/', &block
|
8
|
+
}
|
9
|
+
get '/'
|
7
10
|
end
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
specify "are read from files if Symbols" do
|
16
|
-
|
17
|
-
get '/from_file' do
|
18
|
-
sass :foo, :views_directory => File.dirname(__FILE__) + "/views"
|
19
|
-
end
|
20
|
-
|
21
|
-
get_it '/from_file'
|
22
|
-
should.be.ok
|
23
|
-
body.should.equal "#sass {\n background_color: #FFF; }\n"
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
specify "raise an error if template not found" do
|
28
|
-
get '/' do
|
29
|
-
sass :not_found
|
30
|
-
end
|
31
|
-
|
32
|
-
lambda { get_it '/' }.should.raise(Errno::ENOENT)
|
33
|
-
end
|
34
|
-
|
35
|
-
specify "ignore default layout file with .sass extension" do
|
36
|
-
get '/' do
|
37
|
-
sass :foo, :views_directory => File.dirname(__FILE__) + "/views/layout_test"
|
38
|
-
end
|
39
|
-
|
40
|
-
get_it '/'
|
41
|
-
should.be.ok
|
42
|
-
body.should.equal "#sass {\n background_color: #FFF; }\n"
|
43
|
-
end
|
44
|
-
|
45
|
-
specify "ignore explicitly specified layout file" do
|
46
|
-
get '/' do
|
47
|
-
sass :foo, :layout => :layout, :views_directory => File.dirname(__FILE__) + "/views/layout_test"
|
48
|
-
end
|
12
|
+
it 'renders inline Sass strings' do
|
13
|
+
sass_app { sass "#sass\n :background-color #FFF\n" }
|
14
|
+
assert ok?
|
15
|
+
assert_equal "#sass {\n background-color: #FFF; }\n", body
|
16
|
+
end
|
49
17
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
18
|
+
it 'renders .sass files in views path' do
|
19
|
+
sass_app { sass :hello }
|
20
|
+
assert ok?
|
21
|
+
assert_equal "#sass {\n background-color: #FFF; }\n", body
|
22
|
+
end
|
54
23
|
|
24
|
+
it 'ignores the layout option' do
|
25
|
+
sass_app { sass :hello, :layout => :layout2 }
|
26
|
+
assert ok?
|
27
|
+
assert_equal "#sass {\n background-color: #FFF; }\n", body
|
55
28
|
end
|
56
29
|
|
30
|
+
it "raises error if template not found" do
|
31
|
+
mock_app {
|
32
|
+
get('/') { sass :no_such_template }
|
33
|
+
}
|
34
|
+
assert_raise(Errno::ENOENT) { get('/') }
|
35
|
+
end
|
57
36
|
end
|