sinatra-sinatra 0.9.1.2 → 0.9.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
2
 
3
- describe "Builder Templates" do
3
+ class BuilderTest < Test::Unit::TestCase
4
4
  def builder_app(&block)
5
5
  mock_app {
6
6
  set :views, File.dirname(__FILE__) + '/views'
@@ -0,0 +1,62 @@
1
+ require "test/unit"
2
+
3
+ # Test::Unit loads a default test if the suite is empty, and the only
4
+ # purpose of that test is to fail. As having empty contexts is a common
5
+ # practice, we decided to overwrite TestSuite#empty? in order to
6
+ # allow them. Having a failure when no tests have been defined seems
7
+ # counter-intuitive.
8
+ class Test::Unit::TestSuite
9
+ def empty?
10
+ false
11
+ end
12
+ end
13
+
14
+ # We added setup, test and context as class methods, and the instance
15
+ # method setup now iterates on the setup blocks. Note that all setup
16
+ # blocks must be defined with the block syntax. Adding a setup instance
17
+ # method defeats the purpose of this library.
18
+ class Test::Unit::TestCase
19
+ def self.setup(&block)
20
+ setup_blocks << block
21
+ end
22
+
23
+ def setup
24
+ self.class.setup_blocks.each do |block|
25
+ instance_eval(&block)
26
+ end
27
+ end
28
+
29
+ def self.context(name, &block)
30
+ subclass = Class.new(self.superclass)
31
+ subclass.setup_blocks.unshift(*setup_blocks)
32
+ subclass.class_eval(&block)
33
+ const_set(context_name(name), subclass)
34
+ end
35
+
36
+ def self.test(name, &block)
37
+ define_method(test_name(name), &block)
38
+ end
39
+
40
+ class << self
41
+ alias_method :should, :test
42
+ alias_method :describe, :context
43
+ end
44
+
45
+ private
46
+
47
+ def self.setup_blocks
48
+ @setup_blocks ||= []
49
+ end
50
+
51
+ def self.context_name(name)
52
+ "Test#{sanitize_name(name).gsub(/(^| )(\w)/) { $2.upcase }}".to_sym
53
+ end
54
+
55
+ def self.test_name(name)
56
+ "test_#{sanitize_name(name).gsub(/\s+/,'_')}".to_sym
57
+ end
58
+
59
+ def self.sanitize_name(name)
60
+ name.gsub(/\W+/, ' ').strip
61
+ end
62
+ end
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
2
 
3
- describe "ERB Templates" do
3
+ class ERBTest < Test::Unit::TestCase
4
4
  def erb_app(&block)
5
5
  mock_app {
6
6
  set :views, File.dirname(__FILE__) + '/views'
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
2
 
3
- describe 'Registering extensions' do
3
+ class ExtensionsTest < Test::Unit::TestCase
4
4
  module FooExtensions
5
5
  def foo
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
2
 
3
- describe "Filters" do
3
+ class FilterTest < Test::Unit::TestCase
4
4
  it "executes filters in the order defined" do
5
5
  count = 0
6
6
  mock_app do
@@ -1,6 +1,7 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
+ require 'haml'
2
3
 
3
- describe "HAML Templates" do
4
+ class HAMLTest < Test::Unit::TestCase
4
5
  def haml_app(&block)
5
6
  mock_app {
6
7
  set :views, File.dirname(__FILE__) + '/views'
@@ -47,9 +48,12 @@ describe "HAML Templates" do
47
48
  end
48
49
 
49
50
  it "passes HAML options to the Haml engine" do
50
- haml_app {
51
- haml "!!!\n%h1 Hello World", :options => {:format => :html5}
51
+ mock_app {
52
+ get '/' do
53
+ haml "!!!\n%h1 Hello World", :format => :html5
54
+ end
52
55
  }
56
+ get '/'
53
57
  assert ok?
54
58
  assert_equal "<!DOCTYPE html>\n<h1>Hello World</h1>\n", body
55
59
  end
@@ -65,4 +69,22 @@ describe "HAML Templates" do
65
69
  assert ok?
66
70
  assert_equal "<!DOCTYPE html>\n<h1>Hello World</h1>\n", body
67
71
  end
72
+
73
+ it "merges the default HAML options with the overrides and passes them to the Haml engine" do
74
+ mock_app {
75
+ set :haml, {:format => :html5, :attr_wrapper => '"'} # default HAML attr are <tag attr='single-quoted'>
76
+ get '/' do
77
+ haml "!!!\n%h1{:class => :header} Hello World"
78
+ end
79
+ get '/html4' do
80
+ haml "!!!\n%h1{:class => 'header'} Hello World", :format => :html4
81
+ end
82
+ }
83
+ get '/'
84
+ assert ok?
85
+ assert_equal "<!DOCTYPE html>\n<h1 class=\"header\">Hello World</h1>\n", body
86
+ get '/html4'
87
+ assert ok?
88
+ assert_match(/^<!DOCTYPE html PUBLIC (.*) HTML 4.01/, body)
89
+ end
68
90
  end
@@ -5,71 +5,39 @@ rescue LoadError
5
5
  require 'rack'
6
6
  end
7
7
 
8
+ testdir = File.dirname(__FILE__)
9
+ $LOAD_PATH.unshift testdir unless $LOAD_PATH.include?(testdir)
10
+
8
11
  libdir = File.dirname(File.dirname(__FILE__)) + '/lib'
9
12
  $LOAD_PATH.unshift libdir unless $LOAD_PATH.include?(libdir)
10
13
 
11
- require 'test/unit'
14
+ require 'contest'
12
15
  require 'sinatra/test'
13
16
 
17
+ require 'haml'
18
+ require 'sass'
19
+ require 'builder'
20
+
14
21
  class Sinatra::Base
15
22
  # Allow assertions in request context
16
23
  include Test::Unit::Assertions
17
24
  end
18
25
 
26
+ Sinatra::Base.set :environment, :test
27
+
19
28
  class Test::Unit::TestCase
20
29
  include Sinatra::Test
21
30
 
31
+ class << self
32
+ alias_method :it, :test
33
+ end
34
+
22
35
  # Sets up a Sinatra::Base subclass defined with the block
23
36
  # given. Used in setup or individual spec methods to establish
24
37
  # the application.
25
38
  def mock_app(base=Sinatra::Base, &block)
26
39
  @app = Sinatra.new(base, &block)
27
40
  end
28
-
29
- def restore_default_options
30
- Sinatra::Default.set(
31
- :environment => :development,
32
- :raise_errors => Proc.new { test? },
33
- :dump_errors => true,
34
- :sessions => false,
35
- :logging => Proc.new { ! test? },
36
- :methodoverride => true,
37
- :static => true,
38
- :run => Proc.new { ! test? }
39
- )
40
- end
41
- end
42
-
43
- ##
44
- # test/spec/mini
45
- # http://pastie.caboo.se/158871
46
- # chris@ozmm.org
47
- #
48
- def describe(*args, &block)
49
- return super unless (name = args.first.capitalize) && block
50
- name = "#{name.gsub(/\W/, '')}Test"
51
- Object.send :const_set, name, Class.new(Test::Unit::TestCase)
52
- klass = Object.const_get(name)
53
- klass.class_eval do
54
- def self.it(name, &block)
55
- define_method("test_#{name.gsub(/\W/,'_').downcase}", &block)
56
- end
57
- def self.xspecify(*args) end
58
- def self.before(&block) define_method(:setup, &block) end
59
- def self.after(&block) define_method(:teardown, &block) end
60
- end
61
- klass.class_eval &block
62
- klass
63
- end
64
-
65
- def describe_option(name, &block)
66
- klass = describe("Option #{name}", &block)
67
- klass.before do
68
- restore_default_options
69
- @base = Sinatra.new
70
- @default = Class.new(Sinatra::Default)
71
- end
72
- klass
73
41
  end
74
42
 
75
43
  # Do not output warnings for the duration of the block.
@@ -1,497 +1,499 @@
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
99
- end
100
-
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
- }
151
-
152
- get '/'
153
- assert ok?
154
- assert_equal 'bar', response['X-Foo']
155
- assert_equal 'bling', response['X-Baz']
156
- assert_equal 'kthx', body
157
- end
158
-
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
- }
166
-
167
- get '/'
168
- assert ok?
169
- assert_equal 'bar', response['X-Foo']
170
- end
171
- end
172
-
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
- }
180
-
181
- get '/', :env => { 'rack.session' => { :foo => 'bar' } }
182
- assert_equal 'bar', body
183
- end
184
-
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
- }
193
-
194
- get '/'
195
- assert_equal 'Hi', body
196
- end
197
- end
198
-
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
208
-
209
- it 'returns nil when given nil' do
210
- assert media_type(nil).nil?
211
- end
212
-
213
- it 'returns nil when media type not registered' do
214
- assert media_type(:bizzle).nil?
215
- end
3
+ class HelpersTest < Test::Unit::TestCase
4
+ describe 'status' do
5
+ setup do
6
+ mock_app {
7
+ get '/' do
8
+ status 207
9
+ nil
10
+ end
11
+ }
12
+ end
216
13
 
