darkhelmet-sinatra 0.9.1.1 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/AUTHORS +2 -0
  2. data/CHANGES +180 -0
  3. data/LICENSE +1 -1
  4. data/README.jp.rdoc +552 -0
  5. data/README.rdoc +177 -38
  6. data/Rakefile +18 -25
  7. data/lib/sinatra.rb +1 -2
  8. data/lib/sinatra/base.rb +405 -305
  9. data/lib/sinatra/main.rb +5 -24
  10. data/lib/sinatra/showexceptions.rb +303 -0
  11. data/lib/sinatra/tilt.rb +509 -0
  12. data/sinatra.gemspec +21 -51
  13. data/test/base_test.rb +123 -93
  14. data/test/builder_test.rb +2 -1
  15. data/test/contest.rb +64 -0
  16. data/test/erb_test.rb +1 -1
  17. data/test/erubis_test.rb +82 -0
  18. data/test/extensions_test.rb +24 -8
  19. data/test/filter_test.rb +99 -3
  20. data/test/haml_test.rb +25 -3
  21. data/test/helper.rb +43 -48
  22. data/test/helpers_test.rb +500 -424
  23. data/test/mapped_error_test.rb +163 -137
  24. data/test/middleware_test.rb +3 -3
  25. data/test/request_test.rb +16 -1
  26. data/test/response_test.rb +2 -2
  27. data/test/result_test.rb +1 -1
  28. data/test/route_added_hook_test.rb +59 -0
  29. data/test/routing_test.rb +170 -22
  30. data/test/sass_test.rb +44 -1
  31. data/test/server_test.rb +19 -13
  32. data/test/sinatra_test.rb +1 -1
  33. data/test/static_test.rb +9 -2
  34. data/test/templates_test.rb +78 -11
  35. data/test/views/error.builder +3 -0
  36. data/test/views/error.erb +3 -0
  37. data/test/views/error.erubis +3 -0
  38. data/test/views/error.haml +3 -0
  39. data/test/views/error.sass +2 -0
  40. data/test/views/foo/hello.test +1 -0
  41. data/test/views/hello.erubis +1 -0
  42. data/test/views/layout2.erubis +2 -0
  43. metadata +37 -55
  44. data/compat/app_test.rb +0 -282
  45. data/compat/application_test.rb +0 -262
  46. data/compat/builder_test.rb +0 -101
  47. data/compat/compat_test.rb +0 -12
  48. data/compat/custom_error_test.rb +0 -62
  49. data/compat/erb_test.rb +0 -136
  50. data/compat/events_test.rb +0 -78
  51. data/compat/filter_test.rb +0 -30
  52. data/compat/haml_test.rb +0 -233
  53. data/compat/helper.rb +0 -30
  54. data/compat/mapped_error_test.rb +0 -72
  55. data/compat/pipeline_test.rb +0 -45
  56. data/compat/public/foo.xml +0 -1
  57. data/compat/sass_test.rb +0 -57
  58. data/compat/sessions_test.rb +0 -42
  59. data/compat/streaming_test.rb +0 -133
  60. data/compat/sym_params_test.rb +0 -19
  61. data/compat/template_test.rb +0 -30
  62. data/compat/use_in_file_templates_test.rb +0 -47
  63. data/compat/views/foo.builder +0 -1
  64. data/compat/views/foo.erb +0 -1
  65. data/compat/views/foo.haml +0 -1
  66. data/compat/views/foo.sass +0 -2
  67. data/compat/views/foo_layout.erb +0 -2
  68. data/compat/views/foo_layout.haml +0 -2
  69. data/compat/views/layout_test/foo.builder +0 -1
  70. data/compat/views/layout_test/foo.erb +0 -1
  71. data/compat/views/layout_test/foo.haml +0 -1
  72. data/compat/views/layout_test/foo.sass +0 -2
  73. data/compat/views/layout_test/layout.builder +0 -3
  74. data/compat/views/layout_test/layout.erb +0 -1
  75. data/compat/views/layout_test/layout.haml +0 -1
  76. data/compat/views/layout_test/layout.sass +0 -2
  77. data/compat/views/no_layout/no_layout.builder +0 -1
  78. data/compat/views/no_layout/no_layout.haml +0 -1
  79. data/lib/sinatra/compat.rb +0 -250
  80. data/lib/sinatra/test.rb +0 -126
  81. data/lib/sinatra/test/bacon.rb +0 -19
  82. data/lib/sinatra/test/rspec.rb +0 -13
  83. data/lib/sinatra/test/spec.rb +0 -11
  84. data/lib/sinatra/test/unit.rb +0 -13
  85. data/test/data/reload_app_file.rb +0 -3
  86. data/test/options_test.rb +0 -374
  87. data/test/reload_test.rb +0 -68
  88. data/test/test_test.rb +0 -144
