bmizerany-sinatra 0.9.0.4 → 0.9.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/AUTHORS +1 -1
- data/CHANGES +44 -0
- data/README.rdoc +12 -0
- data/Rakefile +2 -1
- data/compat/app_test.rb +3 -2
- data/compat/compat_test.rb +12 -0
- data/lib/sinatra/base.rb +204 -110
- data/lib/sinatra/compat.rb +18 -16
- data/lib/sinatra/main.rb +4 -4
- data/lib/sinatra/test.rb +10 -8
- data/sinatra.gemspec +7 -2
- data/test/base_test.rb +13 -0
- data/test/extensions_test.rb +63 -0
- data/test/helper.rb +13 -2
- data/test/helpers_test.rb +58 -0
- data/test/mapped_error_test.rb +6 -6
- data/test/middleware_test.rb +3 -1
- data/test/response_test.rb +42 -0
- data/test/routing_test.rb +166 -0
- data/test/server_test.rb +41 -0
- data/test/static_test.rb +8 -10
- data/test/test_test.rb +21 -0
- metadata +11 -2
data/lib/sinatra/compat.rb
CHANGED
@@ -9,7 +9,7 @@ require 'sinatra/base'
|
|
9
9
|
require 'sinatra/main'
|
10
10
|
|
11
11
|
# Like Kernel#warn but outputs the location that triggered the warning.
|
12
|
-
def sinatra_warn(*message)
|
12
|
+
def sinatra_warn(*message) #:nodoc:
|
13
13
|
line = caller.
|
14
14
|
detect { |line| line !~ /(?:lib\/sinatra\/|__DELEGATE__)/ }.
|
15
15
|
sub(/:in .*/, '')
|
@@ -34,25 +34,27 @@ end
|
|
34
34
|
# technically a Sinatra issue but many Sinatra apps access the old
|
35
35
|
# MIME_TYPES constants due to Sinatra example code.
|
36
36
|
require 'rack/file'
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
37
|
+
module Rack #:nodoc:
|
38
|
+
class File #:nodoc:
|
39
|
+
def self.const_missing(const_name)
|
40
|
+
if const_name == :MIME_TYPES
|
41
|
+
hash = Hash.new { |hash,key| Rack::Mime::MIME_TYPES[".#{key}"] }
|
42
|
+
const_set :MIME_TYPES, hash
|
43
|
+
sinatra_warn 'Rack::File::MIME_TYPES is deprecated; use Rack::Mime instead.'
|
44
|
+
hash
|
45
|
+
else
|
46
|
+
super
|
47
|
+
end
|
46
48
|
end
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
50
52
|
module Sinatra
|
51
|
-
module Compat
|
53
|
+
module Compat #:nodoc:
|
52
54
|
end
|
53
55
|
|
54
56
|
# Make Sinatra::EventContext an alias for Sinatra::Default to unbreak plugins.
|
55
|
-
def self.const_missing(const_name)
|
57
|
+
def self.const_missing(const_name) #:nodoc:
|
56
58
|
if const_name == :EventContext
|
57
59
|
const_set :EventContext, Sinatra::Default
|
58
60
|
sinatra_warn 'Sinatra::EventContext is deprecated; use Sinatra::Default instead.'
|
@@ -73,7 +75,7 @@ module Sinatra
|
|
73
75
|
end
|
74
76
|
|
75
77
|
class Default < Base
|
76
|
-
def self.const_missing(const_name)
|
78
|
+
def self.const_missing(const_name) #:nodoc:
|
77
79
|
if const_name == :FORWARD_METHODS
|
78
80
|
sinatra_warn 'Sinatra::Application::FORWARD_METHODS is deprecated;',
|
79
81
|
'use Sinatra::Delegator::METHODS instead.'
|
@@ -107,7 +109,7 @@ module Sinatra
|
|
107
109
|
# Throwing halt with a Symbol and the to_result convention are
|
108
110
|
# deprecated. Override the invoke method to detect those types of return
|
109
111
|
# values.
|
110
|
-
def invoke(&block)
|
112
|
+
def invoke(&block) #:nodoc:
|
111
113
|
res = super
|
112
114
|
case
|
113
115
|
when res.kind_of?(Symbol)
|
@@ -121,7 +123,7 @@ module Sinatra
|
|
121
123
|
res
|
122
124
|
end
|
123
125
|
|
124
|
-
def options
|
126
|
+
def options #:nodoc:
|
125
127
|
Options.new(self.class)
|
126
128
|
end
|
127
129
|
|
@@ -184,7 +186,7 @@ module Sinatra
|
|
184
186
|
end
|
185
187
|
|
186
188
|
# Deprecated. Missing messages are no longer delegated to @response.
|
187
|
-
def method_missing(name, *args, &b)
|
189
|
+
def method_missing(name, *args, &b) #:nodoc:
|
188
190
|
if @response.respond_to?(name)
|
189
191
|
sinatra_warn "The '#{name}' method is deprecated; use 'response.#{name}' instead."
|
190
192
|
@response.send(name, *args, &b)
|
data/lib/sinatra/main.rb
CHANGED
@@ -2,6 +2,10 @@ require 'sinatra/base'
|
|
2
2
|
|
3
3
|
module Sinatra
|
4
4
|
class Default < Base
|
5
|
+
|
6
|
+
# we assume that the first file that requires 'sinatra' is the
|
7
|
+
# app_file. all other path related options are calculated based
|
8
|
+
# on this path by default.
|
5
9
|
set :app_file, lambda {
|
6
10
|
ignore = [
|
7
11
|
/lib\/sinatra.*\.rb$/, # all sinatra code
|
@@ -32,10 +36,6 @@ end
|
|
32
36
|
|
33
37
|
include Sinatra::Delegator
|
34
38
|
|
35
|
-
def helpers(&block)
|
36
|
-
Sinatra::Application.send :class_eval, &block
|
37
|
-
end
|
38
|
-
|
39
39
|
def mime(ext, type)
|
40
40
|
ext = ".#{ext}" unless ext.to_s[0] == ?.
|
41
41
|
Rack::Mime::MIME_TYPES[ext.to_s] = type
|
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
|
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) ;
|
42
|
-
def head(path, *args, &b) ;
|
43
|
-
def post(path, *args, &b) ;
|
44
|
-
def put(path, *args, &b) ;
|
45
|
-
def delete(path, *args, &b) ;
|
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
|
-
|
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
|
-
|
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.
|
7
|
-
s.date = '2009-
|
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
|
-
|
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 < 43', body
|
438
|
+
end
|
439
|
+
end
|
data/test/mapped_error_test.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
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
|
data/test/middleware_test.rb
CHANGED
@@ -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'].
|
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
|