217
- it 'returns the argument when given a media type string' do
218
- assert_equal 'text/plain', media_type('text/plain')
14
+ it 'sets the response status code' do
15
+ get '/'
16
+ assert_equal 207, response.status
17
+ end
219
18
  end
220
- end
221
19
 
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
- }
230
-
231
- get '/'
232
- assert_equal 'text/plain', response['Content-Type']
233
- assert_equal 'Hello World', body
234
- end
20
+ describe 'body' do
21
+ it 'takes a block for defered body generation' do
22
+ mock_app {
23
+ get '/' do
24
+ body { 'Hello World' }
25
+ end
26
+ }
235
27
 
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
28
+ get '/'
29
+ assert_equal 'Hello World', body
30
+ end
249
31
 
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
- }
258
-
259
- get '/foo.xml'
260
- assert ok?
261
- assert_equal 'application/foo', response['Content-Type']
262
- assert_equal 'I AM FOO', body
263
- end
32
+ it 'takes a String, Array, or other object responding to #each' do
33
+ mock_app {
34
+ get '/' do
35
+ body 'Hello World'
36
+ end
37
+ }
264
38
 
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' }
39
+ get '/'
40
+ assert_equal 'Hello World', body
41
+ end
273
42
  end
274
- end
275
43
 
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
44
+ describe 'redirect' do
45
+ it 'uses a 302 when only a path is given' do
46
+ mock_app {
47
+ get '/' do
48
+ redirect '/foo'
49
+ fail 'redirect should halt'
50
+ end
51
+ }
52
+
53
+ get '/'
54
+ assert_equal 302, status
55
+ assert_equal '', body
56
+ assert_equal '/foo', response['Location']
57
+ end
58
+
59
+ it 'uses the code given when specified' do
60
+ mock_app {
61
+ get '/' do
62
+ redirect '/foo', 301
63
+ fail 'redirect should halt'
64
+ end
65
+ }
66
+
67
+ get '/'
68
+ assert_equal 301, status
69
+ assert_equal '', body
70
+ assert_equal '/foo', response['Location']
71
+ end
72
+
73
+ it 'redirects back to request.referer when passed back' do
74
+ mock_app {
75
+ get '/try_redirect' do
76
+ redirect back
77
+ end
78
+ }
281
79
 