@@ -1,497 +1,573 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
2
 
3
- describe 'Helpers#status' do
4
- before do
5
- mock_app {
6
- get '/' do
7
- status 207
8
- nil
9
- end
10
- }
11
- end
12
-
13
- it 'sets the response status code' do
14
- get '/'
15
- assert_equal 207, response.status
16
- end
17
- end
18
-
19
- describe 'Helpers#body' do
20
- it 'takes a block for defered body generation' do
21
- mock_app {
22
- get '/' do
23
- body { 'Hello World' }
24
- end
25
- }
26
-
27
- get '/'
28
- assert_equal 'Hello World', body
29
- end
30
-
31
- it 'takes a String, Array, or other object responding to #each' do
32
- mock_app {
33
- get '/' do
34
- body 'Hello World'
35
- end
36
- }
37
-
38
- get '/'
39
- assert_equal 'Hello World', body
40
- end
41
- end
42
-
43
- describe 'Helpers#redirect' do
44
- it 'uses a 302 when only a path is given' do
45
- mock_app {
46
- get '/' do
47
- redirect '/foo'
48
- fail 'redirect should halt'
49
- end
50
- }
51
-
52
- get '/'
53
- assert_equal 302, status
54
- assert_equal '', body
55
- assert_equal '/foo', response['Location']
56
- end
57
-
58
- it 'uses the code given when specified' do
59
- mock_app {
60
- get '/' do
61
- redirect '/foo', 301
62
- fail 'redirect should halt'
63
- end
64
- }
65
-
66
- get '/'
67
- assert_equal 301, status
68
- assert_equal '', body
69
- assert_equal '/foo', response['Location']
70
- end
71
-
72
- it 'redirects back to request.referer when passed back' do
73
- mock_app {
74
- get '/try_redirect' do
75
- redirect back
76
- end
77
- }
78
-
79
- request = Rack::MockRequest.new(@app)
80
- response = request.get('/try_redirect', 'HTTP_REFERER' => '/foo')
81
- assert_equal 302, response.status
82
- assert_equal '/foo', response['Location']
83
- end
84
-
85
- end
86
-
87
- describe 'Helpers#error' do
88
- it 'sets a status code and halts' do
89
- mock_app {
90
- get '/' do
91
- error 501
92
- fail 'error should halt'
93
- end
94
- }
95
-
96
- get '/'
97
- assert_equal 501, status
98
- assert_equal '', body
3
+ class HelpersTest < Test::Unit::TestCase
4
+ def test_default
5
+ assert true
99
6
  end
100
7
 
101
- it 'takes an optional body' do
102
- mock_app {
103
- get '/' do
104
- error 501, 'FAIL'
105
- fail 'error should halt'
106
- end
107
- }
108
-
109
- get '/'
110
- assert_equal 501, status
111
- assert_equal 'FAIL', body
112
- end
113
-
114
- it 'uses a 500 status code when first argument is a body' do
115
- mock_app {
116
- get '/' do
117
- error 'FAIL'
118
- fail 'error should halt'
119
- end
120
- }
121
-
122
- get '/'
123
- assert_equal 500, status
124
- assert_equal 'FAIL', body
125
- end
126
- end
127
-
128
- describe 'Helpers#not_found' do
129
- it 'halts with a 404 status' do
130
- mock_app {
131
- get '/' do
132
- not_found
133
- fail 'not_found should halt'
134
- end
135
- }
136
-
137
- get '/'
138
- assert_equal 404, status
139
- assert_equal '', body
140
- end
141
- end
142
-
143
- describe 'Helpers#headers' do
144
- it 'sets headers on the response object when given a Hash' do
145
- mock_app {
146
- get '/' do
147
- headers 'X-Foo' => 'bar', 'X-Baz' => 'bling'
148
- 'kthx'
149
- end
150
- }
8
+ describe 'status' do
9
+ setup do
10
+ mock_app {
11
+ get '/' do
12
+ status 207
13
+ nil
14
+ end
15
+ }
16
+ end
151
17
 
