2009-01-13 12:53:53 -05:00
|
|
|
require File.dirname(__FILE__) + '/helper'
|
2008-12-13 16:06:02 -05:00
|
|
|
|
|
|
|
describe "Routing" do
|
|
|
|
%w[get put post delete head].each do |verb|
|
|
|
|
it "defines #{verb.upcase} request handlers with #{verb}" do
|
|
|
|
mock_app {
|
|
|
|
send verb, '/hello' do
|
|
|
|
'Hello World'
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
request = Rack::MockRequest.new(@app)
|
|
|
|
response = request.request(verb.upcase, '/hello', {})
|
|
|
|
response.should.be.ok
|
|
|
|
response.body.should.equal 'Hello World'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
it "404s when no route satisfies the request" do
|
|
|
|
mock_app {
|
|
|
|
get('/foo') { }
|
|
|
|
}
|
|
|
|
get '/bar'
|
|
|
|
status.should.equal 404
|
|
|
|
end
|
|
|
|
|
|
|
|
it "exposes params with indifferent hash" do
|
|
|
|
mock_app {
|
|
|
|
get '/:foo' do
|
|
|
|
params['foo'].should.equal 'bar'
|
|
|
|
params[:foo].should.equal 'bar'
|
|
|
|
'well, alright'
|
|
|
|
end
|
|
|
|
}
|
|
|
|
get '/bar'
|
|
|
|
body.should.equal 'well, alright'
|
|
|
|
end
|
|
|
|
|
|
|
|
it "merges named params and query string params in params" do
|
|
|
|
mock_app {
|
|
|
|
get '/:foo' do
|
|
|
|
params['foo'].should.equal 'bar'
|
|
|
|
params['baz'].should.equal 'biz'
|
|
|
|
end
|
|
|
|
}
|
|
|
|
get '/bar?baz=biz'
|
|
|
|
should.be.ok
|
|
|
|
end
|
|
|
|
|
|
|
|
it "supports named params like /hello/:person" do
|
|
|
|
mock_app {
|
|
|
|
get '/hello/:person' do
|
|
|
|
"Hello #{params['person']}"
|
|
|
|
end
|
|
|
|
}
|
|
|
|
get '/hello/Frank'
|
|
|
|
body.should.equal 'Hello Frank'
|
|
|
|
end
|
|
|
|
|
|
|
|
it "supports optional named params like /?:foo?/?:bar?" do
|
|
|
|
mock_app {
|
|
|
|
get '/?:foo?/?:bar?' do
|
|
|
|
"foo=#{params[:foo]};bar=#{params[:bar]}"
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/hello/world'
|
|
|
|
should.be.ok
|
|
|
|
body.should.equal "foo=hello;bar=world"
|
|
|
|
|
|
|
|
get '/hello'
|
|
|
|
should.be.ok
|
|
|
|
body.should.equal "foo=hello;bar="
|
|
|
|
|
|
|
|
get '/'
|
|
|
|
should.be.ok
|
|
|
|
body.should.equal "foo=;bar="
|
|
|
|
end
|
|
|
|
|
|
|
|
it "supports single splat params like /*" do
|
|
|
|
mock_app {
|
|
|
|
get '/*' do
|
|
|
|
params['splat'].should.be.kind_of Array
|
|
|
|
params['splat'].join "\n"
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/foo'
|
|
|
|
body.should.equal "foo"
|
|
|
|
|
|
|
|
get '/foo/bar/baz'
|
|
|
|
body.should.equal "foo/bar/baz"
|
|
|
|
end
|
|
|
|
|
|
|
|
it "supports mixing multiple splat params like /*/foo/*/*" do
|
|
|
|
mock_app {
|
|
|
|
get '/*/foo/*/*' do
|
|
|
|
params['splat'].should.be.kind_of Array
|
|
|
|
params['splat'].join "\n"
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/bar/foo/bling/baz/boom'
|
|
|
|
body.should.equal "bar\nbling\nbaz/boom"
|
|
|
|
|
|
|
|
get '/bar/foo/baz'
|
|
|
|
should.be.not_found
|
|
|
|
end
|
|
|
|
|
|
|
|
it "supports mixing named and splat params like /:foo/*" do
|
|
|
|
mock_app {
|
|
|
|
get '/:foo/*' do
|
|
|
|
params['foo'].should.equal 'foo'
|
|
|
|
params['splat'].should.equal ['bar/baz']
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/foo/bar/baz'
|
|
|
|
should.be.ok
|
|
|
|
end
|
|
|
|
|
|
|
|
it "supports paths that include spaces" do
|
|
|
|
mock_app {
|
|
|
|
get '/path with spaces' do
|
|
|
|
'looks good'
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/path%20with%20spaces'
|
|
|
|
should.be.ok
|
|
|
|
body.should.equal 'looks good'
|
|
|
|
end
|
|
|
|
|
|
|
|
it "URL decodes named parameters and splats" do
|
|
|
|
mock_app {
|
|
|
|
get '/:foo/*' do
|
|
|
|
params['foo'].should.equal 'hello world'
|
|
|
|
params['splat'].should.equal ['how are you']
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/hello%20world/how%20are%20you'
|
|
|
|
should.be.ok
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'supports regular expressions' do
|
|
|
|
mock_app {
|
|
|
|
get(/^\/foo...\/bar$/) do
|
|
|
|
'Hello World'
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/foooom/bar'
|
|
|
|
should.be.ok
|
|
|
|
body.should.equal 'Hello World'
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'makes regular expression captures available in params[:captures]' do
|
|
|
|
mock_app {
|
|
|
|
get(/^\/fo(.*)\/ba(.*)/) do
|
|
|
|
params[:captures].should.equal ['orooomma', 'f']
|
|
|
|
'right on'
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/foorooomma/baf'
|
|
|
|
should.be.ok
|
|
|
|
body.should.equal 'right on'
|
|
|
|
end
|
|
|
|
|
|
|
|
it "returns response immediately on halt" do
|
|
|
|
mock_app {
|
|
|
|
get '/' do
|
|
|
|
halt 'Hello World'
|
|
|
|
'Boo-hoo World'
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/'
|
|
|
|
should.be.ok
|
|
|
|
body.should.equal 'Hello World'
|
|
|
|
end
|
|
|
|
|
|
|
|
it "transitions to the next matching route on pass" do
|
|
|
|
mock_app {
|
|
|
|
get '/:foo' do
|
|
|
|
pass
|
|
|
|
'Hello Foo'
|
|
|
|
end
|
|
|
|
|
|
|
|
get '/*' do
|
|
|
|
params.should.not.include 'foo'
|
|
|
|
'Hello World'
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/bar'
|
|
|
|
should.be.ok
|
|
|
|
body.should.equal 'Hello World'
|
|
|
|
end
|
|
|
|
|
|
|
|
it "transitions to 404 when passed and no subsequent route matches" do
|
|
|
|
mock_app {
|
|
|
|
get '/:foo' do
|
|
|
|
pass
|
|
|
|
'Hello Foo'
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/bar'
|
|
|
|
should.be.not_found
|
|
|
|
end
|
|
|
|
|
|
|
|
it "passes when matching condition returns false" do
|
|
|
|
mock_app {
|
|
|
|
condition { params[:foo] == 'bar' }
|
|
|
|
get '/:foo' do
|
|
|
|
'Hello World'
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/bar'
|
|
|
|
should.be.ok
|
|
|
|
body.should.equal 'Hello World'
|
|
|
|
|
|
|
|
get '/foo'
|
|
|
|
should.be.not_found
|
|
|
|
end
|
|
|
|
|
|
|
|
it "does not pass when matching condition returns nil" do
|
|
|
|
mock_app {
|
|
|
|
condition { nil }
|
|
|
|
get '/:foo' do
|
|
|
|
'Hello World'
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/bar'
|
|
|
|
should.be.ok
|
|
|
|
body.should.equal 'Hello World'
|
|
|
|
end
|
|
|
|
|
|
|
|
it "passes to next route when condition calls pass explicitly" do
|
|
|
|
mock_app {
|
|
|
|
condition { pass unless params[:foo] == 'bar' }
|
|
|
|
get '/:foo' do
|
|
|
|
'Hello World'
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/bar'
|
|
|
|
should.be.ok
|
|
|
|
body.should.equal 'Hello World'
|
|
|
|
|
|
|
|
get '/foo'
|
|
|
|
should.be.not_found
|
|
|
|
end
|
|
|
|
|
|
|
|
it "passes to the next route when host_name does not match" do
|
|
|
|
mock_app {
|
|
|
|
host_name 'example.com'
|
|
|
|
get '/foo' do
|
|
|
|
'Hello World'
|
|
|
|
end
|
|
|
|
}
|
|
|
|
get '/foo'
|
|
|
|
should.be.not_found
|
|
|
|
|
|
|
|
get '/foo', :env => { 'HTTP_HOST' => 'example.com' }
|
|
|
|
status.should.equal 200
|
|
|
|
body.should.equal 'Hello World'
|
|
|
|
end
|
|
|
|
|
|
|
|
it "passes to the next route when user_agent does not match" do
|
|
|
|
mock_app {
|
2009-01-09 04:49:49 -05:00
|
|
|
user_agent(/Foo/)
|
2008-12-13 16:06:02 -05:00
|
|
|
get '/foo' do
|
|
|
|
'Hello World'
|
|
|
|
end
|
|
|
|
}
|
|
|
|
get '/foo'
|
|
|
|
should.be.not_found
|
|
|
|
|
|
|
|
get '/foo', :env => { 'HTTP_USER_AGENT' => 'Foo Bar' }
|
|
|
|
status.should.equal 200
|
|
|
|
body.should.equal 'Hello World'
|
|
|
|
end
|
|
|
|
|
|
|
|
it "makes captures in user agent pattern available in params[:agent]" do
|
|
|
|
mock_app {
|
2009-01-09 04:49:49 -05:00
|
|
|
user_agent(/Foo (.*)/)
|
2008-12-13 16:06:02 -05:00
|
|
|
get '/foo' do
|
|
|
|
'Hello ' + params[:agent].first
|
|
|
|
end
|
|
|
|
}
|
|
|
|
get '/foo', :env => { 'HTTP_USER_AGENT' => 'Foo Bar' }
|
|
|
|
status.should.equal 200
|
|
|
|
body.should.equal 'Hello Bar'
|
|
|
|
end
|
2009-01-07 14:32:31 -05:00
|
|
|
|
|
|
|
it "filters by accept header" do
|
|
|
|
mock_app {
|
|
|
|
get '/', :provides => :xml do
|
|
|
|
request.env['HTTP_ACCEPT']
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
get '/', :env => { :accept => 'application/xml' }
|
|
|
|
should.be.ok
|
|
|
|
body.should.equal 'application/xml'
|
|
|
|
response.headers['Content-Type'].should.equal 'application/xml'
|
|
|
|
|
|
|
|
get '/', :env => { :accept => 'text/html' }
|
|
|
|
should.not.be.ok
|
|
|
|
end
|
|
|
|
|
|
|
|
it "allows multiple mime types for accept header" do
|
|
|
|
types = ['image/jpeg', 'image/pjpeg']
|
|
|
|
|
|
|
|
mock_app {
|
|
|
|
get '/', :provides => types do
|
|
|
|
request.env['HTTP_ACCEPT']
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
types.each do |type|
|
|
|
|
get '/', :env => { :accept => type }
|
|
|
|
should.be.ok
|
|
|
|
body.should.equal type
|
|
|
|
response.headers['Content-Type'].should.equal type
|
|
|
|
end
|
|
|
|
end
|
2008-12-13 16:06:02 -05:00
|
|
|
end
|