282
- after do
283
- File.unlink @file
284
- @file = nil
80
+ request = Rack::MockRequest.new(@app)
81
+ response = request.get('/try_redirect', 'HTTP_REFERER' => '/foo')
82
+ assert_equal 302, response.status
83
+ assert_equal '/foo', response['Location']
84
+ end
285
85
  end
286
86
 
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
87
+ describe '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
99
+ end
100
+
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
+ }
295
121
 
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
122
+ get '/'
123
+ assert_equal 500, status
124
+ assert_equal 'FAIL', body
125
+ end
301
126
  end
302
127
 
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
128
+ describe '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
+ }
308
136
 
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']
137
+ get '/'
138
+ assert_equal 404, status
139
+ assert_equal '', body
140
+ end
313
141
  end
314
142
 
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']
319
- end
143
+ describe '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
+ }
151
+
152
+ get '/'
153
+ assert ok?
154
+ assert_equal 'bar', response['X-Foo']
155
+ assert_equal 'bling', response['X-Baz']
156
+ assert_equal 'kthx', body
157
+ end
158
+
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
+ }
320
166
 
321
- it "returns a 404 when not found" do
322
- mock_app {
323
- get '/' do
324
- send_file 'this-file-does-not-exist.txt'
325
- end
326
- }
327
- get '/'
328
- assert not_found?
167
+ get '/'
168
+ assert ok?
169
+ assert_equal 'bar', response['X-Foo']
170
+ end
329
171
  end
330
172
 
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
173
+ describe 'session' do
174
+ it 'uses the existing rack.session' do
175
+ mock_app {
176
+ get '/' do
177
+ session[:foo]
178
+ end
179
+ }
180
+
181
+ get '/', :env => { 'rack.session' => { :foo => 'bar' } }
182
+ assert_equal 'bar', body
183
+ end
184
+
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
+ }
336
193
 
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']
194
+ get '/'
195
+ assert_equal 'Hi', body
196
+ end
341
197
  end
342
198
 
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
199
+ describe 'media_type' do
200
+ include Sinatra::Helpers
349
201
 
350
- describe 'Helpers#last_modified' do
351
- before do
352
- now = Time.now
353
- mock_app {
354
- get '/' do
355
- body { 'Hello World' }
356
- last_modified now
357
- 'Boo!'
358
- end
359
- }
360
- @now = now
361
- end
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
362
208
 
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
209
+ it 'returns nil when given nil' do
210
+ assert media_type(nil).nil?
211
+ end
367
212
 
