grape 0.10.1 → 0.11.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +1 -1
  4. data/CHANGELOG.md +18 -0
  5. data/Gemfile +1 -1
  6. data/README.md +124 -9
  7. data/UPGRADING.md +66 -0
  8. data/gemfiles/rails_3.gemfile +1 -1
  9. data/gemfiles/rails_4.gemfile +1 -1
  10. data/lib/grape.rb +4 -0
  11. data/lib/grape/api.rb +1 -5
  12. data/lib/grape/dsl/inside_route.rb +2 -1
  13. data/lib/grape/dsl/parameters.rb +20 -9
  14. data/lib/grape/dsl/routing.rb +11 -1
  15. data/lib/grape/error_formatter/base.rb +1 -1
  16. data/lib/grape/exceptions/invalid_accept_header.rb +10 -0
  17. data/lib/grape/exceptions/invalid_message_body.rb +10 -0
  18. data/lib/grape/exceptions/missing_group_type.rb +10 -0
  19. data/lib/grape/exceptions/unsupported_group_type.rb +10 -0
  20. data/lib/grape/http/request.rb +1 -0
  21. data/lib/grape/locale/en.yml +11 -0
  22. data/lib/grape/middleware/base.rb +1 -1
  23. data/lib/grape/middleware/formatter.rb +2 -0
  24. data/lib/grape/middleware/versioner/header.rb +14 -11
  25. data/lib/grape/parser/json.rb +3 -0
  26. data/lib/grape/parser/xml.rb +3 -0
  27. data/lib/grape/validations/params_scope.rb +20 -4
  28. data/lib/grape/validations/validators/coerce.rb +4 -1
  29. data/lib/grape/validations/validators/values.rb +1 -1
  30. data/lib/grape/version.rb +1 -1
  31. data/spec/grape/api_spec.rb +3 -3
  32. data/spec/grape/dsl/parameters_spec.rb +11 -11
  33. data/spec/grape/dsl/routing_spec.rb +13 -4
  34. data/spec/grape/endpoint_spec.rb +2 -2
  35. data/spec/grape/exceptions/body_parse_errors_spec.rb +105 -0
  36. data/spec/grape/exceptions/invalid_accept_header_spec.rb +330 -0
  37. data/spec/grape/integration/rack_spec.rb +32 -0
  38. data/spec/grape/middleware/base_spec.rb +20 -0
  39. data/spec/grape/middleware/versioner/header_spec.rb +74 -96
  40. data/spec/grape/validations/params_scope_spec.rb +124 -0
  41. data/spec/grape/validations/validators/allow_blank_spec.rb +102 -0
  42. data/spec/grape/validations/validators/values_spec.rb +45 -1
  43. data/spec/grape/validations_spec.rb +54 -16
  44. data/spec/shared/versioning_examples.rb +32 -0
  45. metadata +61 -51