152
- get '/'
153
- assert ok?
154
- assert_equal 'bar', response['X-Foo']
155
- assert_equal 'bling', response['X-Baz']
156
- assert_equal 'kthx', body
18
+ it 'sets the response status code' do
19
+ get '/'
20
+ assert_equal 207, response.status
21
+ end
157
22
  end
158
23
 
159
- it 'returns the response headers hash when no hash provided' do
160
- mock_app {
161
- get '/' do
162
- headers['X-Foo'] = 'bar'
163
- 'kthx'
164
- end
165
- }
24
+ describe 'body' do
25
+ it 'takes a block for defered body generation' do
26
+ mock_app {
27
+ get '/' do
28
+ body { 'Hello World' }
29
+ end
30
+ }
166
31
 
167
- get '/'
168
- assert ok?
169
- assert_equal 'bar', response['X-Foo']
170
- end
171
- end
32
+ get '/'
33
+ assert_equal 'Hello World', body
34
+ end
172
35
 
173
- describe 'Helpers#session' do
174
- it 'uses the existing rack.session' do
175
- mock_app {
176
- get '/' do
177
- session[:foo]
178
- end
179
- }
36
+ it 'takes a String, Array, or other object responding to #each' do
37
+ mock_app {
38
+ get '/' do
39
+ body 'Hello World'
40
+ end
41
+ }
180
42
 
181
- get '/', :env => { 'rack.session' => { :foo => 'bar' } }
182
- assert_equal 'bar', body
43
+ get '/'
44
+ assert_equal 'Hello World', body
45
+ end
183
46
  end
184
47
 
185
- it 'creates a new session when none provided' do
186
- mock_app {
187
- get '/' do
188
- assert session.empty?
189
- session[:foo] = 'bar'
190
- 'Hi'
191
- end
192
- }
48
+ describe 'redirect' do
49
+ it 'uses a 302 when only a path is given' do
50
+ mock_app {
51
+ get '/' do
52
+ redirect '/foo'
53
+ fail 'redirect should halt'
54
+ end
55
+ }
56
+
57
+ get '/'
58
+ assert_equal 302, status
59
+ assert_equal '', body
60
+ assert_equal '/foo', response['Location']
61
+ end
62
+
63
+ it 'uses the code given when specified' do
64
+ mock_app {
65
+ get '/' do
66
+ redirect '/foo', 301
67
+ fail 'redirect should halt'
68
+ end
69
+ }
70
+
71
+ get '/'
72
+ assert_equal 301, status
73
+ assert_equal '', body
74
+ assert_equal '/foo', response['Location']
75
+ end
76
+
77
+ it 'redirects back to request.referer when passed back' do
78
+ mock_app {
79
+ get '/try_redirect' do
80
+ redirect back
81
+ end
82
+ }
193
83
 
194
- get '/'
195
- assert_equal 'Hi', body
84
+ request = Rack::MockRequest.new(@app)
85
+ response = request.get('/try_redirect', 'HTTP_REFERER' => '/foo')
86
+ assert_equal 302, response.status
87
+ assert_equal '/foo', response['Location']
88
+ end
196
89
  end
197
- end
198
90
 
199
- describe 'Helpers#media_type' do
200
- include Sinatra::Helpers
201
-
202
- it "looks up media types in Rack's MIME registry" do
203
- Rack::Mime::MIME_TYPES['.foo'] = 'application/foo'
204
- assert_equal 'application/foo', media_type('foo')
205
- assert_equal 'application/foo', media_type('.foo')
206
- assert_equal 'application/foo', media_type(:foo)
207
- end
91
+ describe 'error' do
92
+ it 'sets a status code and halts' do
93
+ mock_app {
94
+ get '/' do
95
+ error 501
96
+ fail 'error should halt'
97
+ end
98
+ }
99
+
100
+ get '/'
101
+ assert_equal 501, status
102
+ assert_equal '', body
103
+ end
104
+
105
+ it 'takes an optional body' do
106
+ mock_app {
107
+ get '/' do
108
+ error 501, 'FAIL'
109
+ fail 'error should halt'
110
+ end
111
+ }
112
+
113
+ get '/'
114
+ assert_equal 501, status
115
+ assert_equal 'FAIL', body
116
+ end
117
+
118
+ it 'uses a 500 status code when first argument is a body' do
119
+ mock_app {
120
+ get '/' do
121
+ error 'FAIL'
122
+ fail 'error should halt'
123
+ end
124
+ }
208
125
 