368
- it 'returns a body when conditional get misses' do
369
- get '/'
370
- assert_equal 200, status
371
- assert_equal 'Boo!', body
372
- end
213
+ it 'returns nil when media type not registered' do
214
+ assert media_type(:bizzle).nil?
215
+ end
373
216
 
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
217
+ it 'returns the argument when given a media type string' do
218
+ assert_equal 'text/plain', media_type('text/plain')
219
+ end
378
220
  end
379
- end
380
221
 
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
- }
390
- end
222
+ describe '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
+ }
230
+
231
+ get '/'
232
+ assert_equal 'text/plain', response['Content-Type']
233
+ assert_equal 'Hello World', body
234
+ end
235
+
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
249
+
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
+ }
258
+
259
+ get '/foo.xml'
260
+ assert ok?
261
+ assert_equal 'application/foo', response['Content-Type']
262
+ assert_equal 'I AM FOO', body
263
+ end
264
+
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
+ }
391
272
 
392
- it 'sets the ETag header' do
393
- get '/'
394
- assert_equal '"FOO"', response['ETag']
273
+ assert_raise(RuntimeError) { get '/foo.xml' }
274
+ end
395
275
  end
396
276
 
397
- it 'returns a body when conditional get misses' do
398
- get '/'
399
- assert_equal 200, status
400
- assert_equal 'Boo!', body
401
- end
277
+ describe 'send_file' do
278
+ setup do
279
+ @file = File.dirname(__FILE__) + '/file.txt'
280
+ File.open(@file, 'wb') { |io| io.write('Hello World') }
281
+ end
402
282
 
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
283
+ def teardown
284
+ File.unlink @file
285
+ @file = nil
286
+ end
408
287
 
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
288
+ def send_file_app(opts={})
289
+ path = @file
290
+ mock_app {
291
+ get '/file.txt' do
292
+ send_file path, opts
293
+ end
294
+ }
295
+ end
296
+
297
+ it "sends the contents of the file" do
298
+ send_file_app
299
+ get '/file.txt'
300
+ assert ok?
301
+ assert_equal 'Hello World', body
302
+ end
303
+
304
+ it 'sets the Content-Type response header if a mime-type can be located' do
305
+ send_file_app
306
+ get '/file.txt'
307
+ assert_equal 'text/plain', response['Content-Type']
308
+ end
309
+
310
+ it 'sets the Content-Length response header' do
311
+ send_file_app
312
+ get '/file.txt'
313
+ assert_equal 'Hello World'.length.to_s, response['Content-Length']
314
+ end
315
+
316
+ it 'sets the Last-Modified response header' do
317
+ send_file_app
318
+ get '/file.txt'
319
+ assert_equal File.mtime(@file).httpdate, response['Last-Modified']
320
+ end
321
+
322
+ it "returns a 404 when not found" do
323
+ mock_app {
324
+ get '/' do
325
+ send_file 'this-file-does-not-exist.txt'
326
+ end
327
+ }
328
+ get '/'
329
+ assert not_found?
330
+ end
331
+
332
+ it "does not set the Content-Disposition header by default" do
333
+ send_file_app
334
+ get '/file.txt'
335
+ assert_nil response['Content-Disposition']
336
+ end
337
+
338
+ it "sets the Content-Disposition header when :disposition set to 'attachment'" do
339
+ send_file_app :disposition => 'attachment'
340
+ get '/file.txt'
341
+ assert_equal 'attachment; filename="file.txt"', response['Content-Disposition']
342
+ end
343
+
344
+ it "sets the Content-Disposition header when :filename provided" do
345
+ send_file_app :filename => 'foo.txt'
346
+ get '/file.txt'
347
+ assert_equal 'attachment; filename="foo.txt"', response['Content-Disposition']
348
+ end
349
+ end
350
+
351
+ describe 'last_modified' do
352
+ setup do
353
+ now = Time.now
354
+ mock_app {
355
+ get '/' do
356
+ body { 'Hello World' }
357
+ last_modified now
358
+ 'Boo!'
359
+ end
360
+ }
361
+ @now = now
362
+ end
363
+
364
+ it 'sets the Last-Modified header to a valid RFC 2616 date value' do
365
+ get '/'
366
+ assert_equal @now.httpdate, response['Last-Modified']
367
+ end
368
+
369
+ it 'returns a body when conditional get misses' do
370
+ get '/'
371
+ assert_equal 200, status
372
+ assert_equal 'Boo!', body
373
+ end
374
+
375
+ it 'halts when a conditional GET matches' do
376
+ get '/', :env => { 'HTTP_IF_MODIFIED_SINCE' => @now.httpdate }
377
+ assert_equal 304, status
378
+ assert_equal '', body
379
+ end
380
+ end
381
+
382
+ describe 'etag' do
383
+ setup do
384
+ mock_app {
385
+ get '/' do
386
+ body { 'Hello World' }
387
+ etag 'FOO'
388
+ 'Boo!'
389
+ end
390
+ }
391
+ end
392
+
393
+ it 'sets the ETag header' do
394
+ get '/'
395
+ assert_equal '"FOO"', response['ETag']
396
+ end
397
+
398
+ it 'returns a body when conditional get misses' do
399
+ get '/'
400
+ assert_equal 200, status
401
+ assert_equal 'Boo!', body
402
+ end
403
+
404
+ it 'halts when a conditional GET matches' do
405
+ get '/', :env => { 'HTTP_IF_NONE_MATCH' => '"FOO"' }
406
+ assert_equal 304, status
407
+ assert_equal '', body
408
+ end
409
+
410
+ it 'should handle multiple ETag values in If-None-Match header' do
411
+ get '/', :env => { 'HTTP_IF_NONE_MATCH' => '"BAR", *' }
412
+ assert_equal 304, status
413
+ assert_equal '', body
414
+ end
415
+
416
+ it 'uses a weak etag with the :weak option' do
417
+ mock_app {
418
+ get '/' do
419
+ etag 'FOO', :weak
420
+ "that's weak, dude."
421
+ end
422
+ }
423
+ get '/'
424
+ assert_equal 'W/"FOO"', response['ETag']
425
+ end
413
426
  end
