grape 1.6.0 → 1.6.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/CONTRIBUTING.md +1 -0
- data/README.md +9 -1
- data/lib/grape/api.rb +12 -0
- data/lib/grape/dry_types.rb +12 -0
- data/lib/grape/dsl/headers.rb +5 -2
- data/lib/grape/dsl/helpers.rb +1 -1
- data/lib/grape/middleware/auth/dsl.rb +7 -1
- data/lib/grape/middleware/base.rb +1 -1
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/util/strict_hash_configuration.rb +1 -1
- data/lib/grape/validations/types/array_coercer.rb +0 -2
- data/lib/grape/validations/types/dry_type_coercer.rb +1 -10
- data/lib/grape/validations/types/json.rb +0 -2
- data/lib/grape/validations/types/primitive_coercer.rb +5 -7
- data/lib/grape/validations/types/set_coercer.rb +0 -3
- data/lib/grape/validations/types.rb +83 -9
- data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
- data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
- data/lib/grape/validations/validators/as_validator.rb +14 -0
- data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
- data/lib/grape/validations/validators/base.rb +73 -71
- data/lib/grape/validations/validators/coerce_validator.rb +75 -0
- data/lib/grape/validations/validators/default_validator.rb +51 -0
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
- data/lib/grape/validations/validators/except_values_validator.rb +24 -0
- data/lib/grape/validations/validators/multiple_params_base.rb +24 -22
- data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
- data/lib/grape/validations/validators/presence_validator.rb +15 -0
- data/lib/grape/validations/validators/regexp_validator.rb +16 -0
- data/lib/grape/validations/validators/same_as_validator.rb +29 -0
- data/lib/grape/validations/validators/values_validator.rb +88 -0
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +59 -24
- data/spec/grape/api/custom_validations_spec.rb +77 -46
- data/spec/grape/api/deeply_included_options_spec.rb +3 -3
- data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
- data/spec/grape/api/invalid_format_spec.rb +2 -0
- data/spec/grape/api/recognize_path_spec.rb +1 -1
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
- data/spec/grape/api_remount_spec.rb +16 -15
- data/spec/grape/api_spec.rb +317 -193
- data/spec/grape/dsl/callbacks_spec.rb +1 -0
- data/spec/grape/dsl/headers_spec.rb +39 -9
- data/spec/grape/dsl/helpers_spec.rb +3 -2
- data/spec/grape/dsl/inside_route_spec.rb +6 -4
- data/spec/grape/dsl/logger_spec.rb +16 -18
- data/spec/grape/dsl/middleware_spec.rb +1 -0
- data/spec/grape/dsl/parameters_spec.rb +1 -0
- data/spec/grape/dsl/request_response_spec.rb +1 -0
- data/spec/grape/dsl/routing_spec.rb +9 -6
- data/spec/grape/endpoint/declared_spec.rb +12 -12
- data/spec/grape/endpoint_spec.rb +59 -50
- data/spec/grape/entity_spec.rb +13 -13
- data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
- data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
- data/spec/grape/exceptions/validation_spec.rb +5 -3
- data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
- data/spec/grape/integration/rack_sendfile_spec.rb +1 -1
- data/spec/grape/loading_spec.rb +8 -8
- data/spec/grape/middleware/auth/dsl_spec.rb +14 -5
- data/spec/grape/middleware/auth/strategies_spec.rb +60 -20
- data/spec/grape/middleware/base_spec.rb +24 -15
- data/spec/grape/middleware/error_spec.rb +1 -0
- data/spec/grape/middleware/exception_spec.rb +111 -161
- data/spec/grape/middleware/formatter_spec.rb +25 -4
- data/spec/grape/middleware/globals_spec.rb +7 -4
- data/spec/grape/middleware/stack_spec.rb +11 -11
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
- data/spec/grape/middleware/versioner/header_spec.rb +14 -13
- data/spec/grape/middleware/versioner/param_spec.rb +7 -1
- data/spec/grape/middleware/versioner/path_spec.rb +5 -1
- data/spec/grape/middleware/versioner_spec.rb +1 -1
- data/spec/grape/parser_spec.rb +4 -0
- data/spec/grape/path_spec.rb +52 -52
- data/spec/grape/presenters/presenter_spec.rb +7 -6
- data/spec/grape/request_spec.rb +6 -4
- data/spec/grape/util/inheritable_setting_spec.rb +7 -7
- data/spec/grape/util/inheritable_values_spec.rb +3 -2
- data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
- data/spec/grape/util/stackable_values_spec.rb +7 -5
- data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -0
- data/spec/grape/validations/params_scope_spec.rb +9 -7
- data/spec/grape/validations/single_attribute_iterator_spec.rb +1 -0
- data/spec/grape/validations/types/primitive_coercer_spec.rb +2 -2
- data/spec/grape/validations/types_spec.rb +8 -8
- data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
- data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
- data/spec/grape/validations/validators/coerce_spec.rb +10 -12
- data/spec/grape/validations/validators/default_spec.rb +72 -78
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
- data/spec/grape/validations/validators/except_values_spec.rb +1 -1
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
- data/spec/grape/validations/validators/presence_spec.rb +16 -1
- data/spec/grape/validations/validators/regexp_spec.rb +25 -31
- data/spec/grape/validations/validators/same_as_spec.rb +14 -20
- data/spec/grape/validations/validators/values_spec.rb +172 -171
- data/spec/grape/validations_spec.rb +45 -16
- data/spec/integration/eager_load/eager_load_spec.rb +2 -2
- data/spec/integration/multi_json/json_spec.rb +1 -1
- data/spec/integration/multi_xml/xml_spec.rb +1 -1
- data/spec/shared/versioning_examples.rb +10 -7
- data/spec/spec_helper.rb +11 -1
- metadata +116 -116
- data/lib/grape/validations/types/build_coercer.rb +0 -94
- data/lib/grape/validations/validators/all_or_none.rb +0 -16
- data/lib/grape/validations/validators/allow_blank.rb +0 -18
- data/lib/grape/validations/validators/as.rb +0 -12
- data/lib/grape/validations/validators/at_least_one_of.rb +0 -15
- data/lib/grape/validations/validators/coerce.rb +0 -87
- data/lib/grape/validations/validators/default.rb +0 -49
- data/lib/grape/validations/validators/exactly_one_of.rb +0 -17
- data/lib/grape/validations/validators/except_values.rb +0 -22
- data/lib/grape/validations/validators/mutual_exclusion.rb +0 -16
- data/lib/grape/validations/validators/presence.rb +0 -13
- data/lib/grape/validations/validators/regexp.rb +0 -14
- data/lib/grape/validations/validators/same_as.rb +0 -27
- data/lib/grape/validations/validators/values.rb +0 -86
@@ -42,7 +42,17 @@ describe Grape::Middleware::Auth::Strategies do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
module StrategiesSpec
|
45
|
-
class
|
45
|
+
class PasswordHashed < Grape::API
|
46
|
+
http_digest(realm: { realm: 'Test Api', opaque: 'secret', passwords_hashed: true }) do |username|
|
47
|
+
{ 'foo' => Digest::MD5.hexdigest(['foo', 'Test Api', 'bar'].join(':')) }[username]
|
48
|
+
end
|
49
|
+
|
50
|
+
get '/test' do
|
51
|
+
[{ hey: 'you' }, { there: 'bar' }, { foo: 'baz' }]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class PasswordIsNotHashed < Grape::API
|
46
56
|
http_digest(realm: 'Test Api', opaque: 'secret') do |username|
|
47
57
|
{ 'foo' => 'bar' }[username]
|
48
58
|
end
|
@@ -53,30 +63,60 @@ describe Grape::Middleware::Auth::Strategies do
|
|
53
63
|
end
|
54
64
|
end
|
55
65
|
|
56
|
-
|
57
|
-
|
58
|
-
|
66
|
+
context 'when password is hashed' do
|
67
|
+
def app
|
68
|
+
StrategiesSpec::PasswordHashed
|
69
|
+
end
|
59
70
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
71
|
+
it 'is a digest authentication challenge' do
|
72
|
+
get '/test'
|
73
|
+
expect(last_response).to be_challenge
|
74
|
+
end
|
64
75
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
76
|
+
it 'throws a 401 if no auth is given' do
|
77
|
+
get '/test'
|
78
|
+
expect(last_response.status).to eq(401)
|
79
|
+
end
|
69
80
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
81
|
+
it 'authenticates if given valid creds' do
|
82
|
+
digest_authorize 'foo', 'bar'
|
83
|
+
get '/test'
|
84
|
+
expect(last_response.status).to eq(200)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'throws a 401 if given invalid creds' do
|
88
|
+
digest_authorize 'bar', 'foo'
|
89
|
+
get '/test'
|
90
|
+
expect(last_response.status).to eq(401)
|
91
|
+
end
|
74
92
|
end
|
75
93
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
94
|
+
context 'when password is not hashed' do
|
95
|
+
def app
|
96
|
+
StrategiesSpec::PasswordIsNotHashed
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'is a digest authentication challenge' do
|
100
|
+
get '/test'
|
101
|
+
expect(last_response).to be_challenge
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'throws a 401 if no auth is given' do
|
105
|
+
get '/test'
|
106
|
+
expect(last_response.status).to eq(401)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'authenticates if given valid creds' do
|
110
|
+
digest_authorize 'foo', 'bar'
|
111
|
+
get '/test'
|
112
|
+
expect(last_response.status).to eq(200)
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'throws a 401 if given invalid creds' do
|
116
|
+
digest_authorize 'bar', 'foo'
|
117
|
+
get '/test'
|
118
|
+
expect(last_response.status).to eq(401)
|
119
|
+
end
|
80
120
|
end
|
81
121
|
end
|
82
122
|
end
|
@@ -3,7 +3,8 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe Grape::Middleware::Base do
|
6
|
-
subject {
|
6
|
+
subject { described_class.new(blank_app) }
|
7
|
+
|
7
8
|
let(:blank_app) { ->(_) { [200, {}, 'Hi there.'] } }
|
8
9
|
|
9
10
|
before do
|
@@ -20,6 +21,8 @@ describe Grape::Middleware::Base do
|
|
20
21
|
end
|
21
22
|
|
22
23
|
context 'callbacks' do
|
24
|
+
after { subject.call!({}) }
|
25
|
+
|
23
26
|
it 'calls #before' do
|
24
27
|
expect(subject).to receive(:before)
|
25
28
|
end
|
@@ -27,8 +30,6 @@ describe Grape::Middleware::Base do
|
|
27
30
|
it 'calls #after' do
|
28
31
|
expect(subject).to receive(:after)
|
29
32
|
end
|
30
|
-
|
31
|
-
after { subject.call!({}) }
|
32
33
|
end
|
33
34
|
|
34
35
|
context 'callbacks on error' do
|
@@ -58,7 +59,7 @@ describe Grape::Middleware::Base do
|
|
58
59
|
context 'with patched warnings' do
|
59
60
|
before do
|
60
61
|
@warnings = warnings = []
|
61
|
-
allow_any_instance_of(
|
62
|
+
allow_any_instance_of(described_class).to receive(:warn) { |m| warnings << m }
|
62
63
|
allow(subject).to receive(:after).and_raise(StandardError)
|
63
64
|
end
|
64
65
|
|
@@ -75,49 +76,57 @@ describe Grape::Middleware::Base do
|
|
75
76
|
end
|
76
77
|
|
77
78
|
describe '#response' do
|
78
|
-
subject
|
79
|
+
subject do
|
80
|
+
puts described_class
|
81
|
+
described_class.new(response)
|
82
|
+
end
|
79
83
|
|
80
|
-
|
84
|
+
before { subject.call({}) }
|
85
|
+
|
86
|
+
context 'when Array' do
|
81
87
|
let(:response) { ->(_) { [204, { abc: 1 }, 'test'] } }
|
82
88
|
|
83
89
|
it 'status' do
|
84
|
-
subject.call({})
|
85
90
|
expect(subject.response.status).to eq(204)
|
86
91
|
end
|
87
92
|
|
88
93
|
it 'body' do
|
89
|
-
subject.call({})
|
90
94
|
expect(subject.response.body).to eq(['test'])
|
91
95
|
end
|
92
96
|
|
93
97
|
it 'header' do
|
94
|
-
subject.call({})
|
95
98
|
expect(subject.response.header).to have_key(:abc)
|
96
99
|
end
|
100
|
+
|
101
|
+
it 'returns the memoized Rack::Response instance' do
|
102
|
+
expect(subject.response).to be(subject.response)
|
103
|
+
end
|
97
104
|
end
|
98
105
|
|
99
|
-
context Rack::Response do
|
106
|
+
context 'when Rack::Response' do
|
100
107
|
let(:response) { ->(_) { Rack::Response.new('test', 204, abc: 1) } }
|
101
108
|
|
102
109
|
it 'status' do
|
103
|
-
subject.call({})
|
104
110
|
expect(subject.response.status).to eq(204)
|
105
111
|
end
|
106
112
|
|
107
113
|
it 'body' do
|
108
|
-
subject.call({})
|
109
114
|
expect(subject.response.body).to eq(['test'])
|
110
115
|
end
|
111
116
|
|
112
117
|
it 'header' do
|
113
|
-
subject.call({})
|
114
118
|
expect(subject.response.header).to have_key(:abc)
|
115
119
|
end
|
120
|
+
|
121
|
+
it 'returns the memoized Rack::Response instance' do
|
122
|
+
expect(subject.response).to be(subject.response)
|
123
|
+
end
|
116
124
|
end
|
117
125
|
end
|
118
126
|
|
119
127
|
describe '#context' do
|
120
|
-
subject {
|
128
|
+
subject { described_class.new(blank_app) }
|
129
|
+
|
121
130
|
it 'allows access to response context' do
|
122
131
|
subject.call(Grape::Env::API_ENDPOINT => { header: 'some header' })
|
123
132
|
expect(subject.context).to eq(header: 'some header')
|
@@ -126,7 +135,7 @@ describe Grape::Middleware::Base do
|
|
126
135
|
|
127
136
|
context 'options' do
|
128
137
|
it 'persists options passed at initialization' do
|
129
|
-
expect(
|
138
|
+
expect(described_class.new(blank_app, abc: true).options[:abc]).to be true
|
130
139
|
end
|
131
140
|
|
132
141
|
context 'defaults' do
|
@@ -3,76 +3,82 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe Grape::Middleware::Error do
|
6
|
-
|
7
|
-
|
8
|
-
class ExceptionApp
|
6
|
+
let(:exception_app) do
|
7
|
+
Class.new do
|
9
8
|
class << self
|
10
9
|
def call(_env)
|
11
10
|
raise 'rain!'
|
12
11
|
end
|
13
12
|
end
|
14
13
|
end
|
14
|
+
end
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
let(:other_exception_app) do
|
17
|
+
Class.new do
|
18
18
|
class << self
|
19
19
|
def call(_env)
|
20
20
|
raise NotImplementedError, 'snow!'
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
-
|
26
|
+
let(:custom_error_app) do
|
27
|
+
Class.new do
|
27
28
|
class << self
|
28
|
-
|
29
|
-
throw :error, message: { error: message, detail: 'missing widget' }, status: status
|
30
|
-
end
|
29
|
+
class CustomError < Grape::Exceptions::Base; end
|
31
30
|
|
32
31
|
def call(_env)
|
33
|
-
|
32
|
+
raise CustomError.new(status: 400, message: 'failed validation')
|
34
33
|
end
|
35
34
|
end
|
36
35
|
end
|
36
|
+
end
|
37
37
|
|
38
|
-
|
39
|
-
|
38
|
+
let(:error_hash_app) do
|
39
|
+
Class.new do
|
40
40
|
class << self
|
41
41
|
def error!(message, status)
|
42
|
-
throw :error, message: message, status: status
|
42
|
+
throw :error, message: { error: message, detail: 'missing widget' }, status: status
|
43
43
|
end
|
44
44
|
|
45
45
|
def call(_env)
|
46
|
-
error!('
|
46
|
+
error!('rain!', 401)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
|
+
end
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
end
|
54
|
-
|
55
|
-
class CustomErrorApp
|
52
|
+
let(:access_denied_app) do
|
53
|
+
Class.new do
|
56
54
|
class << self
|
55
|
+
def error!(message, status)
|
56
|
+
throw :error, message: message, status: status
|
57
|
+
end
|
58
|
+
|
57
59
|
def call(_env)
|
58
|
-
|
60
|
+
error!('Access Denied', 401)
|
59
61
|
end
|
60
62
|
end
|
61
63
|
end
|
62
64
|
end
|
63
65
|
|
64
|
-
|
65
|
-
|
66
|
+
let(:app) do
|
67
|
+
builder = Rack::Builder.new
|
68
|
+
builder.use Spec::Support::EndpointFaker
|
69
|
+
if options.any?
|
70
|
+
builder.use described_class, options
|
71
|
+
else
|
72
|
+
builder.use described_class
|
73
|
+
end
|
74
|
+
builder.run running_app
|
75
|
+
builder.to_app
|
66
76
|
end
|
67
77
|
|
68
78
|
context 'with defaults' do
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
use Grape::Middleware::Error
|
73
|
-
run ExceptionSpec::ExceptionApp
|
74
|
-
end
|
75
|
-
end
|
79
|
+
let(:running_app) { exception_app }
|
80
|
+
let(:options) { {} }
|
81
|
+
|
76
82
|
it 'does not trap errors by default' do
|
77
83
|
expect { get '/' }.to raise_error(RuntimeError, 'rain!')
|
78
84
|
end
|
@@ -80,17 +86,14 @@ describe Grape::Middleware::Error do
|
|
80
86
|
|
81
87
|
context 'with rescue_all' do
|
82
88
|
context 'StandardError exception' do
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
use Grape::Middleware::Error, rescue_all: true
|
87
|
-
run ExceptionSpec::ExceptionApp
|
88
|
-
end
|
89
|
-
end
|
89
|
+
let(:running_app) { exception_app }
|
90
|
+
let(:options) { { rescue_all: true } }
|
91
|
+
|
90
92
|
it 'sets the message appropriately' do
|
91
93
|
get '/'
|
92
94
|
expect(last_response.body).to eq('rain!')
|
93
95
|
end
|
96
|
+
|
94
97
|
it 'defaults to a 500 status' do
|
95
98
|
get '/'
|
96
99
|
expect(last_response.status).to eq(500)
|
@@ -98,13 +101,9 @@ describe Grape::Middleware::Error do
|
|
98
101
|
end
|
99
102
|
|
100
103
|
context 'Non-StandardError exception' do
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
use Grape::Middleware::Error, rescue_all: true
|
105
|
-
run ExceptionSpec::OtherExceptionApp
|
106
|
-
end
|
107
|
-
end
|
104
|
+
let(:running_app) { other_exception_app }
|
105
|
+
let(:options) { { rescue_all: true } }
|
106
|
+
|
108
107
|
it 'does not trap errors other than StandardError' do
|
109
108
|
expect { get '/' }.to raise_error(NotImplementedError, 'snow!')
|
110
109
|
end
|
@@ -113,13 +112,9 @@ describe Grape::Middleware::Error do
|
|
113
112
|
|
114
113
|
context 'Non-StandardError exception with a provided rescue handler' do
|
115
114
|
context 'default error response' do
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
use Grape::Middleware::Error, rescue_handlers: { NotImplementedError => nil }
|
120
|
-
run ExceptionSpec::OtherExceptionApp
|
121
|
-
end
|
122
|
-
end
|
115
|
+
let(:running_app) { other_exception_app }
|
116
|
+
let(:options) { { rescue_handlers: { NotImplementedError => nil } } }
|
117
|
+
|
123
118
|
it 'rescues the exception using the default handler' do
|
124
119
|
get '/'
|
125
120
|
expect(last_response.body).to eq('snow!')
|
@@ -127,13 +122,9 @@ describe Grape::Middleware::Error do
|
|
127
122
|
end
|
128
123
|
|
129
124
|
context 'custom error response' do
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
use Grape::Middleware::Error, rescue_handlers: { NotImplementedError => -> { Rack::Response.new('rescued', 200, {}) } }
|
134
|
-
run ExceptionSpec::OtherExceptionApp
|
135
|
-
end
|
136
|
-
end
|
125
|
+
let(:running_app) { other_exception_app }
|
126
|
+
let(:options) { { rescue_handlers: { NotImplementedError => -> { Rack::Response.new('rescued', 200, {}) } } } }
|
127
|
+
|
137
128
|
it 'rescues the exception using the provided handler' do
|
138
129
|
get '/'
|
139
130
|
expect(last_response.body).to eq('rescued')
|
@@ -142,13 +133,9 @@ describe Grape::Middleware::Error do
|
|
142
133
|
end
|
143
134
|
|
144
135
|
context do
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
use Grape::Middleware::Error, rescue_all: true, default_status: 500
|
149
|
-
run ExceptionSpec::ExceptionApp
|
150
|
-
end
|
151
|
-
end
|
136
|
+
let(:running_app) { exception_app }
|
137
|
+
let(:options) { { rescue_all: true, default_status: 500 } }
|
138
|
+
|
152
139
|
it 'is possible to specify a different default status code' do
|
153
140
|
get '/'
|
154
141
|
expect(last_response.status).to eq(500)
|
@@ -156,13 +143,9 @@ describe Grape::Middleware::Error do
|
|
156
143
|
end
|
157
144
|
|
158
145
|
context do
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
use Grape::Middleware::Error, rescue_all: true, format: :json
|
163
|
-
run ExceptionSpec::ExceptionApp
|
164
|
-
end
|
165
|
-
end
|
146
|
+
let(:running_app) { exception_app }
|
147
|
+
let(:options) { { rescue_all: true, format: :json } }
|
148
|
+
|
166
149
|
it 'is possible to return errors in json format' do
|
167
150
|
get '/'
|
168
151
|
expect(last_response.body).to eq('{"error":"rain!"}')
|
@@ -170,13 +153,9 @@ describe Grape::Middleware::Error do
|
|
170
153
|
end
|
171
154
|
|
172
155
|
context do
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
use Grape::Middleware::Error, rescue_all: true, format: :json
|
177
|
-
run ExceptionSpec::ErrorHashApp
|
178
|
-
end
|
179
|
-
end
|
156
|
+
let(:running_app) { error_hash_app }
|
157
|
+
let(:options) { { rescue_all: true, format: :json } }
|
158
|
+
|
180
159
|
it 'is possible to return hash errors in json format' do
|
181
160
|
get '/'
|
182
161
|
expect(['{"error":"rain!","detail":"missing widget"}',
|
@@ -185,13 +164,9 @@ describe Grape::Middleware::Error do
|
|
185
164
|
end
|
186
165
|
|
187
166
|
context do
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
use Grape::Middleware::Error, rescue_all: true, format: :jsonapi
|
192
|
-
run ExceptionSpec::ExceptionApp
|
193
|
-
end
|
194
|
-
end
|
167
|
+
let(:running_app) { exception_app }
|
168
|
+
let(:options) { { rescue_all: true, format: :jsonapi } }
|
169
|
+
|
195
170
|
it 'is possible to return errors in jsonapi format' do
|
196
171
|
get '/'
|
197
172
|
expect(last_response.body).to eq('{"error":"rain!"}')
|
@@ -199,13 +174,8 @@ describe Grape::Middleware::Error do
|
|
199
174
|
end
|
200
175
|
|
201
176
|
context do
|
202
|
-
|
203
|
-
|
204
|
-
use Spec::Support::EndpointFaker
|
205
|
-
use Grape::Middleware::Error, rescue_all: true, format: :jsonapi
|
206
|
-
run ExceptionSpec::ErrorHashApp
|
207
|
-
end
|
208
|
-
end
|
177
|
+
let(:running_app) { error_hash_app }
|
178
|
+
let(:options) { { rescue_all: true, format: :jsonapi } }
|
209
179
|
|
210
180
|
it 'is possible to return hash errors in jsonapi format' do
|
211
181
|
get '/'
|
@@ -215,13 +185,9 @@ describe Grape::Middleware::Error do
|
|
215
185
|
end
|
216
186
|
|
217
187
|
context do
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
use Grape::Middleware::Error, rescue_all: true, format: :xml
|
222
|
-
run ExceptionSpec::ExceptionApp
|
223
|
-
end
|
224
|
-
end
|
188
|
+
let(:running_app) { exception_app }
|
189
|
+
let(:options) { { rescue_all: true, format: :xml } }
|
190
|
+
|
225
191
|
it 'is possible to return errors in xml format' do
|
226
192
|
get '/'
|
227
193
|
expect(last_response.body).to eq("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n <message>rain!</message>\n</error>\n")
|
@@ -229,13 +195,9 @@ describe Grape::Middleware::Error do
|
|
229
195
|
end
|
230
196
|
|
231
197
|
context do
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
use Grape::Middleware::Error, rescue_all: true, format: :xml
|
236
|
-
run ExceptionSpec::ErrorHashApp
|
237
|
-
end
|
238
|
-
end
|
198
|
+
let(:running_app) { error_hash_app }
|
199
|
+
let(:options) { { rescue_all: true, format: :xml } }
|
200
|
+
|
239
201
|
it 'is possible to return hash errors in xml format' do
|
240
202
|
get '/'
|
241
203
|
expect(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n <detail>missing widget</detail>\n <error>rain!</error>\n</error>\n",
|
@@ -244,20 +206,19 @@ describe Grape::Middleware::Error do
|
|
244
206
|
end
|
245
207
|
|
246
208
|
context do
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
run ExceptionSpec::ExceptionApp
|
259
|
-
end
|
209
|
+
let(:running_app) { exception_app }
|
210
|
+
let(:options) do
|
211
|
+
{
|
212
|
+
rescue_all: true,
|
213
|
+
format: :custom,
|
214
|
+
error_formatters: {
|
215
|
+
custom: lambda do |message, _backtrace, _options, _env, _original_exception|
|
216
|
+
{ custom_formatter: message }.inspect
|
217
|
+
end
|
218
|
+
}
|
219
|
+
}
|
260
220
|
end
|
221
|
+
|
261
222
|
it 'is possible to specify a custom formatter' do
|
262
223
|
get '/'
|
263
224
|
expect(last_response.body).to eq('{:custom_formatter=>"rain!"}')
|
@@ -265,13 +226,9 @@ describe Grape::Middleware::Error do
|
|
265
226
|
end
|
266
227
|
|
267
228
|
context do
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
use Grape::Middleware::Error
|
272
|
-
run ExceptionSpec::AccessDeniedApp
|
273
|
-
end
|
274
|
-
end
|
229
|
+
let(:running_app) { access_denied_app }
|
230
|
+
let(:options) { {} }
|
231
|
+
|
275
232
|
it 'does not trap regular error! codes' do
|
276
233
|
get '/'
|
277
234
|
expect(last_response.status).to eq(401)
|
@@ -279,13 +236,9 @@ describe Grape::Middleware::Error do
|
|
279
236
|
end
|
280
237
|
|
281
238
|
context do
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
use Grape::Middleware::Error, rescue_all: false
|
286
|
-
run ExceptionSpec::CustomErrorApp
|
287
|
-
end
|
288
|
-
end
|
239
|
+
let(:running_app) { custom_error_app }
|
240
|
+
let(:options) { { rescue_all: false } }
|
241
|
+
|
289
242
|
it 'responds to custom Grape exceptions appropriately' do
|
290
243
|
get '/'
|
291
244
|
expect(last_response.status).to eq(400)
|
@@ -294,16 +247,15 @@ describe Grape::Middleware::Error do
|
|
294
247
|
end
|
295
248
|
|
296
249
|
context 'with rescue_options :backtrace and :exception set to true' do
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
run ExceptionSpec::ExceptionApp
|
305
|
-
end
|
250
|
+
let(:running_app) { exception_app }
|
251
|
+
let(:options) do
|
252
|
+
{
|
253
|
+
rescue_all: true,
|
254
|
+
format: :json,
|
255
|
+
rescue_options: { backtrace: true, original_exception: true }
|
256
|
+
}
|
306
257
|
end
|
258
|
+
|
307
259
|
it 'is possible to return the backtrace and the original exception in json format' do
|
308
260
|
get '/'
|
309
261
|
expect(last_response.body).to include('error', 'rain!', 'backtrace', 'original_exception', 'RuntimeError')
|
@@ -311,16 +263,15 @@ describe Grape::Middleware::Error do
|
|
311
263
|
end
|
312
264
|
|
313
265
|
context do
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
run ExceptionSpec::ExceptionApp
|
322
|
-
end
|
266
|
+
let(:running_app) { exception_app }
|
267
|
+
let(:options) do
|
268
|
+
{
|
269
|
+
rescue_all: true,
|
270
|
+
format: :xml,
|
271
|
+
rescue_options: { backtrace: true, original_exception: true }
|
272
|
+
}
|
323
273
|
end
|
274
|
+
|
324
275
|
it 'is possible to return the backtrace and the original exception in xml format' do
|
325
276
|
get '/'
|
326
277
|
expect(last_response.body).to include('error', 'rain!', 'backtrace', 'original-exception', 'RuntimeError')
|
@@ -328,16 +279,15 @@ describe Grape::Middleware::Error do
|
|
328
279
|
end
|
329
280
|
|
330
281
|
context do
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
run ExceptionSpec::ExceptionApp
|
339
|
-
end
|
282
|
+
let(:running_app) { exception_app }
|
283
|
+
let(:options) do
|
284
|
+
{
|
285
|
+
rescue_all: true,
|
286
|
+
format: :txt,
|
287
|
+
rescue_options: { backtrace: true, original_exception: true }
|
288
|
+
}
|
340
289
|
end
|
290
|
+
|
341
291
|
it 'is possible to return the backtrace and the original exception in txt format' do
|
342
292
|
get '/'
|
343
293
|
expect(last_response.body).to include('error', 'rain!', 'backtrace', 'original exception', 'RuntimeError')
|