209
- it 'returns nil when given nil' do
210
- assert media_type(nil).nil?
126
+ get '/'
127
+ assert_equal 500, status
128
+ assert_equal 'FAIL', body
129
+ end
211
130
  end
212
131
 
213
- it 'returns nil when media type not registered' do
214
- assert media_type(:bizzle).nil?
215
- end
132
+ describe 'not_found' do
133
+ it 'halts with a 404 status' do
134
+ mock_app {
135
+ get '/' do
136
+ not_found
137
+ fail 'not_found should halt'
138
+ end
139
+ }
140
+
141
+ get '/'
142
+ assert_equal 404, status
143
+ assert_equal '', body
144
+ end
145
+
146
+ it 'does not set a X-Cascade header' do
147
+ mock_app {
148
+ get '/' do
149
+ not_found
150
+ fail 'not_found should halt'
151
+ end
152
+ }
216
153
 
217
- it 'returns the argument when given a media type string' do
218
- assert_equal 'text/plain', media_type('text/plain')
154
+ get '/'
155
+ assert_equal 404, status
156
+ assert_equal nil, response.headers['X-Cascade']
157
+ end
219
158
  end
220
- end
221
159
 
222
- describe 'Helpers#content_type' do
223
- it 'sets the Content-Type header' do
224
- mock_app {
225
- get '/' do
226
- content_type 'text/plain'
227
- 'Hello World'
228
- end
229
- }
160
+ describe 'headers' do
161
+ it 'sets headers on the response object when given a Hash' do
162
+ mock_app {
163
+ get '/' do
164
+ headers 'X-Foo' => 'bar', 'X-Baz' => 'bling'
165
+ 'kthx'
166
+ end
167
+ }
168
+
169
+ get '/'
170
+ assert ok?
171
+ assert_equal 'bar', response['X-Foo']
172
+ assert_equal 'bling', response['X-Baz']
173
+ assert_equal 'kthx', body
174
+ end
175
+
176
+ it 'returns the response headers hash when no hash provided' do
177
+ mock_app {
178
+ get '/' do
179
+ headers['X-Foo'] = 'bar'
180
+ 'kthx'
181
+ end
182
+ }
230
183
 
231
- get '/'
232
- assert_equal 'text/plain', response['Content-Type']
233
- assert_equal 'Hello World', body
184
+ get '/'
185
+ assert ok?
186
+ assert_equal 'bar', response['X-Foo']
187
+ end
234
188
  end
235
189
 
236
- it 'takes media type parameters (like charset=)' do
237
- mock_app {
238
- get '/' do
239
- content_type 'text/html', :charset => 'utf-8'
240
- "<h1>Hello, World</h1>"
241
- end
242
- }
243
-
244
- get '/'
245
- assert ok?
246
- assert_equal 'text/html;charset=utf-8', response['Content-Type']
247
- assert_equal "<h1>Hello, World</h1>", body
248
- end
190
+ describe 'session' do
191
+ it 'uses the existing rack.session' do
192
+ mock_app {
193
+ get '/' do
194
+ session[:foo]
195
+ end
196
+ }
249
197
 
250
- it "looks up symbols in Rack's mime types dictionary" do
251
- Rack::Mime::MIME_TYPES['.foo'] = 'application/foo'
252
- mock_app {
253
- get '/foo.xml' do
254
- content_type :foo
255
- "I AM FOO"
256
- end
257
- }
198
+ get '/', {}, { 'rack.session' => { :foo => 'bar' } }
199
+ assert_equal 'bar', body
200
+ end
258
201
 
