grape 1.6.0 → 1.6.2

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +9 -1
  5. data/UPGRADING.md +4 -4
  6. data/lib/grape/api.rb +12 -0
  7. data/lib/grape/dsl/headers.rb +5 -2
  8. data/lib/grape/dsl/helpers.rb +1 -1
  9. data/lib/grape/middleware/auth/dsl.rb +7 -1
  10. data/lib/grape/middleware/base.rb +1 -1
  11. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  12. data/lib/grape/validations/validators/all_or_none.rb +7 -5
  13. data/lib/grape/validations/validators/allow_blank.rb +9 -7
  14. data/lib/grape/validations/validators/as.rb +7 -5
  15. data/lib/grape/validations/validators/at_least_one_of.rb +6 -4
  16. data/lib/grape/validations/validators/base.rb +73 -71
  17. data/lib/grape/validations/validators/coerce.rb +63 -75
  18. data/lib/grape/validations/validators/default.rb +36 -34
  19. data/lib/grape/validations/validators/exactly_one_of.rb +8 -6
  20. data/lib/grape/validations/validators/except_values.rb +13 -11
  21. data/lib/grape/validations/validators/multiple_params_base.rb +24 -22
  22. data/lib/grape/validations/validators/mutual_exclusion.rb +7 -5
  23. data/lib/grape/validations/validators/presence.rb +6 -4
  24. data/lib/grape/validations/validators/regexp.rb +7 -5
  25. data/lib/grape/validations/validators/same_as.rb +17 -15
  26. data/lib/grape/validations/validators/values.rb +59 -57
  27. data/lib/grape/validations.rb +6 -0
  28. data/lib/grape/version.rb +1 -1
  29. data/lib/grape.rb +2 -0
  30. data/spec/grape/api/custom_validations_spec.rb +77 -46
  31. data/spec/grape/api/deeply_included_options_spec.rb +3 -3
  32. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
  33. data/spec/grape/api/invalid_format_spec.rb +2 -0
  34. data/spec/grape/api/recognize_path_spec.rb +1 -1
  35. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
  36. data/spec/grape/api_remount_spec.rb +16 -15
  37. data/spec/grape/api_spec.rb +317 -193
  38. data/spec/grape/dsl/callbacks_spec.rb +1 -0
  39. data/spec/grape/dsl/headers_spec.rb +39 -9
  40. data/spec/grape/dsl/helpers_spec.rb +3 -2
  41. data/spec/grape/dsl/inside_route_spec.rb +6 -4
  42. data/spec/grape/dsl/logger_spec.rb +16 -18
  43. data/spec/grape/dsl/middleware_spec.rb +1 -0
  44. data/spec/grape/dsl/parameters_spec.rb +1 -0
  45. data/spec/grape/dsl/request_response_spec.rb +1 -0
  46. data/spec/grape/dsl/routing_spec.rb +9 -6
  47. data/spec/grape/endpoint/declared_spec.rb +12 -12
  48. data/spec/grape/endpoint_spec.rb +59 -50
  49. data/spec/grape/entity_spec.rb +13 -13
  50. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
  51. data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
  52. data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
  53. data/spec/grape/exceptions/validation_spec.rb +5 -3
  54. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
  55. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
  56. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
  57. data/spec/grape/integration/rack_sendfile_spec.rb +1 -1
  58. data/spec/grape/loading_spec.rb +8 -8
  59. data/spec/grape/middleware/auth/dsl_spec.rb +14 -5
  60. data/spec/grape/middleware/auth/strategies_spec.rb +60 -20
  61. data/spec/grape/middleware/base_spec.rb +24 -15
  62. data/spec/grape/middleware/error_spec.rb +1 -0
  63. data/spec/grape/middleware/exception_spec.rb +111 -161
  64. data/spec/grape/middleware/formatter_spec.rb +25 -4
  65. data/spec/grape/middleware/globals_spec.rb +7 -4
  66. data/spec/grape/middleware/stack_spec.rb +11 -11
  67. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
  68. data/spec/grape/middleware/versioner/header_spec.rb +14 -13
  69. data/spec/grape/middleware/versioner/param_spec.rb +7 -1
  70. data/spec/grape/middleware/versioner/path_spec.rb +5 -1
  71. data/spec/grape/middleware/versioner_spec.rb +1 -1
  72. data/spec/grape/parser_spec.rb +4 -0
  73. data/spec/grape/path_spec.rb +52 -52
  74. data/spec/grape/presenters/presenter_spec.rb +7 -6
  75. data/spec/grape/request_spec.rb +6 -4
  76. data/spec/grape/util/inheritable_setting_spec.rb +7 -7
  77. data/spec/grape/util/inheritable_values_spec.rb +3 -2
  78. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
  79. data/spec/grape/util/stackable_values_spec.rb +7 -5
  80. data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
  81. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -0
  82. data/spec/grape/validations/params_scope_spec.rb +9 -7
  83. data/spec/grape/validations/single_attribute_iterator_spec.rb +1 -0
  84. data/spec/grape/validations/types/primitive_coercer_spec.rb +2 -2
  85. data/spec/grape/validations/types_spec.rb +8 -8
  86. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
  87. data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
  88. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
  89. data/spec/grape/validations/validators/coerce_spec.rb +10 -12
  90. data/spec/grape/validations/validators/default_spec.rb +72 -78
  91. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
  92. data/spec/grape/validations/validators/except_values_spec.rb +1 -1
  93. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
  94. data/spec/grape/validations/validators/presence_spec.rb +16 -1
  95. data/spec/grape/validations/validators/regexp_spec.rb +25 -31
  96. data/spec/grape/validations/validators/same_as_spec.rb +14 -20
  97. data/spec/grape/validations/validators/values_spec.rb +172 -171
  98. data/spec/grape/validations_spec.rb +45 -16
  99. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  100. data/spec/integration/multi_json/json_spec.rb +1 -1
  101. data/spec/integration/multi_xml/xml_spec.rb +1 -1
  102. data/spec/shared/versioning_examples.rb +10 -7
  103. data/spec/spec_helper.rb +11 -1
  104. metadata +102 -102
