sinatra-sinatra 0.9.0.4 → 0.9.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/sinatra/test.rb CHANGED
@@ -7,7 +7,7 @@ module Sinatra
7
7
 
8
8
  attr_reader :app, :request, :response
9
9
 
10
- def test_request(verb, path, *args)
10
+ def make_request(verb, path, *args)
11
11
  @app = Sinatra::Application if @app.nil? && defined?(Sinatra::Application)
12
12
  fail "@app not set - cannot make request" if @app.nil?
13
13
  @request = Rack::MockRequest.new(@app)
@@ -38,14 +38,14 @@ module Sinatra
38
38
  @response = @request.request(verb, path, opts)
39
39
  end
40
40
 
41
- def get(path, *args, &b) ; test_request('GET', path, *args, &b) ; end
42
- def head(path, *args, &b) ; test_request('HEAD', path, *args, &b) ; end
43
- def post(path, *args, &b) ; test_request('POST', path, *args, &b) ; end
44
- def put(path, *args, &b) ; test_request('PUT', path, *args, &b) ; end
45
- def delete(path, *args, &b) ; test_request('DELETE', path, *args, &b) ; end
41
+ def get(path, *args, &b) ; make_request('GET', path, *args, &b) ; end
42
+ def head(path, *args, &b) ; make_request('HEAD', path, *args, &b) ; end
43
+ def post(path, *args, &b) ; make_request('POST', path, *args, &b) ; end
44
+ def put(path, *args, &b) ; make_request('PUT', path, *args, &b) ; end
45
+ def delete(path, *args, &b) ; make_request('DELETE', path, *args, &b) ; end
46
46
 
47
47
  def follow!
48
- test_request 'GET', @response.location
48
+ make_request 'GET', @response.location
49
49
  end
50
50
 
51
51
  def body ; @response.body ; end
@@ -65,6 +65,8 @@ module Sinatra
65
65
  super || (@response && @response.respond_to?(symbol, include_private))
66
66
  end
67
67
 