259
- get '/foo.xml'
260
- assert ok?
261
- assert_equal 'application/foo', response['Content-Type']
262
- assert_equal 'I AM FOO', body
263
- end
202
+ it 'creates a new session when none provided' do
203
+ mock_app {
204
+ enable :sessions
264
205
 
265
- it 'fails when no mime type is registered for the argument provided' do
266
- mock_app {
267
- get '/foo.xml' do
268
- content_type :bizzle
269
- "I AM FOO"
270
- end
271
- }
272
- assert_raise(RuntimeError) { get '/foo.xml' }
273
- end
274
- end
206
+ get '/' do
207
+ assert session.empty?
208
+ session[:foo] = 'bar'
209
+ redirect '/hi'
210
+ end
275
211
 
276
- describe 'Helpers#send_file' do
277
- before do
278
- @file = File.dirname(__FILE__) + '/file.txt'
279
- File.open(@file, 'wb') { |io| io.write('Hello World') }
280
- end
212
+ get '/hi' do
213
+ "hi #{session[:foo]}"
214
+ end
215
+ }
281
216
 
282
- after do
283
- File.unlink @file
284
- @file = nil
217
+ get '/'
218
+ follow_redirect!
219
+ assert_equal 'hi bar', body
220
+ end
285
221
  end
286
222
 
287
- def send_file_app(opts={})
288
- path = @file
289
- mock_app {
290
- get '/file.txt' do
291
- send_file path, opts
292
- end
293
- }
294
- end
223
+ describe 'mime_type' do
224
+ include Sinatra::Helpers
295
225
 
296
- it "sends the contents of the file" do
297
- send_file_app
298
- get '/file.txt'
299
- assert ok?
300
- assert_equal 'Hello World', body
301
- end
226
+ it "looks up mime types in Rack's MIME registry" do
227
+ Rack::Mime::MIME_TYPES['.foo'] = 'application/foo'
228
+ assert_equal 'application/foo', mime_type('foo')
229
+ assert_equal 'application/foo', mime_type('.foo')
230
+ assert_equal 'application/foo', mime_type(:foo)
231
+ end
302
232
 
303
- it 'sets the Content-Type response header if a mime-type can be located' do
304
- send_file_app
305
- get '/file.txt'
306
- assert_equal 'text/plain', response['Content-Type']
307
- end
233
+ it 'returns nil when given nil' do
234
+ assert mime_type(nil).nil?
235
+ end
308
236
 
309
- it 'sets the Content-Length response header' do
310
- send_file_app
311
- get '/file.txt'
312
- assert_equal 'Hello World'.length.to_s, response['Content-Length']
313
- end
237
+ it 'returns nil when media type not registered' do
238
+ assert mime_type(:bizzle).nil?
239
+ end
314
240
 
315
- it 'sets the Last-Modified response header' do
316
- send_file_app
317
- get '/file.txt'
318
- assert_equal File.mtime(@file).httpdate, response['Last-Modified']
241
+ it 'returns the argument when given a media type string' do
242
+ assert_equal 'text/plain', mime_type('text/plain')
243
+ end
319
244
  end
320
245
 
321
- it "returns a 404 when not found" do
246
+ test 'Base.mime_type registers mime type' do
322
247
  mock_app {
323
- get '/' do
324
- send_file 'this-file-does-not-exist.txt'
325
- end
326
- }
327
- get '/'
328
- assert not_found?
329
- end
330
-
331
- it "does not set the Content-Disposition header by default" do
332
- send_file_app
333
- get '/file.txt'
334
- assert_nil response['Content-Disposition']
335
- end
336
-
337
- it "sets the Content-Disposition header when :disposition set to 'attachment'" do
338
- send_file_app :disposition => 'attachment'
339
- get '/file.txt'
340
- assert_equal 'attachment; filename="file.txt"', response['Content-Disposition']
341
- end
342
-
343
- it "sets the Content-Disposition header when :filename provided" do
344
- send_file_app :filename => 'foo.txt'
345
- get '/file.txt'
346
- assert_equal 'attachment; filename="foo.txt"', response['Content-Disposition']
347
- end
348
- end
248
+ mime_type :foo, 'application/foo'
349
249
 
350
- describe 'Helpers#last_modified' do
351
- before do
352
- now = Time.now
353
- mock_app {
354
250
  get '/' do
355
- body { 'Hello World' }
356
- last_modified now
357
- 'Boo!'
251
+ "foo is #{mime_type(:foo)}"
358
252
  end
359
253
  }
360
- @now = now
361
- end
362
-
363
- it 'sets the Last-Modified header to a valid RFC 2616 date value' do
364
- get '/'
365
- assert_equal @now.httpdate, response['Last-Modified']
366
- end
367
254
 
