sinatra-bundles 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +20 -0
  4. data/README.md +20 -0
  5. data/Rakefile +47 -0
  6. data/VERSION +1 -0
  7. data/lib/sinatra-bundles.rb +0 -0
  8. data/lib/sinatra/bundles.rb +111 -0
  9. data/spec/app.rb +11 -0
  10. data/spec/production_app.rb +12 -0
  11. data/spec/public/javascripts/test1.js +5 -0
  12. data/spec/public/javascripts/test2.js +5 -0
  13. data/spec/public/stylesheets/test1.css +3 -0
  14. data/spec/public/stylesheets/test2.css +3 -0
  15. data/spec/sinatra-bundles_spec.rb +154 -0
  16. data/spec/spec.opts +2 -0
  17. data/spec/spec_helper.rb +17 -0
  18. data/vendor/cache/sinatra-0.10.1.gem +0 -0
  19. data/vendor/gems/sinatra-0.10.1/AUTHORS +43 -0
  20. data/vendor/gems/sinatra-0.10.1/CHANGES +467 -0
  21. data/vendor/gems/sinatra-0.10.1/LICENSE +22 -0
  22. data/vendor/gems/sinatra-0.10.1/README.jp.rdoc +552 -0
  23. data/vendor/gems/sinatra-0.10.1/README.rdoc +622 -0
  24. data/vendor/gems/sinatra-0.10.1/Rakefile +129 -0
  25. data/vendor/gems/sinatra-0.10.1/lib/sinatra.rb +7 -0
  26. data/vendor/gems/sinatra-0.10.1/lib/sinatra/base.rb +1143 -0
  27. data/vendor/gems/sinatra-0.10.1/lib/sinatra/images/404.png +0 -0
  28. data/vendor/gems/sinatra-0.10.1/lib/sinatra/images/500.png +0 -0
  29. data/vendor/gems/sinatra-0.10.1/lib/sinatra/main.rb +28 -0
  30. data/vendor/gems/sinatra-0.10.1/lib/sinatra/showexceptions.rb +303 -0
  31. data/vendor/gems/sinatra-0.10.1/lib/sinatra/tilt.rb +509 -0
  32. data/vendor/gems/sinatra-0.10.1/sinatra.gemspec +86 -0
  33. data/vendor/gems/sinatra-0.10.1/test/base_test.rb +160 -0
  34. data/vendor/gems/sinatra-0.10.1/test/builder_test.rb +65 -0
  35. data/vendor/gems/sinatra-0.10.1/test/contest.rb +64 -0
  36. data/vendor/gems/sinatra-0.10.1/test/erb_test.rb +81 -0
  37. data/vendor/gems/sinatra-0.10.1/test/erubis_test.rb +82 -0
  38. data/vendor/gems/sinatra-0.10.1/test/extensions_test.rb +100 -0
  39. data/vendor/gems/sinatra-0.10.1/test/filter_test.rb +195 -0
  40. data/vendor/gems/sinatra-0.10.1/test/haml_test.rb +90 -0
  41. data/vendor/gems/sinatra-0.10.1/test/helper.rb +76 -0
  42. data/vendor/gems/sinatra-0.10.1/test/helpers_test.rb +573 -0
  43. data/vendor/gems/sinatra-0.10.1/test/mapped_error_test.rb +186 -0
  44. data/vendor/gems/sinatra-0.10.1/test/middleware_test.rb +68 -0
  45. data/vendor/gems/sinatra-0.10.1/test/request_test.rb +33 -0
  46. data/vendor/gems/sinatra-0.10.1/test/response_test.rb +42 -0
  47. data/vendor/gems/sinatra-0.10.1/test/result_test.rb +98 -0
  48. data/vendor/gems/sinatra-0.10.1/test/route_added_hook_test.rb +59 -0
  49. data/vendor/gems/sinatra-0.10.1/test/routing_test.rb +878 -0
  50. data/vendor/gems/sinatra-0.10.1/test/sass_test.rb +79 -0
  51. data/vendor/gems/sinatra-0.10.1/test/server_test.rb +47 -0
  52. data/vendor/gems/sinatra-0.10.1/test/sinatra_test.rb +13 -0
  53. data/vendor/gems/sinatra-0.10.1/test/static_test.rb +87 -0
  54. data/vendor/gems/sinatra-0.10.1/test/templates_test.rb +155 -0
  55. data/vendor/gems/sinatra-0.10.1/test/views/error.builder +3 -0
  56. data/vendor/gems/sinatra-0.10.1/test/views/error.erb +3 -0
  57. data/vendor/gems/sinatra-0.10.1/test/views/error.erubis +3 -0
  58. data/vendor/gems/sinatra-0.10.1/test/views/error.haml +3 -0
  59. data/vendor/gems/sinatra-0.10.1/test/views/error.sass +2 -0
  60. data/vendor/gems/sinatra-0.10.1/test/views/foo/hello.test +1 -0
  61. data/vendor/gems/sinatra-0.10.1/test/views/hello.builder +1 -0
  62. data/vendor/gems/sinatra-0.10.1/test/views/hello.erb +1 -0
  63. data/vendor/gems/sinatra-0.10.1/test/views/hello.erubis +1 -0
  64. data/vendor/gems/sinatra-0.10.1/test/views/hello.haml +1 -0
  65. data/vendor/gems/sinatra-0.10.1/test/views/hello.sass +2 -0
  66. data/vendor/gems/sinatra-0.10.1/test/views/hello.test +1 -0
  67. data/vendor/gems/sinatra-0.10.1/test/views/layout2.builder +3 -0
  68. data/vendor/gems/sinatra-0.10.1/test/views/layout2.erb +2 -0
  69. data/vendor/gems/sinatra-0.10.1/test/views/layout2.erubis +2 -0
  70. data/vendor/gems/sinatra-0.10.1/test/views/layout2.haml +2 -0
  71. data/vendor/gems/sinatra-0.10.1/test/views/layout2.test +1 -0
  72. data/vendor/specifications/sinatra-0.10.1.gemspec +40 -0
  73. metadata +169 -0