@@ -3,7 +3,8 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Grape::Middleware::Formatter do
6
- subject { Grape::Middleware::Formatter.new(app) }
6
+ subject { described_class.new(app) }
7
+
7
8
  before { allow(subject).to receive(:dup).and_return(subject) }
8
9
 
9
10
  let(:body) { { 'foo' => 'bar' } }
@@ -11,6 +12,7 @@ describe Grape::Middleware::Formatter do
11
12
 
12
13
  context 'serialization' do
13
14
  let(:body) { { 'abc' => 'def' } }
15
+
14
16
  it 'looks at the bodies for possibly serializable data' do
15
17
  _, _, bodies = *subject.call('PATH_INFO' => '/somewhere', 'HTTP_ACCEPT' => 'application/json')
16
18
  bodies.each { |b| expect(b).to eq(::Grape::Json.dump(body)) }
@@ -18,6 +20,7 @@ describe Grape::Middleware::Formatter do
18
20
 
19
21
  context 'default format' do
20
22
  let(:body) { ['foo'] }
23
+
21
24
  it 'calls #to_json since default format is json' do
22
25
  body.instance_eval do
23
26
  def to_json(*_args)
@@ -31,6 +34,7 @@ describe Grape::Middleware::Formatter do
31
34
 
32
35
  context 'jsonapi' do
33
36
  let(:body) { { 'foos' => [{ 'bar' => 'baz' }] } }
37
+
34
38
  it 'calls #to_json if the content type is jsonapi' do
35
39
  body.instance_eval do
36
40
  def to_json(*_args)
@@ -44,6 +48,7 @@ describe Grape::Middleware::Formatter do
44
48
 
45
49
  context 'xml' do
46
50
  let(:body) { +'string' }
51
+
47
52
  it 'calls #to_xml if the content type is xml' do
48
53
  body.instance_eval do
49
54
  def to_xml
@@ -58,6 +63,7 @@ describe Grape::Middleware::Formatter do
58
63
 
59
64
  context 'error handling' do
60
65
  let(:formatter) { double(:formatter) }
66
+
61
67
  before do
62
68
  allow(Grape::Formatter).to receive(:formatter_for) { formatter }