368
- it 'returns a body when conditional get misses' do
369
255
  get '/'
370
- assert_equal 200, status
371
- assert_equal 'Boo!', body
256
+ assert_equal 'foo is application/foo', body
372
257
  end
373
258
 
374
- it 'halts when a conditional GET matches' do
375
- get '/', :env => { 'HTTP_IF_MODIFIED_SINCE' => @now.httpdate }
376
- assert_equal 304, status
377
- assert_equal '', body
378
- end
379
- end
259
+ describe 'content_type' do
260
+ it 'sets the Content-Type header' do
261
+ mock_app {
262
+ get '/' do
263
+ content_type 'text/plain'
264
+ 'Hello World'
265
+ end
266
+ }
267
+
268
+ get '/'
269
+ assert_equal 'text/plain', response['Content-Type']
270
+ assert_equal 'Hello World', body
271
+ end
272
+
273
+ it 'takes media type parameters (like charset=)' do
274
+ mock_app {
275
+ get '/' do
276
+ content_type 'text/html', :charset => 'utf-8'
277
+ "<h1>Hello, World</h1>"
278
+ end
279
+ }
280
+
281
+ get '/'
282
+ assert ok?
283
+ assert_equal 'text/html;charset=utf-8', response['Content-Type']
284
+ assert_equal "<h1>Hello, World</h1>", body
285
+ end
286
+
287
+ it "looks up symbols in Rack's mime types dictionary" do
288
+ Rack::Mime::MIME_TYPES['.foo'] = 'application/foo'
289
+ mock_app {
290
+ get '/foo.xml' do
291
+ content_type :foo
292
+ "I AM FOO"
293
+ end
294
+ }
295
+
296
+ get '/foo.xml'
297
+ assert ok?
298
+ assert_equal 'application/foo', response['Content-Type']
299
+ assert_equal 'I AM FOO', body
300
+ end
301
+
302
+ it 'fails when no mime type is registered for the argument provided' do
303
+ mock_app {
304
+ get '/foo.xml' do
305
+ content_type :bizzle
306
+ "I AM FOO"
307
+ end
308
+ }
380
309
 
381
- describe 'Helpers#etag' do
382
- before do
383
- mock_app {
384
- get '/' do
385
- body { 'Hello World' }
386
- etag 'FOO'
387
- 'Boo!'
388
- end
389
- }
310
+ assert_raise(RuntimeError) { get '/foo.xml' }
311
+ end
390
312
  end
391
313
 
392
- it 'sets the ETag header' do
393
- get '/'
394
- assert_equal '"FOO"', response['ETag']
395
- end
314
+ describe 'send_file' do
315
+ setup do
316
+ @file = File.dirname(__FILE__) + '/file.txt'
317
+ File.open(@file, 'wb') { |io| io.write('Hello World') }
318
+ end
396
319
 
397
- it 'returns a body when conditional get misses' do
398
- get '/'
399
- assert_equal 200, status
400
- assert_equal 'Boo!', body
401
- end
320
+ def teardown
321
+ File.unlink @file
322
+ @file = nil
323
+ end
402
324
 
