grape 0.12.0 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grape might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Appraisals +9 -4
- data/CHANGELOG.md +265 -215
- data/CONTRIBUTING.md +4 -4
- data/Gemfile +0 -1
- data/Gemfile.lock +166 -0
- data/README.md +426 -161
- data/RELEASING.md +14 -6
- data/Rakefile +30 -33
- data/UPGRADING.md +54 -23
- data/benchmark/simple.rb +27 -0
- data/gemfiles/rack_1.5.2.gemfile +13 -0
- data/gemfiles/rails_3.gemfile +2 -2
- data/gemfiles/rails_4.gemfile +1 -2
- data/grape.gemspec +6 -7
- data/lib/grape/api.rb +24 -4
- data/lib/grape/dsl/callbacks.rb +20 -0
- data/lib/grape/dsl/configuration.rb +59 -2
- data/lib/grape/dsl/helpers.rb +8 -3
- data/lib/grape/dsl/inside_route.rb +100 -45
- data/lib/grape/dsl/parameters.rb +96 -7
- data/lib/grape/dsl/request_response.rb +1 -1
- data/lib/grape/dsl/routing.rb +17 -4
- data/lib/grape/dsl/settings.rb +36 -1
- data/lib/grape/dsl/validations.rb +7 -5
- data/lib/grape/endpoint.rb +102 -57
- data/lib/grape/error_formatter/base.rb +6 -6
- data/lib/grape/exceptions/base.rb +5 -5
- data/lib/grape/exceptions/invalid_version_header.rb +10 -0
- data/lib/grape/exceptions/unknown_parameter.rb +10 -0
- data/lib/grape/exceptions/validation_errors.rb +4 -3
- data/lib/grape/formatter/serializable_hash.rb +3 -2
- data/lib/grape/http/headers.rb +0 -1
- data/lib/grape/locale/en.yml +5 -1
- data/lib/grape/middleware/auth/base.rb +2 -2
- data/lib/grape/middleware/auth/dsl.rb +1 -1
- data/lib/grape/middleware/auth/strategies.rb +1 -1
- data/lib/grape/middleware/base.rb +8 -4
- data/lib/grape/middleware/error.rb +3 -2
- data/lib/grape/middleware/filter.rb +1 -1
- data/lib/grape/middleware/formatter.rb +64 -45
- data/lib/grape/middleware/globals.rb +3 -3
- data/lib/grape/middleware/versioner/accept_version_header.rb +5 -7
- data/lib/grape/middleware/versioner/header.rb +113 -50
- data/lib/grape/middleware/versioner/param.rb +5 -8
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +20 -0
- data/lib/grape/middleware/versioner/path.rb +3 -6
- data/lib/grape/namespace.rb +13 -2
- data/lib/grape/path.rb +4 -3
- data/lib/grape/request.rb +40 -0
- data/lib/grape/route.rb +5 -0
- data/lib/grape/util/content_types.rb +9 -9
- data/lib/grape/util/env.rb +22 -0
- data/lib/grape/util/file_response.rb +21 -0
- data/lib/grape/util/inheritable_setting.rb +23 -2
- data/lib/grape/util/inheritable_values.rb +1 -1
- data/lib/grape/util/stackable_values.rb +5 -2
- data/lib/grape/util/strict_hash_configuration.rb +2 -1
- data/lib/grape/validations/attributes_iterator.rb +8 -3
- data/lib/grape/validations/params_scope.rb +164 -22
- data/lib/grape/validations/types/build_coercer.rb +53 -0
- data/lib/grape/validations/types/custom_type_coercer.rb +183 -0
- data/lib/grape/validations/types/file.rb +28 -0
- data/lib/grape/validations/types/json.rb +65 -0
- data/lib/grape/validations/types/multiple_type_coercer.rb +76 -0
- data/lib/grape/validations/types/variant_collection_coercer.rb +59 -0
- data/lib/grape/validations/types/virtus_collection_patch.rb +16 -0
- data/lib/grape/validations/types.rb +144 -0
- data/lib/grape/validations/validators/all_or_none.rb +1 -1
- data/lib/grape/validations/validators/allow_blank.rb +3 -3
- data/lib/grape/validations/validators/base.rb +7 -0
- data/lib/grape/validations/validators/coerce.rb +32 -34
- data/lib/grape/validations/validators/presence.rb +2 -3
- data/lib/grape/validations/validators/regexp.rb +2 -4
- data/lib/grape/validations/validators/values.rb +3 -3
- data/lib/grape/validations.rb +5 -0
- data/lib/grape/version.rb +2 -1
- data/lib/grape.rb +15 -12
- data/pkg/grape-0.13.0.gem +0 -0
- data/spec/grape/api/custom_validations_spec.rb +5 -4
- data/spec/grape/api/deeply_included_options_spec.rb +7 -7
- data/spec/grape/api/nested_helpers_spec.rb +4 -2
- data/spec/grape/api/shared_helpers_spec.rb +8 -8
- data/spec/grape/api_spec.rb +151 -54
- data/spec/grape/dsl/configuration_spec.rb +13 -0
- data/spec/grape/dsl/helpers_spec.rb +16 -2
- data/spec/grape/dsl/inside_route_spec.rb +40 -4
- data/spec/grape/dsl/parameters_spec.rb +0 -6
- data/spec/grape/dsl/routing_spec.rb +1 -1
- data/spec/grape/dsl/validations_spec.rb +18 -0
- data/spec/grape/endpoint_spec.rb +130 -6
- data/spec/grape/entity_spec.rb +10 -8
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +1 -15
- data/spec/grape/exceptions/validation_errors_spec.rb +28 -0
- data/spec/grape/integration/rack_spec.rb +3 -2
- data/spec/grape/middleware/base_spec.rb +40 -16
- data/spec/grape/middleware/error_spec.rb +16 -15
- data/spec/grape/middleware/exception_spec.rb +45 -43
- data/spec/grape/middleware/formatter_spec.rb +34 -5
- data/spec/grape/middleware/versioner/header_spec.rb +79 -47
- data/spec/grape/path_spec.rb +10 -10
- data/spec/grape/presenters/presenter_spec.rb +2 -2
- data/spec/grape/request_spec.rb +100 -0
- data/spec/grape/util/inheritable_values_spec.rb +14 -0
- data/spec/grape/util/stackable_values_spec.rb +10 -0
- data/spec/grape/validations/params_scope_spec.rb +86 -0
- data/spec/grape/validations/types_spec.rb +95 -0
- data/spec/grape/validations/validators/coerce_spec.rb +364 -10
- data/spec/grape/validations/validators/values_spec.rb +27 -15
- data/spec/grape/validations_spec.rb +53 -24
- data/spec/shared/versioning_examples.rb +2 -2
- data/spec/spec_helper.rb +0 -1
- data/spec/support/versioned_helpers.rb +2 -2
- metadata +55 -14
- data/.gitignore +0 -46
- data/.rspec +0 -2
- data/.rubocop.yml +0 -7
- data/.rubocop_todo.yml +0 -84
- data/.travis.yml +0 -20
- data/.yardopts +0 -2
- data/lib/backports/active_support/deep_dup.rb +0 -49
- data/lib/backports/active_support/duplicable.rb +0 -88
- data/lib/grape/http/request.rb +0 -27
data/spec/grape/endpoint_spec.rb
CHANGED
@@ -11,15 +11,15 @@ describe Grape::Endpoint do
|
|
11
11
|
after { Grape::Endpoint.before_each(nil) }
|
12
12
|
|
13
13
|
it 'should be settable via block' do
|
14
|
-
block =
|
14
|
+
block = ->(_endpoint) { 'noop' }
|
15
15
|
Grape::Endpoint.before_each(&block)
|
16
|
-
expect(Grape::Endpoint.before_each).to eq(block)
|
16
|
+
expect(Grape::Endpoint.before_each.first).to eq(block)
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'should be settable via reference' do
|
20
|
-
block =
|
20
|
+
block = ->(_endpoint) { 'noop' }
|
21
21
|
Grape::Endpoint.before_each block
|
22
|
-
expect(Grape::Endpoint.before_each).to eq(block)
|
22
|
+
expect(Grape::Endpoint.before_each.first).to eq(block)
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'should be able to override a helper' do
|
@@ -36,6 +36,28 @@ describe Grape::Endpoint do
|
|
36
36
|
Grape::Endpoint.before_each(nil)
|
37
37
|
expect { get '/' }.to raise_error(NameError)
|
38
38
|
end
|
39
|
+
|
40
|
+
it 'should be able to stack helper' do
|
41
|
+
subject.get('/') do
|
42
|
+
authenticate_user!
|
43
|
+
current_user
|
44
|
+
end
|
45
|
+
expect { get '/' }.to raise_error(NameError)
|
46
|
+
|
47
|
+
Grape::Endpoint.before_each do |endpoint|
|
48
|
+
allow(endpoint).to receive(:current_user).and_return('Bob')
|
49
|
+
end
|
50
|
+
|
51
|
+
Grape::Endpoint.before_each do |endpoint|
|
52
|
+
allow(endpoint).to receive(:authenticate_user!).and_return(true)
|
53
|
+
end
|
54
|
+
|
55
|
+
get '/'
|
56
|
+
expect(last_response.body).to eq('Bob')
|
57
|
+
|
58
|
+
Grape::Endpoint.before_each(nil)
|
59
|
+
expect { get '/' }.to raise_error(NameError)
|
60
|
+
end
|
39
61
|
end
|
40
62
|
|
41
63
|
describe '#initialize' do
|
@@ -239,6 +261,16 @@ describe Grape::Endpoint do
|
|
239
261
|
end
|
240
262
|
end
|
241
263
|
|
264
|
+
it 'does not work in a before filter' do
|
265
|
+
subject.before do
|
266
|
+
declared(params)
|
267
|
+
end
|
268
|
+
subject.get('/declared') { declared(params) }
|
269
|
+
|
270
|
+
expect { get('/declared') }.to raise_error(
|
271
|
+
Grape::DSL::InsideRoute::MethodNotYetAvailable)
|
272
|
+
end
|
273
|
+
|
242
274
|
it 'has as many keys as there are declared params' do
|
243
275
|
inner_params = nil
|
244
276
|
subject.get '/declared' do
|
@@ -742,7 +774,7 @@ describe Grape::Endpoint do
|
|
742
774
|
get '/hey'
|
743
775
|
expect(last_response.status).to eq 302
|
744
776
|
expect(last_response.headers['Location']).to eq '/ha'
|
745
|
-
expect(last_response.body).to eq ''
|
777
|
+
expect(last_response.body).to eq 'This resource has been moved temporarily to /ha.'
|
746
778
|
end
|
747
779
|
|
748
780
|
it 'has status code 303 if it is not get request and it is http 1.1' do
|
@@ -752,6 +784,7 @@ describe Grape::Endpoint do
|
|
752
784
|
post '/hey', {}, 'HTTP_VERSION' => 'HTTP/1.1'
|
753
785
|
expect(last_response.status).to eq 303
|
754
786
|
expect(last_response.headers['Location']).to eq '/ha'
|
787
|
+
expect(last_response.body).to eq 'An alternate resource is located at /ha.'
|
755
788
|
end
|
756
789
|
|
757
790
|
it 'support permanent redirect' do
|
@@ -761,7 +794,15 @@ describe Grape::Endpoint do
|
|
761
794
|
get '/hey'
|
762
795
|
expect(last_response.status).to eq 301
|
763
796
|
expect(last_response.headers['Location']).to eq '/ha'
|
764
|
-
expect(last_response.body).to eq ''
|
797
|
+
expect(last_response.body).to eq 'This resource has been moved permanently to /ha.'
|
798
|
+
end
|
799
|
+
|
800
|
+
it 'allows for an optional redirect body override' do
|
801
|
+
subject.get('/hey') do
|
802
|
+
redirect '/ha', body: 'test body'
|
803
|
+
end
|
804
|
+
get '/hey'
|
805
|
+
expect(last_response.body).to eq 'test body'
|
765
806
|
end
|
766
807
|
end
|
767
808
|
|
@@ -941,4 +982,87 @@ describe Grape::Endpoint do
|
|
941
982
|
expect(last_response.body).to eq File.read(__FILE__)
|
942
983
|
end
|
943
984
|
end
|
985
|
+
|
986
|
+
context 'validation errors' do
|
987
|
+
before do
|
988
|
+
subject.before do
|
989
|
+
header['Access-Control-Allow-Origin'] = '*'
|
990
|
+
end
|
991
|
+
subject.params do
|
992
|
+
requires :id, type: String
|
993
|
+
end
|
994
|
+
subject.get do
|
995
|
+
'should not get here'
|
996
|
+
end
|
997
|
+
end
|
998
|
+
|
999
|
+
it 'returns the errors, and passes headers' do
|
1000
|
+
get '/'
|
1001
|
+
expect(last_response.status).to eq 400
|
1002
|
+
expect(last_response.body).to eq 'id is missing'
|
1003
|
+
expect(last_response.headers['Access-Control-Allow-Origin']).to eq('*')
|
1004
|
+
end
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
context 'instrumentation' do
|
1008
|
+
before do
|
1009
|
+
subject.before do
|
1010
|
+
# Placeholder
|
1011
|
+
end
|
1012
|
+
subject.get do
|
1013
|
+
'hello'
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
@events = []
|
1017
|
+
@subscriber = ActiveSupport::Notifications.subscribe(/grape/) do |*args|
|
1018
|
+
@events << ActiveSupport::Notifications::Event.new(*args)
|
1019
|
+
end
|
1020
|
+
end
|
1021
|
+
|
1022
|
+
after do
|
1023
|
+
ActiveSupport::Notifications.unsubscribe(@subscriber)
|
1024
|
+
end
|
1025
|
+
|
1026
|
+
it 'notifies AS::N' do
|
1027
|
+
get '/'
|
1028
|
+
|
1029
|
+
# In order that the events finalized (time each block ended)
|
1030
|
+
expect(@events).to contain_exactly(
|
1031
|
+
have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
|
1032
|
+
filters: a_collection_containing_exactly(an_instance_of(Proc)),
|
1033
|
+
type: :before }),
|
1034
|
+
have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
|
1035
|
+
filters: [],
|
1036
|
+
type: :before_validation }),
|
1037
|
+
have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
|
1038
|
+
filters: [],
|
1039
|
+
type: :after_validation }),
|
1040
|
+
have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(Grape::Endpoint) }),
|
1041
|
+
have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
|
1042
|
+
filters: [],
|
1043
|
+
type: :after }),
|
1044
|
+
have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
|
1045
|
+
env: an_instance_of(Hash) })
|
1046
|
+
)
|
1047
|
+
|
1048
|
+
# In order that events were initialized
|
1049
|
+
expect(@events.sort_by(&:time)).to contain_exactly(
|
1050
|
+
have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
|
1051
|
+
env: an_instance_of(Hash) }),
|
1052
|
+
have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
|
1053
|
+
filters: a_collection_containing_exactly(an_instance_of(Proc)),
|
1054
|
+
type: :before }),
|
1055
|
+
have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
|
1056
|
+
filters: [],
|
1057
|
+
type: :before_validation }),
|
1058
|
+
have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
|
1059
|
+
filters: [],
|
1060
|
+
type: :after_validation }),
|
1061
|
+
have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(Grape::Endpoint) }),
|
1062
|
+
have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
|
1063
|
+
filters: [],
|
1064
|
+
type: :after })
|
1065
|
+
)
|
1066
|
+
end
|
1067
|
+
end
|
944
1068
|
end
|
data/spec/grape/entity_spec.rb
CHANGED
@@ -45,22 +45,24 @@ describe Grape::Entity do
|
|
45
45
|
entity = Class.new(Grape::Entity)
|
46
46
|
allow(entity).to receive(:represent).and_return('Hiya')
|
47
47
|
|
48
|
-
|
49
|
-
|
48
|
+
module EntitySpec
|
49
|
+
class TestObject
|
50
|
+
end
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
52
|
+
class FakeCollection
|
53
|
+
def first
|
54
|
+
TestObject.new
|
55
|
+
end
|
54
56
|
end
|
55
57
|
end
|
56
58
|
|
57
|
-
subject.represent TestObject, with: entity
|
59
|
+
subject.represent EntitySpec::TestObject, with: entity
|
58
60
|
subject.get '/example' do
|
59
|
-
present [TestObject.new]
|
61
|
+
present [EntitySpec::TestObject.new]
|
60
62
|
end
|
61
63
|
|
62
64
|
subject.get '/example2' do
|
63
|
-
present FakeCollection.new
|
65
|
+
present EntitySpec::FakeCollection.new
|
64
66
|
end
|
65
67
|
|
66
68
|
get '/example'
|
@@ -54,13 +54,6 @@ describe Grape::Exceptions::InvalidAcceptHeader do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
context 'that receives' do
|
57
|
-
context 'an invalid version in the request' do
|
58
|
-
before do
|
59
|
-
get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77',
|
60
|
-
'CONTENT_TYPE' => 'application/json'
|
61
|
-
end
|
62
|
-
it_should_behave_like 'a rescued request'
|
63
|
-
end
|
64
57
|
context 'an invalid vendor in the request' do
|
65
58
|
before do
|
66
59
|
get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99',
|
@@ -128,13 +121,6 @@ describe Grape::Exceptions::InvalidAcceptHeader do
|
|
128
121
|
end
|
129
122
|
|
130
123
|
context 'that receives' do
|
131
|
-
context 'an invalid version in the request' do
|
132
|
-
before do
|
133
|
-
get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77',
|
134
|
-
'CONTENT_TYPE' => 'application/json'
|
135
|
-
end
|
136
|
-
it_should_behave_like 'a rescued request'
|
137
|
-
end
|
138
124
|
context 'an invalid vendor in the request' do
|
139
125
|
before do
|
140
126
|
get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99',
|
@@ -318,7 +304,7 @@ describe Grape::Exceptions::InvalidAcceptHeader do
|
|
318
304
|
|
319
305
|
context 'that receives' do
|
320
306
|
context 'an invalid version in the request' do
|
321
|
-
before { get '/beer', {},
|
307
|
+
before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77' }
|
322
308
|
it_should_behave_like 'a cascaded request'
|
323
309
|
end
|
324
310
|
context 'an invalid vendor in the request' do
|
@@ -5,6 +5,22 @@ describe Grape::Exceptions::ValidationErrors do
|
|
5
5
|
let(:validation_message) { 'FooBar is invalid' }
|
6
6
|
let(:validation_error) { OpenStruct.new(params: [validation_message]) }
|
7
7
|
|
8
|
+
context 'initialize' do
|
9
|
+
let(:headers) {
|
10
|
+
{
|
11
|
+
'A-Header-Key' => 'A-Header-Value'
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
subject do
|
16
|
+
described_class.new(errors: [validation_error], headers: headers)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should assign headers through base class' do
|
20
|
+
expect(subject.headers).to eq(headers)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
8
24
|
context 'message' do
|
9
25
|
context 'is not repeated' do
|
10
26
|
let(:error) do
|
@@ -17,6 +33,18 @@ describe Grape::Exceptions::ValidationErrors do
|
|
17
33
|
end
|
18
34
|
end
|
19
35
|
|
36
|
+
describe '#full_messages' do
|
37
|
+
context 'with errors' do
|
38
|
+
let(:validation_error_1) { Grape::Exceptions::Validation.new(params: ['id'], message_key: 'presence') }
|
39
|
+
let(:validation_error_2) { Grape::Exceptions::Validation.new(params: ['name'], message_key: 'presence') }
|
40
|
+
subject { described_class.new(errors: [validation_error_1, validation_error_2]).full_messages }
|
41
|
+
|
42
|
+
it 'returns an array with each errors full message' do
|
43
|
+
expect(subject).to contain_exactly('id is missing', 'name is missing')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
20
48
|
context 'api' do
|
21
49
|
subject { Class.new(Grape::API) }
|
22
50
|
|
@@ -20,8 +20,9 @@ describe Rack do
|
|
20
20
|
env = Rack::MockRequest.env_for('/', options)
|
21
21
|
|
22
22
|
unless RUBY_PLATFORM == 'java'
|
23
|
-
major, minor,
|
24
|
-
|
23
|
+
major, minor, patch = Rack.release.split('.').map(&:to_i)
|
24
|
+
patch ||= 0 # rack <= 1.5.2 does not specify patch version
|
25
|
+
pending 'Rack 1.5.3 or 1.6.1 required' unless major >= 1 && ((minor == 5 && patch >= 3) || (minor >= 6))
|
25
26
|
end
|
26
27
|
|
27
28
|
expect(JSON.parse(app.call(env)[2].body.first)['params_keys']).to match_array('test')
|
@@ -36,21 +36,43 @@ describe Grape::Middleware::Base do
|
|
36
36
|
|
37
37
|
describe '#response' do
|
38
38
|
subject { Grape::Middleware::Base.new(response) }
|
39
|
-
let(:response) { ->(_) { [204, { abc: 1 }, 'test'] } }
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
context Array do
|
41
|
+
let(:response) { ->(_) { [204, { abc: 1 }, 'test'] } }
|
42
|
+
|
43
|
+
it 'status' do
|
44
|
+
subject.call({})
|
45
|
+
expect(subject.response.status).to eq(204)
|
46
|
+
end
|
45
47
|
|
46
|
-
|
47
|
-
|
48
|
-
|
48
|
+
it 'body' do
|
49
|
+
subject.call({})
|
50
|
+
expect(subject.response.body).to eq(['test'])
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'header' do
|
54
|
+
subject.call({})
|
55
|
+
expect(subject.response.header).to have_key(:abc)
|
56
|
+
end
|
49
57
|
end
|
50
58
|
|
51
|
-
|
52
|
-
|
53
|
-
|
59
|
+
context Rack::Response do
|
60
|
+
let(:response) { ->(_) { Rack::Response.new('test', 204, abc: 1) } }
|
61
|
+
|
62
|
+
it 'status' do
|
63
|
+
subject.call({})
|
64
|
+
expect(subject.response.status).to eq(204)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'body' do
|
68
|
+
subject.call({})
|
69
|
+
expect(subject.response.body).to eq(['test'])
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'header' do
|
73
|
+
subject.call({})
|
74
|
+
expect(subject.response.header).to have_key(:abc)
|
75
|
+
end
|
54
76
|
end
|
55
77
|
end
|
56
78
|
|
@@ -60,18 +82,20 @@ describe Grape::Middleware::Base do
|
|
60
82
|
end
|
61
83
|
|
62
84
|
context 'defaults' do
|
63
|
-
|
64
|
-
|
65
|
-
|
85
|
+
module BaseSpec
|
86
|
+
class ExampleWare < Grape::Middleware::Base
|
87
|
+
def default_options
|
88
|
+
{ monkey: true }
|
89
|
+
end
|
66
90
|
end
|
67
91
|
end
|
68
92
|
|
69
93
|
it 'persists the default options' do
|
70
|
-
expect(ExampleWare.new(blank_app).options[:monkey]).to be true
|
94
|
+
expect(BaseSpec::ExampleWare.new(blank_app).options[:monkey]).to be true
|
71
95
|
end
|
72
96
|
|
73
97
|
it 'overrides default options when provided' do
|
74
|
-
expect(ExampleWare.new(blank_app, monkey: false).options[:monkey]).to be false
|
98
|
+
expect(BaseSpec::ExampleWare.new(blank_app, monkey: false).options[:monkey]).to be false
|
75
99
|
end
|
76
100
|
end
|
77
101
|
end
|
@@ -11,14 +11,15 @@ describe Grape::Middleware::Error do
|
|
11
11
|
'static text'
|
12
12
|
end
|
13
13
|
end
|
14
|
-
end
|
15
|
-
class ErrApp
|
16
|
-
class << self
|
17
|
-
attr_accessor :error
|
18
|
-
attr_accessor :format
|
19
14
|
|
20
|
-
|
21
|
-
|
15
|
+
class ErrApp
|
16
|
+
class << self
|
17
|
+
attr_accessor :error
|
18
|
+
attr_accessor :format
|
19
|
+
|
20
|
+
def call(_env)
|
21
|
+
throw :error, error
|
22
|
+
end
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
@@ -28,32 +29,32 @@ describe Grape::Middleware::Error do
|
|
28
29
|
Rack::Builder.app do
|
29
30
|
use Spec::Support::EndpointFaker
|
30
31
|
use Grape::Middleware::Error, opts
|
31
|
-
run ErrApp
|
32
|
+
run ErrorSpec::ErrApp
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
35
|
-
let(:options) {
|
36
|
+
let(:options) { { default_message: 'Aww, hamburgers.' } }
|
36
37
|
|
37
38
|
it 'sets the status code appropriately' do
|
38
|
-
ErrApp.error = { status: 410 }
|
39
|
+
ErrorSpec::ErrApp.error = { status: 410 }
|
39
40
|
get '/'
|
40
41
|
expect(last_response.status).to eq(410)
|
41
42
|
end
|
42
43
|
|
43
44
|
it 'sets the error message appropriately' do
|
44
|
-
ErrApp.error = { message: 'Awesome stuff.' }
|
45
|
+
ErrorSpec::ErrApp.error = { message: 'Awesome stuff.' }
|
45
46
|
get '/'
|
46
47
|
expect(last_response.body).to eq('Awesome stuff.')
|
47
48
|
end
|
48
49
|
|
49
50
|
it 'defaults to a 500 status' do
|
50
|
-
ErrApp.error = {}
|
51
|
+
ErrorSpec::ErrApp.error = {}
|
51
52
|
get '/'
|
52
53
|
expect(last_response.status).to eq(500)
|
53
54
|
end
|
54
55
|
|
55
56
|
it 'has a default message' do
|
56
|
-
ErrApp.error = {}
|
57
|
+
ErrorSpec::ErrApp.error = {}
|
57
58
|
get '/'
|
58
59
|
expect(last_response.body).to eq('Aww, hamburgers.')
|
59
60
|
end
|
@@ -61,14 +62,14 @@ describe Grape::Middleware::Error do
|
|
61
62
|
context 'with http code' do
|
62
63
|
let(:options) { { default_message: 'Aww, hamburgers.' } }
|
63
64
|
it 'adds the status code if wanted' do
|
64
|
-
ErrApp.error = { message: { code: 200 } }
|
65
|
+
ErrorSpec::ErrApp.error = { message: { code: 200 } }
|
65
66
|
get '/'
|
66
67
|
|
67
68
|
expect(last_response.body).to eq({ code: 200 }.to_json)
|
68
69
|
end
|
69
70
|
|
70
71
|
it 'presents an error message' do
|
71
|
-
ErrApp.error = { message: { code: 200, with: ErrorSpec::ErrorEntity } }
|
72
|
+
ErrorSpec::ErrApp.error = { message: { code: 200, with: ErrorSpec::ErrorEntity } }
|
72
73
|
get '/'
|
73
74
|
|
74
75
|
expect(last_response.body).to eq({ code: 200, static: 'static text' }.to_json)
|
@@ -3,48 +3,50 @@ require 'active_support/core_ext/hash'
|
|
3
3
|
|
4
4
|
describe Grape::Middleware::Error do
|
5
5
|
# raises a text exception
|
6
|
-
|
7
|
-
class
|
8
|
-
|
9
|
-
|
6
|
+
module ExceptionSpec
|
7
|
+
class ExceptionApp
|
8
|
+
class << self
|
9
|
+
def call(_env)
|
10
|
+
fail 'rain!'
|
11
|
+
end
|
10
12
|
end
|
11
13
|
end
|
12
|
-
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
# raises a hash error
|
16
|
+
class ErrorHashApp
|
17
|
+
class << self
|
18
|
+
def error!(message, status)
|
19
|
+
throw :error, message: { error: message, detail: 'missing widget' }, status: status
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
def call(_env)
|
23
|
+
error!('rain!', 401)
|
24
|
+
end
|
23
25
|
end
|
24
26
|
end
|
25
|
-
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
# raises an error!
|
29
|
+
class AccessDeniedApp
|
30
|
+
class << self
|
31
|
+
def error!(message, status)
|
32
|
+
throw :error, message: message, status: status
|
33
|
+
end
|
33
34
|
|
34
|
-
|
35
|
-
|
35
|
+
def call(_env)
|
36
|
+
error!('Access Denied', 401)
|
37
|
+
end
|
36
38
|
end
|
37
39
|
end
|
38
|
-
end
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
# raises a custom error
|
42
|
+
class CustomError < Grape::Exceptions::Base
|
43
|
+
end
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
class CustomErrorApp
|
46
|
+
class << self
|
47
|
+
def call(_env)
|
48
|
+
fail CustomError, status: 400, message: 'failed validation'
|
49
|
+
end
|
48
50
|
end
|
49
51
|
end
|
50
52
|
end
|
@@ -55,7 +57,7 @@ describe Grape::Middleware::Error do
|
|
55
57
|
@app ||= Rack::Builder.app do
|
56
58
|
use Spec::Support::EndpointFaker
|
57
59
|
use Grape::Middleware::Error
|
58
|
-
run ExceptionApp
|
60
|
+
run ExceptionSpec::ExceptionApp
|
59
61
|
end
|
60
62
|
expect { get '/' }.to raise_error
|
61
63
|
end
|
@@ -65,7 +67,7 @@ describe Grape::Middleware::Error do
|
|
65
67
|
@app ||= Rack::Builder.app do
|
66
68
|
use Spec::Support::EndpointFaker
|
67
69
|
use Grape::Middleware::Error, rescue_all: true
|
68
|
-
run ExceptionApp
|
70
|
+
run ExceptionSpec::ExceptionApp
|
69
71
|
end
|
70
72
|
get '/'
|
71
73
|
expect(last_response.body).to eq('rain!')
|
@@ -75,7 +77,7 @@ describe Grape::Middleware::Error do
|
|
75
77
|
@app ||= Rack::Builder.app do
|
76
78
|
use Spec::Support::EndpointFaker
|
77
79
|
use Grape::Middleware::Error, rescue_all: true
|
78
|
-
run ExceptionApp
|
80
|
+
run ExceptionSpec::ExceptionApp
|
79
81
|
end
|
80
82
|
get '/'
|
81
83
|
expect(last_response.status).to eq(500)
|
@@ -85,7 +87,7 @@ describe Grape::Middleware::Error do
|
|
85
87
|
@app ||= Rack::Builder.app do
|
86
88
|
use Spec::Support::EndpointFaker
|
87
89
|
use Grape::Middleware::Error, rescue_all: true, default_status: 500
|
88
|
-
run ExceptionApp
|
90
|
+
run ExceptionSpec::ExceptionApp
|
89
91
|
end
|
90
92
|
get '/'
|
91
93
|
expect(last_response.status).to eq(500)
|
@@ -95,7 +97,7 @@ describe Grape::Middleware::Error do
|
|
95
97
|
@app ||= Rack::Builder.app do
|
96
98
|
use Spec::Support::EndpointFaker
|
97
99
|
use Grape::Middleware::Error, rescue_all: true, format: :json
|
98
|
-
run ExceptionApp
|
100
|
+
run ExceptionSpec::ExceptionApp
|
99
101
|
end
|
100
102
|
get '/'
|
101
103
|
expect(last_response.body).to eq('{"error":"rain!"}')
|
@@ -105,7 +107,7 @@ describe Grape::Middleware::Error do
|
|
105
107
|
@app ||= Rack::Builder.app do
|
106
108
|
use Spec::Support::EndpointFaker
|
107
109
|
use Grape::Middleware::Error, rescue_all: true, format: :json
|
108
|
-
run ErrorHashApp
|
110
|
+
run ExceptionSpec::ErrorHashApp
|
109
111
|
end
|
110
112
|
get '/'
|
111
113
|
expect(['{"error":"rain!","detail":"missing widget"}',
|
@@ -116,7 +118,7 @@ describe Grape::Middleware::Error do
|
|
116
118
|
@app ||= Rack::Builder.app do
|
117
119
|
use Spec::Support::EndpointFaker
|
118
120
|
use Grape::Middleware::Error, rescue_all: true, format: :jsonapi
|
119
|
-
run ExceptionApp
|
121
|
+
run ExceptionSpec::ExceptionApp
|
120
122
|
end
|
121
123
|
get '/'
|
122
124
|
expect(last_response.body).to eq('{"error":"rain!"}')
|
@@ -126,7 +128,7 @@ describe Grape::Middleware::Error do
|
|
126
128
|
@app ||= Rack::Builder.app do
|
127
129
|
use Spec::Support::EndpointFaker
|
128
130
|
use Grape::Middleware::Error, rescue_all: true, format: :jsonapi
|
129
|
-
run ErrorHashApp
|
131
|
+
run ExceptionSpec::ErrorHashApp
|
130
132
|
end
|
131
133
|
get '/'
|
132
134
|
expect(['{"error":"rain!","detail":"missing widget"}',
|
@@ -137,7 +139,7 @@ describe Grape::Middleware::Error do
|
|
137
139
|
@app ||= Rack::Builder.app do
|
138
140
|
use Spec::Support::EndpointFaker
|
139
141
|
use Grape::Middleware::Error, rescue_all: true, format: :xml
|
140
|
-
run ExceptionApp
|
142
|
+
run ExceptionSpec::ExceptionApp
|
141
143
|
end
|
142
144
|
get '/'
|
143
145
|
expect(last_response.body).to eq("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n <message>rain!</message>\n</error>\n")
|
@@ -147,7 +149,7 @@ describe Grape::Middleware::Error do
|
|
147
149
|
@app ||= Rack::Builder.app do
|
148
150
|
use Spec::Support::EndpointFaker
|
149
151
|
use Grape::Middleware::Error, rescue_all: true, format: :xml
|
150
|
-
run ErrorHashApp
|
152
|
+
run ExceptionSpec::ErrorHashApp
|
151
153
|
end
|
152
154
|
get '/'
|
153
155
|
expect(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n <detail>missing widget</detail>\n <error>rain!</error>\n</error>\n",
|
@@ -164,7 +166,7 @@ describe Grape::Middleware::Error do
|
|
164
166
|
{ custom_formatter: message }.inspect
|
165
167
|
end
|
166
168
|
}
|
167
|
-
run ExceptionApp
|
169
|
+
run ExceptionSpec::ExceptionApp
|
168
170
|
end
|
169
171
|
get '/'
|
170
172
|
expect(last_response.body).to eq('{:custom_formatter=>"rain!"}')
|
@@ -174,7 +176,7 @@ describe Grape::Middleware::Error do
|
|
174
176
|
@app ||= Rack::Builder.app do
|
175
177
|
use Spec::Support::EndpointFaker
|
176
178
|
use Grape::Middleware::Error
|
177
|
-
run AccessDeniedApp
|
179
|
+
run ExceptionSpec::AccessDeniedApp
|
178
180
|
end
|
179
181
|
get '/'
|
180
182
|
expect(last_response.status).to eq(401)
|
@@ -184,7 +186,7 @@ describe Grape::Middleware::Error do
|
|
184
186
|
@app ||= Rack::Builder.app do
|
185
187
|
use Spec::Support::EndpointFaker
|
186
188
|
use Grape::Middleware::Error, rescue_all: false
|
187
|
-
run CustomErrorApp
|
189
|
+
run ExceptionSpec::CustomErrorApp
|
188
190
|
end
|
189
191
|
|
190
192
|
get '/'
|