bmizerany-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 +40 -2
- data/README.rdoc +3 -3
- data/compat/app_test.rb +0 -19
- data/compat/application_test.rb +0 -72
- data/compat/pipeline_test.rb +0 -26
- data/compat/sessions_test.rb +3 -0
- data/compat/streaming_test.rb +4 -4
- data/lib/sinatra/base.rb +96 -83
- data/lib/sinatra/compat.rb +11 -0
- data/lib/sinatra/test.rb +34 -35
- data/lib/sinatra/test/bacon.rb +2 -0
- data/lib/sinatra/test/rspec.rb +2 -0
- data/lib/sinatra/test/spec.rb +2 -0
- data/lib/sinatra/test/unit.rb +2 -0
- data/sinatra.gemspec +3 -3
- data/test/base_test.rb +105 -56
- data/test/erb_test.rb +31 -0
- data/test/extensions_test.rb +21 -0
- data/test/helper.rb +38 -8
- data/test/helpers_test.rb +28 -0
- data/test/middleware_test.rb +8 -0
- data/test/options_test.rb +243 -9
- data/test/routing_test.rb +61 -2
- data/test/test_test.rb +125 -8
- metadata +6 -2
data/lib/sinatra/compat.rb
CHANGED
@@ -106,6 +106,17 @@ module Sinatra
|
|
106
106
|
etag(*args, &block)
|
107
107
|
end
|
108
108
|
|
109
|
+
# Deprecated. Use the #attachment helper and return the data as a String or
|
110
|
+
# Array.
|
111
|
+
def send_data(data, options={})
|
112
|
+
sinatra_warn "The 'send_data' method is deprecated. use attachment, status, content_type, etc. helpers instead."
|
113
|
+
|
114
|
+
status options[:status] if options[:status]
|
115
|
+
attachment options[:filename] if options[:disposition] == 'attachment'
|
116
|
+
content_type options[:type] if options[:type]
|
117
|
+
halt data
|
118
|
+
end
|
119
|
+
|
109
120
|
# Throwing halt with a Symbol and the to_result convention are
|
110
121
|
# deprecated. Override the invoke method to detect those types of return
|
111
122
|
# values.
|
data/lib/sinatra/test.rb
CHANGED
@@ -1,41 +1,40 @@
|
|
1
1
|
require 'sinatra/base'
|
2
2
|
|
3
3
|
module Sinatra
|
4
|
-
|
5
4
|
module Test
|
6
5
|
include Rack::Utils
|
7
6
|
|
8
7
|
attr_reader :app, :request, :response
|
9
8
|
|
10
|
-
def
|
9
|
+
def self.deprecate(framework)
|
10
|
+
warn <<-EOF
|
11
|
+
Warning: support for the #{framework} testing framework is deprecated and
|
12
|
+
will be dropped in Sinatra 1.0. See <http://sinatra.github.com/testing.html>
|
13
|
+
for more information.
|
14
|
+
EOF
|
15
|
+
end
|
16
|
+
|
17
|
+
def make_request(verb, path, body=nil, options={})
|
11
18
|
@app = Sinatra::Application if @app.nil? && defined?(Sinatra::Application)
|
12
19
|
fail "@app not set - cannot make request" if @app.nil?
|
20
|
+
|
13
21
|
@request = Rack::MockRequest.new(@app)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
[{}, data]
|
29
|
-
end
|
30
|
-
when 0
|
31
|
-
[{}, '']
|
32
|
-
else
|
33
|
-
raise ArgumentError, "zero, one, or two arguments expected"
|
34
|
-
end
|
35
|
-
opts = rack_opts(opts)
|
36
|
-
opts[:input] ||= input
|
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
|
+
end
|
35
|
+
|
37
36
|
yield @request if block_given?
|
38
|
-
@response = @request.request(verb, path,
|
37
|
+
@response = @request.request(verb, path, rack_options(options))
|
39
38
|
end
|
40
39
|
|
41
40
|
def get(path, *args, &b) ; make_request('GET', path, *args, &b) ; end
|
@@ -67,18 +66,18 @@ module Sinatra
|
|
67
66
|
|
68
67
|
private
|
69
68
|
|
70
|
-
|
71
|
-
:accept
|
72
|
-
:agent
|
73
|
-
:host
|
74
|
-
:session
|
75
|
-
:cookies
|
76
|
-
:content_type =>
|
69
|
+
RACK_OPTIONS = {
|
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'
|
77
76
|
}
|
78
77
|
|
79
|
-
def
|
78
|
+
def rack_options(opts)
|
80
79
|
opts.merge(:lint => true).inject({}) do |hash,(key,val)|
|
81
|
-
key =
|
80
|
+
key = RACK_OPTIONS[key] || key
|
82
81
|
hash[key] = val
|
83
82
|
hash
|
84
83
|
end
|
data/lib/sinatra/test/bacon.rb
CHANGED
data/lib/sinatra/test/rspec.rb
CHANGED
data/lib/sinatra/test/spec.rb
CHANGED
data/lib/sinatra/test/unit.rb
CHANGED
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.
|
7
|
-
s.date = '2009-
|
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"
|
@@ -104,7 +104,7 @@ Gem::Specification.new do |s|
|
|
104
104
|
s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/}
|
105
105
|
|
106
106
|
s.extra_rdoc_files = %w[README.rdoc LICENSE]
|
107
|
-
s.add_dependency 'rack', '>= 0.9.1'
|
107
|
+
s.add_dependency 'rack', '>= 0.9.1', '< 1.0'
|
108
108
|
|
109
109
|
s.has_rdoc = true
|
110
110
|
s.homepage = "http://sinatra.rubyforge.org"
|
data/test/base_test.rb
CHANGED
@@ -1,81 +1,130 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/helper'
|
2
2
|
|
3
|
-
describe 'Sinatra::Base' do
|
4
|
-
|
5
|
-
|
3
|
+
describe 'Sinatra::Base subclasses' do
|
4
|
+
|
5
|
+
class TestApp < Sinatra::Base
|
6
|
+
get '/' do
|
7
|
+
'Hello World'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'include Rack::Utils' do
|
12
|
+
assert TestApp.included_modules.include?(Rack::Utils)
|
6
13
|
end
|
7
14
|
|
8
|
-
it '
|
9
|
-
|
10
|
-
get '/' do
|
11
|
-
'Hello World'
|
12
|
-
end
|
13
|
-
}
|
14
|
-
assert @app.respond_to?(:call)
|
15
|
+
it 'processes requests with #call' do
|
16
|
+
assert TestApp.respond_to?(:call)
|
15
17
|
|
16
|
-
request = Rack::MockRequest.new(
|
18
|
+
request = Rack::MockRequest.new(TestApp)
|
17
19
|
response = request.get('/')
|
18
20
|
assert response.ok?
|
19
21
|
assert_equal 'Hello World', response.body
|
20
22
|
end
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
24
|
+
class TestApp < Sinatra::Base
|
25
|
+
get '/state' do
|
26
|
+
body = "Foo: #{@foo}"
|
27
|
+
@foo = 'discard'
|
28
|
+
body
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'does not maintain state between requests' do
|
33
|
+
request = Rack::MockRequest.new(TestApp)
|
34
|
+
2.times do
|
35
|
+
response = request.get('/state')
|
36
|
+
assert response.ok?
|
37
|
+
assert_equal 'Foo: ', response.body
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "Sinatra::Base as Rack middleware" do
|
43
|
+
|
44
|
+
app = lambda { |env|
|
45
|
+
[210, {'X-Downstream' => 'true'}, ['Hello from downstream']] }
|
46
|
+
|
47
|
+
class TestMiddleware < Sinatra::Base
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'creates a middleware that responds to #call with .new' do
|
51
|
+
middleware = TestMiddleware.new(app)
|
52
|
+
assert middleware.respond_to?(:call)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'exposes the downstream app' do
|
56
|
+
middleware = TestMiddleware.new(app)
|
34
57
|
assert_same app, middleware.app
|
58
|
+
end
|
59
|
+
|
60
|
+
class TestMiddleware < Sinatra::Base
|
61
|
+
get '/' do
|
62
|
+
'Hello from middleware'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
middleware = TestMiddleware.new(app)
|
67
|
+
request = Rack::MockRequest.new(middleware)
|
35
68
|
|
36
|
-
|
69
|
+
it 'intercepts requests' do
|
37
70
|
response = request.get('/')
|
38
71
|
assert response.ok?
|
39
|
-
assert_equal 'Hello
|
72
|
+
assert_equal 'Hello from middleware', response.body
|
73
|
+
end
|
40
74
|
|
41
|
-
|
42
|
-
|
43
|
-
assert_equal
|
75
|
+
it 'automatically forwards requests downstream when no matching route found' do
|
76
|
+
response = request.get('/missing')
|
77
|
+
assert_equal 210, response.status
|
78
|
+
assert_equal 'Hello from downstream', response.body
|
44
79
|
end
|
45
80
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
81
|
+
class TestMiddleware < Sinatra::Base
|
82
|
+
get '/low-level-forward' do
|
83
|
+
app.call(env)
|
84
|
+
end
|
85
|
+
end
|
52
86
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
87
|
+
it 'can call the downstream app directly and return result' do
|
88
|
+
response = request.get('/low-level-forward')
|
89
|
+
assert_equal 210, response.status
|
90
|
+
assert_equal 'true', response['X-Downstream']
|
91
|
+
assert_equal 'Hello from downstream', response.body
|
92
|
+
end
|
57
93
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
94
|
+
class TestMiddleware < Sinatra::Base
|
95
|
+
get '/explicit-forward' do
|
96
|
+
response['X-Middleware'] = 'true'
|
97
|
+
res = forward
|
98
|
+
assert_nil res
|
99
|
+
assert_equal 210, response.status
|
100
|
+
assert_equal 'true', response['X-Downstream']
|
101
|
+
assert_equal ['Hello from downstream'], response.body
|
102
|
+
'Hello after explicit forward'
|
103
|
+
end
|
104
|
+
end
|
62
105
|
|
63
|
-
|
64
|
-
response = request.get('/
|
65
|
-
|
66
|
-
assert_equal '
|
106
|
+
it 'forwards the request downstream and integrates the response into the current context' do
|
107
|
+
response = request.get('/explicit-forward')
|
108
|
+
assert_equal 210, response.status
|
109
|
+
assert_equal 'true', response['X-Downstream']
|
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
|
67
121
|
end
|
68
122
|
|
69
|
-
|
70
|
-
|
71
|
-
get '/foo' do
|
72
|
-
redirect back
|
73
|
-
end
|
74
|
-
}
|
123
|
+
middleware_content_length = TestMiddlewareContentLength.new(app_content_length)
|
124
|
+
request_content_length = Rack::MockRequest.new(middleware_content_length)
|
75
125
|
|
76
|
-
|
77
|
-
response =
|
78
|
-
|
79
|
-
assert_equal "http://github.com", response.location
|
126
|
+
it "sets content length for last response" do
|
127
|
+
response = request_content_length.get('/forward')
|
128
|
+
assert_equal '28', response['Content-Length']
|
80
129
|
end
|
81
130
|
end
|
data/test/erb_test.rb
CHANGED
@@ -47,4 +47,35 @@ describe "ERB Templates" do
|
|
47
47
|
assert ok?
|
48
48
|
assert_equal "ERB Layout!\nHello World\n", body
|
49
49
|
end
|
50
|
+
|
51
|
+
it "renders erb with blocks" do
|
52
|
+
mock_app {
|
53
|
+
def container
|
54
|
+
@_out_buf << "THIS."
|
55
|
+
yield
|
56
|
+
@_out_buf << "SPARTA!"
|
57
|
+
end
|
58
|
+
def is; "IS." end
|
59
|
+
get '/' do
|
60
|
+
erb '<% container do %> <%= is %> <% end %>'
|
61
|
+
end
|
62
|
+
}
|
63
|
+
get '/'
|
64
|
+
assert ok?
|
65
|
+
assert_equal 'THIS. IS. SPARTA!', body
|
66
|
+
end
|
67
|
+
|
68
|
+
it "can be used in a nested fashion for partials and whatnot" do
|
69
|
+
mock_app {
|
70
|
+
template(:inner) { "<inner><%= 'hi' %></inner>" }
|
71
|
+
template(:outer) { "<outer><%= erb :inner %></outer>" }
|
72
|
+
get '/' do
|
73
|
+
erb :outer
|
74
|
+
end
|
75
|
+
}
|
76
|
+
|
77
|
+
get '/'
|
78
|
+
assert ok?
|
79
|
+
assert_equal '<outer><inner>hi</inner></outer>', body
|
80
|
+
end
|
50
81
|
end
|
data/test/extensions_test.rb
CHANGED
@@ -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
|
data/test/helper.rb
CHANGED
@@ -8,21 +8,40 @@ end
|
|
8
8
|
libdir = File.dirname(File.dirname(__FILE__)) + '/lib'
|
9
9
|
$LOAD_PATH.unshift libdir unless $LOAD_PATH.include?(libdir)
|
10
10
|
|
11
|
-
require '
|
12
|
-
require 'sinatra/test
|
11
|
+
require 'test/unit'
|
12
|
+
require 'sinatra/test'
|
13
|
+
|
14
|
+
class Sinatra::Base
|
15
|
+
# Allow assertions in request context
|
16
|
+
include Test::Unit::Assertions
|
17
|
+
end
|
18
|
+
|
19
|
+
class Test::Unit::TestCase
|
20
|
+
include Sinatra::Test
|
21
|
+
|
22
|
+
def setup
|
23
|
+
Sinatra::Default.set :environment, :test
|
24
|
+
end
|
13
25
|
|
14
|
-
module Sinatra::Test
|
15
26
|
# Sets up a Sinatra::Base subclass defined with the block
|
16
27
|
# given. Used in setup or individual spec methods to establish
|
17
28
|
# the application.
|
18
29
|
def mock_app(base=Sinatra::Base, &block)
|
19
30
|
@app = Sinatra.new(base, &block)
|
20
31
|
end
|
21
|
-
end
|
22
32
|
|
23
|
-
|
24
|
-
|
25
|
-
|
33
|
+
def restore_default_options
|
34
|
+
Sinatra::Default.set(
|
35
|
+
:environment => :development,
|
36
|
+
:raise_errors => Proc.new { test? },
|
37
|
+
:dump_errors => true,
|
38
|
+
:sessions => false,
|
39
|
+
:logging => Proc.new { ! test? },
|
40
|
+
:methodoverride => true,
|
41
|
+
:static => true,
|
42
|
+
:run => Proc.new { ! test? }
|
43
|
+
)
|
44
|
+
end
|
26
45
|
end
|
27
46
|
|
28
47
|
##
|
@@ -31,7 +50,7 @@ end
|
|
31
50
|
# chris@ozmm.org
|
32
51
|
#
|
33
52
|
def describe(*args, &block)
|
34
|
-
return super unless (name = args.first) && block
|
53
|
+
return super unless (name = args.first.capitalize) && block
|
35
54
|
name = "#{name.gsub(/\W/, '')}Test"
|
36
55
|
Object.send :const_set, name, Class.new(Test::Unit::TestCase)
|
37
56
|
klass = Object.const_get(name)
|
@@ -44,6 +63,17 @@ def describe(*args, &block)
|
|
44
63
|
def self.after(&block) define_method(:teardown, &block) end
|
45
64
|
end
|
46
65
|
klass.class_eval &block
|
66
|
+
klass
|
67
|
+
end
|
68
|
+
|
69
|
+
def describe_option(name, &block)
|
70
|
+
klass = describe("Option #{name}", &block)
|
71
|
+
klass.before do
|
72
|
+
restore_default_options
|
73
|
+
@base = Sinatra.new
|
74
|
+
@default = Class.new(Sinatra::Default)
|
75
|
+
end
|
76
|
+
klass
|
47
77
|
end
|
48
78
|
|
49
79
|
# Do not output warnings for the duration of the block.
|