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.

Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +9 -4
  3. data/CHANGELOG.md +265 -215
  4. data/CONTRIBUTING.md +4 -4
  5. data/Gemfile +0 -1
  6. data/Gemfile.lock +166 -0
  7. data/README.md +426 -161
  8. data/RELEASING.md +14 -6
  9. data/Rakefile +30 -33
  10. data/UPGRADING.md +54 -23
  11. data/benchmark/simple.rb +27 -0
  12. data/gemfiles/rack_1.5.2.gemfile +13 -0
  13. data/gemfiles/rails_3.gemfile +2 -2
  14. data/gemfiles/rails_4.gemfile +1 -2
  15. data/grape.gemspec +6 -7
  16. data/lib/grape/api.rb +24 -4
  17. data/lib/grape/dsl/callbacks.rb +20 -0
  18. data/lib/grape/dsl/configuration.rb +59 -2
  19. data/lib/grape/dsl/helpers.rb +8 -3
  20. data/lib/grape/dsl/inside_route.rb +100 -45
  21. data/lib/grape/dsl/parameters.rb +96 -7
  22. data/lib/grape/dsl/request_response.rb +1 -1
  23. data/lib/grape/dsl/routing.rb +17 -4
  24. data/lib/grape/dsl/settings.rb +36 -1
  25. data/lib/grape/dsl/validations.rb +7 -5
  26. data/lib/grape/endpoint.rb +102 -57
  27. data/lib/grape/error_formatter/base.rb +6 -6
  28. data/lib/grape/exceptions/base.rb +5 -5
  29. data/lib/grape/exceptions/invalid_version_header.rb +10 -0
  30. data/lib/grape/exceptions/unknown_parameter.rb +10 -0
  31. data/lib/grape/exceptions/validation_errors.rb +4 -3
  32. data/lib/grape/formatter/serializable_hash.rb +3 -2
  33. data/lib/grape/http/headers.rb +0 -1
  34. data/lib/grape/locale/en.yml +5 -1
  35. data/lib/grape/middleware/auth/base.rb +2 -2
  36. data/lib/grape/middleware/auth/dsl.rb +1 -1
  37. data/lib/grape/middleware/auth/strategies.rb +1 -1
  38. data/lib/grape/middleware/base.rb +8 -4
  39. data/lib/grape/middleware/error.rb +3 -2
  40. data/lib/grape/middleware/filter.rb +1 -1
  41. data/lib/grape/middleware/formatter.rb +64 -45
  42. data/lib/grape/middleware/globals.rb +3 -3
  43. data/lib/grape/middleware/versioner/accept_version_header.rb +5 -7
  44. data/lib/grape/middleware/versioner/header.rb +113 -50
  45. data/lib/grape/middleware/versioner/param.rb +5 -8
  46. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +20 -0
  47. data/lib/grape/middleware/versioner/path.rb +3 -6
  48. data/lib/grape/namespace.rb +13 -2
  49. data/lib/grape/path.rb +4 -3
  50. data/lib/grape/request.rb +40 -0
  51. data/lib/grape/route.rb +5 -0
  52. data/lib/grape/util/content_types.rb +9 -9
  53. data/lib/grape/util/env.rb +22 -0
  54. data/lib/grape/util/file_response.rb +21 -0
  55. data/lib/grape/util/inheritable_setting.rb +23 -2
  56. data/lib/grape/util/inheritable_values.rb +1 -1
  57. data/lib/grape/util/stackable_values.rb +5 -2
  58. data/lib/grape/util/strict_hash_configuration.rb +2 -1
  59. data/lib/grape/validations/attributes_iterator.rb +8 -3
  60. data/lib/grape/validations/params_scope.rb +164 -22
  61. data/lib/grape/validations/types/build_coercer.rb +53 -0
  62. data/lib/grape/validations/types/custom_type_coercer.rb +183 -0
  63. data/lib/grape/validations/types/file.rb +28 -0
  64. data/lib/grape/validations/types/json.rb +65 -0
  65. data/lib/grape/validations/types/multiple_type_coercer.rb +76 -0
  66. data/lib/grape/validations/types/variant_collection_coercer.rb +59 -0
  67. data/lib/grape/validations/types/virtus_collection_patch.rb +16 -0
  68. data/lib/grape/validations/types.rb +144 -0
  69. data/lib/grape/validations/validators/all_or_none.rb +1 -1
  70. data/lib/grape/validations/validators/allow_blank.rb +3 -3
  71. data/lib/grape/validations/validators/base.rb +7 -0
  72. data/lib/grape/validations/validators/coerce.rb +32 -34
  73. data/lib/grape/validations/validators/presence.rb +2 -3
  74. data/lib/grape/validations/validators/regexp.rb +2 -4
  75. data/lib/grape/validations/validators/values.rb +3 -3
  76. data/lib/grape/validations.rb +5 -0
  77. data/lib/grape/version.rb +2 -1
  78. data/lib/grape.rb +15 -12
  79. data/pkg/grape-0.13.0.gem +0 -0
  80. data/spec/grape/api/custom_validations_spec.rb +5 -4
  81. data/spec/grape/api/deeply_included_options_spec.rb +7 -7
  82. data/spec/grape/api/nested_helpers_spec.rb +4 -2
  83. data/spec/grape/api/shared_helpers_spec.rb +8 -8
  84. data/spec/grape/api_spec.rb +151 -54
  85. data/spec/grape/dsl/configuration_spec.rb +13 -0
  86. data/spec/grape/dsl/helpers_spec.rb +16 -2
  87. data/spec/grape/dsl/inside_route_spec.rb +40 -4
  88. data/spec/grape/dsl/parameters_spec.rb +0 -6
  89. data/spec/grape/dsl/routing_spec.rb +1 -1
  90. data/spec/grape/dsl/validations_spec.rb +18 -0
  91. data/spec/grape/endpoint_spec.rb +130 -6
  92. data/spec/grape/entity_spec.rb +10 -8
  93. data/spec/grape/exceptions/invalid_accept_header_spec.rb +1 -15
  94. data/spec/grape/exceptions/validation_errors_spec.rb +28 -0
  95. data/spec/grape/integration/rack_spec.rb +3 -2
  96. data/spec/grape/middleware/base_spec.rb +40 -16
  97. data/spec/grape/middleware/error_spec.rb +16 -15
  98. data/spec/grape/middleware/exception_spec.rb +45 -43
  99. data/spec/grape/middleware/formatter_spec.rb +34 -5
  100. data/spec/grape/middleware/versioner/header_spec.rb +79 -47
  101. data/spec/grape/path_spec.rb +10 -10
  102. data/spec/grape/presenters/presenter_spec.rb +2 -2
  103. data/spec/grape/request_spec.rb +100 -0
  104. data/spec/grape/util/inheritable_values_spec.rb +14 -0
  105. data/spec/grape/util/stackable_values_spec.rb +10 -0
  106. data/spec/grape/validations/params_scope_spec.rb +86 -0
  107. data/spec/grape/validations/types_spec.rb +95 -0
  108. data/spec/grape/validations/validators/coerce_spec.rb +364 -10
  109. data/spec/grape/validations/validators/values_spec.rb +27 -15
  110. data/spec/grape/validations_spec.rb +53 -24
  111. data/spec/shared/versioning_examples.rb +2 -2
  112. data/spec/spec_helper.rb +0 -1
  113. data/spec/support/versioned_helpers.rb +2 -2
  114. metadata +55 -14
  115. data/.gitignore +0 -46
  116. data/.rspec +0 -2
  117. data/.rubocop.yml +0 -7
  118. data/.rubocop_todo.yml +0 -84
  119. data/.travis.yml +0 -20
  120. data/.yardopts +0 -2
  121. data/lib/backports/active_support/deep_dup.rb +0 -49
  122. data/lib/backports/active_support/duplicable.rb +0 -88
  123. data/lib/grape/http/request.rb +0 -27
