grape 1.8.0 → 2.0.0

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.
Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/README.md +19 -22
  4. data/UPGRADING.md +35 -0
  5. data/grape.gemspec +1 -4
  6. data/lib/grape/dsl/desc.rb +1 -1
  7. data/lib/grape/dsl/inside_route.rb +9 -9
  8. data/lib/grape/endpoint.rb +9 -1
  9. data/lib/grape/exceptions/missing_group_type.rb +1 -1
  10. data/lib/grape/exceptions/unsupported_group_type.rb +1 -1
  11. data/lib/grape/http/headers.rb +12 -2
  12. data/lib/grape/middleware/auth/strategies.rb +1 -2
  13. data/lib/grape/middleware/error.rb +4 -4
  14. data/lib/grape/middleware/formatter.rb +5 -5
  15. data/lib/grape/railtie.rb +9 -0
  16. data/lib/grape/request.rb +8 -2
  17. data/lib/grape/router/route.rb +1 -1
  18. data/lib/grape/validations/validators/base.rb +1 -1
  19. data/lib/grape/validations/validators/values_validator.rb +2 -2
  20. data/lib/grape/version.rb +1 -1
  21. data/lib/grape.rb +15 -2
  22. metadata +8 -243
  23. data/spec/grape/api/custom_validations_spec.rb +0 -213
  24. data/spec/grape/api/deeply_included_options_spec.rb +0 -56
  25. data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -38
  26. data/spec/grape/api/documentation_spec.rb +0 -59
  27. data/spec/grape/api/inherited_helpers_spec.rb +0 -114
  28. data/spec/grape/api/instance_spec.rb +0 -103
  29. data/spec/grape/api/invalid_format_spec.rb +0 -45
  30. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -38
  31. data/spec/grape/api/nested_helpers_spec.rb +0 -50
  32. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -43
  33. data/spec/grape/api/parameters_modification_spec.rb +0 -41
  34. data/spec/grape/api/patch_method_helpers_spec.rb +0 -79
  35. data/spec/grape/api/recognize_path_spec.rb +0 -21
  36. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -37
  37. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -26
  38. data/spec/grape/api/routes_with_requirements_spec.rb +0 -59
  39. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -41
  40. data/spec/grape/api/shared_helpers_spec.rb +0 -36
  41. data/spec/grape/api_remount_spec.rb +0 -509
  42. data/spec/grape/api_spec.rb +0 -4356
  43. data/spec/grape/dsl/callbacks_spec.rb +0 -45
  44. data/spec/grape/dsl/desc_spec.rb +0 -98
  45. data/spec/grape/dsl/headers_spec.rb +0 -62
  46. data/spec/grape/dsl/helpers_spec.rb +0 -100
  47. data/spec/grape/dsl/inside_route_spec.rb +0 -531
  48. data/spec/grape/dsl/logger_spec.rb +0 -24
  49. data/spec/grape/dsl/middleware_spec.rb +0 -60
  50. data/spec/grape/dsl/parameters_spec.rb +0 -180
  51. data/spec/grape/dsl/request_response_spec.rb +0 -225
  52. data/spec/grape/dsl/routing_spec.rb +0 -275
  53. data/spec/grape/dsl/settings_spec.rb +0 -261
  54. data/spec/grape/dsl/validations_spec.rb +0 -55
  55. data/spec/grape/endpoint/declared_spec.rb +0 -846
  56. data/spec/grape/endpoint_spec.rb +0 -1085
  57. data/spec/grape/entity_spec.rb +0 -336
  58. data/spec/grape/exceptions/base_spec.rb +0 -81
  59. data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -185
  60. data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -358
  61. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -15
  62. data/spec/grape/exceptions/invalid_response_spec.rb +0 -11
  63. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +0 -15
  64. data/spec/grape/exceptions/missing_group_type_spec.rb +0 -17
  65. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -17
  66. data/spec/grape/exceptions/missing_option_spec.rb +0 -15
  67. data/spec/grape/exceptions/unknown_options_spec.rb +0 -15
  68. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -15
  69. data/spec/grape/exceptions/unsupported_group_type_spec.rb +0 -19
  70. data/spec/grape/exceptions/validation_errors_spec.rb +0 -92
  71. data/spec/grape/exceptions/validation_spec.rb +0 -19
  72. data/spec/grape/extensions/param_builders/hash_spec.rb +0 -83
  73. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -105
  74. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -79
  75. data/spec/grape/grape_spec.rb +0 -9
  76. data/spec/grape/integration/global_namespace_function_spec.rb +0 -29
  77. data/spec/grape/integration/rack_sendfile_spec.rb +0 -48
  78. data/spec/grape/integration/rack_spec.rb +0 -51
  79. data/spec/grape/loading_spec.rb +0 -44
  80. data/spec/grape/middleware/auth/base_spec.rb +0 -31
  81. data/spec/grape/middleware/auth/dsl_spec.rb +0 -60
  82. data/spec/grape/middleware/auth/strategies_spec.rb +0 -120
  83. data/spec/grape/middleware/base_spec.rb +0 -221
  84. data/spec/grape/middleware/error_spec.rb +0 -85
  85. data/spec/grape/middleware/exception_spec.rb +0 -294
  86. data/spec/grape/middleware/formatter_spec.rb +0 -461
  87. data/spec/grape/middleware/globals_spec.rb +0 -30
  88. data/spec/grape/middleware/stack_spec.rb +0 -155
  89. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -122
  90. data/spec/grape/middleware/versioner/header_spec.rb +0 -345
  91. data/spec/grape/middleware/versioner/param_spec.rb +0 -171
  92. data/spec/grape/middleware/versioner/path_spec.rb +0 -62
  93. data/spec/grape/middleware/versioner_spec.rb +0 -21
  94. data/spec/grape/named_api_spec.rb +0 -19
  95. data/spec/grape/parser_spec.rb +0 -86
  96. data/spec/grape/path_spec.rb +0 -252
  97. data/spec/grape/presenters/presenter_spec.rb +0 -71
  98. data/spec/grape/request_spec.rb +0 -126
  99. data/spec/grape/util/inheritable_setting_spec.rb +0 -242
  100. data/spec/grape/util/inheritable_values_spec.rb +0 -79
  101. data/spec/grape/util/reverse_stackable_values_spec.rb +0 -134
  102. data/spec/grape/util/stackable_values_spec.rb +0 -128
  103. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -38
  104. data/spec/grape/validations/attributes_doc_spec.rb +0 -153
  105. data/spec/grape/validations/instance_behaivour_spec.rb +0 -43
  106. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -38
  107. data/spec/grape/validations/params_scope_spec.rb +0 -1420
  108. data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -56
  109. data/spec/grape/validations/types/array_coercer_spec.rb +0 -33
  110. data/spec/grape/validations/types/primitive_coercer_spec.rb +0 -150
  111. data/spec/grape/validations/types/set_coercer_spec.rb +0 -32
  112. data/spec/grape/validations/types_spec.rb +0 -111
  113. data/spec/grape/validations/validators/all_or_none_spec.rb +0 -162
  114. data/spec/grape/validations/validators/allow_blank_spec.rb +0 -575
  115. data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -205
  116. data/spec/grape/validations/validators/base_spec.rb +0 -38
  117. data/spec/grape/validations/validators/coerce_spec.rb +0 -1261
  118. data/spec/grape/validations/validators/default_spec.rb +0 -463
  119. data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -233
  120. data/spec/grape/validations/validators/except_values_spec.rb +0 -192
  121. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -214
  122. data/spec/grape/validations/validators/presence_spec.rb +0 -315
  123. data/spec/grape/validations/validators/regexp_spec.rb +0 -161
  124. data/spec/grape/validations/validators/same_as_spec.rb +0 -57
  125. data/spec/grape/validations/validators/values_spec.rb +0 -733
  126. data/spec/grape/validations/validators/zh-CN.yml +0 -10
  127. data/spec/grape/validations_spec.rb +0 -2030
  128. data/spec/integration/eager_load/eager_load_spec.rb +0 -15
  129. data/spec/integration/multi_json/json_spec.rb +0 -7
  130. data/spec/integration/multi_xml/xml_spec.rb +0 -7
  131. data/spec/shared/deprecated_class_examples.rb +0 -16
  132. data/spec/shared/versioning_examples.rb +0 -215
  133. data/spec/spec_helper.rb +0 -52
  134. data/spec/support/basic_auth_encode_helpers.rb +0 -11
  135. data/spec/support/chunks.rb +0 -14
  136. data/spec/support/content_type_helpers.rb +0 -15
  137. data/spec/support/endpoint_faker.rb +0 -25
  138. data/spec/support/file_streamer.rb +0 -13
  139. data/spec/support/integer_helpers.rb +0 -13
  140. data/spec/support/versioned_helpers.rb +0 -55
