darkhelmet-sinatra 0.9.0.5 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,34 +1,62 @@
1
- = 0.9.1 / unreleased
1
+ = 0.9.1 / 2009-03-01
2
2
 
3
3
  * Sinatra now runs under Ruby 1.9.1 [#61]
4
+
4
5
  * Route patterns (splats, :named, or Regexp captures) are now
5
6
  passed as arguments to the block. [#140]
7
+
6
8
  * The "helpers" method now takes a variable number of modules
7
9
  along with the normal block syntax. [#133]
10
+
8
11
  * New request-level #forward method for middleware components: passes
9
12
  the env to the downstream app and merges the response status, headers,
10
13
  and body into the current context.
14
+
11
15
  * Requests are now automatically forwarded to the downstream app when
12
16
  running as middleware and no matching route is found or all routes
13
17
  pass.
18
+
14
19
  * New simple API for extensions/plugins to add DSL-level and
15
20
  request-level methods. Use Sinatra.register(mixin) to extend
16
21
  the DSL with all public methods defined in the mixin module;
17
22
  use Sinatra.helpers(mixin) to make all public methods defined
18
23
  in the mixin module available at the request level. [#138]
19
- * Added "redirect back" to redirect to the referring URL.
24
+ See http://www.sinatrarb.com/extensions.html for details.
25
+
26
+ * Named parameters in routes now capture the "." character. This makes
27
+ routes like "/:path/:filename" match against requests like
28
+ "/foo/bar.txt"; in this case, "params[:filename]" is "bar.txt".
29
+ Previously, the route would not match at all.
30
+
31
+ * Added request-level "redirect back" to redirect to the referring
32
+ URL.
33
+
20
34
  * Added a new "clean_trace" option that causes backtraces dumped
21
35
  to rack.errors and displayed on the development error page to
22
36
  omit framework and core library backtrace lines. The option is
23
37
  enabled by default. [#77]
24
- * Fix :provides causing crash on any request when request has no
25
- Accept header [#139]
26
- * Fix that ERB templates were evaluated twice per "erb" call.
38
+
27
39
  * The ERB output buffer is now available to helpers via the @_out_buf
28
40
  instance variable.
41
+
42
+ * It's now much easier to test sessions in unit tests by passing a
43
+ ":session" option to any of the mock request methods. e.g.,
44
+ get '/', {}, :session => { 'foo' => 'bar' }
45
+
29
46
  * The request-level #send_data method from Sinatra 0.3.3 has been added
30
47
  for compatibility but is deprecated.
31
48
 
49
+ * Fix :provides causing crash on any request when request has no
50
+ Accept header [#139]
51
+
52
+ * Fix that ERB templates were evaluated twice per "erb" call.
53
+
54
+ * Fix app-level middleware not being run when the Sinatra application is
55
+ run as middleware.
56
+
57
+ * Fixed some issues with running under Rack's CGI handler caused by
58
+ writing informational stuff to stdout.
59
+
32
60
  = 0.9.0.4 / 2009-01-25
33
61
 
34
62
  * Using halt with more than 1 args causes ArgumentError [#131]
data/compat/app_test.rb CHANGED
@@ -146,25 +146,6 @@ context "Sinatra" do
146
146
 
147
147
  end
148
148
 
149
- # Deprecated. WTF was going on here? What's the 1 in [:foo, 1] do?
150
- xspecify "should set status then call helper with a var" do
151
- helpers do
152
- def foo
153
- 'bah!'
154
- end
155
- end
156
-
157
- get '/set_body' do
158
- stop [404, [:foo, 1]]
159
- end
160
-
161
- get_it '/set_body'
162
-
163
- should.be.not_found
164
- body.should.equal 'bah!'
165
-
166
- end
167
-
168
149
  specify "should easily set response Content-Type" do
169
150
  get '/foo.html' do
170
151
  content_type 'text/html', :charset => 'utf-8'
@@ -10,47 +10,6 @@ class TesterWithEach
10
10
  end
11
11
  end
12
12
 
13
- context "Looking up a request" do
14
-
15
- setup do
16
- Sinatra.application = nil
17
- end
18
-
19
- # Deprecated. The lookup method is no longer used.
20
- xspecify "returns what's at the end" do
21
- block = Proc.new { 'Hello' }
22
- get '/', &block
23
-
24
- result = Sinatra.application.lookup(
25
- Rack::Request.new(
26
- 'REQUEST_METHOD' => 'GET',
27
- 'PATH_INFO' => '/'
28
- )
29
- )
30
-
31
- result.should.not.be.nil
32
- result.block.should.be block
33
- end
34
-
35
- # Deprecated. The lookup method is no longer used.
36
- xspecify "takes params in path" do
37
- block = Proc.new { 'Hello' }
38
- get '/:foo', &block
39
-
40
- result = Sinatra.application.lookup(
41
- Rack::Request.new(
42
- 'REQUEST_METHOD' => 'GET',
43
- 'PATH_INFO' => '/bar'
44
- )
45
- )
46
-
47
- result.should.not.be.nil
48
- result.block.should.be block
49
- result.params.should.equal "foo" => 'bar'
50
- end
51
-
52
- end
53
-
54
13
  context "An app returns" do
55
14
 
56
15
  setup do
@@ -85,20 +44,6 @@ context "An app returns" do
85
44
 
86
45
  end
87
46
 
88
- # Deprecated. The body method no longer halts.
89
- xspecify "the body set if set before the last" do
90
-
91
- get '/' do
92
- body 'Blake'
93
- 'Mizerany'
94
- end
95
-
96
- get_it '/'
97
- should.be.ok
98
- body.should.equal 'Blake'
99
-
100
- end
101
-
102
47
  specify "404 if NotFound is raised" do
103
48
 
104
49
  get '/' do
@@ -143,23 +88,6 @@ context "Application#configure blocks" do
143
88
 
144
89
  end
145
90
 
146
- context "Default Application Configuration" do
147
-
148
- # Sinatra::ServerError is no longer used
149
- xspecify "includes 404 and 500 error handlers" do
150
- Sinatra.application.errors.should.include(Sinatra::ServerError)
151
- Sinatra.application.errors[Sinatra::ServerError].should.not.be.nil
152
- Sinatra.application.errors.should.include(Sinatra::NotFound)
153
- Sinatra.application.errors[Sinatra::NotFound].should.not.be.nil
154
- end
155
-
156
- # Deprecated. No such thing as a Static event anymore.
157
- xspecify "includes Static event" do
158
- assert Sinatra.application.events[:get].any? { |e| Sinatra::Static === e }
159
- end
160
-
161
- end
162
-
163
91
  context "Events in an app" do
164
92
 
165
93
  setup do
@@ -23,32 +23,6 @@ context "Middleware Pipelines" do
23
23
  Sinatra.application = nil
24
24
  end
25
25
 
26
- # Sessions and logging are tested elsewhere. This is a bad test because it
27
- # asserts things about the implementation and not the effect.
28
- xspecify "includes default middleware with options set" do
29
- @app.set_options :sessions => true, :logging => true
30
- @app.send(:optional_middleware).should.include([Rack::Session::Cookie, [], nil])
31
- @app.send(:optional_middleware).should.include([Rack::CommonLogger, [], nil])
32
- end
33
-
34
- # Bad test.
35
- xspecify "does not include default middleware with options unset" do
36
- @app.set_options :sessions => false, :logging => false
37
- @app.send(:optional_middleware).should.not.include([Rack::Session::Cookie, [], nil])
38
- @app.send(:optional_middleware).should.not.include([Rack::CommonLogger, [], nil])
39
- end
40
-
41
- # Bad test.
42
- xspecify "includes only optional middleware when no explicit middleware added" do
43
- @app.set_options :sessions => true, :logging => true
44
- @app.send(:middleware).should.equal @app.send(:optional_middleware)
45
- end
46
-
47
- # Bad test.
48
- xspecify "should clear middleware before reload" do
49
- @app.clearables.should.include(@app.send(:explicit_middleware))
50
- end
51
-
52
26
  specify "should add middleware with use" do
53
27
  block = Proc.new { |env| }
54
28
  @app.use UpcaseMiddleware
@@ -21,6 +21,7 @@ context "Sessions" do
21
21
 
22
22
  specify "should be able to store data accross requests" do
23
23
  set_option :sessions, true
24
+ set_option :environment, :not_test # necessary because sessions are disabled
24
25
 
25
26
  get '/foo' do
26
27
  session[:test] = true
@@ -34,6 +35,8 @@ context "Sessions" do
34
35
  get_it '/foo', :env => { :host => 'foo.sinatrarb.com' }
35
36
  assert ok?
36
37
  assert include?('Set-Cookie')
38
+
39
+ set_option :environment, :test
37
40
  end
38
41
 
39
42
  end
@@ -105,9 +105,10 @@ context "SendData" do
105
105
  end
106
106
 
107
107
  # Deprecated. The Content-Disposition is no longer handled by sendfile.
108
- xspecify "should include a Content-Disposition header" do
108
+ specify "should include a Content-Disposition header" do
109
109
  get '/' do
110
- send_file File.dirname(__FILE__) + '/public/foo.xml'
110
+ send_file File.dirname(__FILE__) + '/public/foo.xml',
111
+ :disposition => 'attachment'
111
112
  end
112
113
 
113
114
  get_it '/'
@@ -115,7 +116,6 @@ context "SendData" do
115
116
  should.be.ok
116
117
  headers['Content-Disposition'].should.not.be.nil
117
118
  headers['Content-Disposition'].should.equal 'attachment; filename="foo.xml"'
118
- headers['Content-Transfer-Encoding'].should.equal 'binary'
119
119
  end
120
120
 
121
121
  specify "should include a Content-Disposition header when :disposition set to attachment" do
data/lib/sinatra/base.rb CHANGED
@@ -6,7 +6,7 @@ require 'rack/builder'
6
6
  require 'colored'
7
7
 
8
8
  module Sinatra
9
- VERSION = '0.9.0.5'
9
+ VERSION = '0.9.1'
10
10
 
11
11
  # The request object. See Rack::Request for more info:
12
12
  # http://rack.rubyforge.org/doc/classes/Rack/Request.html
@@ -50,7 +50,7 @@ module Sinatra
50
50
  else
51
51
  body = @body || []
52
52
  body = [body] if body.respond_to? :to_str
53
- if header["Content-Length"].nil? && body.respond_to?(:to_ary)
53
+ if body.respond_to?(:to_ary)
54
54
  header["Content-Length"] = body.to_ary.
55
55
  inject(0) { |len, part| len + part.bytesize }.to_s
56
56
  end
@@ -345,10 +345,17 @@ module Sinatra
345
345
  invoke { dispatch! }
346
346
  invoke { error_block!(response.status) }
347
347
 
348
- # never respond with a body on HEAD requests
349
- @response.body = [] if @env['REQUEST_METHOD'] == 'HEAD'
348
+ status, header, body = @response.finish
350
349
 
351
- @response.finish
350
+ # Never produce a body on HEAD requests. Do retain the Content-Length
351
+ # unless it's "0", in which case we assume it was calculated erroneously
352
+ # for a manual HEAD response and remove it entirely.
353
+ if @env['REQUEST_METHOD'] == 'HEAD'
354
+ body = []
355
+ header.delete('Content-Length') if header['Content-Length'] == '0'
356
+ end
357
+
358
+ [status, header, body]
352
359
  end
353
360
 
354
361
  # Access options defined with Base.set.
@@ -542,8 +549,8 @@ module Sinatra
542
549
  @conditions = []
543
550
  @templates = {}
544
551
  @middleware = []
545
- @callsite = nil
546
552
  @errors = {}
553
+ @prototype = nil
547
554
 
548
555
  class << self
549
556
  attr_accessor :routes, :filters, :conditions, :templates,
@@ -720,13 +727,16 @@ module Sinatra
720
727
 
721
728
  public
722
729
  def helpers(*extensions, &block)
723
- class_eval(&block) if block_given?
724
- include *extensions
730
+ class_eval(&block) if block_given?
731
+ include *extensions if extensions.any?
725
732
  end
726
733
 
727
734
  def register(*extensions, &block)
728
- extensions << Module.new(&block) if block
729
- extend *extensions
735
+ extensions << Module.new(&block) if block_given?
736
+ extensions.each do |extension|
737
+ extend extension
738
+ extension.registered(self) if extension.respond_to?(:registered)
739
+ end
730
740
  end
731
741
 
732
742
  def development? ; environment == :development ; end
@@ -739,7 +749,7 @@ module Sinatra
739
749
  end
740
750
 
741
751
  def use(middleware, *args, &block)
742
- reset_middleware
752
+ @prototype = nil
743
753
  @middleware << [middleware, args, block]
744
754
  end
745
755
 
@@ -760,22 +770,61 @@ module Sinatra
760
770
  puts "== Someone is already performing on port #{port}!"
761
771
  end
762
772
 
773
+ # The prototype instance used to process requests.
774
+ def prototype
775
+ @prototype ||= new
776
+ end
777
+
778
+ # Create a new instance of the class fronted by its middleware
779
+ # pipeline. The object is guaranteed to respond to #call but may not be
780
+ # an instance of the class new was called on.
781
+ def new(*args, &bk)
782
+ builder = Rack::Builder.new
783
+ builder.use Rack::Session::Cookie if sessions? && !test?
784
+ builder.use Rack::CommonLogger if logging?
785
+ builder.use Rack::MethodOverride if methodoverride?
786
+ @middleware.each { |c, args, bk| builder.use(c, *args, &bk) }
787
+ builder.run super
788
+ builder.to_app
789
+ end
790
+
763
791
  def call(env)
764
792
  synchronize do
765
793
  reload! if reload?
766
- construct_middleware if @callsite.nil?
767
- @callsite.call(env)
794
+ prototype.call(env)
768
795
  end
769
796
  end
770
797
 
798
+ def reloading?
799
+ @reloading
800
+ end
801
+
771
802
  def reload!
772
803
  @reloading = true
773
- superclass.send :reset!, self
804
+ reset!
774
805
  $LOADED_FEATURES.delete("sinatra.rb")
775
806
  ::Kernel.load app_file
776
807
  @reloading = false
777
808
  end
778
809
 
810
+ def reset!(base=superclass)
811
+ @routes = base.dupe_routes
812
+ @templates = base.templates.dup
813
+ @conditions = []
814
+ @filters = base.filters.dup
815
+ @errors = base.errors.dup
816
+ @middleware = base.middleware.dup
817
+ @prototype = nil
818
+ end
819
+
820
+ protected
821
+ def dupe_routes
822
+ routes.inject({}) do |hash,(request_method,routes)|
823
+ hash[request_method] = routes.dup
824
+ hash
825
+ end
826
+ end
827
+
779
828
  private
780
829
  def detect_rack_handler
781
830
  servers = Array(self.server)
@@ -789,38 +838,11 @@ module Sinatra
789
838
  fail "Server handler (#{servers.join(',')}) not found."
790
839
  end
791
840
 
792
- def construct_middleware(builder=Rack::Builder.new)
793
- builder.use Rack::Session::Cookie if sessions?
794
- builder.use Rack::CommonLogger if logging?
795
- builder.use Rack::MethodOverride if methodoverride?
796
- @middleware.each { |c, args, bk| builder.use(c, *args, &bk) }
797
- builder.run new
798
- @callsite = builder.to_app
799
- end
800
-
801
- def reset_middleware
802
- @callsite = nil
803
- end
804
-
805
- def reset!(subclass = self)
806
- subclass.routes = dupe_routes
807
- subclass.templates = templates.dup
808
- subclass.conditions = []
809
- subclass.filters = filters.dup
810
- subclass.errors = errors.dup
811
- subclass.middleware = middleware.dup
812
- subclass.send :reset_middleware
813
- end
814
-
815
841
  def inherited(subclass)
816
- reset!(subclass)
842
+ subclass.reset! self
817
843
  super
818
844
  end
819
845
 
820
- def reloading?
821
- @reloading ||= false
822
- end
823
-
824
846
  @@mutex = Mutex.new
825
847
  def synchronize(&block)
826
848
  if lock?
@@ -830,13 +852,6 @@ module Sinatra
830
852
  end
831
853
  end
832
854
 
833
- def dupe_routes
834
- routes.inject({}) do |hash,(request_method,routes)|
835
- hash[request_method] = routes.dup
836
- hash
837
- end
838
- end
839
-
840
855
  def metadef(message, &block)
841
856
  (class << self; self; end).
842
857
  send :define_method, message, &block
data/lib/sinatra/test.rb CHANGED
@@ -14,27 +14,27 @@ for more information.
14
14
  EOF
15
15
  end
16
16
 
17
- def make_request(verb, path, data=nil, h=nil)
17
+ def make_request(verb, path, body=nil, options={})
18
18
  @app = Sinatra::Application if @app.nil? && defined?(Sinatra::Application)
19
19
  fail "@app not set - cannot make request" if @app.nil?
20
20
 
21
21
  @request = Rack::MockRequest.new(@app)
22
- options = { :lint => true }
23
-
24
- case data
25
- when Hash
26
- if env = data.delete(:env)
27
- options = rack_options(env)
28
- end
29
- options.merge!(h) if h.is_a?(Hash)
30
- options[:input] = param_string(data)
31
- when String
32
- options = rack_options(h) if h.is_a?(Hash)
33
- options[:input] = data
22
+ options = { :lint => true }.merge(options || {})
23
+
24
+ case
25
+ when body.respond_to?(:to_hash)
26
+ options.merge! body.delete(:env) if body.key?(:env)
27
+ options[:input] = param_string(body)
28
+ when body.respond_to?(:to_str)
29
+ options[:input] = body
30
+ when body.nil?
31
+ options[:input] = ''
32
+ else
33
+ raise ArgumentError, "body must be a Hash, String, or nil"
34
34
  end
35
35
 
36
- # TODO: yield @request if block_given?
37
- @response = @request.request(verb, path, options)
36
+ yield @request if block_given?
37
+ @response = @request.request(verb, path, rack_options(options))
38
38
  end
39
39
 
40
40
  def get(path, *args, &b) ; make_request('GET', path, *args, &b) ; end
@@ -67,12 +67,12 @@ for more information.
67
67
  private
68
68
 
69
69
  RACK_OPTIONS = {
70
- :accept => "HTTP_ACCEPT",
71
- :agent => "HTTP_USER_AGENT",
72
- :host => "HTTP_HOST",
73
- :session => "HTTP_COOKIE",
74
- :cookies => "HTTP_COOKIE",
75
- :content_type => "CONTENT_TYPE"
70
+ :accept => 'HTTP_ACCEPT',
71
+ :agent => 'HTTP_USER_AGENT',
72
+ :host => 'HTTP_HOST',
73
+ :session => 'rack.session',
74
+ :cookies => 'HTTP_COOKIE',
75
+ :content_type => 'CONTENT_TYPE'
76
76
  }
77
77
 
78
78
  def rack_options(opts)
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.5'
7
- s.date = '2009-02-10'
6
+ s.version = '0.9.1'
7
+ s.date = '2009-03-01'
8
8
 
9
9
  s.description = "Classy web-development dressed in a DSL"
10
10
  s.summary = "Classy web-development dressed in a DSL"
data/test/base_test.rb CHANGED
@@ -108,5 +108,23 @@ describe "Sinatra::Base as Rack middleware" do
108
108
  assert_equal 210, response.status
109
109
  assert_equal 'true', response['X-Downstream']
110
110
  assert_equal 'Hello after explicit forward', response.body
111
+ assert_equal '28', response['Content-Length']
112
+ end
113
+
114
+ app_content_length = lambda {|env|
115
+ [200, {'Content-Length' => '16'}, 'From downstream!']}
116
+ class TestMiddlewareContentLength < Sinatra::Base
117
+ get '/forward' do
118
+ res = forward
119
+ 'From after explicit forward!'
120
+ end
121
+ end
122
+
123
+ middleware_content_length = TestMiddlewareContentLength.new(app_content_length)
124
+ request_content_length = Rack::MockRequest.new(middleware_content_length)
125
+
126
+ it "sets content length for last response" do
127
+ response = request_content_length.get('/forward')
128
+ assert_equal '28', response['Content-Length']
111
129
  end
112
130
  end
@@ -60,4 +60,25 @@ describe 'Registering extensions' do
60
60
  assert !Sinatra::Base.respond_to?(:baz)
61
61
  assert Sinatra::Default.respond_to?(:baz)
62
62
  end
63
+
64
+ module BizzleExtension
65
+ def bizzle
66
+ bizzle_option
67
+ end
68
+
69
+ def self.registered(base)
70
+ fail "base should be BizzleApp" unless base == BizzleApp
71
+ fail "base should have already extended BizzleExtension" unless base.respond_to?(:bizzle)
72
+ base.set :bizzle_option, 'bizzle!'
73
+ end
74
+ end
75
+
76
+ class BizzleApp < Sinatra::Base
77
+ end
78
+
79
+ it 'sends .registered to the extension module after extending the class' do
80
+ BizzleApp.register BizzleExtension
81
+ assert_equal 'bizzle!', BizzleApp.bizzle_option
82
+ assert_equal 'bizzle!', BizzleApp.bizzle
83
+ end
63
84
  end
@@ -57,4 +57,12 @@ describe "Middleware" do
57
57
  assert_equal '/foo', body
58
58
  assert_equal "UpcaseMiddleware, DowncaseMiddleware", response['X-Tests']
59
59
  end
60
+
61
+ it "works when app is used as middleware" do
62
+ @app.use UpcaseMiddleware
63
+ @app = @app.new
64
+ get '/Foo'
65
+ assert_equal "/FOO", body
66
+ assert_equal "UpcaseMiddleware", response['X-Tests']
67
+ end
60
68
  end
data/test/test_test.rb CHANGED
@@ -45,7 +45,8 @@ describe 'Sinatra::Test' do
45
45
  assert_equal('DELETE', request['REQUEST_METHOD'])
46
46
 
47
47
  head '/'
48
- assert_equal('0', headers['Content-Length'])
48
+ assert_equal('596', response.headers['Content-Length'])
49
+ assert_equal('', response.body)
49
50
  end
50
51
 
51
52
  it 'allows to specify a body' do
@@ -92,7 +93,7 @@ describe 'Sinatra::Test' do
92
93
  assert_equal '1.2.3.4', request['HTTP_HOST']
93
94
 
94
95
  get '/', :env => { :session => 'foo' }
95
- assert_equal 'foo', request['HTTP_COOKIE']
96
+ assert_equal 'foo', request['rack.session']
96
97
 
97
98
  get '/', :env => { :cookies => 'foo' }
98
99
  assert_equal 'foo', request['HTTP_COOKIE']
@@ -101,6 +102,34 @@ describe 'Sinatra::Test' do
101
102
  assert_equal 'text/plain', request['CONTENT_TYPE']
102
103
  end
103
104
 
105
+ it 'allow to test session easily' do
106
+ app = mock_app(Sinatra::Default) {
107
+ get '/' do
108
+ session['foo'] = 'bar'
109
+ 200
110
+ end
111
+
112
+ post '/' do
113
+ assert_equal 'bar', session['foo']
114
+ session['foo'] || "blah"
115
+ end
116
+ }
117
+
118
+ browser = Sinatra::TestHarness.new(app)
119
+ browser.get '/'
120
+ browser.post '/', {}, :session => { 'foo' => 'bar' }
121
+ assert_equal 'bar', browser.response.body
122
+ end
123
+
124
+ it 'yields the request object to the block before invoking the application' do
125
+ called = false
126
+ get '/' do |req|
127
+ called = true
128
+ assert req.kind_of?(Rack::MockRequest)
129
+ end
130
+ assert called
131
+ end
132
+
104
133
  def test_TestHarness
105
134
  session = Sinatra::TestHarness.new(@app)
106
135
  response = session.get('/')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: darkhelmet-sinatra
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0.5
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blake Mizerany
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-10 00:00:00 -08:00
12
+ date: 2009-03-01 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency