1
0
Fork 0
mirror of https://github.com/sinatra/sinatra synced 2023-03-27 23:18:01 -04:00
sinatra/test/mapped_error_test.rb
Eloy Pérez f10e571f4d
Minor cleaning setting up tests (#1875)
We use minitest for Sinatra's test suite but we weren't using its rake task. I've updated the Rakefile to require and use Minitest default rake task to simplify.

Another change is to rename the `helper.rb` file to `test_helper.rb` because I think that name is used more in the community and require it directly without calling `File.expand_path`
2023-02-12 19:09:35 +01:00

285 lines
7.1 KiB
Ruby

require_relative 'test_helper'
class FooError < RuntimeError
end
class FooNotFound < Sinatra::NotFound
end
class FooSpecialError < Sinatra::Error
def http_status; 501 end
end
class FooStatusOutOfRangeError < Sinatra::Error
def code; 4000 end
end
class FooWithCode < Sinatra::Error
def code; 419 end
end
class FirstError < RuntimeError; end
class SecondError < RuntimeError; end
class MappedErrorTest < Minitest::Test
def test_default
assert true
end
describe 'Exception Mappings' do
it 'invokes handlers registered with ::error when raised' do
mock_app do
set :raise_errors, false
error(FooError) { 'Foo!' }
get('/') { raise FooError }
end
get '/'
assert_equal 500, status
assert_equal 'Foo!', body
end
it 'passes the exception object to the error handler' do
mock_app do
set :raise_errors, false
error(FooError) { |e| assert_equal(FooError, e.class) }
get('/') { raise FooError }
end
get('/')
end
it 'uses the Exception handler if no matching handler found' do
mock_app do
set :raise_errors, false
error(Exception) { 'Exception!' }
get('/') { raise FooError }
end
get '/'
assert_equal 500, status
assert_equal 'Exception!', body
end
it 'walks down inheritance chain for errors' do
mock_app do
set :raise_errors, false
error(RuntimeError) { 'Exception!' }
get('/') { raise FooError }
end
get '/'
assert_equal 500, status
assert_equal 'Exception!', body
end
it 'favors subclass handler over superclass handler if available' do
mock_app do
set :raise_errors, false
error(Exception) { 'Exception!' }
error(FooError) { 'FooError!' }
error(RuntimeError) { 'Exception!' }
get('/') { raise FooError }
end
get '/'
assert_equal 500, status
assert_equal 'FooError!', body
end
it "sets env['sinatra.error'] to the rescued exception" do
mock_app do
set :raise_errors, false
error(FooError) do
assert env.include?('sinatra.error')
assert env['sinatra.error'].kind_of?(FooError)
'looks good'
end
get('/') { raise FooError }
end
get '/'
assert_equal 'looks good', body
end
it "raises errors from the app when raise_errors set and no handler defined" do
mock_app do
set :raise_errors, true
get('/') { raise FooError }
end
assert_raises(FooError) { get '/' }
end
it "calls error handlers before raising errors even when raise_errors is set" do
mock_app do
set :raise_errors, true
error(FooError) { "she's there." }
get('/') { raise FooError }
end
get '/'
assert_equal 500, status
end
it "never raises Sinatra::NotFound beyond the application" do
mock_app(Sinatra::Application) do
get('/') { raise Sinatra::NotFound }
end
get '/'
assert_equal 404, status
end
it "cascades for subclasses of Sinatra::NotFound" do
mock_app do
set :raise_errors, true
error(FooNotFound) { "foo! not found." }
get('/') { raise FooNotFound }
end
get '/'
assert_equal 404, status
assert_equal 'foo! not found.', body
end
it 'has a not_found method for backwards compatibility' do
mock_app { not_found { "Lost, are we?" } }
get '/test'
assert_equal 404, status
assert_equal "Lost, are we?", body
end
it 'inherits error mappings from base class' do
base = Class.new(Sinatra::Base)
base.error(FooError) { 'base class' }
mock_app(base) do
set :raise_errors, false
get('/') { raise FooError }
end
get '/'
assert_equal 'base class', body
end
it 'overrides error mappings in base class' do
base = Class.new(Sinatra::Base)
base.error(FooError) { 'base class' }
mock_app(base) do
set :raise_errors, false
error(FooError) { 'subclass' }
get('/') { raise FooError }
end
get '/'
assert_equal 'subclass', body
end
it 'honors Exception#http_status if present' do
mock_app do
set :raise_errors, false
error(501) { 'Foo!' }
get('/') { raise FooSpecialError }
end
get '/'
assert_equal 501, status
assert_equal 'Foo!', body
end
it 'does not use Exception#code by default' do
mock_app do
set :raise_errors, false
get('/') { raise FooWithCode }
end
get '/'
assert_equal 500, status
end
it 'uses Exception#code if use_code is enabled' do
mock_app do
set :raise_errors, false
set :use_code, true
get('/') { raise FooWithCode }
end
get '/'
assert_equal 419, status
end
it 'does not rely on Exception#code for invalid codes' do
mock_app do
set :raise_errors, false
set :use_code, true
get('/') { raise FooStatusOutOfRangeError }
end
get '/'
assert_equal 500, status
end
it "allows a stack of exception_handlers" do
mock_app do
set :raise_errors, false
error(FirstError) { 'First!' }
error(SecondError) { 'Second!' }
get('/'){ raise SecondError }
end
get '/'
assert_equal 500, status
assert_equal 'Second!', body
end
it "allows an exception handler to pass control to the next exception handler" do
mock_app do
set :raise_errors, false
error(500, FirstError) { 'First!' }
error(500, SecondError) { pass }
get('/') { raise 500 }
end
get '/'
assert_equal 500, status
assert_equal 'First!', body
end
it "allows an exception handler to handle the exception" do
mock_app do
set :raise_errors, false
error(500, FirstError) { 'First!' }
error(500, SecondError) { 'Second!' }
get('/') { raise 500 }
end
get '/'
assert_equal 500, status
assert_equal 'Second!', body
end
end
describe 'Custom Error Pages' do
it 'allows numeric status code mappings to be registered with ::error' do
mock_app do
set :raise_errors, false
error(500) { 'Foo!' }
get('/') { [500, {}, 'Internal Foo Error'] }
end
get '/'
assert_equal 500, status
assert_equal 'Foo!', body
end
it 'allows ranges of status code mappings to be registered with :error' do
mock_app do
set :raise_errors, false
error(500..550) { "Error: #{response.status}" }
get('/') { [507, {}, 'A very special error'] }
end
get '/'
assert_equal 507, status
assert_equal 'Error: 507', body
end
it 'allows passing more than one range' do
mock_app do
set :raise_errors, false
error(409..411, 503..509) { "Error: #{response.status}" }
get('/') { [507, {}, 'A very special error'] }
end
get '/'
assert_equal 507, status
assert_equal 'Error: 507', body
end
end
end