@@ -0,0 +1,76 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+
3
+ begin
4
+ require 'rack'
5
+ rescue LoadError
6
+ require 'rubygems'
7
+ require 'rack'
8
+ end
9
+
10
+ testdir = File.dirname(__FILE__)
11
+ $LOAD_PATH.unshift testdir unless $LOAD_PATH.include?(testdir)
12
+
13
+ libdir = File.dirname(File.dirname(__FILE__)) + '/lib'
14
+ $LOAD_PATH.unshift libdir unless $LOAD_PATH.include?(libdir)
15
+
16
+ require 'contest'
17
+ require 'rack/test'
18
+ require 'sinatra/base'
19
+
20
+ class Sinatra::Base
21
+ # Allow assertions in request context
22
+ include Test::Unit::Assertions
23
+ end
24
+
25
+ Sinatra::Base.set :environment, :test
26
+
27
+ class Test::Unit::TestCase
28
+ include Rack::Test::Methods
29
+
30
+ class << self
31
+ alias_method :it, :test
32
+ end
33
+
34
+ alias_method :response, :last_response
35
+
36
+ setup do
37
+ Sinatra::Base.set :environment, :test
38
+ end
39
+
40
+ # Sets up a Sinatra::Base subclass defined with the block
41
+ # given. Used in setup or individual spec methods to establish
42
+ # the application.
43
+ def mock_app(base=Sinatra::Base, &block)
44
+ @app = Sinatra.new(base, &block)
45
+ end
46
+
47
+ def app
48
+ Rack::Lint.new(@app)
49
+ end
50
+
51
+ def body
52
+ response.body.to_s
53
+ end
54
+
55
+ # Delegate other missing methods to response.
56
+ def method_missing(name, *args, &block)
57
+ if response && response.respond_to?(name)
58
+ response.send(name, *args, &block)
59
+ else
60
+ super
61
+ end
62
+ end
63
+
64
+ # Also check response since we delegate there.
65
+ def respond_to?(symbol, include_private=false)
66
+ super || (response && response.respond_to?(symbol, include_private))
67
+ end
68
+
69
+ # Do not output warnings for the duration of the block.
70
+ def silence_warnings
71
+ $VERBOSE, v = nil, $VERBOSE
72
+ yield
73
+ ensure
74
+ $VERBOSE = v
75
+ end
76
+ end
@@ -0,0 +1,573 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class HelpersTest < Test::Unit::TestCase
4
+ def test_default
5
+ assert true
6
+ end
7
+
8
+ describe 'status' do
9
+ setup do
10
+ mock_app {
11
+ get '/' do
12
+ status 207
13
+ nil
14
+ end
15
+ }
16
+ end
17
+
18
+ it 'sets the response status code' do
19
+ get '/'
20
+ assert_equal 207, response.status
21
+ end
22
+ end
23
+
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
+ }
31
+
32
+ get '/'
33
+ assert_equal 'Hello World', body
34
+ end
35
+
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
+ }
42
+
43
+ get '/'
44
+ assert_equal 'Hello World', body
45
+ end
46
+ end
47
+
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
+ }
83
+
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
89
+ end
90
+
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
+ }
125
+
126
+ get '/'
127
+ assert_equal 500, status
128
+ assert_equal 'FAIL', body
129
+ end
130
+ end
131
+
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
+ }
153
+
154
+ get '/'
155
+ assert_equal 404, status
156
+ assert_equal nil, response.headers['X-Cascade']
157
+ end
158
+ end
159
+
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
+ }
183
+
184
+ get '/'
185
+ assert ok?
186
+ assert_equal 'bar', response['X-Foo']
187
+ end
188
+ end
189
+
190
+ describe 'session' do
191
+ it 'uses the existing rack.session' do
192
+ mock_app {
193
+ get '/' do
194
+ session[:foo]
195
+ end
196
+ }
197
+
198
+ get '/', {}, { 'rack.session' => { :foo => 'bar' } }
199
+ assert_equal 'bar', body
200
+ end
201
+
202
+ it 'creates a new session when none provided' do
203
+ mock_app {
204
+ enable :sessions
205
+
206
+ get '/' do
207
+ assert session.empty?
208
+ session[:foo] = 'bar'
209
+ redirect '/hi'
210
+ end
211
+
212
+ get '/hi' do
213
+ "hi #{session[:foo]}"
214
+ end
215
+ }
216
+
217
+ get '/'
218
+ follow_redirect!
219
+ assert_equal 'hi bar', body
220
+ end
221
+ end
222
+
223
+ describe 'mime_type' do
224
+ include Sinatra::Helpers
225
+
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
232
+
233
+ it 'returns nil when given nil' do
234
+ assert mime_type(nil).nil?
235
+ end
236
+
237
+ it 'returns nil when media type not registered' do
238
+ assert mime_type(:bizzle).nil?
239
+ end
240
+
241
+ it 'returns the argument when given a media type string' do
242
+ assert_equal 'text/plain', mime_type('text/plain')
243
+ end
244
+ end
245
+
246
+ test 'Base.mime_type registers mime type' do
247
+ mock_app {
248
+ mime_type :foo, 'application/foo'
249
+
250
+ get '/' do
251
+ "foo is #{mime_type(:foo)}"
252
+ end
253
+ }
254
+
255
+ get '/'
256
+ assert_equal 'foo is application/foo', body
257
+ end
258
+
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
+ }
309
+
310
+ assert_raise(RuntimeError) { get '/foo.xml' }
311
+ end
312
+ end
313
+
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
319
+
320
+ def teardown
321
+ File.unlink @file
322
+ @file = nil
323
+ end
324
+
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
397
+
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
402
+ end
403
+
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
500
+ end
501
+
502
+ describe 'back' do
503
+ it "makes redirecting back pretty" do
504
+ mock_app {
505
+ get '/foo' do
506
+ redirect back
507
+ end
508
+ }
509
+
510
+ get '/foo', {}, 'HTTP_REFERER' => 'http://github.com'
511
+ assert redirect?
512
+ assert_equal "http://github.com", response.location
513
+ end
514
+ end
515
+
516
+ module ::HelperOne; def one; '1'; end; end
517
+ module ::HelperTwo; def two; '2'; end; end
518
+
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
523
+
524
+ get '/one' do
525
+ one
526
+ end
527
+
528
+ get '/two' do
529
+ two
530
+ end
531
+ }
532
+
533
+ get '/one'
534
+ assert_equal '1', body
535
+
536
+ get '/two'
537
+ assert_equal '2', body
538
+ end
539
+
540
+ it 'takes a block to mix into the app' do
541
+ mock_app {
542
+ helpers do
543
+ def foo
544
+ 'foo'
545
+ end
546
+ end
547
+
548
+ get '/' do
549
+ foo
550
+ end
551
+ }
552
+
553
+ get '/'
554
+ assert_equal 'foo', body
555
+ end
556
+
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
562
+
563
+ get '/' do
564
+ h('42 < 43')
565
+ end
566
+ }
567
+
568
+ get '/'
569
+ assert ok?
570
+ assert_equal '42 &lt; 43', body
571
+ end
572
+ end
573
+ end