414
427
 
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']
424
- end
425
- end
428
+ describe 'back' do
429
+ it "makes redirecting back pretty" do
430
+ mock_app {
431
+ get '/foo' do
432
+ redirect back
433
+ end
434
+ }
426
435
 
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
- }
434
-
435
- get '/foo', {}, 'HTTP_REFERER' => 'http://github.com'
436
- assert redirect?
437
- assert_equal "http://github.com", response.location
436
+ get '/foo', {}, 'HTTP_REFERER' => 'http://github.com'
437
+ assert redirect?
438
+ assert_equal "http://github.com", response.location
439
+ end
438
440
  end
439
- end
440
441
 
441
- module HelperOne; def one; '1'; end; end
442
- module HelperTwo; def two; '2'; end; end
442
+ module ::HelperOne; def one; '1'; end; end
443
+ module ::HelperTwo; def two; '2'; end; end
443
444
 
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
445
+ describe 'Adding new helpers' do
446
+ it 'takes a list of modules to mix into the app' do
447
+ mock_app {
448
+ helpers ::HelperOne, ::HelperTwo
448
449
 
449
- get '/one' do
450
- one
451
- end
450
+ get '/one' do
451
+ one
452
+ end
452
453
 
453
- get '/two' do
454
- two
455
- end
456
- }
454
+ get '/two' do
455
+ two
456
+ end
457
+ }
457
458
 
458
- get '/one'
459
- assert_equal '1', body
459
+ get '/one'
460
+ assert_equal '1', body
460
461
 
461
- get '/two'
462
- assert_equal '2', body
463
- end
462
+ get '/two'
463
+ assert_equal '2', body
464
+ end
464
465
 
465
- it 'takes a block to mix into the app' do
466
- mock_app {
467
- helpers do
468
- def foo
469
- 'foo'
466
+ it 'takes a block to mix into the app' do
467
+ mock_app {
468
+ helpers do
469
+ def foo
470
+ 'foo'
471
+ end
470
472
  end
471
- end
472
473
 
473
- get '/' do
474
- foo
475
- end
476
- }
474
+ get '/' do
475
+ foo
476
+ end
477
+ }
477
478
 
478
- get '/'
479
- assert_equal 'foo', body
480
- end
479
+ get '/'
480
+ assert_equal 'foo', body
481
+ end
481
482
 
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
483
+ it 'evaluates the block in class context so that methods can be aliased' do
484
+ mock_app {
485
+ helpers do
486
+ alias_method :h, :escape_html
487
+ end
487
488
 
488
- get '/' do
489
- h('42 < 43')
490
- end
491
- }
489
+ get '/' do
490
+ h('42 < 43')
491
+ end
492
+ }
492
493
 
493
- get '/'
494
- assert ok?
495
- assert_equal '42 &lt; 43', body
494
+ get '/'
495
+ assert ok?
496
+ assert_equal '42 &lt; 43', body
497
+ end
496
498
  end
497
499
  end