@@ -0,0 +1,330 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grape::Exceptions::InvalidAcceptHeader do
4
+ shared_examples_for 'a valid request' do
5
+ it 'does return with status 200' do
6
+ expect(last_response.status).to eq 200
7
+ end
8
+ it 'does return the expected result' do
9
+ expect(last_response.body).to eq('beer received')
10
+ end
11
+ end
12
+ shared_examples_for 'a cascaded request' do
13
+ it 'does not find a matching route' do
14
+ expect(last_response.status).to eq 404
15
+ end
16
+ end
17
+ shared_examples_for 'a not-cascaded request' do
18
+ it 'does not include the X-Cascade=pass header' do
19
+ expect(last_response.headers['X-Cascade']).to be_nil
20
+ end
21
+ it 'does not accept the request' do
22
+ expect(last_response.status).to eq 406
23
+ end
24
+ end
25
+ shared_examples_for 'a rescued request' do
26
+ it 'does not include the X-Cascade=pass header' do
27
+ expect(last_response.headers['X-Cascade']).to be_nil
28
+ end
29
+ it 'does show rescue handler processing' do
30
+ expect(last_response.status).to eq 400
31
+ expect(last_response.body).to eq('message was processed')
32
+ end
33
+ end
34
+
35
+ context 'API with cascade=false and rescue_from :all handler' do
36
+ subject { Class.new(Grape::API) }
37
+ before {
38
+ subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: false
39
+ subject.rescue_from :all do |e|
40
+ rack_response 'message was processed', 400, e[:headers]
41
+ end
42
+ subject.get '/beer' do
43
+ 'beer received'
44
+ end
45
+ }
46
+
47
+ def app
48
+ subject
49
+ end
50
+
51
+ context 'that received a request with correct vendor and version' do
52
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
53
+ it_should_behave_like 'a valid request'
54
+ end
55
+
56
+ context 'that receives' do
57
+ context 'an invalid version in the request' do
58
+ before {
59
+ get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77',
60
+ 'CONTENT_TYPE' => 'application/json'
61
+ }
62
+ it_should_behave_like 'a rescued request'
63
+ end
64
+ context 'an invalid vendor in the request' do
65
+ before {
66
+ get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99',
67
+ 'CONTENT_TYPE' => 'application/json'
68
+ }
69
+ it_should_behave_like 'a rescued request'
70
+ end
71
+ end
72
+ end
73
+
74
+ context 'API with cascade=false and without a rescue handler' do
75
+ subject { Class.new(Grape::API) }
76
+ before {
77
+ subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: false
78
+ subject.get '/beer' do
79
+ 'beer received'
80
+ end
81
+ }
82
+
83
+ def app
84
+ subject
85
+ end
86
+
87
+ context 'that received a request with correct vendor and version' do
88
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
89
+ it_should_behave_like 'a valid request'
90
+ end
91
+
92
+ context 'that receives' do
93
+ context 'an invalid version in the request' do
94
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77' }
95
+ it_should_behave_like 'a not-cascaded request'
96
+ end
97
+ context 'an invalid vendor in the request' do
98
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99' }
99
+ it_should_behave_like 'a not-cascaded request'
100
+ end
101
+ end
102
+ end
103
+
104
+ context 'API with cascade=false and with rescue_from :all handler and http_codes' do
105
+ subject { Class.new(Grape::API) }
106
+ before {
107
+ subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: false
108
+ subject.rescue_from :all do |e|
109
+ rack_response 'message was processed', 400, e[:headers]
110
+ end
111
+ subject.desc 'Get beer' do
112
+ failure [[400, 'Bad Request'], [401, 'Unauthorized'], [403, 'Forbidden'],
113
+ [404, 'Resource not found'], [406, 'API vendor or version not found'],
114
+ [500, 'Internal processing error']]
115
+ end
116
+ subject.get '/beer' do
117
+ 'beer received'
118
+ end
119
+ }
120
+
121
+ def app
122
+ subject
123
+ end
124
+
125
+ context 'that received a request with correct vendor and version' do
126
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
127
+ it_should_behave_like 'a valid request'
128
+ end
129
+
130
+ context 'that receives' do
131
+ context 'an invalid version in the request' do
132
+ before {
133
+ get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77',
134
+ 'CONTENT_TYPE' => 'application/json'
135
+ }
136
+ it_should_behave_like 'a rescued request'
137
+ end
138
+ context 'an invalid vendor in the request' do
139
+ before {
140
+ get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99',
141
+ 'CONTENT_TYPE' => 'application/json'
142
+ }
143
+ it_should_behave_like 'a rescued request'
144
+ end
145
+ end
146
+ end
147
+
148
+ context 'API with cascade=false, http_codes but without a rescue handler' do
149
+ subject { Class.new(Grape::API) }
150
+ before {
151
+ subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: false
152
+ subject.desc 'Get beer' do
153
+ failure [[400, 'Bad Request'], [401, 'Unauthorized'], [403, 'Forbidden'],
154
+ [404, 'Resource not found'], [406, 'API vendor or version not found'],
155
+ [500, 'Internal processing error']]
156
+ end
157
+ subject.get '/beer' do
158
+ 'beer received'
159
+ end
160
+ }
161
+
162
+ def app
163
+ subject
164
+ end
165
+
166
+ context 'that received a request with correct vendor and version' do
167
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
168
+ it_should_behave_like 'a valid request'
169
+ end
170
+
171
+ context 'that receives' do
172
+ context 'an invalid version in the request' do
173
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77' }
174
+ it_should_behave_like 'a not-cascaded request'
175
+ end
176
+ context 'an invalid vendor in the request' do
177
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99' }
178
+ it_should_behave_like 'a not-cascaded request'
179
+ end
180
+ end
181
+ end
182
+
183
+ context 'API with cascade=true and rescue_from :all handler' do
184
+ subject { Class.new(Grape::API) }
185
+ before {
186
+ subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: true
187
+ subject.rescue_from :all do |e|
188
+ rack_response 'message was processed', 400, e[:headers]
189
+ end
190
+ subject.get '/beer' do
191
+ 'beer received'
192
+ end
193
+ }
194
+
195
+ def app
196
+ subject
197
+ end
198
+
199
+ context 'that received a request with correct vendor and version' do
200
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
201
+ it_should_behave_like 'a valid request'
202
+ end
203
+
204
+ context 'that receives' do
205
+ context 'an invalid version in the request' do
206
+ before {
207
+ get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77',
208
+ 'CONTENT_TYPE' => 'application/json'
209
+ }
210
+ it_should_behave_like 'a cascaded request'
211
+ end
212
+ context 'an invalid vendor in the request' do
213
+ before {
214
+ get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99',
215
+ 'CONTENT_TYPE' => 'application/json'
216
+ }
217
+ it_should_behave_like 'a cascaded request'
218
+ end
219
+ end
220
+ end
221
+
222
+ context 'API with cascade=true and without a rescue handler' do
223
+ subject { Class.new(Grape::API) }
224
+ before {
225
+ subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: true
226
+ subject.get '/beer' do
227
+ 'beer received'
228
+ end
229
+ }
230
+
231
+ def app
232
+ subject
233
+ end
234
+
235
+ context 'that received a request with correct vendor and version' do
236
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
237
+ it_should_behave_like 'a valid request'
238
+ end
239
+
240
+ context 'that receives' do
241
+ context 'an invalid version in the request' do
242
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77' }
243
+ it_should_behave_like 'a cascaded request'
244
+ end
245
+ context 'an invalid vendor in the request' do
246
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99' }
247
+ it_should_behave_like 'a cascaded request'
248
+ end
249
+ end
250
+ end
251
+
252
+ context 'API with cascade=true and with rescue_from :all handler and http_codes' do
253
+ subject { Class.new(Grape::API) }
254
+ before {
255
+ subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: true
256
+ subject.rescue_from :all do |e|
257
+ rack_response 'message was processed', 400, e[:headers]
258
+ end
259
+ subject.desc 'Get beer' do
260
+ failure [[400, 'Bad Request'], [401, 'Unauthorized'], [403, 'Forbidden'],
261
+ [404, 'Resource not found'], [406, 'API vendor or version not found'],
262
+ [500, 'Internal processing error']]
263
+ end
264
+ subject.get '/beer' do
265
+ 'beer received'
266
+ end
267
+ }
268
+
269
+ def app
270
+ subject
271
+ end
272
+
273
+ context 'that received a request with correct vendor and version' do
274
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
275
+ it_should_behave_like 'a valid request'
276
+ end
277
+
278
+ context 'that receives' do
279
+ context 'an invalid version in the request' do
280
+ before {
281
+ get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77',
282
+ 'CONTENT_TYPE' => 'application/json'
283
+ }
284
+ it_should_behave_like 'a cascaded request'
285
+ end
286
+ context 'an invalid vendor in the request' do
287
+ before {
288
+ get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99',
289
+ 'CONTENT_TYPE' => 'application/json'
290
+ }
291
+ it_should_behave_like 'a cascaded request'
292
+ end
293
+ end
294
+ end
295
+
296
+ context 'API with cascade=true, http_codes but without a rescue handler' do
297
+ subject { Class.new(Grape::API) }
298
+ before {
299
+ subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: true
300
+ subject.desc 'Get beer' do
301
+ failure [[400, 'Bad Request'], [401, 'Unauthorized'], [403, 'Forbidden'],
302
+ [404, 'Resource not found'], [406, 'API vendor or version not found'],
303
+ [500, 'Internal processing error']]
304
+ end
305
+ subject.get '/beer' do
306
+ 'beer received'
307
+ end
308
+ }
309
+
310
+ def app
311
+ subject
312
+ end
313
+
314
+ context 'that received a request with correct vendor and version' do
315
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
316
+ it_should_behave_like 'a valid request'
317
+ end
318
+
319
+ context 'that receives' do
320
+ context 'an invalid version in the request' do
321
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77' }
322
+ it_should_behave_like 'a cascaded request'
323
+ end
324
+ context 'an invalid vendor in the request' do
325
+ before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99' }
326
+ it_should_behave_like 'a cascaded request'
327
+ end
328
+ end
329
+ end
330
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack do
4
+ it 'correctly populates params from a Tempfile' do
5
+ input = Tempfile.new 'rubbish'
6
+ begin
7
+ app = Class.new(Grape::API) do
8
+ format :json
9
+ post do
10
+ { params_keys: params.keys }
11
+ end
12
+ end
13
+ input.write({ test: '123' * 10_000 }.to_json)
14
+ input.rewind
15
+ options = {
16
+ input: input,
17
+ method: 'POST',
18
+ 'CONTENT_TYPE' => 'application/json'
19
+ }
20
+ env = Rack::MockRequest.env_for('/', options)
21
+
22
+ # requires Rack 1.6.0 to pass
23
+ # can't check explicitly version of Rack because of https://github.com/rack/rack/issues/773
24
+ pending 'Rack 1.6.0 is required' unless ::Rack.const_defined?(:TempfileReaper) || RUBY_PLATFORM == 'java'
25
+
26
+ expect(JSON.parse(app.call(env)[2].body.first)['params_keys']).to match_array('test')
27
+ ensure
28
+ input.close
29
+ input.unlink
30
+ end
31
+ end
32
+ end
@@ -34,6 +34,26 @@ describe Grape::Middleware::Base do
34
34
  expect(subject.response).to be_kind_of(Rack::Response)
