adamwiggins-sinatra 0.8.9
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 +40 -0
- data/CHANGES +167 -0
- data/LICENSE +22 -0
- data/README.rdoc +529 -0
- data/Rakefile +180 -0
- data/compat/app_test.rb +300 -0
- data/compat/application_test.rb +334 -0
- data/compat/builder_test.rb +101 -0
- data/compat/custom_error_test.rb +62 -0
- data/compat/erb_test.rb +136 -0
- data/compat/events_test.rb +75 -0
- data/compat/filter_test.rb +30 -0
- data/compat/haml_test.rb +233 -0
- data/compat/helper.rb +21 -0
- data/compat/mapped_error_test.rb +72 -0
- data/compat/pipeline_test.rb +71 -0
- data/compat/public/foo.xml +1 -0
- data/compat/sass_test.rb +57 -0
- data/compat/sessions_test.rb +39 -0
- data/compat/streaming_test.rb +121 -0
- data/compat/sym_params_test.rb +19 -0
- data/compat/template_test.rb +30 -0
- data/compat/use_in_file_templates_test.rb +47 -0
- data/compat/views/foo.builder +1 -0
- data/compat/views/foo.erb +1 -0
- data/compat/views/foo.haml +1 -0
- data/compat/views/foo.sass +2 -0
- data/compat/views/foo_layout.erb +2 -0
- data/compat/views/foo_layout.haml +2 -0
- data/compat/views/layout_test/foo.builder +1 -0
- data/compat/views/layout_test/foo.erb +1 -0
- data/compat/views/layout_test/foo.haml +1 -0
- data/compat/views/layout_test/foo.sass +2 -0
- data/compat/views/layout_test/layout.builder +3 -0
- data/compat/views/layout_test/layout.erb +1 -0
- data/compat/views/layout_test/layout.haml +1 -0
- data/compat/views/layout_test/layout.sass +2 -0
- data/compat/views/no_layout/no_layout.builder +1 -0
- data/compat/views/no_layout/no_layout.haml +1 -0
- data/lib/sinatra/base.rb +818 -0
- data/lib/sinatra/compat.rb +239 -0
- data/lib/sinatra/images/404.png +0 -0
- data/lib/sinatra/images/500.png +0 -0
- data/lib/sinatra/main.rb +48 -0
- data/lib/sinatra/test/rspec.rb +2 -0
- data/lib/sinatra/test/spec.rb +2 -0
- data/lib/sinatra/test/unit.rb +11 -0
- data/lib/sinatra/test.rb +112 -0
- data/lib/sinatra.rb +3 -0
- data/sinatra.gemspec +107 -0
- data/test/base_test.rb +72 -0
- data/test/builder_test.rb +68 -0
- data/test/data/reload_app_file.rb +3 -0
- data/test/erb_test.rb +55 -0
- data/test/filter_test.rb +39 -0
- data/test/haml_test.rb +72 -0
- data/test/helpers_test.rb +368 -0
- data/test/mapped_error_test.rb +164 -0
- data/test/middleware_test.rb +63 -0
- data/test/options_test.rb +103 -0
- data/test/reload_test.rb +65 -0
- data/test/request_test.rb +11 -0
- data/test/result_test.rb +92 -0
- data/test/routing_test.rb +338 -0
- data/test/sass_test.rb +40 -0
- data/test/sinatra_test.rb +15 -0
- data/test/static_test.rb +60 -0
- data/test/templates_test.rb +92 -0
- data/test/views/hello.builder +1 -0
- data/test/views/hello.erb +1 -0
- data/test/views/hello.haml +1 -0
- data/test/views/hello.sass +2 -0
- data/test/views/hello.test +1 -0
- data/test/views/layout2.builder +3 -0
- data/test/views/layout2.erb +2 -0
- data/test/views/layout2.haml +2 -0
- data/test/views/layout2.test +1 -0
- metadata +159 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require 'test/spec'
|
|
2
|
+
require 'sinatra/base'
|
|
3
|
+
require 'sinatra/test'
|
|
4
|
+
|
|
5
|
+
describe "Middleware" do
|
|
6
|
+
include Sinatra::Test
|
|
7
|
+
|
|
8
|
+
before do
|
|
9
|
+
@app = mock_app(Sinatra::Default) {
|
|
10
|
+
get '/*' do
|
|
11
|
+
response.headers['X-Tests'] = env['test.ran'].join(', ')
|
|
12
|
+
env['PATH_INFO']
|
|
13
|
+
end
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class MockMiddleware < Struct.new(:app)
|
|
18
|
+
def call(env)
|
|
19
|
+
(env['test.ran'] ||= []) << self.class.to_s
|
|
20
|
+
app.call(env)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class UpcaseMiddleware < MockMiddleware
|
|
25
|
+
def call(env)
|
|
26
|
+
env['PATH_INFO'] = env['PATH_INFO'].upcase
|
|
27
|
+
super
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "is added with Sinatra::Application.use" do
|
|
32
|
+
@app.use UpcaseMiddleware
|
|
33
|
+
get '/hello-world'
|
|
34
|
+
response.should.be.ok
|
|
35
|
+
body.should.equal '/HELLO-WORLD'
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class DowncaseMiddleware < MockMiddleware
|
|
39
|
+
def call(env)
|
|
40
|
+
env['PATH_INFO'] = env['PATH_INFO'].downcase
|
|
41
|
+
super
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
specify "runs in the order defined" do
|
|
46
|
+
@app.use UpcaseMiddleware
|
|
47
|
+
@app.use DowncaseMiddleware
|
|
48
|
+
get '/Foo'
|
|
49
|
+
body.should.equal "/foo"
|
|
50
|
+
response['X-Tests'].should.equal "UpcaseMiddleware, DowncaseMiddleware"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
specify "resets the prebuilt pipeline when new middleware is added" do
|
|
54
|
+
@app.use UpcaseMiddleware
|
|
55
|
+
get '/Foo'
|
|
56
|
+
body.should.equal "/FOO"
|
|
57
|
+
@app.use DowncaseMiddleware
|
|
58
|
+
get '/Foo'
|
|
59
|
+
body.should.equal '/foo'
|
|
60
|
+
response['X-Tests'].should.equal "UpcaseMiddleware, DowncaseMiddleware"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
require 'test/spec'
|
|
2
|
+
require 'sinatra/base'
|
|
3
|
+
require 'sinatra/test'
|
|
4
|
+
|
|
5
|
+
describe 'Options' do
|
|
6
|
+
include Sinatra::Test
|
|
7
|
+
|
|
8
|
+
before do
|
|
9
|
+
@app = Class.new(Sinatra::Base)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'sets options to literal values' do
|
|
13
|
+
@app.set(:foo, 'bar')
|
|
14
|
+
@app.should.respond_to? :foo
|
|
15
|
+
@app.foo.should.equal 'bar'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'sets options to Procs' do
|
|
19
|
+
@app.set(:foo, Proc.new { 'baz' })
|
|
20
|
+
@app.should.respond_to? :foo
|
|
21
|
+
@app.foo.should.equal 'baz'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "sets multiple options with a Hash" do
|
|
25
|
+
@app.set :foo => 1234,
|
|
26
|
+
:bar => 'Hello World',
|
|
27
|
+
:baz => Proc.new { 'bizzle' }
|
|
28
|
+
@app.foo.should.equal 1234
|
|
29
|
+
@app.bar.should.equal 'Hello World'
|
|
30
|
+
@app.baz.should.equal 'bizzle'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'inherits option methods when subclassed' do
|
|
34
|
+
@app.set :foo, 'bar'
|
|
35
|
+
@app.set :biz, Proc.new { 'baz' }
|
|
36
|
+
|
|
37
|
+
sub = Class.new(@app)
|
|
38
|
+
sub.should.respond_to :foo
|
|
39
|
+
sub.foo.should.equal 'bar'
|
|
40
|
+
sub.should.respond_to :biz
|
|
41
|
+
sub.biz.should.equal 'baz'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'overrides options in subclass' do
|
|
45
|
+
@app.set :foo, 'bar'
|
|
46
|
+
@app.set :biz, Proc.new { 'baz' }
|
|
47
|
+
sub = Class.new(@app)
|
|
48
|
+
sub.set :foo, 'bling'
|
|
49
|
+
sub.foo.should.equal 'bling'
|
|
50
|
+
@app.foo.should.equal 'bar'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'creates setter methods when first defined' do
|
|
54
|
+
@app.set :foo, 'bar'
|
|
55
|
+
@app.should.respond_to 'foo='
|
|
56
|
+
@app.foo = 'biz'
|
|
57
|
+
@app.foo.should.equal 'biz'
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'creates predicate methods when first defined' do
|
|
61
|
+
@app.set :foo, 'hello world'
|
|
62
|
+
@app.should.respond_to :foo?
|
|
63
|
+
@app.foo?.should.be true
|
|
64
|
+
@app.set :foo, nil
|
|
65
|
+
@app.foo?.should.be false
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'uses existing setter methods if detected' do
|
|
69
|
+
class << @app
|
|
70
|
+
def foo
|
|
71
|
+
@foo
|
|
72
|
+
end
|
|
73
|
+
def foo=(value)
|
|
74
|
+
@foo = 'oops'
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
@app.set :foo, 'bam'
|
|
79
|
+
@app.foo.should.equal 'oops'
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "sets multiple options to true with #enable" do
|
|
83
|
+
@app.enable :sessions, :foo, :bar
|
|
84
|
+
@app.sessions.should.be true
|
|
85
|
+
@app.foo.should.be true
|
|
86
|
+
@app.bar.should.be true
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "sets multiple options to false with #disable" do
|
|
90
|
+
@app.disable :sessions, :foo, :bar
|
|
91
|
+
@app.sessions.should.be false
|
|
92
|
+
@app.foo.should.be false
|
|
93
|
+
@app.bar.should.be false
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'enables MethodOverride middleware when :methodoverride is enabled' do
|
|
97
|
+
@app.set :methodoverride, true
|
|
98
|
+
@app.put('/') { 'okay' }
|
|
99
|
+
post '/', {'_method'=>'PUT'}, {}
|
|
100
|
+
status.should.equal 200
|
|
101
|
+
body.should.equal 'okay'
|
|
102
|
+
end
|
|
103
|
+
end
|
data/test/reload_test.rb
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'test/spec'
|
|
2
|
+
require 'sinatra/base'
|
|
3
|
+
require 'sinatra/test'
|
|
4
|
+
|
|
5
|
+
$reload_count = 0
|
|
6
|
+
$reload_app = nil
|
|
7
|
+
|
|
8
|
+
describe "Reloading" do
|
|
9
|
+
include Sinatra::Test
|
|
10
|
+
|
|
11
|
+
before {
|
|
12
|
+
@app = mock_app(Sinatra::Default)
|
|
13
|
+
$reload_app = @app
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
after {
|
|
17
|
+
$reload_app = nil
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
it 'is enabled by default when in development and the app_file is set' do
|
|
21
|
+
@app.set :app_file, __FILE__
|
|
22
|
+
@app.set :environment, :development
|
|
23
|
+
@app.reload.should.be true
|
|
24
|
+
@app.reload?.should.be true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'is disabled by default when running in non-development environment' do
|
|
28
|
+
@app.set :app_file, __FILE__
|
|
29
|
+
@app.set :environment, :test
|
|
30
|
+
@app.reload.should.not.be true
|
|
31
|
+
@app.reload?.should.be false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'is disabled by default when no app_file is available' do
|
|
35
|
+
@app.set :app_file, nil
|
|
36
|
+
@app.set :environment, :development
|
|
37
|
+
@app.reload.should.not.be true
|
|
38
|
+
@app.reload?.should.be false
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'can be turned off explicitly' do
|
|
42
|
+
@app.set :app_file, __FILE__
|
|
43
|
+
@app.set :environment, :development
|
|
44
|
+
@app.reload.should.be true
|
|
45
|
+
@app.set :reload, false
|
|
46
|
+
@app.reload.should.be false
|
|
47
|
+
@app.reload?.should.be false
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'reloads the app_file each time a request is made' do
|
|
51
|
+
@app.set :app_file, File.dirname(__FILE__) + '/data/reload_app_file.rb'
|
|
52
|
+
@app.set :reload, true
|
|
53
|
+
@app.get('/') { 'Hello World' }
|
|
54
|
+
|
|
55
|
+
get '/'
|
|
56
|
+
status.should.equal 200
|
|
57
|
+
body.should.equal 'Hello from reload file'
|
|
58
|
+
$reload_count.should.equal 1
|
|
59
|
+
|
|
60
|
+
get '/'
|
|
61
|
+
status.should.equal 200
|
|
62
|
+
body.should.equal 'Hello from reload file'
|
|
63
|
+
$reload_count.should.equal 2
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require 'test/spec'
|
|
2
|
+
require 'sinatra/base'
|
|
3
|
+
require 'sinatra/test'
|
|
4
|
+
|
|
5
|
+
describe 'Sinatra::Request' do
|
|
6
|
+
it 'responds to #user_agent' do
|
|
7
|
+
request = Sinatra::Request.new({'HTTP_USER_AGENT' => 'Test'})
|
|
8
|
+
request.should.respond_to :user_agent
|
|
9
|
+
request.user_agent.should.equal 'Test'
|
|
10
|
+
end
|
|
11
|
+
end
|
data/test/result_test.rb
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
require 'test/spec'
|
|
2
|
+
require 'sinatra/base'
|
|
3
|
+
require 'sinatra/test'
|
|
4
|
+
|
|
5
|
+
describe 'Result Handling' do
|
|
6
|
+
include Sinatra::Test
|
|
7
|
+
|
|
8
|
+
it "sets response.body when result is a String" do
|
|
9
|
+
mock_app {
|
|
10
|
+
get '/' do
|
|
11
|
+
'Hello World'
|
|
12
|
+
end
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
get '/'
|
|
16
|
+
should.be.ok
|
|
17
|
+
body.should.equal 'Hello World'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "sets response.body when result is an Array of Strings" do
|
|
21
|
+
mock_app {
|
|
22
|
+
get '/' do
|
|
23
|
+
['Hello', 'World']
|
|
24
|
+
end
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get '/'
|
|
28
|
+
should.be.ok
|
|
29
|
+
body.should.equal 'HelloWorld'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "sets response.body when result responds to #each" do
|
|
33
|
+
mock_app {
|
|
34
|
+
get '/' do
|
|
35
|
+
res = lambda { 'Hello World' }
|
|
36
|
+
def res.each ; yield call ; end
|
|
37
|
+
res
|
|
38
|
+
end
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
get '/'
|
|
42
|
+
should.be.ok
|
|
43
|
+
body.should.equal 'Hello World'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "sets response.body to [] when result is nil" do
|
|
47
|
+
mock_app {
|
|
48
|
+
get '/' do
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get '/'
|
|
54
|
+
should.be.ok
|
|
55
|
+
body.should.equal ''
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "sets status, headers, and body when result is a Rack response tuple" do
|
|
59
|
+
mock_app {
|
|
60
|
+
get '/' do
|
|
61
|
+
[205, {'Content-Type' => 'foo/bar'}, 'Hello World']
|
|
62
|
+
end
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get '/'
|
|
66
|
+
status.should.equal 205
|
|
67
|
+
response['Content-Type'].should.equal 'foo/bar'
|
|
68
|
+
body.should.equal 'Hello World'
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "sets status and body when result is a two-tuple" do
|
|
72
|
+
mock_app {
|
|
73
|
+
get '/' do
|
|
74
|
+
[409, 'formula of']
|
|
75
|
+
end
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
get '/'
|
|
79
|
+
status.should.equal 409
|
|
80
|
+
body.should.equal 'formula of'
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "sets status when result is a Fixnum status code" do
|
|
84
|
+
mock_app {
|
|
85
|
+
get('/') { 205 }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
get '/'
|
|
89
|
+
status.should.equal 205
|
|
90
|
+
body.should.be.empty
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
require 'test/spec'
|
|
2
|
+
require 'sinatra/base'
|
|
3
|
+
require 'sinatra/test'
|
|
4
|
+
|
|
5
|
+
describe "Routing" do
|
|
6
|
+
include Sinatra::Test
|
|
7
|
+
|
|
8
|
+
%w[get put post delete head].each do |verb|
|
|
9
|
+
it "defines #{verb.upcase} request handlers with #{verb}" do
|
|
10
|
+
mock_app {
|
|
11
|
+
send verb, '/hello' do
|
|
12
|
+
'Hello World'
|
|
13
|
+
end
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
request = Rack::MockRequest.new(@app)
|
|
17
|
+
response = request.request(verb.upcase, '/hello', {})
|
|
18
|
+
response.should.be.ok
|
|
19
|
+
response.body.should.equal 'Hello World'
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "404s when no route satisfies the request" do
|
|
24
|
+
mock_app {
|
|
25
|
+
get('/foo') { }
|
|
26
|
+
}
|
|
27
|
+
get '/bar'
|
|
28
|
+
status.should.equal 404
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "exposes params with indifferent hash" do
|
|
32
|
+
mock_app {
|
|
33
|
+
get '/:foo' do
|
|
34
|
+
params['foo'].should.equal 'bar'
|
|
35
|
+
params[:foo].should.equal 'bar'
|
|
36
|
+
'well, alright'
|
|
37
|
+
end
|
|
38
|
+
}
|
|
39
|
+
get '/bar'
|
|
40
|
+
body.should.equal 'well, alright'
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "merges named params and query string params in params" do
|
|
44
|
+
mock_app {
|
|
45
|
+
get '/:foo' do
|
|
46
|
+
params['foo'].should.equal 'bar'
|
|
47
|
+
params['baz'].should.equal 'biz'
|
|
48
|
+
end
|
|
49
|
+
}
|
|
50
|
+
get '/bar?baz=biz'
|
|
51
|
+
should.be.ok
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "supports named params like /hello/:person" do
|
|
55
|
+
mock_app {
|
|
56
|
+
get '/hello/:person' do
|
|
57
|
+
"Hello #{params['person']}"
|
|
58
|
+
end
|
|
59
|
+
}
|
|
60
|
+
get '/hello/Frank'
|
|
61
|
+
body.should.equal 'Hello Frank'
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "supports optional named params like /?:foo?/?:bar?" do
|
|
65
|
+
mock_app {
|
|
66
|
+
get '/?:foo?/?:bar?' do
|
|
67
|
+
"foo=#{params[:foo]};bar=#{params[:bar]}"
|
|
68
|
+
end
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
get '/hello/world'
|
|
72
|
+
should.be.ok
|
|
73
|
+
body.should.equal "foo=hello;bar=world"
|
|
74
|
+
|
|
75
|
+
get '/hello'
|
|
76
|
+
should.be.ok
|
|
77
|
+
body.should.equal "foo=hello;bar="
|
|
78
|
+
|
|
79
|
+
get '/'
|
|
80
|
+
should.be.ok
|
|
81
|
+
body.should.equal "foo=;bar="
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "supports single splat params like /*" do
|
|
85
|
+
mock_app {
|
|
86
|
+
get '/*' do
|
|
87
|
+
params['splat'].should.be.kind_of Array
|
|
88
|
+
params['splat'].join "\n"
|
|
89
|
+
end
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
get '/foo'
|
|
93
|
+
body.should.equal "foo"
|
|
94
|
+
|
|
95
|
+
get '/foo/bar/baz'
|
|
96
|
+
body.should.equal "foo/bar/baz"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "supports mixing multiple splat params like /*/foo/*/*" do
|
|
100
|
+
mock_app {
|
|
101
|
+
get '/*/foo/*/*' do
|
|
102
|
+
params['splat'].should.be.kind_of Array
|
|
103
|
+
params['splat'].join "\n"
|
|
104
|
+
end
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
get '/bar/foo/bling/baz/boom'
|
|
108
|
+
body.should.equal "bar\nbling\nbaz/boom"
|
|
109
|
+
|
|
110
|
+
get '/bar/foo/baz'
|
|
111
|
+
should.be.not_found
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "supports mixing named and splat params like /:foo/*" do
|
|
115
|
+
mock_app {
|
|
116
|
+
get '/:foo/*' do
|
|
117
|
+
params['foo'].should.equal 'foo'
|
|
118
|
+
params['splat'].should.equal ['bar/baz']
|
|
119
|
+
end
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
get '/foo/bar/baz'
|
|
123
|
+
should.be.ok
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "supports paths that include spaces" do
|
|
127
|
+
mock_app {
|
|
128
|
+
get '/path with spaces' do
|
|
129
|
+
'looks good'
|
|
130
|
+
end
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
get '/path%20with%20spaces'
|
|
134
|
+
should.be.ok
|
|
135
|
+
body.should.equal 'looks good'
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it "URL decodes named parameters and splats" do
|
|
139
|
+
mock_app {
|
|
140
|
+
get '/:foo/*' do
|
|
141
|
+
params['foo'].should.equal 'hello world'
|
|
142
|
+
params['splat'].should.equal ['how are you']
|
|
143
|
+
nil
|
|
144
|
+
end
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
get '/hello%20world/how%20are%20you'
|
|
148
|
+
should.be.ok
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it 'supports regular expressions' do
|
|
152
|
+
mock_app {
|
|
153
|
+
get(/^\/foo...\/bar$/) do
|
|
154
|
+
'Hello World'
|
|
155
|
+
end
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
get '/foooom/bar'
|
|
159
|
+
should.be.ok
|
|
160
|
+
body.should.equal 'Hello World'
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it 'makes regular expression captures available in params[:captures]' do
|
|
164
|
+
mock_app {
|
|
165
|
+
get(/^\/fo(.*)\/ba(.*)/) do
|
|
166
|
+
params[:captures].should.equal ['orooomma', 'f']
|
|
167
|
+
'right on'
|
|
168
|
+
end
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
get '/foorooomma/baf'
|
|
172
|
+
should.be.ok
|
|
173
|
+
body.should.equal 'right on'
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it "returns response immediately on halt" do
|
|
177
|
+
mock_app {
|
|
178
|
+
get '/' do
|
|
179
|
+
halt 'Hello World'
|
|
180
|
+
'Boo-hoo World'
|
|
181
|
+
end
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
get '/'
|
|
185
|
+
should.be.ok
|
|
186
|
+
body.should.equal 'Hello World'
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
it "transitions to the next matching route on pass" do
|
|
190
|
+
mock_app {
|
|
191
|
+
get '/:foo' do
|
|
192
|
+
pass
|
|
193
|
+
'Hello Foo'
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
get '/*' do
|
|
197
|
+
params.should.not.include 'foo'
|
|
198
|
+
'Hello World'
|
|
199
|
+
end
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
get '/bar'
|
|
203
|
+
should.be.ok
|
|
204
|
+
body.should.equal 'Hello World'
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it "transitions to 404 when passed and no subsequent route matches" do
|
|
208
|
+
mock_app {
|
|
209
|
+
get '/:foo' do
|
|
210
|
+
pass
|
|
211
|
+
'Hello Foo'
|
|
212
|
+
end
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
get '/bar'
|
|
216
|
+
should.be.not_found
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it "passes when matching condition returns false" do
|
|
220
|
+
mock_app {
|
|
221
|
+
condition { params[:foo] == 'bar' }
|
|
222
|
+
get '/:foo' do
|
|
223
|
+
'Hello World'
|
|
224
|
+
end
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
get '/bar'
|
|
228
|
+
should.be.ok
|
|
229
|
+
body.should.equal 'Hello World'
|
|
230
|
+
|
|
231
|
+
get '/foo'
|
|
232
|
+
should.be.not_found
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
it "does not pass when matching condition returns nil" do
|
|
236
|
+
mock_app {
|
|
237
|
+
condition { nil }
|
|
238
|
+
get '/:foo' do
|
|
239
|
+
'Hello World'
|
|
240
|
+
end
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
get '/bar'
|
|
244
|
+
should.be.ok
|
|
245
|
+
body.should.equal 'Hello World'
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
it "passes to next route when condition calls pass explicitly" do
|
|
249
|
+
mock_app {
|
|
250
|
+
condition { pass unless params[:foo] == 'bar' }
|
|
251
|
+
get '/:foo' do
|
|
252
|
+
'Hello World'
|
|
253
|
+
end
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
get '/bar'
|
|
257
|
+
should.be.ok
|
|
258
|
+
body.should.equal 'Hello World'
|
|
259
|
+
|
|
260
|
+
get '/foo'
|
|
261
|
+
should.be.not_found
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
it "passes to the next route when host_name does not match" do
|
|
265
|
+
mock_app {
|
|
266
|
+
host_name 'example.com'
|
|
267
|
+
get '/foo' do
|
|
268
|
+
'Hello World'
|
|
269
|
+
end
|
|
270
|
+
}
|
|
271
|
+
get '/foo'
|
|
272
|
+
should.be.not_found
|
|
273
|
+
|
|
274
|
+
get '/foo', :env => { 'HTTP_HOST' => 'example.com' }
|
|
275
|
+
status.should.equal 200
|
|
276
|
+
body.should.equal 'Hello World'
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it "passes to the next route when user_agent does not match" do
|
|
280
|
+
mock_app {
|
|
281
|
+
user_agent(/Foo/)
|
|
282
|
+
get '/foo' do
|
|
283
|
+
'Hello World'
|
|
284
|
+
end
|
|
285
|
+
}
|
|
286
|
+
get '/foo'
|
|
287
|
+
should.be.not_found
|
|
288
|
+
|
|
289
|
+
get '/foo', :env => { 'HTTP_USER_AGENT' => 'Foo Bar' }
|
|
290
|
+
status.should.equal 200
|
|
291
|
+
body.should.equal 'Hello World'
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
it "makes captures in user agent pattern available in params[:agent]" do
|
|
295
|
+
mock_app {
|
|
296
|
+
user_agent(/Foo (.*)/)
|
|
297
|
+
get '/foo' do
|
|
298
|
+
'Hello ' + params[:agent].first
|
|
299
|
+
end
|
|
300
|
+
}
|
|
301
|
+
get '/foo', :env => { 'HTTP_USER_AGENT' => 'Foo Bar' }
|
|
302
|
+
status.should.equal 200
|
|
303
|
+
body.should.equal 'Hello Bar'
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
it "filters by accept header" do
|
|
307
|
+
mock_app {
|
|
308
|
+
get '/', :provides => :xml do
|
|
309
|
+
request.env['HTTP_ACCEPT']
|
|
310
|
+
end
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
get '/', :env => { :accept => 'application/xml' }
|
|
314
|
+
should.be.ok
|
|
315
|
+
body.should.equal 'application/xml'
|
|
316
|
+
response.headers['Content-Type'].should.equal 'application/xml'
|
|
317
|
+
|
|
318
|
+
get '/', :env => { :accept => 'text/html' }
|
|
319
|
+
should.not.be.ok
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
it "allows multiple mime types for accept header" do
|
|
323
|
+
types = ['image/jpeg', 'image/pjpeg']
|
|
324
|
+
|
|
325
|
+
mock_app {
|
|
326
|
+
get '/', :provides => types do
|
|
327
|
+
request.env['HTTP_ACCEPT']
|
|
328
|
+
end
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
types.each do |type|
|
|
332
|
+
get '/', :env => { :accept => type }
|
|
333
|
+
should.be.ok
|
|
334
|
+
body.should.equal type
|
|
335
|
+
response.headers['Content-Type'].should.equal type
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
end
|
data/test/sass_test.rb
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'test/spec'
|
|
2
|
+
require 'sinatra/base'
|
|
3
|
+
require 'sinatra/test'
|
|
4
|
+
|
|
5
|
+
describe "Sass Templates" do
|
|
6
|
+
include Sinatra::Test
|
|
7
|
+
|
|
8
|
+
def sass_app(&block)
|
|
9
|
+
mock_app {
|
|
10
|
+
set :views, File.dirname(__FILE__) + '/views'
|
|
11
|
+
get '/', &block
|
|
12
|
+
}
|
|
13
|
+
get '/'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'renders inline Sass strings' do
|
|
17
|
+
sass_app { sass "#sass\n :background-color #FFF\n" }
|
|
18
|
+
should.be.ok
|
|
19
|
+
body.should.equal "#sass {\n background-color: #FFF; }\n"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'renders .sass files in views path' do
|
|
23
|
+
sass_app { sass :hello }
|
|
24
|
+
should.be.ok
|
|
25
|
+
body.should.equal "#sass {\n background-color: #FFF; }\n"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'ignores the layout option' do
|
|
29
|
+
sass_app { sass :hello, :layout => :layout2 }
|
|
30
|
+
should.be.ok
|
|
31
|
+
body.should.equal "#sass {\n background-color: #FFF; }\n"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "raises error if template not found" do
|
|
35
|
+
mock_app {
|
|
36
|
+
get('/') { sass :no_such_template }
|
|
37
|
+
}
|
|
38
|
+
lambda { get('/') }.should.raise(Errno::ENOENT)
|
|
39
|
+
end
|
|
40
|
+
end
|