2013-03-25 22:32:34 -04:00
|
|
|
require 'multi_json'
|
|
|
|
|
2014-05-09 02:39:16 -04:00
|
|
|
require 'spec_helper'
|
|
|
|
require 'okjson'
|
2011-03-25 19:02:03 -04:00
|
|
|
|
2022-02-05 07:27:48 -05:00
|
|
|
RSpec.describe Sinatra::RespondWith do
|
2011-03-25 19:02:03 -04:00
|
|
|
def respond_app(&block)
|
|
|
|
mock_app do
|
|
|
|
set :app_file, __FILE__
|
|
|
|
set :views, root + '/respond_with'
|
|
|
|
register Sinatra::RespondWith
|
|
|
|
class_eval(&block)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def respond_to(*args, &block)
|
|
|
|
respond_app { get('/') { respond_to(*args, &block) } }
|
|
|
|
end
|
|
|
|
|
|
|
|
def respond_with(*args, &block)
|
|
|
|
respond_app { get('/') { respond_with(*args, &block) } }
|
|
|
|
end
|
|
|
|
|
|
|
|
def req(*types)
|
2017-08-18 03:01:27 -04:00
|
|
|
path = types.shift if types.first.is_a?(String) && types.first.start_with?('/')
|
2011-03-25 19:02:03 -04:00
|
|
|
accept = types.map { |t| Sinatra::Base.mime_type(t).to_s }.join ','
|
2017-08-18 03:01:27 -04:00
|
|
|
get (path || '/'), {}, 'HTTP_ACCEPT' => accept
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
describe "Helpers#respond_to" do
|
|
|
|
it 'allows defining handlers by file extensions' do
|
|
|
|
respond_to do |format|
|
|
|
|
format.html { "html!" }
|
|
|
|
format.json { "json!" }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html).body).to eq("html!")
|
|
|
|
expect(req(:json).body).to eq("json!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'respects quality' do
|
|
|
|
respond_to do |format|
|
|
|
|
format.html { "html!" }
|
|
|
|
format.json { "json!" }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req("text/html;q=0.7, application/json;q=0.3").body).to eq("html!")
|
|
|
|
expect(req("text/html;q=0.3, application/json;q=0.7").body).to eq("json!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows using mime types' do
|
|
|
|
respond_to do |format|
|
|
|
|
format.on('text/html') { "html!" }
|
|
|
|
format.json { "json!" }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html).body).to eq("html!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows using wildcards in format matchers' do
|
|
|
|
respond_to do |format|
|
|
|
|
format.on('text/*') { "text!" }
|
|
|
|
format.json { "json!" }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html).body).to eq("text!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows using catch all wildcards in format matchers' do
|
|
|
|
respond_to do |format|
|
|
|
|
format.on('*/*') { "anything!" }
|
|
|
|
format.json { "json!" }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html).body).to eq("anything!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'prefers concret over generic' do
|
|
|
|
respond_to do |format|
|
|
|
|
format.on('text/*') { "text!" }
|
|
|
|
format.on('*/*') { "anything!" }
|
|
|
|
format.json { "json!" }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:json).body).to eq("json!")
|
|
|
|
expect(req(:html).body).to eq("text!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not set up default handlers' do
|
|
|
|
respond_to
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req).not_to be_ok
|
2016-07-21 06:18:17 -04:00
|
|
|
expect(status).to eq(500)
|
|
|
|
expect(body).to eq("Unknown template engine")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "Helpers#respond_with" do
|
|
|
|
describe "matching" do
|
|
|
|
it 'allows defining handlers by file extensions' do
|
|
|
|
respond_with(:ignore) do |format|
|
|
|
|
format.html { "html!" }
|
|
|
|
format.json { "json!" }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html).body).to eq("html!")
|
|
|
|
expect(req(:json).body).to eq("json!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'respects quality' do
|
|
|
|
respond_with(:ignore) do |format|
|
|
|
|
format.html { "html!" }
|
|
|
|
format.json { "json!" }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req("text/html;q=0.7, application/json;q=0.3").body).to eq("html!")
|
|
|
|
expect(req("text/html;q=0.3, application/json;q=0.7").body).to eq("json!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows using mime types' do
|
|
|
|
respond_with(:ignore) do |format|
|
|
|
|
format.on('text/html') { "html!" }
|
|
|
|
format.json { "json!" }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html).body).to eq("html!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows using wildcards in format matchers' do
|
|
|
|
respond_with(:ignore) do |format|
|
|
|
|
format.on('text/*') { "text!" }
|
|
|
|
format.json { "json!" }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html).body).to eq("text!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'allows using catch all wildcards in format matchers' do
|
|
|
|
respond_with(:ignore) do |format|
|
|
|
|
format.on('*/*') { "anything!" }
|
|
|
|
format.json { "json!" }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html).body).to eq("anything!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'prefers concret over generic' do
|
|
|
|
respond_with(:ignore) do |format|
|
|
|
|
format.on('text/*') { "text!" }
|
|
|
|
format.on('*/*') { "anything!" }
|
|
|
|
format.json { "json!" }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:json).body).to eq("json!")
|
|
|
|
expect(req(:html).body).to eq("text!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "default behavior" do
|
|
|
|
it 'converts objects to json out of the box' do
|
|
|
|
respond_with 'a' => 'b'
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(OkJson.decode(req(:json).body)).to eq({'a' => 'b'})
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'handles multiple routes correctly' do
|
|
|
|
respond_app do
|
|
|
|
get('/') { respond_with 'a' => 'b' }
|
|
|
|
get('/:name') { respond_with 'a' => params[:name] }
|
|
|
|
end
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(OkJson.decode(req('/', :json).body)).to eq({'a' => 'b'})
|
|
|
|
expect(OkJson.decode(req('/b', :json).body)).to eq({'a' => 'b'})
|
|
|
|
expect(OkJson.decode(req('/c', :json).body)).to eq({'a' => 'c'})
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "calls to_EXT if available" do
|
|
|
|
respond_with Struct.new(:to_pdf).new("hello")
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:pdf).body).to eq("hello")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
2016-07-21 06:18:17 -04:00
|
|
|
it 'results in a 500 if format cannot be produced' do
|
2011-03-25 19:02:03 -04:00
|
|
|
respond_with({})
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html)).not_to be_ok
|
2016-07-21 06:18:17 -04:00
|
|
|
expect(status).to eq(500)
|
|
|
|
expect(body).to eq("Unknown template engine")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'templates' do
|
|
|
|
it 'looks for templates with name.target.engine' do
|
|
|
|
respond_with :foo, :name => 'World'
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html)).to be_ok
|
|
|
|
expect(body).to eq("Hello World!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'looks for templates with name.engine for specific engines' do
|
|
|
|
respond_with :bar
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html)).to be_ok
|
|
|
|
expect(body).to eq("guten Tag!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'does not use name.engine for engines producing other formats' do
|
|
|
|
respond_with :not_html
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html)).not_to be_ok
|
2016-07-21 06:18:17 -04:00
|
|
|
expect(status).to eq(500)
|
|
|
|
expect(body).to eq("Unknown template engine")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
2011-05-09 02:03:34 -04:00
|
|
|
it 'falls back to #json if no template is found' do
|
2011-03-25 19:02:03 -04:00
|
|
|
respond_with :foo, :name => 'World'
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:json)).to be_ok
|
|
|
|
expect(OkJson.decode(body)).to eq({'name' => 'World'})
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
2011-05-09 02:03:34 -04:00
|
|
|
it 'favors templates over #json' do
|
2011-03-25 19:02:03 -04:00
|
|
|
respond_with :bar, :name => 'World'
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:json)).to be_ok
|
|
|
|
expect(body).to eq('json!')
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
2011-05-09 02:03:34 -04:00
|
|
|
|
|
|
|
it 'falls back to to_EXT if no template is found' do
|
|
|
|
object = {:name => 'World'}
|
|
|
|
def object.to_pdf; "hi" end
|
|
|
|
respond_with :foo, object
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:pdf)).to be_ok
|
|
|
|
expect(body).to eq("hi")
|
2011-05-09 02:03:34 -04:00
|
|
|
end
|
2013-03-25 23:27:25 -04:00
|
|
|
|
2013-04-05 18:09:30 -04:00
|
|
|
unless defined? JRUBY_VERSION
|
|
|
|
it 'uses yajl for json' do
|
|
|
|
respond_with :baz
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:json)).to be_ok
|
|
|
|
expect(body).to eq("\"yajl!\"")
|
2013-04-05 18:09:30 -04:00
|
|
|
end
|
2013-03-25 23:27:25 -04:00
|
|
|
end
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
describe 'customizing' do
|
|
|
|
it 'allows customizing' do
|
|
|
|
respond_with(:foo, :name => 'World') { |f| f.html { 'html!' }}
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html)).to be_ok
|
|
|
|
expect(body).to eq("html!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'falls back to default behavior if none matches' do
|
|
|
|
respond_with(:foo, :name => 'World') { |f| f.json { 'json!' }}
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html)).to be_ok
|
|
|
|
expect(body).to eq("Hello World!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'favors generic rule over default behavior' do
|
|
|
|
respond_with(:foo, :name => 'World') { |f| f.on('*/*') { 'generic!' }}
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req(:html)).to be_ok
|
|
|
|
expect(body).to eq("generic!")
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
end
|
2013-08-16 17:25:55 -04:00
|
|
|
|
|
|
|
describe "inherited" do
|
|
|
|
it "registers RespondWith in an inherited app" do
|
2013-08-19 14:44:07 -04:00
|
|
|
app = Sinatra.new do
|
|
|
|
set :app_file, __FILE__
|
|
|
|
set :views, root + '/respond_with'
|
2013-08-16 17:25:55 -04:00
|
|
|
register Sinatra::RespondWith
|
|
|
|
|
|
|
|
get '/a' do
|
|
|
|
respond_with :json
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-08-19 14:44:07 -04:00
|
|
|
self.app = Sinatra.new(app)
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req('/a', :json)).not_to be_ok
|
2013-08-16 17:25:55 -04:00
|
|
|
end
|
|
|
|
end
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
describe :respond_to do
|
2011-03-25 19:16:40 -04:00
|
|
|
it 'acts as global provides condition' do
|
|
|
|
respond_app do
|
|
|
|
respond_to :json, :html
|
|
|
|
get('/a') { 'ok' }
|
|
|
|
get('/b') { 'ok' }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req('/b', :xml)).not_to be_ok
|
|
|
|
expect(req('/b', :html)).to be_ok
|
2011-03-25 19:16:40 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'still allows provides' do
|
|
|
|
respond_app do
|
|
|
|
respond_to :json, :html
|
|
|
|
get('/a') { 'ok' }
|
|
|
|
get('/b', :provides => :json) { 'ok' }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req('/b', :html)).not_to be_ok
|
|
|
|
expect(req('/b', :json)).to be_ok
|
2011-03-25 19:16:40 -04:00
|
|
|
end
|
2011-03-25 19:22:19 -04:00
|
|
|
|
|
|
|
it 'plays well with namespaces' do
|
|
|
|
respond_app do
|
|
|
|
register Sinatra::Namespace
|
|
|
|
namespace '/a' do
|
|
|
|
respond_to :json
|
|
|
|
get { 'json' }
|
|
|
|
end
|
|
|
|
get('/b') { 'anything' }
|
|
|
|
end
|
|
|
|
|
2016-05-10 10:08:54 -04:00
|
|
|
expect(req('/a', :html)).not_to be_ok
|
|
|
|
expect(req('/b', :html)).to be_ok
|
2011-03-25 19:22:19 -04:00
|
|
|
end
|
2011-03-25 19:02:03 -04:00
|
|
|
end
|
|
|
|
end
|