35
35
  end
36
36
 
37
+ describe '#response' do
38
+ subject { Grape::Middleware::Base.new(response) }
39
+ let(:response) { lambda { |_| [204, { abc: 1 }, 'test'] } }
40
+
41
+ it 'status' do
42
+ subject.call({})
43
+ expect(subject.response.status).to eq(204)
44
+ end
45
+
46
+ it 'body' do
47
+ subject.call({})
48
+ expect(subject.response.body).to eq(['test'])
49
+ end
50
+
51
+ it 'header' do
52
+ subject.call({})
53
+ expect(subject.response.header).to have_key(:abc)
54
+ end
55
+ end
56
+
37
57
  context 'options' do
38
58
  it 'persists options passed at initialization' do
39
59
  expect(Grape::Middleware::Base.new(blank_app, abc: true).options[:abc]).to be true
@@ -84,14 +84,13 @@ describe Grape::Middleware::Versioner::Header do
84
84
  end
85
85
 
86
86
  it 'fails with 406 Not Acceptable if vendor is invalid' do
87
- expect do
88
- subject.call('HTTP_ACCEPT' => 'application/vnd.othervendor+json').last
89
- end.to throw_symbol(
90
- :error,
91
- status: 406,
92
- headers: { 'X-Cascade' => 'pass' },
93
- message: 'API vendor or version not found.'
94
- )
87
+ expect { subject.call('HTTP_ACCEPT' => 'application/vnd.othervendor+json').last }
88
+ .to raise_exception do |exception|
89
+ expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
90
+ expect(exception.headers).to eql('X-Cascade' => 'pass')
91
+ expect(exception.status).to eql 406
92
+ expect(exception.message).to include 'API vendor or version not found'
93
+ end
95
94
  end