63
69
  end
@@ -67,7 +73,7 @@ describe Grape::Middleware::Formatter do
67
73
 
68
74
  expect do
69
75
  catch(:error) { subject.call('PATH_INFO' => '/somewhere.xml', 'HTTP_ACCEPT' => 'application/json') }
70
- end.to_not raise_error
76
+ end.not_to raise_error
71
77
  end
72
78
 
73
79
  it 'does not rescue other exceptions' do
@@ -147,7 +153,7 @@ describe Grape::Middleware::Formatter do
147
153
  subject.options[:content_types][:custom] = 'application/vnd.test+json'
148
154
  end
149
155
 
150
- it 'it uses the custom type' do
156
+ it 'uses the custom type' do
151
157
  subject.call('PATH_INFO' => '/info', 'HTTP_ACCEPT' => 'application/vnd.test+json')
152
158
  expect(subject.env['api.format']).to eq(:custom)
153
159
  end
@@ -164,26 +170,31 @@ describe Grape::Middleware::Formatter do
164
170
  _, headers, = subject.call('PATH_INFO' => '/info.json')
165
171
  expect(headers['Content-type']).to eq('application/json')
166
172
  end
173
+
167
174
  it 'is set for xml' do
168
175
  _, headers, = subject.call('PATH_INFO' => '/info.xml')
169
176
  expect(headers['Content-type']).to eq('application/xml')
170
177
  end
178
+
171
179
  it 'is set for txt' do
172
180
  _, headers, = subject.call('PATH_INFO' => '/info.txt')
173
181
  expect(headers['Content-type']).to eq('text/plain')
174
182
  end
183
+
175
184
  it 'is set for custom' do
176
185
  subject.options[:content_types] = {}
177
186
  subject.options[:content_types][:custom] = 'application/x-custom'
178
187
  _, headers, = subject.call('PATH_INFO' => '/info.custom')
179
188
  expect(headers['Content-type']).to eq('application/x-custom')
180
189
  end
190
+
181
191
  it 'is set for vendored with registered type' do
182
192
  subject.options[:content_types] = {}
183
193
  subject.options[:content_types][:custom] = 'application/vnd.test+json'
184
194
  _, headers, = subject.call('PATH_INFO' => '/info', 'HTTP_ACCEPT' => 'application/vnd.test+json')
185
195
  expect(headers['Content-type']).to eq('application/vnd.test+json')
186
196
  end
197
+
187
198
  it 'is set to closest generic for custom vendored/versioned without registered type' do
188
199
  _, headers, = subject.call('PATH_INFO' => '/info', 'HTTP_ACCEPT' => 'application/vnd.test+json')
189
200
  expect(headers['Content-type']).to eq('application/json')
@@ -198,13 +209,16 @@ describe Grape::Middleware::Formatter do
198
209
  _, _, body = subject.call('PATH_INFO' => '/info.custom')
199
210
  expect(read_chunks(body)).to eq(['CUSTOM FORMAT'])
200
211
  end
212
+
201
213
  context 'default' do
202
214
  let(:body) { ['blah'] }
215
+
203
216
  it 'uses default json formatter' do
204
217
  _, _, body = subject.call('PATH_INFO' => '/info.json')
205
218
  expect(read_chunks(body)).to eq(['["blah"]'])
206
219
  end
207
220
  end
221
+
208
222
  it 'uses custom json formatter' do
209
223
  subject.options[:formatters][:json] = ->(_obj, _env) { 'CUSTOM JSON FORMAT' }
210
224
  _, _, body = subject.call('PATH_INFO' => '/info.json')
@@ -272,6 +286,7 @@ describe Grape::Middleware::Formatter do
272
286
 
273
287
  context 'when body is nil' do
274
288
  let(:io) { double }
289
+
275
290
  before do
276
291
  allow(io).to receive_message_chain(:rewind, :read).and_return(nil)
277
292
  end
@@ -290,6 +305,7 @@ describe Grape::Middleware::Formatter do
290
305
 
291
306
  context 'when body is empty' do
292
307
  let(:io) { double }
308
+
293
309
  before do
294
310
  allow(io).to receive_message_chain(:rewind, :read).and_return('')
