grape 1.7.1 → 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 (163) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -1
  3. data/CONTRIBUTING.md +1 -1
  4. data/README.md +30 -25
  5. data/UPGRADING.md +35 -0
  6. data/grape.gemspec +3 -6
  7. data/lib/grape/api.rb +2 -2
  8. data/lib/grape/content_types.rb +2 -8
  9. data/lib/grape/dsl/desc.rb +1 -1
  10. data/lib/grape/dsl/inside_route.rb +11 -11
  11. data/lib/grape/dsl/request_response.rb +2 -1
  12. data/lib/grape/dsl/settings.rb +2 -6
  13. data/lib/grape/endpoint.rb +28 -18
  14. data/lib/grape/error_formatter/base.rb +1 -1
  15. data/lib/grape/exceptions/base.rb +2 -2
  16. data/lib/grape/exceptions/missing_group_type.rb +1 -6
  17. data/lib/grape/exceptions/unsupported_group_type.rb +1 -6
  18. data/lib/grape/exceptions/validation_errors.rb +1 -6
  19. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +3 -3
  20. data/lib/grape/extensions/hash.rb +4 -7
  21. data/lib/grape/extensions/hashie/mash.rb +3 -3
  22. data/lib/grape/formatter/serializable_hash.rb +7 -7
  23. data/lib/grape/http/headers.rb +12 -2
  24. data/lib/grape/middleware/auth/base.rb +1 -1
  25. data/lib/grape/middleware/auth/strategies.rb +1 -2
  26. data/lib/grape/middleware/error.rb +5 -5
  27. data/lib/grape/middleware/formatter.rb +6 -6
  28. data/lib/grape/middleware/versioner/header.rb +11 -19
  29. data/lib/grape/railtie.rb +9 -0
  30. data/lib/grape/request.rb +8 -2
  31. data/lib/grape/router/route.rb +1 -3
  32. data/lib/grape/util/lazy_value.rb +3 -11
  33. data/lib/grape/util/strict_hash_configuration.rb +3 -4
  34. data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
  35. data/lib/grape/validations/params_scope.rb +8 -2
  36. data/lib/grape/validations/single_attribute_iterator.rb +3 -1
  37. data/lib/grape/validations/types/custom_type_coercer.rb +2 -16
  38. data/lib/grape/validations/validators/base.rb +9 -20
  39. data/lib/grape/validations/validators/default_validator.rb +2 -20
  40. data/lib/grape/validations/validators/multiple_params_base.rb +4 -8
  41. data/lib/grape/validations/validators/values_validator.rb +14 -5
  42. data/lib/grape/version.rb +1 -1
  43. data/lib/grape.rb +26 -5
  44. metadata +13 -253
  45. data/lib/grape/config.rb +0 -34
  46. data/lib/grape/extensions/deep_mergeable_hash.rb +0 -21
  47. data/lib/grape/extensions/deep_symbolize_hash.rb +0 -32
  48. data/spec/grape/api/custom_validations_spec.rb +0 -256
  49. data/spec/grape/api/deeply_included_options_spec.rb +0 -56
  50. data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -38
  51. data/spec/grape/api/documentation_spec.rb +0 -59
  52. data/spec/grape/api/inherited_helpers_spec.rb +0 -114
  53. data/spec/grape/api/instance_spec.rb +0 -103
  54. data/spec/grape/api/invalid_format_spec.rb +0 -45
  55. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -38
  56. data/spec/grape/api/nested_helpers_spec.rb +0 -50
  57. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -43
  58. data/spec/grape/api/parameters_modification_spec.rb +0 -41
  59. data/spec/grape/api/patch_method_helpers_spec.rb +0 -79
  60. data/spec/grape/api/recognize_path_spec.rb +0 -21
  61. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -37
  62. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -26
  63. data/spec/grape/api/routes_with_requirements_spec.rb +0 -59
  64. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -41
  65. data/spec/grape/api/shared_helpers_spec.rb +0 -36
  66. data/spec/grape/api_remount_spec.rb +0 -473
  67. data/spec/grape/api_spec.rb +0 -4347
  68. data/spec/grape/config_spec.rb +0 -17
  69. data/spec/grape/dsl/callbacks_spec.rb +0 -45
  70. data/spec/grape/dsl/desc_spec.rb +0 -101
  71. data/spec/grape/dsl/headers_spec.rb +0 -62
  72. data/spec/grape/dsl/helpers_spec.rb +0 -100
  73. data/spec/grape/dsl/inside_route_spec.rb +0 -535
  74. data/spec/grape/dsl/logger_spec.rb +0 -24
  75. data/spec/grape/dsl/middleware_spec.rb +0 -60
  76. data/spec/grape/dsl/parameters_spec.rb +0 -180
  77. data/spec/grape/dsl/request_response_spec.rb +0 -206
  78. data/spec/grape/dsl/routing_spec.rb +0 -275
  79. data/spec/grape/dsl/settings_spec.rb +0 -261
  80. data/spec/grape/dsl/validations_spec.rb +0 -55
  81. data/spec/grape/endpoint/declared_spec.rb +0 -846
  82. data/spec/grape/endpoint_spec.rb +0 -1085
  83. data/spec/grape/entity_spec.rb +0 -336
  84. data/spec/grape/exceptions/base_spec.rb +0 -81
  85. data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -145
  86. data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -358
  87. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -15
  88. data/spec/grape/exceptions/invalid_response_spec.rb +0 -11
  89. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +0 -15
  90. data/spec/grape/exceptions/missing_group_type_spec.rb +0 -21
  91. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -17
  92. data/spec/grape/exceptions/missing_option_spec.rb +0 -15
  93. data/spec/grape/exceptions/unknown_options_spec.rb +0 -15
  94. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -15
  95. data/spec/grape/exceptions/unsupported_group_type_spec.rb +0 -23
  96. data/spec/grape/exceptions/validation_errors_spec.rb +0 -92
  97. data/spec/grape/exceptions/validation_spec.rb +0 -19
  98. data/spec/grape/extensions/param_builders/hash_spec.rb +0 -83
  99. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -105
  100. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -79
  101. data/spec/grape/integration/global_namespace_function_spec.rb +0 -29
  102. data/spec/grape/integration/rack_sendfile_spec.rb +0 -48
  103. data/spec/grape/integration/rack_spec.rb +0 -51
  104. data/spec/grape/loading_spec.rb +0 -44
  105. data/spec/grape/middleware/auth/base_spec.rb +0 -31
  106. data/spec/grape/middleware/auth/dsl_spec.rb +0 -60
  107. data/spec/grape/middleware/auth/strategies_spec.rb +0 -120
  108. data/spec/grape/middleware/base_spec.rb +0 -221
  109. data/spec/grape/middleware/error_spec.rb +0 -85
  110. data/spec/grape/middleware/exception_spec.rb +0 -294
  111. data/spec/grape/middleware/formatter_spec.rb +0 -461
  112. data/spec/grape/middleware/globals_spec.rb +0 -30
  113. data/spec/grape/middleware/stack_spec.rb +0 -155
  114. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -122
  115. data/spec/grape/middleware/versioner/header_spec.rb +0 -345
  116. data/spec/grape/middleware/versioner/param_spec.rb +0 -171
  117. data/spec/grape/middleware/versioner/path_spec.rb +0 -62
  118. data/spec/grape/middleware/versioner_spec.rb +0 -21
  119. data/spec/grape/named_api_spec.rb +0 -19
  120. data/spec/grape/parser_spec.rb +0 -86
  121. data/spec/grape/path_spec.rb +0 -252
  122. data/spec/grape/presenters/presenter_spec.rb +0 -71
  123. data/spec/grape/request_spec.rb +0 -136
  124. data/spec/grape/util/inheritable_setting_spec.rb +0 -242
  125. data/spec/grape/util/inheritable_values_spec.rb +0 -79
  126. data/spec/grape/util/reverse_stackable_values_spec.rb +0 -134
  127. data/spec/grape/util/stackable_values_spec.rb +0 -128
  128. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -38
  129. data/spec/grape/validations/attributes_doc_spec.rb +0 -153
  130. data/spec/grape/validations/instance_behaivour_spec.rb +0 -43
  131. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -40
  132. data/spec/grape/validations/params_scope_spec.rb +0 -1420
  133. data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -57
  134. data/spec/grape/validations/types/array_coercer_spec.rb +0 -33
  135. data/spec/grape/validations/types/primitive_coercer_spec.rb +0 -150
  136. data/spec/grape/validations/types/set_coercer_spec.rb +0 -32
  137. data/spec/grape/validations/types_spec.rb +0 -111
  138. data/spec/grape/validations/validators/all_or_none_spec.rb +0 -162
  139. data/spec/grape/validations/validators/allow_blank_spec.rb +0 -575
  140. data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -205
  141. data/spec/grape/validations/validators/coerce_spec.rb +0 -1261
  142. data/spec/grape/validations/validators/default_spec.rb +0 -463
  143. data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -233
  144. data/spec/grape/validations/validators/except_values_spec.rb +0 -192
  145. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -214
  146. data/spec/grape/validations/validators/presence_spec.rb +0 -315
  147. data/spec/grape/validations/validators/regexp_spec.rb +0 -161
  148. data/spec/grape/validations/validators/same_as_spec.rb +0 -57
  149. data/spec/grape/validations/validators/values_spec.rb +0 -696
  150. data/spec/grape/validations/validators/zh-CN.yml +0 -10
  151. data/spec/grape/validations_spec.rb +0 -2029
  152. data/spec/integration/eager_load/eager_load_spec.rb +0 -15
  153. data/spec/integration/multi_json/json_spec.rb +0 -7
  154. data/spec/integration/multi_xml/xml_spec.rb +0 -7
  155. data/spec/shared/versioning_examples.rb +0 -215
  156. data/spec/spec_helper.rb +0 -52
  157. data/spec/support/basic_auth_encode_helpers.rb +0 -11
  158. data/spec/support/chunks.rb +0 -14
  159. data/spec/support/content_type_helpers.rb +0 -15
  160. data/spec/support/endpoint_faker.rb +0 -25
  161. data/spec/support/file_streamer.rb +0 -13
  162. data/spec/support/integer_helpers.rb +0 -13
  163. 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,145 +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 without a rescue handler' do
