sinatra 1.4.8 → 2.0.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.

Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +111 -47
  3. data/CONTRIBUTING.md +1 -1
  4. data/Gemfile +41 -49
  5. data/LICENSE +4 -1
  6. data/MAINTENANCE.md +42 -0
  7. data/README.de.md +644 -436
  8. data/README.es.md +6 -6
  9. data/README.fr.md +9 -9
  10. data/README.hu.md +37 -3
  11. data/README.ja.md +103 -45
  12. data/README.ko.md +8 -8
  13. data/README.md +471 -363
  14. data/README.pt-br.md +3 -3
  15. data/README.pt-pt.md +2 -2
  16. data/README.ru.md +42 -64
  17. data/README.zh.md +8 -8
  18. data/Rakefile +72 -49
  19. data/SECURITY.md +35 -0
  20. data/lib/sinatra/base.rb +137 -195
  21. data/lib/sinatra/indifferent_hash.rb +150 -0
  22. data/lib/sinatra/main.rb +1 -0
  23. data/lib/sinatra/show_exceptions.rb +63 -55
  24. data/lib/sinatra/version.rb +1 -1
  25. data/sinatra.gemspec +19 -7
  26. metadata +30 -164
  27. data/lib/sinatra/ext.rb +0 -17
  28. data/test/asciidoctor_test.rb +0 -72
  29. data/test/base_test.rb +0 -167
  30. data/test/builder_test.rb +0 -91
  31. data/test/coffee_test.rb +0 -96
  32. data/test/compile_test.rb +0 -183
  33. data/test/contest.rb +0 -91
  34. data/test/creole_test.rb +0 -65
  35. data/test/delegator_test.rb +0 -160
  36. data/test/encoding_test.rb +0 -20
  37. data/test/erb_test.rb +0 -116
  38. data/test/extensions_test.rb +0 -98
  39. data/test/filter_test.rb +0 -487
  40. data/test/haml_test.rb +0 -109
  41. data/test/helper.rb +0 -132
  42. data/test/helpers_test.rb +0 -1917
  43. data/test/integration/app.rb +0 -79
  44. data/test/integration_helper.rb +0 -236
  45. data/test/integration_test.rb +0 -104
  46. data/test/less_test.rb +0 -69
  47. data/test/liquid_test.rb +0 -77
  48. data/test/mapped_error_test.rb +0 -285
  49. data/test/markaby_test.rb +0 -80
  50. data/test/markdown_test.rb +0 -85
  51. data/test/mediawiki_test.rb +0 -68
  52. data/test/middleware_test.rb +0 -68
  53. data/test/nokogiri_test.rb +0 -67
  54. data/test/public/favicon.ico +0 -0
  55. data/test/public/hello+world.txt +0 -1
  56. data/test/rabl_test.rb +0 -89
  57. data/test/rack_test.rb +0 -45
  58. data/test/radius_test.rb +0 -59
  59. data/test/rdoc_test.rb +0 -66
  60. data/test/readme_test.rb +0 -130
  61. data/test/request_test.rb +0 -100
  62. data/test/response_test.rb +0 -63
  63. data/test/result_test.rb +0 -76
  64. data/test/route_added_hook_test.rb +0 -59
  65. data/test/routing_test.rb +0 -1456
  66. data/test/sass_test.rb +0 -115
  67. data/test/scss_test.rb +0 -88
  68. data/test/server_test.rb +0 -56
  69. data/test/settings_test.rb +0 -582
  70. data/test/sinatra_test.rb +0 -12
  71. data/test/slim_test.rb +0 -102
  72. data/test/static_test.rb +0 -266
  73. data/test/streaming_test.rb +0 -149
  74. data/test/stylus_test.rb +0 -90
  75. data/test/templates_test.rb +0 -382
  76. data/test/textile_test.rb +0 -65
  77. data/test/views/a/in_a.str +0 -1
  78. data/test/views/ascii.erb +0 -2
  79. data/test/views/b/in_b.str +0 -1
  80. data/test/views/calc.html.erb +0 -1
  81. data/test/views/error.builder +0 -3
  82. data/test/views/error.erb +0 -3
  83. data/test/views/error.haml +0 -3
  84. data/test/views/error.sass +0 -2
  85. data/test/views/explicitly_nested.str +0 -1
  86. data/test/views/foo/hello.test +0 -1
  87. data/test/views/hello.asciidoc +0 -1
  88. data/test/views/hello.builder +0 -1
  89. data/test/views/hello.coffee +0 -1
  90. data/test/views/hello.creole +0 -1
  91. data/test/views/hello.erb +0 -1
  92. data/test/views/hello.haml +0 -1
  93. data/test/views/hello.less +0 -5
  94. data/test/views/hello.liquid +0 -1
  95. data/test/views/hello.mab +0 -1
  96. data/test/views/hello.md +0 -1
  97. data/test/views/hello.mediawiki +0 -1
  98. data/test/views/hello.nokogiri +0 -1
  99. data/test/views/hello.rabl +0 -2
  100. data/test/views/hello.radius +0 -1
  101. data/test/views/hello.rdoc +0 -1
  102. data/test/views/hello.sass +0 -2
  103. data/test/views/hello.scss +0 -3
  104. data/test/views/hello.slim +0 -1
  105. data/test/views/hello.str +0 -1
  106. data/test/views/hello.styl +0 -2
  107. data/test/views/hello.test +0 -1
  108. data/test/views/hello.textile +0 -1
  109. data/test/views/hello.wlang +0 -1
  110. data/test/views/hello.yajl +0 -1
  111. data/test/views/layout2.builder +0 -3
  112. data/test/views/layout2.erb +0 -2
  113. data/test/views/layout2.haml +0 -2
  114. data/test/views/layout2.liquid +0 -2
  115. data/test/views/layout2.mab +0 -2
  116. data/test/views/layout2.nokogiri +0 -3
  117. data/test/views/layout2.rabl +0 -3
  118. data/test/views/layout2.radius +0 -2
  119. data/test/views/layout2.slim +0 -3
  120. data/test/views/layout2.str +0 -2
  121. data/test/views/layout2.test +0 -1
  122. data/test/views/layout2.wlang +0 -2
  123. data/test/views/nested.str +0 -1
  124. data/test/views/utf8.erb +0 -2
  125. data/test/wlang_test.rb +0 -87
  126. data/test/yajl_test.rb +0 -86