403
- it 'halts when a conditional GET matches' do
404
- get '/', :env => { 'HTTP_IF_NONE_MATCH' => '"FOO"' }
405
- assert_equal 304, status
406
- assert_equal '', body
407
- end
325
+ def send_file_app(opts={})
326
+ path = @file
327
+ mock_app {
328
+ get '/file.txt' do
329
+ send_file path, opts
330
+ end
331
+ }
332
+ end
333
+
334
+ it "sends the contents of the file" do
335
+ send_file_app
336
+ get '/file.txt'
337
+ assert ok?
338
+ assert_equal 'Hello World', body
339
+ end
340
+
341
+ it 'sets the Content-Type response header if a mime-type can be located' do
342
+ send_file_app
343
+ get '/file.txt'
344
+ assert_equal 'text/plain', response['Content-Type']
345
+ end
346
+
347
+ it 'sets the Content-Length response header' do
348
+ send_file_app
349
+ get '/file.txt'
350
+ assert_equal 'Hello World'.length.to_s, response['Content-Length']
351
+ end
352
+
353
+ it 'sets the Last-Modified response header' do
354
+ send_file_app
355
+ get '/file.txt'
356
+ assert_equal File.mtime(@file).httpdate, response['Last-Modified']
357
+ end
358
+
359
+ it "returns a 404 when not found" do
360
+ mock_app {
361
+ get '/' do
362
+ send_file 'this-file-does-not-exist.txt'
363
+ end
364
+ }
365
+ get '/'
366
+ assert not_found?
367
+ end
368
+
369
+ it "does not set the Content-Disposition header by default" do
370
+ send_file_app
371
+ get '/file.txt'
372
+ assert_nil response['Content-Disposition']
373
+ end
374
+
375
+ it "sets the Content-Disposition header when :disposition set to 'attachment'" do
376
+ send_file_app :disposition => 'attachment'
377
+ get '/file.txt'
378
+ assert_equal 'attachment; filename="file.txt"', response['Content-Disposition']
379
+ end
380
+
381
+ it "sets the Content-Disposition header when :filename provided" do
382
+ send_file_app :filename => 'foo.txt'
383
+ get '/file.txt'
384
+ assert_equal 'attachment; filename="foo.txt"', response['Content-Disposition']
385
+ end
386
+ end
387
+
388
+ describe 'cache_control' do
389
+ setup do
390
+ mock_app {
391
+ get '/' do
392
+ cache_control :public, :no_cache, :max_age => 60
393
+ 'Hello World'
394
+ end
395
+ }
396
+ end
408
397
 
409
- it 'should handle multiple ETag values in If-None-Match header' do
410
- get '/', :env => { 'HTTP_IF_NONE_MATCH' => '"BAR", *' }
411
- assert_equal 304, status
412
- assert_equal '', body
398
+ it 'sets the Cache-Control header' do
399
+ get '/'
400
+ assert_equal ['public', 'no-cache', 'max-age=60'], response['Cache-Control'].split(', ')
401
+ end
413
402
  end
414
403
 
415
- it 'uses a weak etag with the :weak option' do
416
- mock_app {
417
- get '/' do
418
- etag 'FOO', :weak
419
- "that's weak, dude."
420
- end
421
- }
422
- get '/'
423
- assert_equal 'W/"FOO"', response['ETag']
404
+ describe 'expires' do
405
+ setup do
406
+ mock_app {
407
+ get '/' do
408
+ expires 60, :public, :no_cache
409
+ 'Hello World'
410
+ end
411
+ }
412
+ end
413
+
414
+ it 'sets the Cache-Control header' do
415
+ get '/'
416
+ assert_equal ['public', 'no-cache', 'max-age=60'], response['Cache-Control'].split(', ')
417
+ end
418
+
419
+ it 'sets the Expires header' do
420
+ get '/'
421
+ assert_not_nil response['Expires']
422
+ end
423
+ end
424
+
425
+ describe 'last_modified' do
426
+ setup do
427
+ now = Time.now
428
+ mock_app {
429
+ get '/' do
430
+ body { 'Hello World' }
431
+ last_modified now
432
+ 'Boo!'
433
+ end
434
+ }
435
+ @now = now
436
+ end
437
+
438
+ it 'sets the Last-Modified header to a valid RFC 2616 date value' do
439
+ get '/'
440
+ assert_equal @now.httpdate, response['Last-Modified']
441
+ end
442
+
443
+ it 'returns a body when conditional get misses' do
444
+ get '/'
445
+ assert_equal 200, status
446
+ assert_equal 'Boo!', body
447
+ end
448
+
449
+ it 'halts when a conditional GET matches' do
450
+ get '/', {}, { 'HTTP_IF_MODIFIED_SINCE' => @now.httpdate }
451
+ assert_equal 304, status
452
+ assert_equal '', body
453
+ end
454
+ end
455
+
456
+ describe 'etag' do
457
+ setup do
458
+ mock_app {
459
+ get '/' do
460
+ body { 'Hello World' }
461
+ etag 'FOO'
462
+ 'Boo!'
463
+ end
464
+ }
465
+ end
466
+
467
+ it 'sets the ETag header' do
468
+ get '/'
469
+ assert_equal '"FOO"', response['ETag']
470
+ end
471
+
472
+ it 'returns a body when conditional get misses' do
473
+ get '/'
474
+ assert_equal 200, status
475
+ assert_equal 'Boo!', body
476
+ end
477
+
478
+ it 'halts when a conditional GET matches' do
479
+ get '/', {}, { 'HTTP_IF_NONE_MATCH' => '"FOO"' }
480
+ assert_equal 304, status
481
+ assert_equal '', body
482
+ end
483
+
484
+ it 'should handle multiple ETag values in If-None-Match header' do
485
+ get '/', {}, { 'HTTP_IF_NONE_MATCH' => '"BAR", *' }
486
+ assert_equal 304, status
487
+ assert_equal '', body
488
+ end
489
+
490
+ it 'uses a weak etag with the :weak option' do
491
+ mock_app {
492
+ get '/' do
493
+ etag 'FOO', :weak
494
+ "that's weak, dude."
495
+ end
496
+ }
497
+ get '/'
498
+ assert_equal 'W/"FOO"', response['ETag']
499
+ end
424
500
  end