295
311
  end
@@ -334,6 +350,7 @@ describe Grape::Middleware::Formatter do
334
350
  expect(subject.env['rack.request.form_hash']['is_boolean']).to be true
335
351
  expect(subject.env['rack.request.form_hash']['string']).to eq('thing')
336
352
  end
353
+
337
354
  it 'rewinds IO' do
338
355
  io = StringIO.new('{"is_boolean":true,"string":"thing"}')
339
356
  io.read
@@ -347,6 +364,7 @@ describe Grape::Middleware::Formatter do
347
364
  expect(subject.env['rack.request.form_hash']['is_boolean']).to be true
348
365
  expect(subject.env['rack.request.form_hash']['string']).to eq('thing')
349
366
  end
367
+
350
368
  it "parses the body from an xml #{method} and copies values into rack.request.from_hash" do
351
369
  io = StringIO.new('<thing><name>Test</name></thing>')
352
370
  subject.call(
@@ -362,6 +380,7 @@ describe Grape::Middleware::Formatter do
362
380
  expect(subject.env['rack.request.form_hash']['thing']['name']['__content__']).to eq('Test')
363
381
  end
364
382
  end
383
+
365
384
  [Rack::Request::FORM_DATA_MEDIA_TYPES, Rack::Request::PARSEABLE_DATA_MEDIA_TYPES].flatten.each do |content_type|
366
385
  it "ignores #{content_type}" do
367
386
  io = StringIO.new('name=Other+Test+Thing')
@@ -400,10 +419,12 @@ describe Grape::Middleware::Formatter do
400
419
  end
401
420
  end
402
421
  let(:app) { ->(_env) { [200, {}, ['']] } }
422
+
403
423
  before do
404
424
  Grape::Formatter.register :invalid, InvalidFormatter
405
425
  Grape::ContentTypes.register :invalid, 'application/x-invalid'
406
426
  end
427
+
407
428
  after do
408
429
  Grape::ContentTypes.default_elements.delete(:invalid)
409
430
  Grape::Formatter.default_elements.delete(:invalid)
@@ -418,7 +439,7 @@ describe Grape::Middleware::Formatter do
418
439
 
419
440
  context 'custom parser raises exception and rescue options are enabled for backtrace and original_exception' do
420
441
  it 'adds the backtrace and original_exception to the error output' do
421
- subject = Grape::Middleware::Formatter.new(
442
+ subject = described_class.new(
422
443
  app,
423
444
  rescue_options: { backtrace: true, original_exception: true },
424
445
  parsers: { json: ->(_object, _env) { raise StandardError, 'fail' } }
@@ -3,7 +3,8 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Grape::Middleware::Globals do
6
- subject { Grape::Middleware::Globals.new(blank_app) }
6
+ subject { described_class.new(blank_app) }
7
+
7
8
  before { allow(subject).to receive(:dup).and_return(subject) }
8
9
 
9
10
  let(:blank_app) { ->(_env) { [200, {}, 'Hi there.'] } }
@@ -13,15 +14,17 @@ describe Grape::Middleware::Globals do
13
14
  end
14
15
 
15
16
  context 'environment' do
16
- it 'should set the grape.request environment' do
17
+ it 'sets the grape.request environment' do
17
18
  subject.call({})
18
19
  expect(subject.env['grape.request']).to be_a(Grape::Request)
19
20
  end
20
- it 'should set the grape.request.headers environment' do
21
+
22
+ it 'sets the grape.request.headers environment' do
21
23
  subject.call({})
22
24
  expect(subject.env['grape.request.headers']).to be_a(Hash)
23
25
  end
24
- it 'should set the grape.request.params environment' do
26
+
27
+ it 'sets the grape.request.params environment' do
25
28
  subject.call('QUERY_STRING' => 'test=1', 'rack.input' => StringIO.new)
26
29
  expect(subject.env['grape.request.params']).to be_a(Hash)
27
30
  end
@@ -17,11 +17,11 @@ describe Grape::Middleware::Stack do
17
17
  end
18
18
  end
19
19
 
20
+ subject { described_class.new }
21
+
20
22
  let(:proc) { -> {} }
21
23
  let(:others) { [[:use, StackSpec::BarMiddleware], [:insert_before, StackSpec::BarMiddleware, StackSpec::BlockMiddleware, proc]] }
22
24
 
23
- subject { Grape::Middleware::Stack.new }
24
-
25
25
  before do
26
26
  subject.use StackSpec::FooMiddleware
27
27
  end
@@ -29,20 +29,20 @@ describe Grape::Middleware::Stack do
29
29
  describe '#use' do
30
30
  it 'pushes a middleware class onto the stack' do
31
31
  expect { subject.use StackSpec::BarMiddleware }
32
- .to change { subject.size }.by(1)
32
+ .to change(subject, :size).by(1)
33
33
  expect(subject.last).to eq(StackSpec::BarMiddleware)
34
34
  end
35
35
 
36
36
  it 'pushes a middleware class with arguments onto the stack' do
37
37
  expect { subject.use StackSpec::BarMiddleware, false, my_arg: 42 }
38
- .to change { subject.size }.by(1)
38
+ .to change(subject, :size).by(1)
39
39
  expect(subject.last).to eq(StackSpec::BarMiddleware)
40
40
  expect(subject.last.args).to eq([false, { my_arg: 42 }])
41
41
  end
42
42
 
43
43
  it 'pushes a middleware class with block arguments onto the stack' do
44
44
  expect { subject.use StackSpec::BlockMiddleware, &proc }
45
- .to change { subject.size }.by(1)
45
+ .to change(subject, :size).by(1)
46
46
  expect(subject.last).to eq(StackSpec::BlockMiddleware)
47
47
  expect(subject.last.args).to eq([])
48
48
  expect(subject.last.block).to eq(proc)
@@ -52,7 +52,7 @@ describe Grape::Middleware::Stack do
52
52
  describe '#insert' do
53
53
  it 'inserts a middleware class at the integer index' do
54
54
  expect { subject.insert 0, StackSpec::BarMiddleware }
55
- .to change { subject.size }.by(1)
55
+ .to change(subject, :size).by(1)
56
56
  expect(subject[0]).to eq(StackSpec::BarMiddleware)
57
57
  expect(subject[1]).to eq(StackSpec::FooMiddleware)
58
58
  end
@@ -61,7 +61,7 @@ describe Grape::Middleware::Stack do
61
61
  describe '#insert_before' do
62
62
  it 'inserts a middleware before another middleware class' do
63
63
  expect { subject.insert_before StackSpec::FooMiddleware, StackSpec::BarMiddleware }
64
- .to change { subject.size }.by(1)
64
+ .to change(subject, :size).by(1)
65
65
  expect(subject[0]).to eq(StackSpec::BarMiddleware)
66
66
  expect(subject[1]).to eq(StackSpec::FooMiddleware)
67
67
  end
@@ -70,7 +70,7 @@ describe Grape::Middleware::Stack do
70
70
  subject.use Class.new(StackSpec::BlockMiddleware)
71
71
 
72
72
  expect { subject.insert_before StackSpec::BlockMiddleware, StackSpec::BarMiddleware }
73
- .to change { subject.size }.by(1)
73
+ .to change(subject, :size).by(1)
74
74
 
75
75
  expect(subject[1]).to eq(StackSpec::BarMiddleware)
76
76
  expect(subject[2]).to eq(StackSpec::BlockMiddleware)
@@ -85,7 +85,7 @@ describe Grape::Middleware::Stack do
85
85
  describe '#insert_after' do
86
86
  it 'inserts a middleware after another middleware class' do
87
87
  expect { subject.insert_after StackSpec::FooMiddleware, StackSpec::BarMiddleware }
88
- .to change { subject.size }.by(1)
88
+ .to change(subject, :size).by(1)
89
89
  expect(subject[1]).to eq(StackSpec::BarMiddleware)
90
90
  expect(subject[0]).to eq(StackSpec::FooMiddleware)
91
91
  end
@@ -94,7 +94,7 @@ describe Grape::Middleware::Stack do
94
94
  subject.use Class.new(StackSpec::BlockMiddleware)
95
95
 
96
96
  expect { subject.insert_after StackSpec::BlockMiddleware, StackSpec::BarMiddleware }
97
- .to change { subject.size }.by(1)
97
+ .to change(subject, :size).by(1)
98
98
 
99
99
  expect(subject[1]).to eq(StackSpec::BlockMiddleware)
100
100
  expect(subject[2]).to eq(StackSpec::BarMiddleware)
@@ -109,7 +109,7 @@ describe Grape::Middleware::Stack do
109
109
  describe '#merge_with' do
110
110
  it 'applies a collection of operations and middlewares' do
111
111
  expect { subject.merge_with(others) }
112
- .to change { subject.size }.by(2)
112
+ .to change(subject, :size).by(2)
113
113
  expect(subject[0]).to eq(StackSpec::FooMiddleware)
114
114
  expect(subject[1]).to eq(StackSpec::BlockMiddleware)
115
115
  expect(subject[2]).to eq(StackSpec::BarMiddleware)
@@ -3,8 +3,9 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Grape::Middleware::Versioner::AcceptVersionHeader do
6
+ subject { described_class.new(app, **(@options || {})) }
7
+
6
8
  let(:app) { ->(env) { [200, env, env] } }
7
- subject { Grape::Middleware::Versioner::AcceptVersionHeader.new(app, **(@options || {})) }
8
9
 
9
10
  before do
10
11
  @options = {
@@ -3,8 +3,9 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Grape::Middleware::Versioner::Header do
6
+ subject { described_class.new(app, **(@options || {})) }
7
+
6
8
  let(:app) { ->(env) { [200, env, env] } }
7
- subject { Grape::Middleware::Versioner::Header.new(app, **(@options || {})) }
8
9
 
9
10
  before do
10
11
  @options = {
@@ -47,7 +48,7 @@ describe Grape::Middleware::Versioner::Header do
47
48
 
48
49
  it 'is nil if not provided' do
49
50
  status, _, env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor')
50
- expect(env['api.format']).to eql nil
51
+ expect(env['api.format']).to be nil
51
52
  expect(status).to eq(200)
52
53
  end
53
54
 
@@ -65,7 +66,7 @@ describe Grape::Middleware::Versioner::Header do
65
66
 
66
67
  it 'is nil if not provided' do
67
68
  status, _, env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v1')
68
- expect(env['api.format']).to eql nil
69
+ expect(env['api.format']).to be nil
69
70
  expect(status).to eq(200)
70
71
  end
71
72
  end
@@ -90,7 +91,7 @@ describe Grape::Middleware::Versioner::Header do
90
91
  .to raise_exception do |exception|
91
92
  expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
92
93
  expect(exception.headers).to eql('X-Cascade' => 'pass')
93
- expect(exception.status).to eql 406
94
+ expect(exception.status).to be 406
94
95
  expect(exception.message).to include 'API vendor not found'
95
96
  end
96
97
  end
@@ -117,7 +118,7 @@ describe Grape::Middleware::Versioner::Header do
117
118
  .to raise_exception do |exception|
118
119
  expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
119
120
  expect(exception.headers).to eql('X-Cascade' => 'pass')
120
- expect(exception.status).to eql 406
121
+ expect(exception.status).to be 406
121
122
  expect(exception.message).to include('API vendor not found')
122
123
  end
123
124
  end
@@ -145,7 +146,7 @@ describe Grape::Middleware::Versioner::Header do
145
146
  expect { subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v2+json').last }.to raise_exception do |exception|
146
147
  expect(exception).to be_a(Grape::Exceptions::InvalidVersionHeader)
147
148
  expect(exception.headers).to eql('X-Cascade' => 'pass')
148
- expect(exception.status).to eql 406
149
+ expect(exception.status).to be 406
149
150
  expect(exception.message).to include('API version not found')
150
151
  end
151
152
  end
@@ -178,7 +179,7 @@ describe Grape::Middleware::Versioner::Header do
178
179
  expect { subject.call({}).last }.to raise_exception do |exception|
179
180
  expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
180
181
  expect(exception.headers).to eql('X-Cascade' => 'pass')
181
- expect(exception.status).to eql 406
182
+ expect(exception.status).to be 406
182
183
  expect(exception.message).to include('Accept header must be set.')
183
184
  end
184
185
  end
@@ -187,7 +188,7 @@ describe Grape::Middleware::Versioner::Header do
187
188
  expect { subject.call('HTTP_ACCEPT' => '').last }.to raise_exception do |exception|
188
189
  expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
189
190
  expect(exception.headers).to eql('X-Cascade' => 'pass')
190
- expect(exception.status).to eql 406
191
+ expect(exception.status).to be 406
191
192
  expect(exception.message).to include('Accept header must be set.')
192
193
  end
193
194
  end
@@ -208,7 +209,7 @@ describe Grape::Middleware::Versioner::Header do
208
209
  expect { subject.call({}).last }.to raise_exception do |exception|
209
210
  expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
210
211
  expect(exception.headers).to eql({})
211
- expect(exception.status).to eql 406
212
+ expect(exception.status).to be 406
212
213
  expect(exception.message).to include('Accept header must be set.')
213
214
  end
214
215
  end
@@ -218,7 +219,7 @@ describe Grape::Middleware::Versioner::Header do
218
219
  .to raise_exception do |exception|
219
220
  expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
220
221
  expect(exception.headers).to eql({})
221
- expect(exception.status).to eql 406
222
+ expect(exception.status).to be 406
222
223
  expect(exception.message).to include('API vendor or version not found.')
223
224
  end
224
225
  end
@@ -227,7 +228,7 @@ describe Grape::Middleware::Versioner::Header do
227
228
  expect { subject.call('HTTP_ACCEPT' => '').last }.to raise_exception do |exception|
228
229
  expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
229
230
  expect(exception.headers).to eql({})
230
- expect(exception.status).to eql 406
231
+ expect(exception.status).to be 406
231
232
  expect(exception.message).to include('Accept header must be set.')
232
233
  end
233
234
  end
@@ -237,7 +238,7 @@ describe Grape::Middleware::Versioner::Header do
237
238
  .to raise_exception do |exception|
238
239
  expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
239
240
  expect(exception.headers).to eql({})
240
- expect(exception.status).to eql 406
241
+ expect(exception.status).to be 406
241
242
  expect(exception.message).to include('API vendor or version not found.')
242
243
  end
243
244
  end
@@ -264,7 +265,7 @@ describe Grape::Middleware::Versioner::Header do
264
265
  expect { subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v3+json') }.to raise_exception do |exception|
265
266
  expect(exception).to be_a(Grape::Exceptions::InvalidVersionHeader)
266
267
  expect(exception.headers).to eql('X-Cascade' => 'pass')
267
- expect(exception.status).to eql 406
268
+ expect(exception.status).to be 406
268
269
  expect(exception.message).to include('API version not found')
269
270
  end
270
271
  end
@@ -3,9 +3,10 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Grape::Middleware::Versioner::Param do
6
+ subject { described_class.new(app, **options) }
7
+
6
8
  let(:app) { ->(env) { [200, env, env['api.version']] } }
7
9
  let(:options) { {} }
8
- subject { Grape::Middleware::Versioner::Param.new(app, **options) }
9
10
 
10
11
  it 'sets the API version based on the default param (apiver)' do
11
12
  env = Rack::MockRequest.env_for('/awesome', params: { 'apiver' => 'v1' })
@@ -26,10 +27,12 @@ describe Grape::Middleware::Versioner::Param do
26
27
 
27
28
  context 'with specified parameter name' do
28
29
  let(:options) { { version_options: { parameter: 'v' } } }
30
+
29
31
  it 'sets the API version based on the custom parameter name' do
30
32
  env = Rack::MockRequest.env_for('/awesome', params: { 'v' => 'v1' })
31
33
  expect(subject.call(env)[1]['api.version']).to eq('v1')
32
34
  end
35
+
33
36
  it 'does not set the API version based on the default param' do
34
37
  env = Rack::MockRequest.env_for('/awesome', params: { 'apiver' => 'v1' })
35
38
  expect(subject.call(env)[1]['api.version']).to be_nil
@@ -38,10 +41,12 @@ describe Grape::Middleware::Versioner::Param do
38
41
 
39
42
  context 'with specified versions' do
40
43
  let(:options) { { versions: %w[v1 v2] } }
44
+
41
45
  it 'throws an error if a non-allowed version is specified' do
42
46
  env = Rack::MockRequest.env_for('/awesome', params: { 'apiver' => 'v3' })
43
47
  expect(catch(:error) { subject.call(env) }[:status]).to eq(404)
44
48
  end
49
+
45
50
  it 'allows versions that have been specified' do
46
51
  env = Rack::MockRequest.env_for('/awesome', params: { 'apiver' => 'v1' })
47
52
  expect(subject.call(env)[1]['api.version']).to eq('v1')
@@ -55,6 +60,7 @@ describe Grape::Middleware::Versioner::Param do
55
60
  version_options: { using: :header }
56
61
  }
57
62
  end
63
+
58
64
  it 'returns a 200 (matches the first version found)' do
59
65
  env = Rack::MockRequest.env_for('/awesome', params: {})
60
66
  expect(subject.call(env).first).to eq(200)
@@ -3,9 +3,10 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Grape::Middleware::Versioner::Path do
6
+ subject { described_class.new(app, **options) }
7
+
6
8
  let(:app) { ->(env) { [200, env, env['api.version']] } }
7
9
  let(:options) { {} }
8
- subject { Grape::Middleware::Versioner::Path.new(app, **options) }
9
10
 
10
11
  it 'sets the API version based on the first path' do
11
12
  expect(subject.call('PATH_INFO' => '/v1/awesome').last).to eq('v1')
@@ -21,6 +22,7 @@ describe Grape::Middleware::Versioner::Path do
21
22
 
22
23
  context 'with a pattern' do
23
24
  let(:options) { { pattern: /v./i } }
25
+
24
26
  it 'sets the version if it matches' do
25
27
  expect(subject.call('PATH_INFO' => '/v1/awesome').last).to eq('v1')
26
28
  end
@@ -46,6 +48,7 @@ describe Grape::Middleware::Versioner::Path do
46
48
 
47
49
  context 'with prefix, but requested version is not matched' do
48
50
  let(:options) { { prefix: '/v1', pattern: /v./i } }
51
+
49
52
  it 'recognizes potential version' do
50
53
  expect(subject.call('PATH_INFO' => '/v3/foo').last).to eq('v3')
51
54
  end
@@ -53,6 +56,7 @@ describe Grape::Middleware::Versioner::Path do
53
56
 
54
57
  context 'with mount path' do
55
58
  let(:options) { { mount_path: '/mounted', versions: [:v1] } }
59
+
56
60
  it 'recognizes potential version' do
57
61
  expect(subject.call('PATH_INFO' => '/mounted/v1/foo').last).to eq('v1')
58
62
  end
@@ -3,7 +3,7 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Grape::Middleware::Versioner do
6
- let(:klass) { Grape::Middleware::Versioner }
6
+ let(:klass) { described_class }
7
7
 
8
8
  it 'recognizes :path' do
9
9
  expect(klass.using(:path)).to eq(Grape::Middleware::Versioner::Path)
@@ -26,6 +26,7 @@ describe Grape::Parser do
26
26
 
27
27
  context 'with :parsers option' do
28
28
  let(:parsers) { { customized: Class.new } }
29
+
29
30
  it 'includes passed :parsers values' do
30
31
  expect(subject.parsers(parsers: parsers)).to include(parsers)
31
32
  end
@@ -33,7 +34,9 @@ describe Grape::Parser do
33
34
 
34
35
  context 'with added parser by using `register` keyword' do
35
36
  let(:added_parser) { Class.new }
37
+
36
38
  before { subject.register :added, added_parser }
39
+
37
40
  it 'includes added parser' do
38
41
  expect(subject.parsers(**{})).to include(added: added_parser)
39
42
  end
@@ -54,6 +57,7 @@ describe Grape::Parser do
54
57
 
55
58
  context 'when parser is available' do
56
59
  before { subject.register :customized_json, Grape::Parser::Json }
60
+
57
61
  it 'returns registered parser if available' do
58
62
  expect(subject.parser_for(:customized_json)).to eq(Grape::Parser::Json)
59
63
  end