data/test/routing_test.rb DELETED
@@ -1,1456 +0,0 @@
1
- # I like coding: UTF-8
2
- require File.expand_path('../helper', __FILE__)
3
-
4
- # Helper method for easy route pattern matching testing
5
- def route_def(pattern)
6
- mock_app { get(pattern) { } }
7
- end
8
-
9
- class RegexpLookAlike
10
- class MatchData
11
- def captures
12
- ["this", "is", "a", "test"]
13
- end
14
- end
15
-
16
- def match(string)
17
- ::RegexpLookAlike::MatchData.new if string == "/this/is/a/test/"
18
- end
19
-
20
- def keys
21
- ["one", "two", "three", "four"]
22
- end
23
- end
24
-
25
- class RoutingTest < Minitest::Test
26
- %w[get put post delete options patch link unlink].each do |verb|
27
- it "defines #{verb.upcase} request handlers with #{verb}" do
28
- mock_app {
29
- send verb, '/hello' do
30
- 'Hello World'
31
- end
32
- }
33
-
34
- request = Rack::MockRequest.new(@app)
35
- response = request.request(verb.upcase, '/hello', {})
36
- assert response.ok?
37
- assert_equal 'Hello World', response.body
38
- end
39
- end
40
-
41
- it "defines HEAD request handlers with HEAD" do
42
- mock_app {
43
- head '/hello' do
44
- response['X-Hello'] = 'World!'
45
- 'remove me'
46
- end
47
- }
48
-
49
- request = Rack::MockRequest.new(@app)
50
- response = request.request('HEAD', '/hello', {})
51
- assert response.ok?
52
- assert_equal 'World!', response['X-Hello']
53
- assert_equal '', response.body
54
- end
55
-
56
- it "404s when no route satisfies the request" do
57
- mock_app {
58
- get('/foo') { }
59
- }
60
- get '/bar'
61
- assert_equal 404, status
62
- end
63
-
64
- it "404s and sets X-Cascade header when no route satisfies the request" do
65
- mock_app {
66
- get('/foo') { }
67
- }
68
- get '/bar'
69
- assert_equal 404, status
70
- assert_equal 'pass', response.headers['X-Cascade']
71
- end
72
-
73
- it "404s and does not set X-Cascade header when no route satisfies the request and x_cascade has been disabled" do
74
- mock_app {
75
- disable :x_cascade
76
- get('/foo') { }
77
- }
78
- get '/bar'
79
- assert_equal 404, status
80
- assert_equal nil, response.headers['X-Cascade']
81
- end
82
-
83
-
84
- it "allows using unicode" do
85
- mock_app do
86
- get('/föö') { }
87
- end
88
- get '/f%C3%B6%C3%B6'
89
- assert_equal 200, status
90
- end
91
-
92
- it "it handles encoded slashes correctly" do
93
- mock_app {
94
- set :protection, :except => :path_traversal
95
- get("/:a") { |a| a }
96
- }
97
- get '/foo%2Fbar'
98
- assert_equal 200, status
99
- assert_body "foo/bar"
100
- end
101
-
102
- it "it handles encoded colons correctly" do
103
- mock_app {
104
- get("/:") { 'a' }
105
- get("/a/:") { 'b' }
106
- get("/a/:/b") { 'c' }
107
- get("/a/b:") { 'd' }
108
- get("/a/b: ") { 'e' }
109
- }
110
- get '/:'
111
- assert_equal 200, status
112
- assert_body "a"
113
- get '/%3a'
114
- assert_equal 200, status
115
- assert_body "a"
116
-
117
- get '/a/:'
118
- assert_equal 200, status
119
- assert_body "b"
120
- get '/a/%3a'
121
- assert_equal 200, status
122
- assert_body "b"
123
-
124
- get '/a/:/b'
125
- assert_equal 200, status
126
- assert_body "c"
127
- get '/a/%3A/b'
128
- assert_equal 200, status
129
- assert_body "c"
130
-
131
- get '/a/b:'
132
- assert_equal 200, status
133
- assert_body "d"
134
- get '/a/b%3a'
135
- assert_equal 200, status
136
- assert_body "d"
137
-
138
- get '/a/b%3a%20'
139
- assert_equal 200, status
140
- assert_body "e"
141
- get '/a/b%3a+'
142
- assert_equal 200, status
143
- assert_body "e"
144
- end
145
-
146
- it "overrides the content-type in error handlers" do
147
- mock_app {
148
- before { content_type 'text/plain' }
149
- error Sinatra::NotFound do
150
- content_type "text/html"
151
- "<h1>Not Found</h1>"
152
- end
153
- }
154
-
155
- get '/foo'
156
- assert_equal 404, status
157
- assert_equal 'text/html;charset=utf-8', response["Content-Type"]
158
- assert_equal "<h1>Not Found</h1>", response.body
159
- end
160
-
161
- it "recalculates body length correctly for 404 response" do
162
- mock_app {
163
- get '/' do
164
- @response["Content-Length"] = "30"
165
- raise Sinatra::NotFound
166
- end
167
- }
168
-
169
- get "/"
170
- assert_equal "18", response["Content-Length"]
171
- assert_equal 404, status
172
- end
173
-
174
- it 'matches empty PATH_INFO to "/" if no route is defined for ""' do
175
- mock_app do
176
- get '/' do
177
- 'worked'
178
- end
179
- end
180
-
181
- get '/', {}, "PATH_INFO" => ""
182
- assert ok?
183
- assert_equal 'worked', body
184
- end
185
-
186
- it 'matches empty PATH_INFO to "" if a route is defined for ""' do
187
- mock_app do
188
- disable :protection
189
-
190
- get '/' do
191
- 'did not work'
192
- end
193
-
194
- get '' do
195
- 'worked'
196
- end
197
- end
198
-
199
- get '/', {}, "PATH_INFO" => ""
200
- assert ok?
201
- assert_equal 'worked', body
202
- end
203
-
204
- it 'takes multiple definitions of a route' do
205
- mock_app {
206
- user_agent(/Foo/)
207
- get '/foo' do
208
- 'foo'
209
- end
210
-
211
- get '/foo' do
212
- 'not foo'
213
- end
214
- }
215
-
216
- get '/foo', {}, 'HTTP_USER_AGENT' => 'Foo'
217
- assert ok?
218
- assert_equal 'foo', body
219
-
220
- get '/foo'
221
- assert ok?
222
- assert_equal 'not foo', body
223
- end
224
-
225
- it "exposes params with indifferent hash" do
226
- mock_app {
227
- get '/:foo' do
228
- assert_equal 'bar', params['foo']
229
- assert_equal 'bar', params[:foo]
230
- 'well, alright'
231
- end
232
- }
233
- get '/bar'
234
- assert_equal 'well, alright', body
235
- end
236
-
237
- it "merges named params and query string params in params" do
238
- mock_app {
239
- get '/:foo' do
240
- assert_equal 'bar', params['foo']
241
- assert_equal 'biz', params['baz']
242
- end
243
- }
244
- get '/bar?baz=biz'
245
- assert ok?
246
- end
247
-
248
- it "supports named params like /hello/:person" do
249
- mock_app {
250
- get '/hello/:person' do
251
- "Hello #{params['person']}"
252
- end
253
- }
254
- get '/hello/Frank'
255
- assert_equal 'Hello Frank', body
256
- end
257
-
258
- it "supports optional named params like /?:foo?/?:bar?" do
259
- mock_app {
260
- get '/?:foo?/?:bar?' do
261
- "foo=#{params[:foo]};bar=#{params[:bar]}"
262
- end
263
- }
264
-
265
- get '/hello/world'
266
- assert ok?
267
- assert_equal "foo=hello;bar=world", body
268
-
269
- get '/hello'
270
- assert ok?
271
- assert_equal "foo=hello;bar=", body
272
-
273
- get '/'
274
- assert ok?
275
- assert_equal "foo=;bar=", body
276
- end
277
-
278
- it "supports named captures like %r{/hello/(?<person>[^/?#]+)} on Ruby >= 1.9" do
279
- next if RUBY_VERSION < '1.9'
280
- mock_app {
281
- get Regexp.new('/hello/(?<person>[^/?#]+)') do
282
- "Hello #{params['person']}"
283
- end
284
- }
285
- get '/hello/Frank'
286
- assert_equal 'Hello Frank', body
287
- end
288
-
289
- it "supports optional named captures like %r{/page(?<format>.[^/?#]+)?} on Ruby >= 1.9" do
290
- next if RUBY_VERSION < '1.9'
291
- mock_app {
292
- get Regexp.new('/page(?<format>.[^/?#]+)?') do
293
- "format=#{params[:format]}"
294
- end
295
- }
296
-
297
- get '/page.html'
298
- assert ok?
299
- assert_equal "format=.html", body
300
-
301
- get '/page.xml'
302
- assert ok?
303
- assert_equal "format=.xml", body
304
-
305
- get '/page'
306
- assert ok?
307
- assert_equal "format=", body
308
- end
309
-
310
- it 'does not concatenate params with the same name' do
311
- mock_app { get('/:foo') { params[:foo] } }
312
- get '/a?foo=b'
313
- assert_body 'a'
314
- end
315
-
316
- it "supports single splat params like /*" do
317
- mock_app {
318
- get '/*' do
319
- assert params['splat'].kind_of?(Array)
320
- params['splat'].join "\n"
321
- end
322
- }
323
-
324
- get '/foo'
325
- assert_equal "foo", body
326
-
327
- get '/foo/bar/baz'
328
- assert_equal "foo/bar/baz", body
329
- end
330
-
331
- it "supports mixing multiple splat params like /*/foo/*/*" do
332
- mock_app {
333
- get '/*/foo/*/*' do
334
- assert params['splat'].kind_of?(Array)
335
- params['splat'].join "\n"
336
- end
337
- }
338
-
339
- get '/bar/foo/bling/baz/boom'
340
- assert_equal "bar\nbling\nbaz/boom", body
341
-
342
- get '/bar/foo/baz'
343
- assert not_found?
344
- end
345
-
346
- it "supports mixing named and splat params like /:foo/*" do
347
- mock_app {
348
- get '/:foo/*' do
349
- assert_equal 'foo', params['foo']
350
- assert_equal ['bar/baz'], params['splat']
351
- end
352
- }
353
-
354
- get '/foo/bar/baz'
355
- assert ok?
356
- end
357
-
358
- it "matches a dot ('.') as part of a named param" do
359
- mock_app {
360
- get '/:foo/:bar' do
361
- params[:foo]
362
- end
363
- }
364
-
365
- get '/user@example.com/name'
366
- assert_equal 200, response.status
367
- assert_equal 'user@example.com', body
368
- end
369
-
370
- it "matches a literal dot ('.') outside of named params" do
371
- mock_app {
372
- get '/:file.:ext' do
373
- assert_equal 'pony', params[:file]
374
- assert_equal 'jpg', params[:ext]
375
- 'right on'
376
- end
377
- }
378
-
379
- get '/pony.jpg'
380
- assert_equal 200, response.status
381
- assert_equal 'right on', body
382
- end
383
-
384
- it "literally matches dot in paths" do
385
- route_def '/test.bar'
386
-
387
- get '/test.bar'
388
- assert ok?
389
- get 'test0bar'
390
- assert not_found?
391
- end
392
-
393
- it "literally matches dollar sign in paths" do
394
- route_def '/test$/'
395
-
396
- get '/test$/'
397
- assert ok?
398
- end
399
-
400
- it "literally matches plus sign in paths" do
401
- route_def '/te+st/'
402
-
403
- get '/te%2Bst/'
404
- assert ok?
405
- get '/teeeeeeest/'
406
- assert not_found?
407
- end
408
-
409
- it "does not convert plus sign into space as the value of a named param" do
410
- mock_app do
411
- get '/:test' do
412
- params["test"]
413
- end
414
- end
415
- get '/bob+ross'
416
- assert ok?
417
- assert_equal 'bob+ross', body
418
- end
419
-
420
- it "literally matches parens in paths" do
421
- route_def '/test(bar)/'
422
-
423
- get '/test(bar)/'
424
- assert ok?
425
- end
426
-
427
- it "supports basic nested params" do
428
- mock_app {
429
- get '/hi' do
430
- params["person"]["name"]
431
- end
432
- }
433
-
434
- get "/hi?person[name]=John+Doe"
435
- assert ok?
436
- assert_equal "John Doe", body
437
- end
438
-
439
- it "exposes nested params with indifferent hash" do
440
- mock_app {
441
- get '/testme' do
442
- assert_equal 'baz', params['bar']['foo']
443
- assert_equal 'baz', params['bar'][:foo]
444
- 'well, alright'
445
- end
446
- }
447
- get '/testme?bar[foo]=baz'
448
- assert_equal 'well, alright', body
449
- end
450
-
451
- it "exposes params nested within arrays with indifferent hash" do
452
- mock_app {
453
- get '/testme' do
454
- assert_equal 'baz', params['bar'][0]['foo']
455
- assert_equal 'baz', params['bar'][0][:foo]
456
- 'well, alright'
457
- end
458
- }
459
- get '/testme?bar[][foo]=baz'
460
- assert_equal 'well, alright', body
461
- end
462
-
463
- it "supports arrays within params" do
464
- mock_app {
465
- get '/foo' do
466
- assert_equal ['A', 'B'], params['bar']
467
- 'looks good'
468
- end
469
- }
470
- get '/foo?bar[]=A&bar[]=B'
471
- assert ok?
472
- assert_equal 'looks good', body
473
- end
474
-
475
- it "supports deeply nested params" do
476
- expected_params = {
477
- "emacs" => {
478
- "map" => { "goto-line" => "M-g g" },
479
- "version" => "22.3.1"
480
- },
481
- "browser" => {
482
- "firefox" => {"engine" => {"name"=>"spidermonkey", "version"=>"1.7.0"}},
483
- "chrome" => {"engine" => {"name"=>"V8", "version"=>"1.0"}}
484
- },
485
- "paste" => {"name"=>"hello world", "syntax"=>"ruby"}
486
- }
487
- mock_app {
488
- get '/foo' do
489
- assert_equal expected_params, params
490
- 'looks good'
491
- end
492
- }
493
- get '/foo', expected_params
494
- assert ok?
495
- assert_equal 'looks good', body
496
- end
497
-
498
- it "preserves non-nested params" do
499
- mock_app {
500
- get '/foo' do
501
- assert_equal "2", params["article_id"]
502
- assert_equal "awesome", params['comment']['body']
503
- assert_nil params['comment[body]']
504
- 'looks good'
505
- end
506
- }
507
-
508
- get '/foo?article_id=2&comment[body]=awesome'
509
- assert ok?
510
- assert_equal 'looks good', body
511
- end
512
-
513
- it "matches paths that include spaces encoded with %20" do
514
- mock_app {
515
- get '/path with spaces' do
516
- 'looks good'
517
- end
518
- }
519
-
520
- get '/path%20with%20spaces'
521
- assert ok?
522
- assert_equal 'looks good', body
523
- end
524
-
525
- it "matches paths that include spaces encoded with +" do
526
- mock_app {
527
- get '/path with spaces' do
528
- 'looks good'
529
- end
530
- }
531
-
532
- get '/path+with+spaces'
533
- assert ok?
534
- assert_equal 'looks good', body
535
- end
536
-
537
- it "matches paths that include ampersands" do
538
- mock_app {
539
- get '/:name' do
540
- 'looks good'
541
- end
542
- }
543
-
544
- get '/foo&bar'
545
- assert ok?
546
- assert_equal 'looks good', body
547
- end
548
-
549
- it "URL decodes named parameters and splats" do
550
- mock_app {
551
- get '/:foo/*' do
552
- assert_equal 'hello world', params['foo']
553
- assert_equal ['how are you'], params['splat']
554
- nil
555
- end
556
- }
557
-
558
- get '/hello%20world/how%20are%20you'
559
- assert ok?
560
- end
561
-
562
- it 'supports regular expressions' do
563
- mock_app {
564
- get(/^\/foo...\/bar$/) do
565
- 'Hello World'
566
- end
567
- }
568
-
569
- get '/foooom/bar'
570
- assert ok?
571
- assert_equal 'Hello World', body
572
- end
573
-
574
- it 'makes regular expression captures available in params[:captures]' do
575
- mock_app {
576
- get(/^\/fo(.*)\/ba(.*)/) do
577
- assert_equal ['orooomma', 'f'], params[:captures]
578
- 'right on'
579
- end
580
- }
581
-
582
- get '/foorooomma/baf'
583
- assert ok?
584
- assert_equal 'right on', body
585
- end
586
-
587
- it 'supports regular expression look-alike routes' do
588
- mock_app {
589
- get(RegexpLookAlike.new) do
590
- assert_equal 'this', params[:one]
591
- assert_equal 'is', params[:two]
592
- assert_equal 'a', params[:three]
593
- assert_equal 'test', params[:four]
594
- 'right on'
595
- end
596
- }
597
-
598
- get '/this/is/a/test/'
599
- assert ok?
600
- assert_equal 'right on', body
601
- end
602
-
603
- it 'raises a TypeError when pattern is not a String or Regexp' do
604
- assert_raises(TypeError) {
605
- mock_app { get(42){} }
606
- }
607
- end
608
-
609
- it "returns response immediately on halt" do
610
- mock_app {
611
- get '/' do
612
- halt 'Hello World'
613
- 'Boo-hoo World'
614
- end
615
- }
616
-
617
- get '/'
618
- assert ok?
619
- assert_equal 'Hello World', body
620
- end
621
-
622
- it "halts with a response tuple" do
623
- mock_app {
624
- get '/' do
625
- halt 295, {'Content-Type' => 'text/plain'}, 'Hello World'
626
- end
627
- }
628
-
629
- get '/'
630
- assert_equal 295, status
631
- assert_equal 'text/plain', response['Content-Type']
632
- assert_equal 'Hello World', body
633
- end
634
-
635
- it "halts with an array of strings" do
636
- mock_app {
637
- get '/' do
638
- halt %w[Hello World How Are You]
639
- end
640
- }
641
-
642
- get '/'
643
- assert_equal 'HelloWorldHowAreYou', body
644
- end
645
-
646
- it 'sets response.status with halt' do
647
- status_was = nil
648
- mock_app do
649
- after { status_was = status }
650
- get('/') { halt 500, 'error' }
651
- end
652
- get '/'
653
- assert_status 500
654
- assert_equal 500, status_was
655
- end
656
-
657
- it "transitions to the next matching route on pass" do
658
- mock_app {
659
- get '/:foo' do
660
- pass
661
- 'Hello Foo'
662
- end
663
-
664
- get '/*' do
665
- assert !params.include?('foo')
666
- 'Hello World'
667
- end
668
- }
669
-
670
- get '/bar'
671
- assert ok?
672
- assert_equal 'Hello World', body
673
- end
674
-
675
- it "transitions to 404 when passed and no subsequent route matches" do
676
- mock_app {
677
- get '/:foo' do
678
- pass
679
- 'Hello Foo'
680
- end
681
- }
682
-
683
- get '/bar'
684
- assert not_found?
685
- end
686
-
687
- it "transitions to 404 and sets X-Cascade header when passed and no subsequent route matches" do
688
- mock_app {
689
- get '/:foo' do
690
- pass
691
- 'Hello Foo'
692
- end
693
-
694
- get '/bar' do
695
- 'Hello Bar'
696
- end
697
- }
698
-
699
- get '/foo'
700
- assert not_found?
701
- assert_equal 'pass', response.headers['X-Cascade']
702
- end
703
-
704
- it "uses optional block passed to pass as route block if no other route is found" do
705
- mock_app {
706
- get "/" do
707
- pass do
708
- "this"
709
- end
710
- "not this"
711
- end
712
- }
713
-
714
- get "/"
715
- assert ok?
716
- assert "this", body
717
- end
718
-
719
- it "uses optional block passed to pass as route block if no other route is found and superclass has non-matching routes" do
720
- base = Class.new(Sinatra::Base)
721
- base.get('/foo') { 'foo in baseclass' }
722
-
723
- mock_app(base) {
724
- get "/" do
725
- pass do
726
- "this"
727
- end
728
- "not this"
729
- end
730
- }
731
-
732
- get "/"
733
- assert_equal 200, status
734
- assert "this", body
735
- end
736
-
737
- it "passes when matching condition returns false" do
738
- mock_app {
739
- condition { params[:foo] == 'bar' }
740
- get '/:foo' do
741
- 'Hello World'
742
- end
743
- }
744
-
745
- get '/bar'
746
- assert ok?
747
- assert_equal 'Hello World', body
748
-
749
- get '/foo'
750
- assert not_found?
751
- end
752
-
753
- it "does not pass when matching condition returns nil" do
754
- mock_app {
755
- condition { nil }
756
- get '/:foo' do
757
- 'Hello World'
758
- end
759
- }
760
-
761
- get '/bar'
762
- assert ok?
763
- assert_equal 'Hello World', body
764
- end
765
-
766
- it "passes to next route when condition calls pass explicitly" do
767
- mock_app {
768
- condition { pass unless params[:foo] == 'bar' }
769
- get '/:foo' do
770
- 'Hello World'
771
- end
772
- }
773
-
774
- get '/bar'
775
- assert ok?
776
- assert_equal 'Hello World', body
777
-
778
- get '/foo'
779
- assert not_found?
780
- end
781
-
782
- it "passes to the next route when host_name does not match" do
783
- mock_app {
784
- host_name 'example.com'
785
- get '/foo' do
786
- 'Hello World'
787
- end
788
- }
789
- get '/foo'
790
- assert not_found?
791
-
792
- get '/foo', {}, { 'HTTP_HOST' => 'example.com' }
793
- assert_equal 200, status
794
- assert_equal 'Hello World', body
795
- end
796
-
797
- it "passes to the next route when user_agent does not match" do
798
- mock_app {
799
- user_agent(/Foo/)
800
- get '/foo' do
801
- 'Hello World'
802
- end
803
- }
804
- get '/foo'
805
- assert not_found?
806
-
807
- get '/foo', {}, { 'HTTP_USER_AGENT' => 'Foo Bar' }
808
- assert_equal 200, status
809
- assert_equal 'Hello World', body
810
- end
811
-
812
- it "treats missing user agent like an empty string" do
813
- mock_app do
814
- user_agent(/.*/)
815
- get '/' do
816
- "Hello World"
817
- end
818
- end
819
- get '/'
820
- assert_equal 200, status
821
- assert_equal 'Hello World', body
822
- end
823
-
824
- it "makes captures in user agent pattern available in params[:agent]" do
825
- mock_app {
826
- user_agent(/Foo (.*)/)
827
- get '/foo' do
828
- 'Hello ' + params[:agent].first
829
- end
830
- }
831
- get '/foo', {}, { 'HTTP_USER_AGENT' => 'Foo Bar' }
832
- assert_equal 200, status
833
- assert_equal 'Hello Bar', body
834
- end
835
-
836
- it 'matches mime_types with dots, hyphens and plus signs' do
837
- mime_types = %w(
838
- application/atom+xml
839
- application/ecmascript
840
- application/EDI-X12
841
- application/EDIFACT
842
- application/json
843
- application/javascript
844
- application/octet-stream
845
- application/ogg
846
- application/pdf
847
- application/postscript
848
- application/rdf+xml
849
- application/rss+xml
850
- application/soap+xml
851
- application/font-woff
852
- application/xhtml+xml
853
- application/xml
854
- application/xml-dtd
855
- application/xop+xml
856
- application/zip
857
- application/gzip
858
- audio/basic
859
- audio/L24
860
- audio/mp4
861
- audio/mpeg
862
- audio/ogg
863
- audio/vorbis
864
- audio/vnd.rn-realaudio
865
- audio/vnd.wave
866
- audio/webm
867
- image/gif
868
- image/jpeg
869
- image/pjpeg
870
- image/png
871
- image/svg+xml
872
- image/tiff
873
- image/vnd.microsoft.icon
874
- message/http
875
- message/imdn+xml
876
- message/partial
877
- message/rfc822
878
- model/example
879
- model/iges
880
- model/mesh
881
- model/vrml
882
- model/x3d+binary
883
- model/x3d+vrml
884
- model/x3d+xml
885
- multipart/mixed
886
- multipart/alternative
887
- multipart/related
888
- multipart/form-data
889
- multipart/signed
890
- multipart/encrypted
891
- text/cmd
892
- text/css
893
- text/csv
894
- text/html
895
- text/javascript
896
- application/javascript
897
- text/plain
898
- text/vcard
899
- text/xml
900
- video/mpeg
901
- video/mp4
902
- video/ogg
903
- video/quicktime
904
- video/webm
905
- video/x-matroska
906
- video/x-ms-wmv
907
- video/x-flv
908
- application/vnd.oasis.opendocument.text
909
- application/vnd.oasis.opendocument.spreadsheet
910
- application/vnd.oasis.opendocument.presentation
911
- application/vnd.oasis.opendocument.graphics
912
- application/vnd.ms-excel
913
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
914
- application/vnd.ms-powerpoint
915
- application/vnd.openxmlformats-officedocument.presentationml.presentation
916
- application/vnd.openxmlformats-officedocument.wordprocessingml.document
917
- application/vnd.mozilla.xul+xml
918
- application/vnd.google-earth.kml+xml
919
- application/x-deb
920
- application/x-dvi
921
- application/x-font-ttf
922
- application/x-javascript
923
- application/x-latex
924
- application/x-mpegURL
925
- application/x-rar-compressed
926
- application/x-shockwave-flash
927
- application/x-stuffit
928
- application/x-tar
929
- application/x-www-form-urlencoded
930
- application/x-xpinstall
931
- audio/x-aac
932
- audio/x-caf
933
- image/x-xcf
934
- text/x-gwt-rpc
935
- text/x-jquery-tmpl
936
- application/x-pkcs12
937
- application/x-pkcs12
938
- application/x-pkcs7-certificates
939
- application/x-pkcs7-certificates
940
- application/x-pkcs7-certreqresp
941
- application/x-pkcs7-mime
942
- application/x-pkcs7-mime
943
- application/x-pkcs7-signature
944
- )
945
-
946
- mime_types.each { |mime_type| assert mime_type.match(Sinatra::Request::HEADER_VALUE_WITH_PARAMS) }
947
- end
948
-
949
- it "filters by accept header" do
950
- mock_app {
951
- get '/', :provides => :xml do
952
- env['HTTP_ACCEPT']
953
- end
954
- get '/foo', :provides => :html do
955
- env['HTTP_ACCEPT']
956
- end
957
- get '/stream', :provides => 'text/event-stream' do
958
- env['HTTP_ACCEPT']
959
- end
960
- }
961
-
962
- get '/', {}, { 'HTTP_ACCEPT' => 'application/xml' }
963
- assert ok?
964
- assert_equal 'application/xml', body
965
- assert_equal 'application/xml;charset=utf-8', response.headers['Content-Type']
966
-
967
- get '/', {}, {}
968
- assert ok?
969
- assert_equal '', body
970
- assert_equal 'application/xml;charset=utf-8', response.headers['Content-Type']
971
-
972
- get '/', {}, { 'HTTP_ACCEPT' => '*/*' }
973
- assert ok?
974
- assert_equal '*/*', body
975
- assert_equal 'application/xml;charset=utf-8', response.headers['Content-Type']
976
-
977
- get '/', {}, { 'HTTP_ACCEPT' => 'text/html;q=0.9' }
978
- assert !ok?
979
-
980
- get '/foo', {}, { 'HTTP_ACCEPT' => 'text/html;q=0.9' }
981
- assert ok?
982
- assert_equal 'text/html;q=0.9', body
983
-
984
- get '/foo', {}, { 'HTTP_ACCEPT' => '' }
985
- assert ok?
986
- assert_equal '', body
987
-
988
- get '/foo', {}, { 'HTTP_ACCEPT' => '*/*' }
989
- assert ok?
990
- assert_equal '*/*', body
991
-
992
- get '/foo', {}, { 'HTTP_ACCEPT' => 'application/xml' }
993
- assert !ok?
994
-
995
- get '/stream', {}, { 'HTTP_ACCEPT' => 'text/event-stream' }
996
- assert ok?
997
- assert_equal 'text/event-stream', body
998
-
999
- get '/stream', {}, { 'HTTP_ACCEPT' => '' }
1000
- assert ok?
1001
- assert_equal '', body
1002
-
1003
- get '/stream', {}, { 'HTTP_ACCEPT' => '*/*' }
1004
- assert ok?
1005
- assert_equal '*/*', body
1006
-
1007
- get '/stream', {}, { 'HTTP_ACCEPT' => 'application/xml' }
1008
- assert !ok?
1009
- end
1010
-
1011
- it "filters by current Content-Type" do
1012
- mock_app do
1013
- before('/txt') { content_type :txt }
1014
- get('*', :provides => :txt) { 'txt' }
1015
-
1016
- before('/html') { content_type :html }
1017
- get('*', :provides => :html) { 'html' }
1018
- end
1019
-
1020
- get '/', {}, { 'HTTP_ACCEPT' => '*/*' }
1021
- assert ok?
1022
- assert_equal 'text/plain;charset=utf-8', response.headers['Content-Type']
1023
- assert_body 'txt'
1024
-
1025
- get '/txt', {}, { 'HTTP_ACCEPT' => 'text/plain' }
1026
- assert ok?
1027
- assert_equal 'text/plain;charset=utf-8', response.headers['Content-Type']
1028
- assert_body 'txt'
1029
-
1030
- get '/', {}, { 'HTTP_ACCEPT' => 'text/html' }
1031
- assert ok?
1032
- assert_equal 'text/html;charset=utf-8', response.headers['Content-Type']
1033
- assert_body 'html'
1034
- end
1035
-
1036
- it "allows multiple mime types for accept header" do
1037
- types = ['image/jpeg', 'image/pjpeg']
1038
-
1039
- mock_app {
1040
- get '/', :provides => types do
1041
- env['HTTP_ACCEPT']
1042
- end
1043
- }
1044
-
1045
- types.each do |type|
1046
- get '/', {}, { 'HTTP_ACCEPT' => type }
1047
- assert ok?
1048
- assert_equal type, body
1049
- assert_equal type, response.headers['Content-Type']
1050
- end
1051
- end
1052
-
1053
- it 'respects user agent preferences for the content type' do
1054
- mock_app { get('/', :provides => [:png, :html]) { content_type }}
1055
- get '/', {}, { 'HTTP_ACCEPT' => 'image/png;q=0.5,text/html;q=0.8' }
1056
- assert_body 'text/html;charset=utf-8'
1057
- get '/', {}, { 'HTTP_ACCEPT' => 'image/png;q=0.8,text/html;q=0.5' }
1058
- assert_body 'image/png'
1059
- end
1060
-
1061
- it 'accepts generic types' do
1062
- mock_app do
1063
- get('/', :provides => :xml) { content_type }
1064
- get('/') { 'no match' }
1065
- end
1066
- get '/', {}, { 'HTTP_ACCEPT' => 'foo/*' }
1067
- assert_body 'no match'
1068
- get '/', {}, { 'HTTP_ACCEPT' => 'application/*' }
1069
- assert_body 'application/xml;charset=utf-8'
1070
- get '/', {}, { 'HTTP_ACCEPT' => '*/*' }
1071
- assert_body 'application/xml;charset=utf-8'
1072
- end
1073
-
1074
- it 'prefers concrete over partly generic types' do
1075
- mock_app { get('/', :provides => [:png, :html]) { content_type }}
1076
- get '/', {}, { 'HTTP_ACCEPT' => 'image/*, text/html' }
1077
- assert_body 'text/html;charset=utf-8'
1078
- get '/', {}, { 'HTTP_ACCEPT' => 'image/png, text/*' }
1079
- assert_body 'image/png'
1080
- end
1081
-
1082
- it 'prefers concrete over fully generic types' do
1083
- mock_app { get('/', :provides => [:png, :html]) { content_type }}
1084
- get '/', {}, { 'HTTP_ACCEPT' => '*/*, text/html' }
1085
- assert_body 'text/html;charset=utf-8'
1086
- get '/', {}, { 'HTTP_ACCEPT' => 'image/png, */*' }
1087
- assert_body 'image/png'
1088
- end
1089
-
1090
- it 'prefers partly generic over fully generic types' do
1091
- mock_app { get('/', :provides => [:png, :html]) { content_type }}
1092
- get '/', {}, { 'HTTP_ACCEPT' => '*/*, text/*' }
1093
- assert_body 'text/html;charset=utf-8'
1094
- get '/', {}, { 'HTTP_ACCEPT' => 'image/*, */*' }
1095
- assert_body 'image/png'
1096
- end
1097
-
1098
- it 'respects quality with generic types' do
1099
- mock_app { get('/', :provides => [:png, :html]) { content_type }}
1100
- get '/', {}, { 'HTTP_ACCEPT' => 'image/*;q=1, text/html;q=0' }
1101
- assert_body 'image/png'
1102
- get '/', {}, { 'HTTP_ACCEPT' => 'image/png;q=0.5, text/*;q=0.7' }
1103
- assert_body 'text/html;charset=utf-8'
1104
- end
1105
-
1106
- it 'supplies a default quality of 1.0' do
1107
- mock_app { get('/', :provides => [:png, :html]) { content_type }}
1108
- get '/', {}, { 'HTTP_ACCEPT' => 'image/png;q=0.5, text/*' }
1109
- assert_body 'text/html;charset=utf-8'
1110
- end
1111
-
1112
- it 'orders types with equal quality by parameter count' do
1113
- mock_app do
1114
- get('/', :provides => [:png, :jpg]) { content_type }
1115
- end
1116
-
1117
- lo_png = 'image/png;q=0.5'
1118
- hi_png = 'image/png;q=0.5;profile=FOGRA40;gamma=0.8'
1119
- jpeg = 'image/jpeg;q=0.5;compress=0.25'
1120
-
1121
- get '/', {}, { 'HTTP_ACCEPT' => "#{lo_png}, #{jpeg}" }
1122
- assert_body 'image/jpeg'
1123
- get '/', {}, { 'HTTP_ACCEPT' => "#{hi_png}, #{jpeg}" }
1124
- assert_body 'image/png'
1125
- end
1126
-
1127
- it 'ignores the quality parameter when ordering by parameter count' do
1128
- mock_app do
1129
- get('/', :provides => [:png, :jpg]) { content_type }
1130
- end
1131
-
1132
- lo_png = 'image/png'
1133
- hi_png = 'image/png;profile=FOGRA40;gamma=0.8'
1134
- jpeg = 'image/jpeg;q=1.0;compress=0.25'
1135
-
1136
- get '/', {}, { 'HTTP_ACCEPT' => "#{jpeg}, #{lo_png}" }
1137
- assert_body 'image/jpeg'
1138
- get '/', {}, { 'HTTP_ACCEPT' => "#{jpeg}, #{hi_png}" }
1139
- assert_body 'image/png'
1140
- end
1141
-
1142
- it 'properly handles quoted strings in parameters' do
1143
- mock_app do
1144
- get('/', :provides => [:png, :jpg]) { content_type }
1145
- end
1146
-
1147
- get '/', {}, { 'HTTP_ACCEPT' => 'image/png;q=0.5;profile=",image/jpeg,"' }
1148
- assert_body 'image/png'
1149
- get '/', {}, { 'HTTP_ACCEPT' => 'image/png;q=0.5,image/jpeg;q=0;x=";q=1.0"' }
1150
- assert_body 'image/png'
1151
- get '/', {}, { 'HTTP_ACCEPT' => 'image/png;q=0.5,image/jpeg;q=0;x="\";q=1.0"' }
1152
- assert_body 'image/png'
1153
- end
1154
-
1155
- it 'accepts both text/javascript and application/javascript for js' do
1156
- mock_app { get('/', :provides => :js) { content_type }}
1157
- get '/', {}, { 'HTTP_ACCEPT' => 'application/javascript' }
1158
- assert_body 'application/javascript;charset=utf-8'
1159
- get '/', {}, { 'HTTP_ACCEPT' => 'text/javascript' }
1160
- assert_body 'text/javascript;charset=utf-8'
1161
- end
1162
-
1163
- it 'accepts both text/xml and application/xml for xml' do
1164
- mock_app { get('/', :provides => :xml) { content_type }}
1165
- get '/', {}, { 'HTTP_ACCEPT' => 'application/xml' }
1166
- assert_body 'application/xml;charset=utf-8'
1167
- get '/', {}, { 'HTTP_ACCEPT' => 'text/xml' }
1168
- assert_body 'text/xml;charset=utf-8'
1169
- end
1170
-
1171
- it 'passes a single url param as block parameters when one param is specified' do
1172
- mock_app {
1173
- get '/:foo' do |foo|
1174
- assert_equal 'bar', foo
1175
- end
1176
- }
1177
-
1178
- get '/bar'
1179
- assert ok?
1180
- end
1181
-
1182
- it 'passes multiple params as block parameters when many are specified' do
1183
- mock_app {
1184
- get '/:foo/:bar/:baz' do |foo, bar, baz|
1185
- assert_equal 'abc', foo
1186
- assert_equal 'def', bar
1187
- assert_equal 'ghi', baz
1188
- end
1189
- }
1190
-
1191
- get '/abc/def/ghi'
1192
- assert ok?
1193
- end
1194
-
1195
- it 'passes regular expression captures as block parameters' do
1196
- mock_app {
1197
- get(/^\/fo(.*)\/ba(.*)/) do |foo, bar|
1198
- assert_equal 'orooomma', foo
1199
- assert_equal 'f', bar
1200
- 'looks good'
1201
- end
1202
- }
1203
-
1204
- get '/foorooomma/baf'
1205
- assert ok?
1206
- assert_equal 'looks good', body
1207
- end
1208
-
1209
- it "supports mixing multiple splat params like /*/foo/*/* as block parameters" do
1210
- mock_app {
1211
- get '/*/foo/*/*' do |foo, bar, baz|
1212
- assert_equal 'bar', foo
1213
- assert_equal 'bling', bar
1214
- assert_equal 'baz/boom', baz
1215
- 'looks good'
1216
- end
1217
- }
1218
-
1219
- get '/bar/foo/bling/baz/boom'
1220
- assert ok?
1221
- assert_equal 'looks good', body
1222
- end
1223
-
1224
- it 'raises an ArgumentError with block arity > 1 and too many values' do
1225
- mock_app do
1226
- get '/:foo/:bar/:baz' do |foo, bar|
1227
- 'quux'
1228
- end
1229
- end
1230
-
1231
- assert_raises(ArgumentError) { get '/a/b/c' }
1232
- end
1233
-
1234
- it 'raises an ArgumentError with block param arity > 1 and too few values' do
1235
- mock_app {
1236
- get '/:foo/:bar' do |foo, bar, baz|
1237
- 'quux'
1238
- end
1239
- }
1240
-
1241
- assert_raises(ArgumentError) { get '/a/b' }
1242
- end
1243
-
1244
- it 'succeeds if no block parameters are specified' do
1245
- mock_app {
1246
- get '/:foo/:bar' do
1247
- 'quux'
1248
- end
1249
- }
1250
-
1251
- get '/a/b'
1252
- assert ok?
1253
- assert_equal 'quux', body
1254
- end
1255
-
1256
- it 'passes all params with block param arity -1 (splat args)' do
1257
- mock_app {
1258
- get '/:foo/:bar' do |*args|
1259
- args.join
1260
- end
1261
- }
1262
-
1263
- get '/a/b'
1264
- assert ok?
1265
- assert_equal 'ab', body
1266
- end
1267
-
1268
- it 'allows custom route-conditions to be set via route options' do
1269
- protector = Module.new {
1270
- def protect(*args)
1271
- condition {
1272
- unless authorize(params["user"], params["password"])
1273
- halt 403, "go away"
1274
- end
1275
- }
1276
- end
1277
- }
1278
-
1279
- mock_app {
1280
- register protector
1281
-
1282
- helpers do
1283
- def authorize(username, password)
1284
- username == "foo" && password == "bar"
1285
- end
1286
- end
1287
-
1288
- get "/", :protect => true do
1289
- "hey"
1290
- end
1291
- }
1292
-
1293
- get "/"
1294
- assert forbidden?
1295
- assert_equal "go away", body
1296
-
1297
- get "/", :user => "foo", :password => "bar"
1298
- assert ok?
1299
- assert_equal "hey", body
1300
- end
1301
-
1302
- # NOTE Block params behaves differently under 1.8 and 1.9. Under 1.8, block
1303
- # param arity is lax: declaring a mismatched number of block params results
1304
- # in a warning. Under 1.9, block param arity is strict: mismatched block
1305
- # arity raises an ArgumentError.
1306
-
1307
- if RUBY_VERSION >= '1.9'
1308
-
1309
- it 'raises an ArgumentError with block param arity 1 and no values' do
1310
- mock_app {
1311
- get '/foo' do |foo|
1312
- 'quux'
1313
- end
1314
- }
1315
-
1316
- assert_raises(ArgumentError) { get '/foo' }
1317
- end
1318
-
1319
- it 'raises an ArgumentError with block param arity 1 and too many values' do
1320
- mock_app {
1321
- get '/:foo/:bar/:baz' do |foo|
1322
- 'quux'
1323
- end
1324
- }
1325
-
1326
- assert_raises(ArgumentError) { get '/a/b/c' }
1327
- end
1328
-
1329
- else
1330
-
1331
- it 'does not raise an ArgumentError with block param arity 1 and no values' do
1332
- mock_app {
1333
- get '/foo' do |foo|
1334
- 'quux'
1335
- end
1336
- }
1337
-
1338
- silence_warnings { get '/foo' }
1339
- assert ok?
1340
- assert_equal 'quux', body
1341
- end
1342
-
1343
- it 'does not raise an ArgumentError with block param arity 1 and too many values' do
1344
- mock_app {
1345
- get '/:foo/:bar/:baz' do |foo|
1346
- 'quux'
1347
- end
1348
- }
1349
-
1350
- silence_warnings { get '/a/b/c' }
1351
- assert ok?
1352
- assert_equal 'quux', body
1353
- end
1354
-
1355
- end
1356
-
1357
- it "matches routes defined in superclasses" do
1358
- base = Class.new(Sinatra::Base)
1359
- base.get('/foo') { 'foo in baseclass' }
1360
-
1361
- mock_app(base) {
1362
- get('/bar') { 'bar in subclass' }
1363
- }
1364
-
1365
- get '/foo'
1366
- assert ok?
1367
- assert_equal 'foo in baseclass', body
1368
-
1369
- get '/bar'
1370
- assert ok?
1371
- assert_equal 'bar in subclass', body
1372
- end
1373
-
1374
- it "matches routes in subclasses before superclasses" do
1375
- base = Class.new(Sinatra::Base)
1376
- base.get('/foo') { 'foo in baseclass' }
1377
- base.get('/bar') { 'bar in baseclass' }
1378
-
1379
- mock_app(base) {
1380
- get('/foo') { 'foo in subclass' }
1381
- }
1382
-
1383
- get '/foo'
1384
- assert ok?
1385
- assert_equal 'foo in subclass', body
1386
-
1387
- get '/bar'
1388
- assert ok?
1389
- assert_equal 'bar in baseclass', body
1390
- end
1391
-
1392
- it "adds hostname condition when it is in options" do
1393
- mock_app {
1394
- get '/foo', :host => 'host' do
1395
- 'foo'
1396
- end
1397
- }
1398
-
1399
- get '/foo'
1400
- assert not_found?
1401
- end
1402
-
1403
- it 'allows using call to fire another request internally' do
1404
- mock_app do
1405
- get '/foo' do
1406
- status, headers, body = call env.merge("PATH_INFO" => '/bar')
1407
- [status, headers, body.each.map(&:upcase)]
1408
- end
1409
-
1410
- get '/bar' do
1411
- "bar"
1412
- end
1413
- end
1414
-
1415
- get '/foo'
1416
- assert ok?
1417
- assert_body "BAR"
1418
- end
1419
-
1420
- it 'plays well with other routing middleware' do
1421
- middleware = Sinatra.new
1422
- inner_app = Sinatra.new { get('/foo') { 'hello' } }
1423
- builder = Rack::Builder.new do
1424
- use middleware
1425
- map('/test') { run inner_app }
1426
- end
1427
-
1428
- @app = builder.to_app
1429
- get '/test/foo'
1430
- assert ok?
1431
- assert_body 'hello'
1432
- end
1433
-
1434
- it 'returns the route signature' do
1435
- signature = list = nil
1436
-
1437
- mock_app do
1438
- signature = post('/') { }
1439
- list = routes['POST']
1440
- end
1441
-
1442
- assert_equal Array, signature.class
1443
- assert_equal 4, signature.length
1444
- assert list.include?(signature)
1445
- end
1446
-
1447
- it "sets env['sinatra.route'] to the matched route" do
1448
- mock_app do
1449
- after do
1450
- assert_equal 'GET /users/:id/status', env['sinatra.route']
1451
- end
1452
- get('/users/:id/status') { 'ok' }
1453
- end
1454
- get '/users/1/status'
1455
- end
1456
- end