425
- end
426
501
 
427
- describe 'Helpers#back' do
428
- it "makes redirecting back pretty" do
429
- mock_app {
430
- get '/foo' do
431
- redirect back
432
- end
433
- }
502
+ describe 'back' do
503
+ it "makes redirecting back pretty" do
504
+ mock_app {
505
+ get '/foo' do
506
+ redirect back
507
+ end
508
+ }
434
509
 
435
- get '/foo', {}, 'HTTP_REFERER' => 'http://github.com'
436
- assert redirect?
437
- assert_equal "http://github.com", response.location
510
+ get '/foo', {}, 'HTTP_REFERER' => 'http://github.com'
511
+ assert redirect?
512
+ assert_equal "http://github.com", response.location
513
+ end
438
514
  end
439
- end
440
515
 
441
- module HelperOne; def one; '1'; end; end
442
- module HelperTwo; def two; '2'; end; end
516
+ module ::HelperOne; def one; '1'; end; end
517
+ module ::HelperTwo; def two; '2'; end; end
443
518
 
444
- describe 'Adding new helpers' do
445
- it 'takes a list of modules to mix into the app' do
446
- mock_app {
447
- helpers HelperOne, HelperTwo
519
+ describe 'Adding new helpers' do
520
+ it 'takes a list of modules to mix into the app' do
521
+ mock_app {
522
+ helpers ::HelperOne, ::HelperTwo
448
523
 
449
- get '/one' do
450
- one
451
- end
524
+ get '/one' do
525
+ one
526
+ end
452
527
 
453
- get '/two' do
454
- two
455
- end
456
- }
528
+ get '/two' do
529
+ two
530
+ end
531
+ }
457
532
 
458
- get '/one'
459
- assert_equal '1', body
533
+ get '/one'
534
+ assert_equal '1', body
460
535
 
461
- get '/two'
462
- assert_equal '2', body
463
- end
536
+ get '/two'
537
+ assert_equal '2', body
538
+ end
464
539
 
465
- it 'takes a block to mix into the app' do
466
- mock_app {
467
- helpers do
468
- def foo
469
- 'foo'
540
+ it 'takes a block to mix into the app' do
541
+ mock_app {
542
+ helpers do
543
+ def foo
544
+ 'foo'
545
+ end
470
546
  end
471
- end
472
547
 
473
- get '/' do
474
- foo
475
- end
476
- }
548
+ get '/' do
549
+ foo
550
+ end
551
+ }
477
552
 
478
- get '/'
479
- assert_equal 'foo', body
480
- end
553
+ get '/'
554
+ assert_equal 'foo', body
555
+ end
481
556
 
482
- it 'evaluates the block in class context so that methods can be aliased' do
483
- mock_app {
484
- helpers do
485
- alias_method :h, :escape_html
486
- end
557
+ it 'evaluates the block in class context so that methods can be aliased' do
558
+ mock_app {
559
+ helpers do
560
+ alias_method :h, :escape_html
561
+ end
487
562
 
488
- get '/' do
489
- h('42 < 43')
490
- end
491
- }
563
+ get '/' do
564
+ h('42 < 43')
565
+ end
566
+ }
492
567
 
493
- get '/'
494
- assert ok?
495
- assert_equal '42 &lt; 43', body
568
+ get '/'
569
+ assert ok?
570
+ assert_equal '42 &lt; 43', body
571
+ end
496
572
  end
497
573
  end