@@ -1,336 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'grape_entity'
4
-
5
- describe Grape::Entity do
6
- subject { Class.new(Grape::API) }
7
-
8
- def app
9
- subject
10
- end
11
-
12
- describe '#present' do
13
- it 'sets the object as the body if no options are provided' do
14
- inner_body = nil
15
- subject.get '/example' do
16
- present(abc: 'def')
17
- inner_body = body
18
- end
19
- get '/example'
20
- expect(inner_body).to eql(abc: 'def')
21
- end
22
-
23
- it 'calls through to the provided entity class if one is given' do
24
- entity_mock = Object.new
25
- allow(entity_mock).to receive(:represent)
26
-
27
- subject.get '/example' do
28
- present Object.new, with: entity_mock
29
- end
30
- get '/example'
31
- end
32
-
33
- it 'pulls a representation from the class options if it exists' do
34
- entity = Class.new(described_class)
35
- allow(entity).to receive(:represent).and_return('Hiya')
36
-
37
- subject.represent Object, with: entity
38
- subject.get '/example' do
39
- present Object.new
40
- end
41
- get '/example'
42
- expect(last_response.body).to eq('Hiya')
43
- end
44
-
45
- it 'pulls a representation from the class options if the presented object is a collection of objects' do
46
- entity = Class.new(described_class)
47
- allow(entity).to receive(:represent).and_return('Hiya')
48
-
49
- module EntitySpec
50
- class TestObject
51
- end
52
-
53
- class FakeCollection
54
- def first
55
- TestObject.new
56
- end
57
- end
58
- end
59
-
60
- subject.represent EntitySpec::TestObject, with: entity
61
- subject.get '/example' do
62
- present [EntitySpec::TestObject.new]
63
- end
64
-
65
- subject.get '/example2' do
66
- present EntitySpec::FakeCollection.new
67
- end
68
-
69
- get '/example'
70
- expect(last_response.body).to eq('Hiya')
71
-
72
- get '/example2'
73
- expect(last_response.body).to eq('Hiya')
74
- end
75
-
76
- it 'pulls a representation from the class ancestor if it exists' do
77
- entity = Class.new(described_class)
78
- allow(entity).to receive(:represent).and_return('Hiya')
79
-
80
- subclass = Class.new(Object)
81
-
82
- subject.represent Object, with: entity
83
- subject.get '/example' do
84
- present subclass.new
85
- end
86
- get '/example'
87
- expect(last_response.body).to eq('Hiya')
88
- end
89
-
90
- it 'automatically uses Klass::Entity if that exists' do
91
- some_model = Class.new
92
- entity = Class.new(described_class)
93
- allow(entity).to receive(:represent).and_return('Auto-detect!')
94
-
95
- some_model.const_set :Entity, entity
96
-
97
- subject.get '/example' do
98
- present some_model.new
99
- end
100
- get '/example'
101
- expect(last_response.body).to eq('Auto-detect!')
102
- end
103
-
104
- it 'automatically uses Klass::Entity based on the first object in the collection being presented' do
105
- some_model = Class.new
106
- entity = Class.new(described_class)
107
- allow(entity).to receive(:represent).and_return('Auto-detect!')
108
-
109
- some_model.const_set :Entity, entity
110
-
111
- subject.get '/example' do
112
- present [some_model.new]
113
- end
114
- get '/example'
115
- expect(last_response.body).to eq('Auto-detect!')
116
- end
117
-
118
- it 'does not run autodetection for Entity when explicitly provided' do
119
- entity = Class.new(described_class)
120
- some_array = []
121
-
122
- subject.get '/example' do
123
- present some_array, with: entity
124
- end
125
-
126
- expect(some_array).not_to receive(:first)
127
- get '/example'
128
- end
129
-
130
- it 'does not use #first method on ActiveRecord::Relation to prevent needless sql query' do
131
- entity = Class.new(described_class)
132
- some_relation = Class.new
133
- some_model = Class.new
134
-
135
- allow(entity).to receive(:represent).and_return('Auto-detect!')
136
- allow(some_relation).to receive(:first)
137
- allow(some_relation).to receive(:klass).and_return(some_model)
138
-
139
- some_model.const_set :Entity, entity
140
-
141
- subject.get '/example' do
142
- present some_relation
143
- end
144
-
145
- expect(some_relation).not_to receive(:first)
146
- get '/example'
147
- expect(last_response.body).to eq('Auto-detect!')
148
- end
149
-
150
- it 'autodetection does not use Entity if it is not a presenter' do
151
- some_model = Class.new
152
- entity = Class.new
153
-
154
- some_model.class.const_set :Entity, entity
155
-
156
- subject.get '/example' do
157
- present some_model
158
- end
159
- get '/example'
160
- expect(entity).not_to receive(:represent)
161
- end
162
-
163
- it 'adds a root key to the output if one is given' do
164
- inner_body = nil
165
- subject.get '/example' do
166
- present({ abc: 'def' }, root: :root)
167
- inner_body = body
168
- end
169
- get '/example'
170
- expect(inner_body).to eql(root: { abc: 'def' })
171
- end
172
-
173
- %i[json serializable_hash].each do |format|
174
- it "presents with #{format}" do
175
- entity = Class.new(described_class)
176
- entity.root 'examples', 'example'
177
- entity.expose :id
178
-
179
- subject.format format
180
- subject.get '/example' do
181
- c = Class.new do
182
- attr_reader :id
183
-
184
- def initialize(id)
185
- @id = id
186
- end
187
- end
188
- present c.new(1), with: entity
189
- end
190
-
191
- get '/example'
192
- expect(last_response.status).to eq(200)
193
- expect(last_response.body).to eq('{"example":{"id":1}}')
194
- end
195
-
196
- it "presents with #{format} collection" do
197
- entity = Class.new(described_class)
198
- entity.root 'examples', 'example'
199
- entity.expose :id
200
-
201
- subject.format format
202
- subject.get '/examples' do
203
- c = Class.new do
204
- attr_reader :id
205
-
206
- def initialize(id)
207
- @id = id
208
- end
209
- end
210
- examples = [c.new(1), c.new(2)]
211
- present examples, with: entity
212
- end
213
-
214
- get '/examples'
215
- expect(last_response.status).to eq(200)
216
- expect(last_response.body).to eq('{"examples":[{"id":1},{"id":2}]}')
217
- end
218
- end
219
-
220
- it 'presents with xml' do
221
- entity = Class.new(described_class)
222
- entity.root 'examples', 'example'
223
- entity.expose :name
224
-
225
- subject.format :xml
226
-
227
- subject.get '/example' do
228
- c = Class.new do
229
- attr_reader :name
230
-
231
- def initialize(args)
232
- @name = args[:name] || 'no name set'
233
- end
234
- end
235
- present c.new(name: 'johnnyiller'), with: entity
236
- end
237
- get '/example'
238
- expect(last_response.status).to eq(200)
239
- expect(last_response.headers['Content-type']).to eq('application/xml')
240
- expect(last_response.body).to eq <<~XML
241
- <?xml version="1.0" encoding="UTF-8"?>
242
- <hash>
243
- <example>
244
- <name>johnnyiller</name>
245
- </example>
246
- </hash>
247
- XML
248
- end
249
-
250
- it 'presents with json' do
251
- entity = Class.new(described_class)
252
- entity.root 'examples', 'example'
253
- entity.expose :name
254
-
255
- subject.format :json
256
-
257
- subject.get '/example' do
258
- c = Class.new do
259
- attr_reader :name
260
-
261
- def initialize(args)
262
- @name = args[:name] || 'no name set'
263
- end
264
- end
265
- present c.new(name: 'johnnyiller'), with: entity
266
- end
267
- get '/example'
268
- expect(last_response.status).to eq(200)
269
- expect(last_response.headers['Content-type']).to eq('application/json')
270
- expect(last_response.body).to eq('{"example":{"name":"johnnyiller"}}')
271
- end
272
-
273
- it 'presents with jsonp utilising Rack::JSONP' do
274
- # Include JSONP middleware
275
- subject.use Rack::JSONP
276
-
277
- entity = Class.new(described_class)
278
- entity.root 'examples', 'example'
279
- entity.expose :name
280
-
281
- # Rack::JSONP expects a standard JSON response in UTF-8 format
282
- subject.format :json
283
- subject.formatter :json, lambda { |object, _|
284
- object.to_json.encode('utf-8')
285
- }
286
-
287
- subject.get '/example' do
288
- c = Class.new do
289
- attr_reader :name
290
-
291
- def initialize(args)
292
- @name = args[:name] || 'no name set'
293
- end
294
- end
295
-
296
- present c.new(name: 'johnnyiller'), with: entity
297
- end
298
-
299
- get '/example?callback=abcDef'
300
- expect(last_response.status).to eq(200)
301
- expect(last_response.headers['Content-type']).to eq('application/javascript')
302
- expect(last_response.body).to include 'abcDef({"example":{"name":"johnnyiller"}})'
303
- end
304
-
305
- context 'present with multiple entities' do
306
- it 'present with multiple entities using optional symbol' do
307
- user = Class.new do
308
- attr_reader :name
309
-
310
- def initialize(args)
311
- @name = args[:name] || 'no name set'
312
- end
313
- end
314
- user1 = user.new(name: 'user1')
315
- user2 = user.new(name: 'user2')
316
-
317
- entity = Class.new(described_class)
318
- entity.expose :name
319
-
320
- subject.format :json
321
- subject.get '/example' do
322
- present :page, 1
323
- present :user1, user1, with: entity
324
- present :user2, user2, with: entity
325
- end
326
- get '/example'
327
- expect_response_json = {
328
- 'page' => 1,
329
- 'user1' => { 'name' => 'user1' },
330
- 'user2' => { 'name' => 'user2' }
331
- }
332
- expect(JSON(last_response.body)).to eq(expect_response_json)
333
- end
334
- end
335
- end
336
- end
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- describe Grape::Exceptions::Base do
4
- describe '#to_s' do
5
- subject { described_class.new(message: message).to_s }
6
-
7
- let(:message) { 'a_message' }
8
-
9
- it { is_expected.to eq(message) }
10
- end
11
-
12
- describe '#message' do
13
- subject { described_class.new(message: message).message }
14
-
15
- let(:message) { 'a_message' }
16
-
17
- it { is_expected.to eq(message) }
18
- end
19
-
20
- describe '#compose_message' do
21
- subject { described_class.new.send(:compose_message, key, **attributes) }
22
-
23
- let(:key) { :invalid_formatter }
24
- let(:attributes) { { klass: String, to_format: 'xml' } }
25
-
26
- after do
27
- I18n.enforce_available_locales = true
28
- I18n.available_locales = %i[en]
29
- I18n.locale = :en
30
- I18n.default_locale = :en
31
- I18n.reload!
32
- end
33
-
34
- context 'when I18n enforces available locales' do
35
- before { I18n.enforce_available_locales = true }
36
-
37
- context 'when the fallback locale is available' do
38
- before do
39
- I18n.available_locales = %i[de en]
40
- I18n.default_locale = :de
41
- end
42
-
43
- it 'returns the translated message' do
44
- expect(subject).to eq('cannot convert String to xml')
45
- end
46
- end
47
-
48
- context 'when the fallback locale is not available' do
49
- before do
50
- I18n.available_locales = %i[de jp]
51
- I18n.locale = :de
52
- I18n.default_locale = :de
53
- end
54
-
55
- it 'returns the translation string' do
56
- expect(subject).to eq("grape.errors.messages.#{key}")
57
- end
58
- end
59
- end
60
-
61
- context 'when I18n does not enforce available locales' do
62
- before { I18n.enforce_available_locales = false }
63
-
64
- context 'when the fallback locale is available' do
65
- before { I18n.available_locales = %i[de en] }
66
-
67
- it 'returns the translated message' do
68
- expect(subject).to eq('cannot convert String to xml')
69
- end
70
- end
71
-
72
- context 'when the fallback locale is not available' do
73
- before { I18n.available_locales = %i[de jp] }
74
-
75
- it 'returns the translated message' do
76
- expect(subject).to eq('cannot convert String to xml')
77
- end
78
- end
79
- end
80
- end
81
- end
@@ -1,185 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- describe Grape::Exceptions::ValidationErrors do
4
- context 'api with rescue_from :all handler' do
5
- subject { Class.new(Grape::API) }
6
-
7
- before do
8
- subject.rescue_from :all do |_e|
9
- rack_response 'message was processed', 400
10
- end
11
- subject.params do
12
- requires :beer
13
- end
14
- subject.post '/beer' do
15
- 'beer received'
16
- end
17
- end
18
-
19
- def app
20
- subject
21
- end
22
-
23
- context 'with content_type json' do
24
- it 'can recover from failed body parsing' do
25
- post '/beer', 'test', 'CONTENT_TYPE' => 'application/json'
26
- expect(last_response.status).to eq 400
27
- expect(last_response.body).to eq('message was processed')
28
- end
29
- end
30
-
31
- context 'with content_type xml' do
32
- it 'can recover from failed body parsing' do
33
- post '/beer', 'test', 'CONTENT_TYPE' => 'application/xml'
34
- expect(last_response.status).to eq 400
35
- expect(last_response.body).to eq('message was processed')
36
- end
37
- end
38
-
39
- context 'with content_type text' do
40
- it 'can recover from failed body parsing' do
41
- post '/beer', 'test', 'CONTENT_TYPE' => 'text/plain'
42
- expect(last_response.status).to eq 400
43
- expect(last_response.body).to eq('message was processed')
44
- end
45
- end
46
-
47
- context 'with no specific content_type' do
48
- it 'can recover from failed body parsing' do
49
- post '/beer', 'test', {}
50
- expect(last_response.status).to eq 400
51
- expect(last_response.body).to eq('message was processed')
52
- end
53
- end
54
- end
55
-
56
- context 'api with rescue_from :grape_exceptions handler' do
57
- subject { Class.new(Grape::API) }
58
-
59
- before do
60
- subject.rescue_from :all do |_e|
61
- rack_response 'message was processed', 400
62
- end
63
- subject.rescue_from :grape_exceptions
64
-
65
- subject.params do
66
- requires :beer
67
- end
68
- subject.post '/beer' do
69
- 'beer received'
70
- end
71
- end
72
-
73
- def app
74
- subject
75
- end
76
-
77
- context 'with content_type json' do
78
- it 'returns body parsing error message' do
79
- post '/beer', 'test', 'CONTENT_TYPE' => 'application/json'
80
- expect(last_response.status).to eq 400
81
- expect(last_response.body).to include 'message body does not match declared format'
82
- end
83
- end
84
-
85
- context 'with content_type xml' do
86
- it 'returns body parsing error message' do
87
- post '/beer', 'test', 'CONTENT_TYPE' => 'application/xml'
88
- expect(last_response.status).to eq 400
89
- expect(last_response.body).to include 'message body does not match declared format'
90
- end
91
- end
92
- end
93
-
94
- context 'api with rescue_from :grape_exceptions handler with block' do
95
- subject { Class.new(Grape::API) }
96
-
97
- before do
98
- subject.rescue_from :grape_exceptions do |e|
99
- rack_response "Custom Error Contents, Original Message: #{e.message}", 400
100
- end
101
-
102
- subject.params do
103
- requires :beer
104
- end
105
-
106
- subject.post '/beer' do
107
- 'beer received'
108
- end
109
- end
110
-
111
- def app
112
- subject
113
- end
114
-
115
- context 'with content_type json' do
116
- it 'returns body parsing error message' do
117
- post '/beer', 'test', 'CONTENT_TYPE' => 'application/json'
118
- expect(last_response.status).to eq 400
119
- expect(last_response.body).to include 'message body does not match declared format'
120
- expect(last_response.body).to include 'Custom Error Contents, Original Message'
121
- end
122
- end
123
-
124
- context 'with content_type xml' do
125
- it 'returns body parsing error message' do
126
- post '/beer', 'test', 'CONTENT_TYPE' => 'application/xml'
127
- expect(last_response.status).to eq 400
128
- expect(last_response.body).to include 'message body does not match declared format'
129
- expect(last_response.body).to include 'Custom Error Contents, Original Message'
130
- end
131
- end
132
- end
133
-
134
- context 'api without a rescue handler' do
135
- subject { Class.new(Grape::API) }
136
-
137
- before do
138
- subject.params do
139
- requires :beer
140
- end
141
- subject.post '/beer' do
142
- 'beer received'
143
- end
144
- end
145
-
146
- def app
147
- subject
148
- end
149
-
150
- context 'and with content_type json' do
151
- it 'can recover from failed body parsing' do
152
- post '/beer', 'test', 'CONTENT_TYPE' => 'application/json'
153
- expect(last_response.status).to eq 400
154
- expect(last_response.body).to include('message body does not match declared format')
155
- expect(last_response.body).to include('application/json')
156
- end
157
- end
158
-
159
- context 'with content_type xml' do
160
- it 'can recover from failed body parsing' do
161
- post '/beer', 'test', 'CONTENT_TYPE' => 'application/xml'
162
- expect(last_response.status).to eq 400
163
- expect(last_response.body).to include('message body does not match declared format')
164
- expect(last_response.body).to include('application/xml')
165
- end
166
- end
167
-
168
- context 'with content_type text' do
169
- it 'can recover from failed body parsing' do
170
- post '/beer', 'test', 'CONTENT_TYPE' => 'text/plain'
171
- expect(last_response.status).to eq 400
172
- expect(last_response.body).to eq('beer is missing')
173
- end
174
- end
175
-
176
- context 'and with no specific content_type' do
177
- it 'can recover from failed body parsing' do
178
- post '/beer', 'test', {}
179
- expect(last_response.status).to eq 400
180
- # plain response with text/html
181
- expect(last_response.body).to eq('beer is missing')
182
- end
183
- end
184
- end
185
- end