95
- subject { Class.new(Grape::API) }
96
-
97
- before do
98
- subject.params do
99
- requires :beer
100
- end
101
- subject.post '/beer' do
102
- 'beer received'
103
- end
104
- end
105
-
106
- def app
107
- subject
108
- end
109
-
110
- context 'and with content_type json' do
111
- it 'can recover from failed body parsing' do
112
- post '/beer', 'test', 'CONTENT_TYPE' => 'application/json'
113
- expect(last_response.status).to eq 400
114
- expect(last_response.body).to include('message body does not match declared format')
115
- expect(last_response.body).to include('application/json')
116
- end
117
- end
118
-
119
- context 'with content_type xml' do
120
- it 'can recover from failed body parsing' do
121
- post '/beer', 'test', 'CONTENT_TYPE' => 'application/xml'
122
- expect(last_response.status).to eq 400
123
- expect(last_response.body).to include('message body does not match declared format')
124
- expect(last_response.body).to include('application/xml')
125
- end
126
- end
127
-
128
- context 'with content_type text' do
129
- it 'can recover from failed body parsing' do
130
- post '/beer', 'test', 'CONTENT_TYPE' => 'text/plain'
131
- expect(last_response.status).to eq 400
132
- expect(last_response.body).to eq('beer is missing')
133
- end
134
- end
135
-
136
- context 'and with no specific content_type' do
137
- it 'can recover from failed body parsing' do
138
- post '/beer', 'test', {}
139
- expect(last_response.status).to eq 400
140
- # plain response with text/html
141
- expect(last_response.body).to eq('beer is missing')
142
- end
143
- end
144
- end
145
- end