96
95
 
97
96
  context 'when version is set' do
@@ -112,14 +111,13 @@ describe Grape::Middleware::Versioner::Header do
112
111
  end
113
112
 
114
113
  it 'fails with 406 Not Acceptable if vendor is invalid' do
115
- expect do
116
- subject.call('HTTP_ACCEPT' => 'application/vnd.othervendor-v1+json').last
117
- end.to throw_symbol(
118
- :error,
119
- status: 406,
120
- headers: { 'X-Cascade' => 'pass' },
121
- message: 'API vendor or version not found.'
122
- )
114
+ expect { subject.call('HTTP_ACCEPT' => 'application/vnd.othervendor-v1+json').last }
115
+ .to raise_exception do |exception|
116
+ expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
117
+ expect(exception.headers).to eql('X-Cascade' => 'pass')
118
+ expect(exception.status).to eql 406
119
+ expect(exception.message).to include('API vendor or version not found')
120
+ end
123
121
  end
124
122
  end
125
123
  end
@@ -142,14 +140,12 @@ describe Grape::Middleware::Versioner::Header do
142
140
  end
143
141
 
144
142
  it 'fails with 406 Not Acceptable if version is invalid' do
145
- expect do
146
- subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v2+json').last
147
- end.to throw_symbol(
148
- :error,
149
- status: 406,
150
- headers: { 'X-Cascade' => 'pass' },
151
- message: 'API vendor or version not found.'
152
- )
143
+ expect { subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v2+json').last }.to raise_exception do |exception|
144
+ expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
145
+ expect(exception.headers).to eql('X-Cascade' => 'pass')
146
+ expect(exception.status).to eql 406
147
+ expect(exception.message).to include('API vendor or version not found')
148
+ end
153
149
  end
154
150
  end
155
151
 
@@ -171,47 +167,39 @@ describe Grape::Middleware::Versioner::Header do
171
167
  end
172
168
 
173
169
  it 'fails with 406 Not Acceptable if header is not set' do
174
- expect do
175
- subject.call({}).last
176
- end.to throw_symbol(
177
- :error,
178
- status: 406,
179
- headers: { 'X-Cascade' => 'pass' },
180
- message: 'Accept header must be set.'
181
- )
170
+ expect { subject.call({}).last }.to raise_exception do |exception|
171
+ expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
172
+ expect(exception.headers).to eql('X-Cascade' => 'pass')
173
+ expect(exception.status).to eql 406
174
+ expect(exception.message).to include('Accept header must be set.')
175
+ end
182
176
  end
183
177
 
184
178
  it 'fails with 406 Not Acceptable if header is empty' do
185
- expect do
186
- subject.call('HTTP_ACCEPT' => '').last
187
- end.to throw_symbol(
188
- :error,
189
- status: 406,
190
- headers: { 'X-Cascade' => 'pass' },
191
- message: 'Accept header must be set.'
192
- )
179
+ expect { subject.call('HTTP_ACCEPT' => '').last }.to raise_exception do |exception|
180
+ expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
181
+ expect(exception.headers).to eql('X-Cascade' => 'pass')
182
+ expect(exception.status).to eql 406
183
+ expect(exception.message).to include('Accept header must be set.')
184
+ end
193
185
  end
194
186
 
195
187
  it 'fails with 406 Not Acceptable if type is a range' do
196
- expect do
197
- subject.call('HTTP_ACCEPT' => '*/*').last
198
- end.to throw_symbol(
199
- :error,
200
- status: 406,
201
- headers: { 'X-Cascade' => 'pass' },
202
- message: 'Accept header must not contain ranges ("*").'
203
- )
188
+ expect { subject.call('HTTP_ACCEPT' => '*/*').last }.to raise_exception do |exception|
189
+ expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
190
+ expect(exception.headers).to eql('X-Cascade' => 'pass')
191
+ expect(exception.status).to eql 406
192
+ expect(exception.message).to include('Accept header must not contain ranges ("*").')
193
+ end
204
194
  end
205
195
 
206
196
  it 'fails with 406 Not Acceptable if subtype is a range' do
207
- expect do
208
- subject.call('HTTP_ACCEPT' => 'application/*').last
209
- end.to throw_symbol(
210
- :error,
211
- status: 406,
212
- headers: { 'X-Cascade' => 'pass' },
213
- message: 'Accept header must not contain ranges ("*").'
214
- )
197
+ expect { subject.call('HTTP_ACCEPT' => 'application/*').last }.to raise_exception do |exception|
198
+ expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
199
+ expect(exception.headers).to eql('X-Cascade' => 'pass')
200
+ expect(exception.status).to eql 406
201
+ expect(exception.message).to include('Accept header must not contain ranges ("*").')
202
+ end
215
203
  end
216
204
 
217
205
  it 'succeeds if proper header is set' do
@@ -227,47 +215,39 @@ describe Grape::Middleware::Versioner::Header do
227
215
  end
228
216
 
229
217
  it 'fails with 406 Not Acceptable if header is not set' do
230
- expect do
231
- subject.call({}).last
232
- end.to throw_symbol(
233
- :error,
234
- status: 406,
235
- headers: {},
236
- message: 'Accept header must be set.'
237
- )
218
+ expect { subject.call({}).last }.to raise_exception do |exception|
219
+ expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
220
+ expect(exception.headers).to eql({})
221
+ expect(exception.status).to eql 406
222
+ expect(exception.message).to include('Accept header must be set.')
223
+ end
238
224
  end
239
225
 
240
226
  it 'fails with 406 Not Acceptable if header is empty' do
241
- expect do
242
- subject.call('HTTP_ACCEPT' => '').last
243
- end.to throw_symbol(
244
- :error,
245
- status: 406,
246
- headers: {},
247
- message: 'Accept header must be set.'
248
- )
227
+ expect { subject.call('HTTP_ACCEPT' => '').last }.to raise_exception do |exception|
228
+ expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
229
+ expect(exception.headers).to eql({})
230
+ expect(exception.status).to eql 406
231
+ expect(exception.message).to include('Accept header must be set.')
232
+ end
249
233
  end
250
234
 
251
235
  it 'fails with 406 Not Acceptable if type is a range' do
252
- expect do
253
- subject.call('HTTP_ACCEPT' => '*/*').last
254
- end.to throw_symbol(
255
- :error,
256
- status: 406,
257
- headers: {},
258
- message: 'Accept header must not contain ranges ("*").'
259
- )
236
+ expect { subject.call('HTTP_ACCEPT' => '*/*').last }.to raise_exception do |exception|
237
+ expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
238
+ expect(exception.headers).to eql({})
239
+ expect(exception.status).to eql 406
240
+ expect(exception.message).to include('Accept header must not contain ranges ("*").')
241
+ end
260
242
  end
261
243
 
262
244
  it 'fails with 406 Not Acceptable if subtype is a range' do
263
- expect do
264
- subject.call('HTTP_ACCEPT' => 'application/*').last
265
- end.to throw_symbol(
266
- :error,
267
- status: 406,
268
- headers: {},
269
- message: 'Accept header must not contain ranges ("*").'
270
- )
245
+ expect { subject.call('HTTP_ACCEPT' => 'application/*').last }.to raise_exception do |exception|
246
+ expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
247
+ expect(exception.headers).to eql({})
248
+ expect(exception.status).to eql 406
249
+ expect(exception.message).to include('Accept header must not contain ranges ("*").')
250
+ end
271
251
  end
272
252
 
273
253
  it 'succeeds if proper header is set' do
@@ -289,14 +269,12 @@ describe Grape::Middleware::Versioner::Header do
289
269
  end
290
270
 
291
271
  it 'fails with another version' do
292
- expect do
293
- subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v3+json')
294
- end.to throw_symbol(
295
- :error,
296
- status: 406,
297
- headers: { 'X-Cascade' => 'pass' },
298
- message: 'API vendor or version not found.'
299
- )
272
+ expect { subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v3+json') }.to raise_exception do |exception|
273
+ expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
274
+ expect(exception.headers).to eql('X-Cascade' => 'pass')
275
+ expect(exception.status).to eql 406
276
+ expect(exception.message).to include('API vendor or version not found')
277
+ end
300
278
  end
301
279
  end
302
280
  end