@@ -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 = lambda { |_endpoint| 'noop' }
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 = lambda { |_endpoint| 'noop' }
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
@@ -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
- class TestObject
49
- end
48
+ module EntitySpec
49
+ class TestObject
50
+ end
50
51
 
51
- class FakeCollection
52
- def first
53
- TestObject.new
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', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77' }
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, release = Rack.release.split('.').map(&:to_i)
24
- pending 'Rack 1.5.3 or 1.6.1 required' unless major >= 1 && ((minor == 5 && release >= 3) || (minor >= 6))
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
- it 'status' do
42
- subject.call({})
43
- expect(subject.response.status).to eq(204)
44
- end
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
- it 'body' do
47
- subject.call({})
48
- expect(subject.response.body).to eq(['test'])
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
- it 'header' do
52
- subject.call({})
53
- expect(subject.response.header).to have_key(:abc)
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
- class ExampleWare < Grape::Middleware::Base
64
- def default_options
65
- { monkey: true }
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
- def call(_env)
21
- throw :error, error
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) { { default_message: 'Aww, hamburgers.' } }
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
- class ExceptionApp
7
- class << self
8
- def call(_env)
9
- fail 'rain!'
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
- # raises a hash error
15
- class ErrorHashApp
16
- class << self
17
- def error!(message, status)
18
- throw :error, message: { error: message, detail: 'missing widget' }, status: status
19
- end
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
- def call(_env)
22
- error!('rain!', 401)
22
+ def call(_env)
23
+ error!('rain!', 401)
24
+ end
23
25
  end
24
26
  end
25
- end
26
27
 
27
- # raises an error!
28
- class AccessDeniedApp
29
- class << self
30
- def error!(message, status)
31
- throw :error, message: message, status: status
32
- end
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
- def call(_env)
35
- error!('Access Denied', 401)
35
+ def call(_env)
36
+ error!('Access Denied', 401)
37
+ end
36
38
  end
37
39
  end
38
- end
39
40
 
40
- # raises a custom error
41
- class CustomError < Grape::Exceptions::Base
42
- end
41
+ # raises a custom error
42
+ class CustomError < Grape::Exceptions::Base
43
+ end
43
44
 
44
- class CustomErrorApp
45
- class << self
46
- def call(_env)
47
- fail CustomError, status: 400, message: 'failed validation'
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 '/'