68
+ private
69
+
68
70
  RACK_OPT_NAMES = {
69
71
  :accept => "HTTP_ACCEPT",
70
72
  :agent => "HTTP_USER_AGENT",
@@ -103,7 +105,7 @@ module Sinatra
103
105
  eval <<-RUBY, binding, __FILE__, __LINE__
104
106
  def #{verb}_it(*args, &block)
105
107
  sinatra_warn "The #{verb}_it method is deprecated; use #{verb} instead."
106
- test_request('#{verb.upcase}', *args, &block)
108
+ make_request('#{verb.upcase}', *args, &block)
107
109
  end
108
110
  RUBY
109
111
  end
data/sinatra.gemspec CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
3
3
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
4
 
5
5
  s.name = 'sinatra'
6
- s.version = '0.9.0.4'
7
- s.date = '2009-01-25'
6
+ s.version = '0.9.0.5'
7
+ s.date = '2009-02-10'
8
8
 
9
9
  s.description = "Classy web-development dressed in a DSL"
10
10
  s.summary = "Classy web-development dressed in a DSL"
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
22
22
  compat/app_test.rb
23
23
  compat/application_test.rb
24
24
  compat/builder_test.rb
25
+ compat/compat_test.rb
25
26
  compat/custom_error_test.rb
26
27
  compat/erb_test.rb
27
28
  compat/events_test.rb
@@ -69,6 +70,7 @@ Gem::Specification.new do |s|
69
70
  test/builder_test.rb
70
71
  test/data/reload_app_file.rb
71
72
  test/erb_test.rb
73
+ test/extensions_test.rb
72
74
  test/filter_test.rb
73
75
  test/haml_test.rb
74
76
  test/helper.rb
@@ -78,12 +80,15 @@ Gem::Specification.new do |s|
78
80
  test/options_test.rb
79
81
  test/reload_test.rb
80
82
  test/request_test.rb
83
+ test/response_test.rb
81
84
  test/result_test.rb
82
85
  test/routing_test.rb
83
86
  test/sass_test.rb
87
+ test/server_test.rb
84
88
  test/sinatra_test.rb
85
89
  test/static_test.rb
86
90
  test/templates_test.rb
91
+ test/test_test.rb
87
92
  test/views/hello.builder
88
93
  test/views/hello.erb
89
94
  test/views/hello.haml
data/test/base_test.rb CHANGED
@@ -65,4 +65,17 @@ describe 'Sinatra::Base' do
65
65
  assert response.ok?
66
66
  assert_equal 'not foo', response.body
67
67
  end
68
+
69
+ it "makes redirecting back pretty" do
70
+ app = mock_app {
71
+ get '/foo' do
72
+ redirect back
73
+ end
74
+ }
75
+
76
+ request = Rack::MockRequest.new(app)
77
+ response = request.get('/foo', 'HTTP_REFERER' => 'http://github.com')
78
+ assert response.redirect?
79
+ assert_equal "http://github.com", response.location
80
+ end
68
81
  end
@@ -0,0 +1,63 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ describe 'Registering extensions' do
4
+ module FooExtensions
5
+ def foo
6
+ end
7
+
8
+ private
9
+ def im_hiding_in_ur_foos
10
+ end
11
+ end
12
+
13
+ module BarExtensions
14
+ def bar
15
+ end
16
+ end
17
+
18
+ module BazExtensions
19
+ def baz
20
+ end
21
+ end
22
+
23
+ module QuuxExtensions
24
+ def quux
25
+ end
26
+ end
27
+
28
+ it 'will add the methods to the DSL for the class in which you register them and its subclasses' do
29
+ Sinatra::Base.register FooExtensions
30
+ assert Sinatra::Base.respond_to?(:foo)
31
+
32
+ Sinatra::Default.register BarExtensions
33
+ assert Sinatra::Default.respond_to?(:bar)
34
+ assert Sinatra::Default.respond_to?(:foo)
35
+ assert !Sinatra::Base.respond_to?(:bar)
36
+ end
37
+
38
+ it 'allows extending by passing a block' do
39
+ Sinatra::Base.register {
40
+ def im_in_ur_anonymous_module; end
41
+ }
42
+ assert Sinatra::Base.respond_to?(:im_in_ur_anonymous_module)
43
+ end
44
+
45
+ it 'will make sure any public methods added via Default#register are delegated to Sinatra::Delegator' do
46
+ Sinatra::Default.register FooExtensions
47
+ assert Sinatra::Delegator.private_instance_methods.
48
+ map { |m| m.to_sym }.include?(:foo)
49
+ assert !Sinatra::Delegator.private_instance_methods.
50
+ map { |m| m.to_sym }.include?(:im_hiding_in_ur_foos)
51
+ end
52
+
53
+ it 'will not delegate methods on Base#register' do
54
+ Sinatra::Base.register QuuxExtensions
55
+ assert !Sinatra::Delegator.private_instance_methods.include?("quux")
56
+ end
57
+
58
+ it 'will extend the Sinatra::Default application by default' do
59
+ Sinatra.register BazExtensions
60
+ assert !Sinatra::Base.respond_to?(:baz)
61
+ assert Sinatra::Default.respond_to?(:baz)
62
+ end
63
+ end
data/test/helper.rb CHANGED
@@ -32,9 +32,12 @@ end
32
32
  #
33
33
  def describe(*args, &block)
34
34
  return super unless (name = args.first) && block
35
- klass = Class.new(Test::Unit::TestCase) do
35
+ name = "#{name.gsub(/\W/, '')}Test"
36
+ Object.send :const_set, name, Class.new(Test::Unit::TestCase)
37
+ klass = Object.const_get(name)
38
+ klass.class_eval do
36
39
  def self.it(name, &block)
37
- define_method("test_#{name.gsub(/\W/,'_')}", &block)
40
+ define_method("test_#{name.gsub(/\W/,'_').downcase}", &block)
38
41
  end
39
42
  def self.xspecify(*args) end
40
43
  def self.before(&block) define_method(:setup, &block) end
@@ -42,3 +45,11 @@ def describe(*args, &block)
42
45
  end
43
46
  klass.class_eval &block
44
47
  end
48
+
49
+ # Do not output warnings for the duration of the block.
50
+ def silence_warnings
51
+ $VERBOSE, v = nil, $VERBOSE
52
+ yield
53
+ ensure
54
+ $VERBOSE = v
55
+ end
data/test/helpers_test.rb CHANGED
@@ -379,3 +379,61 @@ describe 'Helpers#etag' do
379
379
  assert_equal 'W/"FOO"', response['ETag']
380
380
  end
381
381
  end
382
+
383
+ module HelperOne; def one; '1'; end; end
384
+ module HelperTwo; def two; '2'; end; end
385
+
386
+ describe 'Adding new helpers' do
387
+ it 'takes a list of modules to mix into the app' do
388
+ mock_app {
389
+ helpers HelperOne, HelperTwo
390
+
391
+ get '/one' do
392
+ one
393
+ end
394
+
395
+ get '/two' do
396
+ two
397
+ end
398
+ }
399
+
400
+ get '/one'
401
+ assert_equal '1', body
402
+
403
+ get '/two'
404
+ assert_equal '2', body
405
+ end
406
+
407
+ it 'takes a block to mix into the app' do
408
+ mock_app {
409
+ helpers do
410
+ def foo
411
+ 'foo'
412
+ end
413
+ end
414
+
415
+ get '/' do
416
+ foo
417
+ end
418
+ }
419
+
420
+ get '/'
421
+ assert_equal 'foo', body
422
+ end
423
+
424
+ it 'evaluates the block in class context so that methods can be aliased' do
425
+ mock_app {
426
+ helpers do
427
+ alias_method :h, :escape_html
428
+ end
429
+
430
+ get '/' do
431
+ h('42 < 43')
432
+ end
433
+ }
434
+
435
+ get '/'
436
+ assert ok?
437
+ assert_equal '42 &lt; 43', body
438
+ end
439
+ end
@@ -1,9 +1,12 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
2
 
3
- describe 'Exception Mappings' do
4
- class FooError < RuntimeError
5
- end
3
+ class FooError < RuntimeError
4
+ end
6
5
 
6
+ class FooNotFound < Sinatra::NotFound
7
+ end
8
+
9
+ describe 'Exception Mappings' do
7
10
  it 'invokes handlers registered with ::error when raised' do
8
11
  mock_app {
9
12
  set :raise_errors, false
@@ -80,9 +83,6 @@ describe 'Exception Mappings' do
80
83
  assert_equal 404, status
81
84
  end
82
85
 
83
- class FooNotFound < Sinatra::NotFound
84
- end
85
-
86
86
  it "cascades for subclasses of Sinatra::NotFound" do
87
87
  mock_app {
88
88
  set :raise_errors, true
@@ -4,7 +4,9 @@ describe "Middleware" do
4
4
  before do
5
5
  @app = mock_app(Sinatra::Default) {
6
6
  get '/*' do
7
- response.headers['X-Tests'] = env['test.ran'].join(', ')
7
+ response.headers['X-Tests'] = env['test.ran'].
8
+ map { |n| n.split('::').last }.
9
+ join(', ')
8
10
  env['PATH_INFO']
9
11
  end
10
12
  }
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+
3
+ require File.dirname(__FILE__) + '/helper'
4
+
5
+ describe 'Sinatra::Response' do
6
+ before do
7
+ @response = Sinatra::Response.new
8
+ end
9
+
10
+ it "initializes with 200, text/html, and empty body" do
11
+ assert_equal 200, @response.status
12
+ assert_equal 'text/html', @response['Content-Type']
13
+ assert_equal [], @response.body
14
+ end
15
+
16
+ it 'uses case insensitive headers' do
17
+ @response['content-type'] = 'application/foo'
18
+ assert_equal 'application/foo', @response['Content-Type']
19
+ assert_equal 'application/foo', @response['CONTENT-TYPE']
20
+ end
21
+
22
+ it 'writes to body' do
23
+ @response.body = 'Hello'
24
+ @response.write ' World'
25
+ assert_equal 'Hello World', @response.body
26
+ end
27
+
28
+ [204, 304].each do |status_code|
29
+ it "removes the Content-Type header and body when response status is #{status_code}" do
30
+ @response.status = status_code
31
+ @response.body = ['Hello World']
32
+ assert_equal [status_code, {}, []], @response.finish
33
+ end
34
+ end
35
+
36
+ it 'Calculates the Content-Length using the bytesize of the body' do
37
+ @response.body = ['Hello', 'World!', '✈']
38
+ status, headers, body = @response.finish
39
+ assert_equal '14', headers['Content-Length']
40
+ assert_equal @response.body, body
41
+ end
42
+ end
data/test/routing_test.rb CHANGED
@@ -484,4 +484,170 @@ describe "Routing" do
484
484
  assert_equal type, response.headers['Content-Type']
485
485
  end
486
486
  end
487
+
488
+ it 'degrades gracefully when optional accept header is not provided' do
489
+ mock_app {
490
+ get '/', :provides => :xml do
491
+ request.env['HTTP_ACCEPT']
492
+ end
493
+ get '/' do
494
+ 'default'
495
+ end
496
+ }
497
+ get '/'
498
+ assert ok?
499
+ assert_equal 'default', body
500
+ end
501
+
502
+ it 'passes a single url param as block parameters when one param is specified' do
503
+ mock_app {
504
+ get '/:foo' do |foo|
505
+ assert_equal 'bar', foo
506
+ end
507
+ }
508
+
509
+ get '/bar'
510
+ assert ok?
511
+ end
512
+
513
+ it 'passes multiple params as block parameters when many are specified' do
514
+ mock_app {
515
+ get '/:foo/:bar/:baz' do |foo, bar, baz|
516
+ assert_equal 'abc', foo
517
+ assert_equal 'def', bar
518
+ assert_equal 'ghi', baz
519
+ end
520
+ }
521
+
522
+ get '/abc/def/ghi'
523
+ assert ok?
524
+ end
525
+
526
+ it 'passes regular expression captures as block parameters' do
527
+ mock_app {
528
+ get(/^\/fo(.*)\/ba(.*)/) do |foo, bar|
529
+ assert_equal 'orooomma', foo
530
+ assert_equal 'f', bar
531
+ 'looks good'
532
+ end
533
+ }
534
+
535
+ get '/foorooomma/baf'
536
+ assert ok?
537
+ assert_equal 'looks good', body
538
+ end
539
+
540
+ it "supports mixing multiple splat params like /*/foo/*/* as block parameters" do
541
+ mock_app {
542
+ get '/*/foo/*/*' do |foo, bar, baz|
543
+ assert_equal 'bar', foo
544
+ assert_equal 'bling', bar
545
+ assert_equal 'baz/boom', baz
546
+ 'looks good'
547
+ end
548
+ }
549
+
550
+ get '/bar/foo/bling/baz/boom'
551
+ assert ok?
552
+ assert_equal 'looks good', body
553
+ end
554
+
555
+ it 'raises an ArgumentError with block arity > 1 and too many values' do
556
+ mock_app {
557
+ get '/:foo/:bar/:baz' do |foo, bar|
558
+ 'quux'
559
+ end
560
+ }
561
+
562
+ assert_raise(ArgumentError) { get '/a/b/c' }
563
+ end
564
+
565
+ it 'raises an ArgumentError with block param arity > 1 and too few values' do
566
+ mock_app {
567
+ get '/:foo/:bar' do |foo, bar, baz|
568
+ 'quux'
569
+ end
570
+ }
571
+
572
+ assert_raise(ArgumentError) { get '/a/b' }
573
+ end
574
+
575
+ it 'succeeds if no block parameters are specified' do
576
+ mock_app {
577
+ get '/:foo/:bar' do
578
+ 'quux'
579
+ end
580
+ }
581
+
582
+ get '/a/b'
583
+ assert ok?
584
+ assert_equal 'quux', body
585
+ end
586
+
587
+ it 'passes all params with block param arity -1 (splat args)' do
588
+ mock_app {
589
+ get '/:foo/:bar' do |*args|
590
+ args.join
591
+ end
592
+ }
593
+
594
+ get '/a/b'
595
+ assert ok?
596
+ assert_equal 'ab', body
597
+ end
598
+
599
+ # NOTE Block params behaves differently under 1.8 and 1.9. Under 1.8, block
600
+ # param arity is lax: declaring a mismatched number of block params results
601
+ # in a warning. Under 1.9, block param arity is strict: mismatched block
602
+ # arity raises an ArgumentError.
603
+
604
+ if RUBY_VERSION >= '1.9'
605
+
606
+ it 'raises an ArgumentError with block param arity 1 and no values' do
607
+ mock_app {
608
+ get '/foo' do |foo|
609
+ 'quux'
610
+ end
611
+ }
612
+
613
+ assert_raise(ArgumentError) { get '/foo' }
614
+ end
615
+
616
+ it 'raises an ArgumentError with block param arity 1 and too many values' do
617
+ mock_app {
618
+ get '/:foo/:bar/:baz' do |foo|
619
+ 'quux'
620
+ end
621
+ }
622
+
623
+ assert_raise(ArgumentError) { get '/a/b/c' }
624
+ end
625
+
626
+ else
627
+
628
+ it 'does not raise an ArgumentError with block param arity 1 and no values' do
629
+ mock_app {
630
+ get '/foo' do |foo|
631
+ 'quux'
632
+ end
633
+ }
634
+
635
+ silence_warnings { get '/foo' }
636
+ assert ok?
637
+ assert_equal 'quux', body
638
+ end
639
+
640
+ it 'does not raise an ArgumentError with block param arity 1 and too many values' do
641
+ mock_app {
642
+ get '/:foo/:bar/:baz' do |foo|
643
+ 'quux'
644
+ end
645
+ }
646
+
647
+ silence_warnings { get '/a/b/c' }
648
+ assert ok?
649
+ assert_equal 'quux', body
650
+ end
651
+
652
+ end
487
653
  end
@@ -0,0 +1,41 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class Rack::Handler::Mock
4
+ extend Test::Unit::Assertions
5
+
6
+ def self.run(app, options={})
7
+ assert(app < Sinatra::Base)
8
+ assert_equal 9001, options[:Port]
9
+ assert_equal 'foo.local', options[:Host]
10
+ yield new
11
+ end
12
+
13
+ def stop
14
+ end
15
+ end
16
+
17
+ describe 'Sinatra::Base.run!' do
18
+ before do
19
+ mock_app {
20
+ set :server, 'mock'
21
+ set :host, 'foo.local'
22
+ set :port, 9001
23
+ }
24
+ $stdout = File.open('/dev/null', 'wb')
25
+ end
26
+
27
+ after { $stdout = STDOUT }
28
+
29
+ it "locates the appropriate Rack handler and calls ::run" do
30
+ @app.run!
31
+ end
32
+
33
+ it "sets options on the app before running" do
34
+ @app.run! :sessions => true
35
+ assert @app.sessions?
36
+ end
37
+
38
+ it "falls back on the next server handler when not found" do
39
+ @app.run! :server => %w[foo bar mock]
40
+ end
41
+ end
data/test/static_test.rb CHANGED
@@ -1,17 +1,15 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
2
 
3
3
  describe 'Static' do
4
- F = ::File
5
-
6
4
  before do
7
5
  mock_app {
8
6
  set :static, true
9
- set :public, F.dirname(__FILE__)
7
+ set :public, File.dirname(__FILE__)
10
8
  }
11
9
  end
12
10
 
13
11
  it 'serves GET requests for files in the public directory' do
14
- get "/#{F.basename(__FILE__)}"
12
+ get "/#{File.basename(__FILE__)}"
15
13
  assert ok?
16
14
  assert_equal File.read(__FILE__), body
17
15
  assert_equal File.size(__FILE__).to_s, response['Content-Length']
@@ -19,7 +17,7 @@ describe 'Static' do
19
17
  end
20
18
 
21
19
  it 'produces a body that can be iterated over multiple times' do
22
- env = Rack::MockRequest.env_for("/#{F.basename(__FILE__)}")
20
+ env = Rack::MockRequest.env_for("/#{File.basename(__FILE__)}")
23
21
  status, headers, body = @app.call(env)
24
22
  buf1, buf2 = [], []
25
23
  body.each { |part| buf1 << part }
@@ -29,7 +27,7 @@ describe 'Static' do
29
27
  end
30
28
 
31
29
  it 'serves HEAD requests for files in the public directory' do
32
- head "/#{F.basename(__FILE__)}"
30
+ head "/#{File.basename(__FILE__)}"
33
31
  assert ok?
34
32
  assert_equal '', body
35
33
  assert_equal File.size(__FILE__).to_s, response['Content-Length']
@@ -37,8 +35,8 @@ describe 'Static' do
37
35
  end
38
36
 
39
37
  it 'serves files in preference to custom routes' do
40
- @app.get("/#{F.basename(__FILE__)}") { 'Hello World' }
41
- get "/#{F.basename(__FILE__)}"
38
+ @app.get("/#{File.basename(__FILE__)}") { 'Hello World' }
39
+ get "/#{File.basename(__FILE__)}"
42
40
  assert ok?
43
41
  assert body != 'Hello World'
44
42
  end
@@ -50,13 +48,13 @@ describe 'Static' do
50
48
 
51
49
  it 'passes to the next handler when the static option is disabled' do
52
50
  @app.set :static, false
53
- get "/#{F.basename(__FILE__)}"
51
+ get "/#{File.basename(__FILE__)}"
54
52
  assert not_found?
55
53
  end
56
54
 
57
55
  it 'passes to the next handler when the public option is nil' do
58
56
  @app.set :public, nil
59
- get "/#{F.basename(__FILE__)}"
57
+ get "/#{File.basename(__FILE__)}"
60
58
  assert not_found?
61
59
  end
62
60
 
data/test/test_test.rb ADDED
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ describe "Sinatra::Test" do
4
+ it "support nested parameters" do
5
+ mock_app {
6
+ get '/' do
7
+ params[:post][:title]
8
+ end
9
+
10
+ post '/' do
11
+ params[:post][:content]
12
+ end
13
+ }
14
+
15
+ get '/', :post => { :title => 'My Post Title' }
16
+ assert_equal 'My Post Title', body
17
+
18
+ post '/', :post => { :content => 'Post Content' }
19
+ assert_equal 'Post Content', body
20
+ end
21
+ end