grape 1.3.3 → 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 (165) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +111 -2
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +135 -23
  5. data/UPGRADING.md +237 -46
  6. data/grape.gemspec +5 -5
  7. data/lib/grape/api/instance.rb +34 -42
  8. data/lib/grape/api.rb +21 -16
  9. data/lib/grape/cookies.rb +2 -0
  10. data/lib/grape/dsl/callbacks.rb +1 -1
  11. data/lib/grape/dsl/desc.rb +3 -5
  12. data/lib/grape/dsl/headers.rb +5 -2
  13. data/lib/grape/dsl/helpers.rb +8 -5
  14. data/lib/grape/dsl/inside_route.rb +72 -53
  15. data/lib/grape/dsl/middleware.rb +4 -4
  16. data/lib/grape/dsl/parameters.rb +11 -7
  17. data/lib/grape/dsl/request_response.rb +9 -6
  18. data/lib/grape/dsl/routing.rb +8 -9
  19. data/lib/grape/dsl/settings.rb +5 -5
  20. data/lib/grape/dsl/validations.rb +18 -1
  21. data/lib/grape/eager_load.rb +1 -1
  22. data/lib/grape/endpoint.rb +29 -42
  23. data/lib/grape/error_formatter/json.rb +2 -6
  24. data/lib/grape/error_formatter/xml.rb +2 -6
  25. data/lib/grape/exceptions/empty_message_body.rb +11 -0
  26. data/lib/grape/exceptions/validation.rb +2 -3
  27. data/lib/grape/exceptions/validation_errors.rb +1 -1
  28. data/lib/grape/formatter/json.rb +1 -0
  29. data/lib/grape/formatter/serializable_hash.rb +2 -1
  30. data/lib/grape/formatter/xml.rb +1 -0
  31. data/lib/grape/locale/en.yml +1 -1
  32. data/lib/grape/middleware/auth/base.rb +3 -3
  33. data/lib/grape/middleware/auth/dsl.rb +7 -1
  34. data/lib/grape/middleware/base.rb +6 -3
  35. data/lib/grape/middleware/error.rb +11 -13
  36. data/lib/grape/middleware/formatter.rb +7 -7
  37. data/lib/grape/middleware/stack.rb +10 -3
  38. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
  39. data/lib/grape/middleware/versioner/header.rb +6 -4
  40. data/lib/grape/middleware/versioner/param.rb +1 -0
  41. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  42. data/lib/grape/middleware/versioner/path.rb +2 -0
  43. data/lib/grape/parser/json.rb +1 -1
  44. data/lib/grape/parser/xml.rb +1 -1
  45. data/lib/grape/path.rb +1 -0
  46. data/lib/grape/request.rb +4 -1
  47. data/lib/grape/router/attribute_translator.rb +3 -3
  48. data/lib/grape/router/pattern.rb +1 -1
  49. data/lib/grape/router/route.rb +2 -2
  50. data/lib/grape/router.rb +31 -30
  51. data/lib/grape/{serve_file → serve_stream}/file_body.rb +1 -1
  52. data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +1 -1
  53. data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +8 -8
  54. data/lib/grape/util/base_inheritable.rb +2 -2
  55. data/lib/grape/util/inheritable_setting.rb +1 -3
  56. data/lib/grape/util/lazy_value.rb +4 -2
  57. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  58. data/lib/grape/validations/attributes_iterator.rb +8 -0
  59. data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
  60. data/lib/grape/validations/params_scope.rb +97 -62
  61. data/lib/grape/validations/single_attribute_iterator.rb +1 -1
  62. data/lib/grape/validations/types/custom_type_coercer.rb +16 -3
  63. data/lib/grape/validations/types/dry_type_coercer.rb +1 -1
  64. data/lib/grape/validations/types/invalid_value.rb +24 -0
  65. data/lib/grape/validations/types/json.rb +2 -1
  66. data/lib/grape/validations/types/primitive_coercer.rb +4 -5
  67. data/lib/grape/validations/types.rb +1 -4
  68. data/lib/grape/validations/validator_factory.rb +1 -1
  69. data/lib/grape/validations/validators/all_or_none.rb +8 -5
  70. data/lib/grape/validations/validators/allow_blank.rb +9 -7
  71. data/lib/grape/validations/validators/as.rb +6 -8
  72. data/lib/grape/validations/validators/at_least_one_of.rb +7 -4
  73. data/lib/grape/validations/validators/base.rb +74 -69
  74. data/lib/grape/validations/validators/coerce.rb +63 -76
  75. data/lib/grape/validations/validators/default.rb +36 -34
  76. data/lib/grape/validations/validators/exactly_one_of.rb +9 -6
  77. data/lib/grape/validations/validators/except_values.rb +13 -11
  78. data/lib/grape/validations/validators/multiple_params_base.rb +24 -19
  79. data/lib/grape/validations/validators/mutual_exclusion.rb +8 -5
  80. data/lib/grape/validations/validators/presence.rb +7 -4
  81. data/lib/grape/validations/validators/regexp.rb +8 -5
  82. data/lib/grape/validations/validators/same_as.rb +18 -15
  83. data/lib/grape/validations/validators/values.rb +61 -56
  84. data/lib/grape/validations.rb +6 -0
  85. data/lib/grape/version.rb +1 -1
  86. data/lib/grape.rb +7 -3
  87. data/spec/grape/api/custom_validations_spec.rb +77 -45
  88. data/spec/grape/api/deeply_included_options_spec.rb +3 -3
  89. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
  90. data/spec/grape/api/invalid_format_spec.rb +2 -0
  91. data/spec/grape/api/recognize_path_spec.rb +1 -1
  92. data/spec/grape/api/routes_with_requirements_spec.rb +8 -8
  93. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
  94. data/spec/grape/api_remount_spec.rb +25 -19
  95. data/spec/grape/api_spec.rb +576 -211
  96. data/spec/grape/dsl/callbacks_spec.rb +2 -1
  97. data/spec/grape/dsl/headers_spec.rb +39 -9
  98. data/spec/grape/dsl/helpers_spec.rb +3 -2
  99. data/spec/grape/dsl/inside_route_spec.rb +185 -34
  100. data/spec/grape/dsl/logger_spec.rb +16 -18
  101. data/spec/grape/dsl/middleware_spec.rb +2 -1
  102. data/spec/grape/dsl/parameters_spec.rb +2 -0
  103. data/spec/grape/dsl/request_response_spec.rb +1 -0
  104. data/spec/grape/dsl/routing_spec.rb +10 -7
  105. data/spec/grape/endpoint/declared_spec.rb +848 -0
  106. data/spec/grape/endpoint_spec.rb +77 -589
  107. data/spec/grape/entity_spec.rb +29 -23
  108. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
  109. data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
  110. data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
  111. data/spec/grape/exceptions/validation_spec.rb +5 -3
  112. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
  113. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
  114. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
  115. data/spec/grape/integration/rack_sendfile_spec.rb +13 -9
  116. data/spec/grape/loading_spec.rb +8 -8
  117. data/spec/grape/middleware/auth/dsl_spec.rb +15 -6
  118. data/spec/grape/middleware/auth/strategies_spec.rb +61 -21
  119. data/spec/grape/middleware/base_spec.rb +24 -15
  120. data/spec/grape/middleware/error_spec.rb +3 -3
  121. data/spec/grape/middleware/exception_spec.rb +111 -161
  122. data/spec/grape/middleware/formatter_spec.rb +28 -7
  123. data/spec/grape/middleware/globals_spec.rb +7 -4
  124. data/spec/grape/middleware/stack_spec.rb +15 -12
  125. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
  126. data/spec/grape/middleware/versioner/header_spec.rb +14 -13
  127. data/spec/grape/middleware/versioner/param_spec.rb +7 -1
  128. data/spec/grape/middleware/versioner/path_spec.rb +5 -1
  129. data/spec/grape/middleware/versioner_spec.rb +1 -1
  130. data/spec/grape/parser_spec.rb +4 -0
  131. data/spec/grape/path_spec.rb +52 -52
  132. data/spec/grape/presenters/presenter_spec.rb +7 -6
  133. data/spec/grape/request_spec.rb +6 -4
  134. data/spec/grape/util/inheritable_setting_spec.rb +7 -7
  135. data/spec/grape/util/inheritable_values_spec.rb +3 -2
  136. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
  137. data/spec/grape/util/stackable_values_spec.rb +7 -5
  138. data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
  139. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +14 -3
  140. data/spec/grape/validations/params_scope_spec.rb +72 -10
  141. data/spec/grape/validations/single_attribute_iterator_spec.rb +18 -6
  142. data/spec/grape/validations/types/primitive_coercer_spec.rb +63 -7
  143. data/spec/grape/validations/types_spec.rb +8 -8
  144. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
  145. data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
  146. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
  147. data/spec/grape/validations/validators/coerce_spec.rb +248 -33
  148. data/spec/grape/validations/validators/default_spec.rb +121 -78
  149. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
  150. data/spec/grape/validations/validators/except_values_spec.rb +4 -3
  151. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
  152. data/spec/grape/validations/validators/presence_spec.rb +16 -1
  153. data/spec/grape/validations/validators/regexp_spec.rb +25 -31
  154. data/spec/grape/validations/validators/same_as_spec.rb +14 -20
  155. data/spec/grape/validations/validators/values_spec.rb +183 -178
  156. data/spec/grape/validations_spec.rb +342 -29
  157. data/spec/integration/eager_load/eager_load_spec.rb +15 -0
  158. data/spec/integration/multi_json/json_spec.rb +1 -1
  159. data/spec/integration/multi_xml/xml_spec.rb +1 -1
  160. data/spec/shared/versioning_examples.rb +32 -29
  161. data/spec/spec_helper.rb +12 -12
  162. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  163. data/spec/support/chunks.rb +14 -0
  164. data/spec/support/versioned_helpers.rb +4 -6
  165. metadata +110 -102
@@ -5,19 +5,22 @@ require 'spec_helper'
5
5
  describe Grape::Middleware::Stack do
6
6
  module StackSpec
7
7
  class FooMiddleware; end
8
+
8
9
  class BarMiddleware; end
10
+
9
11
  class BlockMiddleware
10
12
  attr_reader :block
13
+
11
14
  def initialize(&block)
12
15
  @block = block
13
16
  end
14
17
  end
15
18
  end
16
19
 
17
- let(:proc) { ->() {} }
18
- let(:others) { [[:use, StackSpec::BarMiddleware], [:insert_before, StackSpec::BarMiddleware, StackSpec::BlockMiddleware, proc]] }
20
+ subject { described_class.new }
19
21
 
20
- subject { Grape::Middleware::Stack.new }
22
+ let(:proc) { -> {} }
23
+ let(:others) { [[:use, StackSpec::BarMiddleware], [:insert_before, StackSpec::BarMiddleware, StackSpec::BlockMiddleware, proc]] }
21
24
 
22
25
  before do
23
26
  subject.use StackSpec::FooMiddleware
@@ -26,20 +29,20 @@ describe Grape::Middleware::Stack do
26
29
  describe '#use' do
27
30
  it 'pushes a middleware class onto the stack' do
28
31
  expect { subject.use StackSpec::BarMiddleware }
29
- .to change { subject.size }.by(1)
32
+ .to change(subject, :size).by(1)
30
33
  expect(subject.last).to eq(StackSpec::BarMiddleware)
31
34
  end
32
35
 
33
36
  it 'pushes a middleware class with arguments onto the stack' do
34
37
  expect { subject.use StackSpec::BarMiddleware, false, my_arg: 42 }
35
- .to change { subject.size }.by(1)
38
+ .to change(subject, :size).by(1)
36
39
  expect(subject.last).to eq(StackSpec::BarMiddleware)
37
40
  expect(subject.last.args).to eq([false, { my_arg: 42 }])
38
41
  end
39
42
 
40
43
  it 'pushes a middleware class with block arguments onto the stack' do
41
44
  expect { subject.use StackSpec::BlockMiddleware, &proc }
42
- .to change { subject.size }.by(1)
45
+ .to change(subject, :size).by(1)
43
46
  expect(subject.last).to eq(StackSpec::BlockMiddleware)
44
47
  expect(subject.last.args).to eq([])
45
48
  expect(subject.last.block).to eq(proc)
@@ -49,7 +52,7 @@ describe Grape::Middleware::Stack do
49
52
  describe '#insert' do
50
53
  it 'inserts a middleware class at the integer index' do
51
54
  expect { subject.insert 0, StackSpec::BarMiddleware }
52
- .to change { subject.size }.by(1)
55
+ .to change(subject, :size).by(1)
53
56
  expect(subject[0]).to eq(StackSpec::BarMiddleware)
54
57
  expect(subject[1]).to eq(StackSpec::FooMiddleware)
55
58
  end
@@ -58,7 +61,7 @@ describe Grape::Middleware::Stack do
58
61
  describe '#insert_before' do
59
62
  it 'inserts a middleware before another middleware class' do
60
63
  expect { subject.insert_before StackSpec::FooMiddleware, StackSpec::BarMiddleware }
61
- .to change { subject.size }.by(1)
64
+ .to change(subject, :size).by(1)
62
65
  expect(subject[0]).to eq(StackSpec::BarMiddleware)
63
66
  expect(subject[1]).to eq(StackSpec::FooMiddleware)
64
67
  end
@@ -67,7 +70,7 @@ describe Grape::Middleware::Stack do
67
70
  subject.use Class.new(StackSpec::BlockMiddleware)
68
71
 
69
72
  expect { subject.insert_before StackSpec::BlockMiddleware, StackSpec::BarMiddleware }
70
- .to change { subject.size }.by(1)
73
+ .to change(subject, :size).by(1)
71
74
 
72
75
  expect(subject[1]).to eq(StackSpec::BarMiddleware)
73
76
  expect(subject[2]).to eq(StackSpec::BlockMiddleware)
@@ -82,7 +85,7 @@ describe Grape::Middleware::Stack do
82
85
  describe '#insert_after' do
83
86
  it 'inserts a middleware after another middleware class' do
84
87
  expect { subject.insert_after StackSpec::FooMiddleware, StackSpec::BarMiddleware }
85
- .to change { subject.size }.by(1)
88
+ .to change(subject, :size).by(1)
86
89
  expect(subject[1]).to eq(StackSpec::BarMiddleware)
87
90
  expect(subject[0]).to eq(StackSpec::FooMiddleware)
88
91
  end
@@ -91,7 +94,7 @@ describe Grape::Middleware::Stack do
91
94
  subject.use Class.new(StackSpec::BlockMiddleware)
92
95
 
93
96
  expect { subject.insert_after StackSpec::BlockMiddleware, StackSpec::BarMiddleware }
94
- .to change { subject.size }.by(1)
97
+ .to change(subject, :size).by(1)
95
98
 
96
99
  expect(subject[1]).to eq(StackSpec::BlockMiddleware)
97
100
  expect(subject[2]).to eq(StackSpec::BarMiddleware)
@@ -106,7 +109,7 @@ describe Grape::Middleware::Stack do
106
109
  describe '#merge_with' do
107
110
  it 'applies a collection of operations and middlewares' do
108
111
  expect { subject.merge_with(others) }
109
- .to change { subject.size }.by(2)
112
+ .to change(subject, :size).by(2)
110
113
  expect(subject[0]).to eq(StackSpec::FooMiddleware)
111
114
  expect(subject[1]).to eq(StackSpec::BlockMiddleware)
112
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
@@ -6,63 +6,63 @@ module Grape
6
6
  describe Path do
7
7
  describe '#initialize' do
8
8
  it 'remembers the path' do
9
- path = Path.new('/:id', anything, anything)
9
+ path = described_class.new('/:id', anything, anything)
10
10
  expect(path.raw_path).to eql('/:id')
11
11
  end
12
12
 
13
13
  it 'remembers the namespace' do
14
- path = Path.new(anything, '/users', anything)
14
+ path = described_class.new(anything, '/users', anything)
15
15
  expect(path.namespace).to eql('/users')
16
16
  end
17
17
 
18
18
  it 'remebers the settings' do
19
- path = Path.new(anything, anything, foo: 'bar')
19
+ path = described_class.new(anything, anything, foo: 'bar')
20
20
  expect(path.settings).to eql(foo: 'bar')
21
21
  end
22
22
  end
23
23
 
24
24
  describe '#mount_path' do
25
25
  it 'is nil when no mount path setting exists' do
26
- path = Path.new(anything, anything, {})
26
+ path = described_class.new(anything, anything, {})
27
27
  expect(path.mount_path).to be_nil
28
28
  end
29
29
 
30
30
  it 'is nil when the mount path is nil' do
31
- path = Path.new(anything, anything, mount_path: nil)
31
+ path = described_class.new(anything, anything, mount_path: nil)
32
32
  expect(path.mount_path).to be_nil
33
33
  end
34
34
 
35
35
  it 'splits the mount path' do
36
- path = Path.new(anything, anything, mount_path: %w[foo bar])
36
+ path = described_class.new(anything, anything, mount_path: %w[foo bar])
37
37
  expect(path.mount_path).to eql(%w[foo bar])
38
38
  end
39
39
  end
40
40
 
41
41
  describe '#root_prefix' do
42
42
  it 'is nil when no root prefix setting exists' do
43
- path = Path.new(anything, anything, {})
43
+ path = described_class.new(anything, anything, {})
44
44
  expect(path.root_prefix).to be_nil
45
45
  end
46
46
 
47
47
  it 'is nil when the mount path is nil' do
48
- path = Path.new(anything, anything, root_prefix: nil)
48
+ path = described_class.new(anything, anything, root_prefix: nil)
49
49
  expect(path.root_prefix).to be_nil
50
50
  end
51
51
 
52
52
  it 'splits the mount path' do
53
- path = Path.new(anything, anything, root_prefix: 'hello/world')
53
+ path = described_class.new(anything, anything, root_prefix: 'hello/world')
54
54
  expect(path.root_prefix).to eql(%w[hello world])
55
55
  end
56
56
  end
57
57
 
58
58
  describe '#uses_path_versioning?' do
59
59
  it 'is false when the version setting is nil' do
60
- path = Path.new(anything, anything, version: nil)
60
+ path = described_class.new(anything, anything, version: nil)
61
61
  expect(path.uses_path_versioning?).to be false
62
62
  end
63
63
 
64
64
  it 'is false when the version option is header' do
65
- path = Path.new(
65
+ path = described_class.new(
66
66
  anything,
67
67
  anything,
68
68
  version: 'v1',
@@ -73,7 +73,7 @@ module Grape
73
73
  end
74
74
 
75
75
  it 'is true when the version option is path' do
76
- path = Path.new(
76
+ path = described_class.new(
77
77
  anything,
78
78
  anything,
79
79
  version: 'v1',
@@ -86,44 +86,44 @@ module Grape
86
86
 
87
87
  describe '#namespace?' do
88
88
  it 'is false when the namespace is nil' do
89
- path = Path.new(anything, nil, anything)
90
- expect(path.namespace?).to be_falsey
89
+ path = described_class.new(anything, nil, anything)
90
+ expect(path).not_to be_namespace
91
91
  end
92
92
 
93
93
  it 'is false when the namespace starts with whitespace' do
94
- path = Path.new(anything, ' /foo', anything)
95
- expect(path.namespace?).to be_falsey
94
+ path = described_class.new(anything, ' /foo', anything)
95
+ expect(path).not_to be_namespace
96
96
  end
97
97
 
98
98
  it 'is false when the namespace is the root path' do
99
- path = Path.new(anything, '/', anything)
99
+ path = described_class.new(anything, '/', anything)
100
100
  expect(path.namespace?).to be false
101
101
  end
102
102
 
103
103
  it 'is true otherwise' do
104
- path = Path.new(anything, '/world', anything)
104
+ path = described_class.new(anything, '/world', anything)
105
105
  expect(path.namespace?).to be true
106
106
  end
107
107
  end
108
108
 
109
109
  describe '#path?' do
110
110
  it 'is false when the path is nil' do
111
- path = Path.new(nil, anything, anything)
112
- expect(path.path?).to be_falsey
111
+ path = described_class.new(nil, anything, anything)
112
+ expect(path).not_to be_path
113
113
  end
114
114
 
115
115
  it 'is false when the path starts with whitespace' do
116
- path = Path.new(' /foo', anything, anything)
117
- expect(path.path?).to be_falsey
116
+ path = described_class.new(' /foo', anything, anything)
117
+ expect(path).not_to be_path
118
118
  end
119
119
 
120
120
  it 'is false when the path is the root path' do
121
- path = Path.new('/', anything, anything)
121
+ path = described_class.new('/', anything, anything)
122
122
  expect(path.path?).to be false
123
123
  end
124
124
 
125
125
  it 'is true otherwise' do
126
- path = Path.new('/hello', anything, anything)
126
+ path = described_class.new('/hello', anything, anything)
127
127
  expect(path.path?).to be true
128
128
  end
129
129
  end
@@ -131,24 +131,24 @@ module Grape
131
131
  describe '#path' do
132
132
  context 'mount_path' do
133
133
  it 'is not included when it is nil' do
134
- path = Path.new(nil, nil, mount_path: '/foo/bar')
134
+ path = described_class.new(nil, nil, mount_path: '/foo/bar')
135
135
  expect(path.path).to eql '/foo/bar'
136
136
  end
137
137
 
138
138
  it 'is included when it is not nil' do
139
- path = Path.new(nil, nil, {})
139
+ path = described_class.new(nil, nil, {})
140
140
  expect(path.path).to eql('/')
141
141
  end
142
142
  end
143
143
 
144
144
  context 'root_prefix' do
145
145
  it 'is not included when it is nil' do
146
- path = Path.new(nil, nil, {})
146
+ path = described_class.new(nil, nil, {})
147
147
  expect(path.path).to eql('/')
148
148
  end
149
149
 
150
150
  it 'is included after the mount path' do
151
- path = Path.new(
151
+ path = described_class.new(
152
152
  nil,
153
153
  nil,
154
154
  mount_path: '/foo',
@@ -160,7 +160,7 @@ module Grape
160
160
  end
161
161
 
162
162
  it 'uses the namespace after the mount path and root prefix' do
163
- path = Path.new(
163
+ path = described_class.new(
164
164
  nil,
165
165
  'namespace',
166
166
  mount_path: '/foo',
@@ -171,7 +171,7 @@ module Grape
171
171
  end
172
172
 
173
173
  it 'uses the raw path after the namespace' do
174
- path = Path.new(
174
+ path = described_class.new(
175
175
  'raw_path',
176
176
  'namespace',
177
177
  mount_path: '/foo',
@@ -185,9 +185,9 @@ module Grape
185
185
  describe '#suffix' do
186
186
  context 'when using a specific format' do
187
187
  it 'accepts specified format' do
188
- path = Path.new(nil, nil, {})
189
- allow(path).to receive(:uses_specific_format?) { true }
190
- allow(path).to receive(:settings) { { format: :json } }
188
+ path = described_class.new(nil, nil, {})
189
+ allow(path).to receive(:uses_specific_format?).and_return(true)
190
+ allow(path).to receive(:settings).and_return({ format: :json })
191
191
 
192
192
  expect(path.suffix).to eql('(.json)')
193
193
  end
@@ -195,9 +195,9 @@ module Grape
195
195
 
196
196
  context 'when path versioning is used' do
197
197
  it "includes a '/'" do
198
- path = Path.new(nil, nil, {})
199
- allow(path).to receive(:uses_specific_format?) { false }
200
- allow(path).to receive(:uses_path_versioning?) { true }
198
+ path = described_class.new(nil, nil, {})
199
+ allow(path).to receive(:uses_specific_format?).and_return(false)
200
+ allow(path).to receive(:uses_path_versioning?).and_return(true)
201
201
 
202
202
  expect(path.suffix).to eql('(/.:format)')
203
203
  end
@@ -205,25 +205,25 @@ module Grape
205
205
 
206
206
  context 'when path versioning is not used' do
207
207
  it "does not include a '/' when the path has a namespace" do
208
- path = Path.new(nil, 'namespace', {})
209
- allow(path).to receive(:uses_specific_format?) { false }
210
- allow(path).to receive(:uses_path_versioning?) { true }
208
+ path = described_class.new(nil, 'namespace', {})
209
+ allow(path).to receive(:uses_specific_format?).and_return(false)
210
+ allow(path).to receive(:uses_path_versioning?).and_return(true)
211
211
 
212
212
  expect(path.suffix).to eql('(.:format)')
213
213
  end
214
214
 
215
215
  it "does not include a '/' when the path has a path" do
216
- path = Path.new('/path', nil, {})
217
- allow(path).to receive(:uses_specific_format?) { false }
218
- allow(path).to receive(:uses_path_versioning?) { true }
216
+ path = described_class.new('/path', nil, {})
217
+ allow(path).to receive(:uses_specific_format?).and_return(false)
218
+ allow(path).to receive(:uses_path_versioning?).and_return(true)
219
219
 
220
220
  expect(path.suffix).to eql('(.:format)')
221
221
  end
222
222
 
223
223
  it "includes a '/' otherwise" do
224
- path = Path.new(nil, nil, {})
225
- allow(path).to receive(:uses_specific_format?) { false }
226
- allow(path).to receive(:uses_path_versioning?) { true }
224
+ path = described_class.new(nil, nil, {})
225
+ allow(path).to receive(:uses_specific_format?).and_return(false)
226
+ allow(path).to receive(:uses_path_versioning?).and_return(true)
227
227
 
228
228
  expect(path.suffix).to eql('(/.:format)')
229
229
  end
@@ -232,19 +232,19 @@ module Grape
232
232
 
233
233
  describe '#path_with_suffix' do
234
234
  it 'combines the path and suffix' do
235
- path = Path.new(nil, nil, {})
236
- allow(path).to receive(:path) { '/the/path' }
237
- allow(path).to receive(:suffix) { 'suffix' }
235
+ path = described_class.new(nil, nil, {})
236
+ allow(path).to receive(:path).and_return('/the/path')
237
+ allow(path).to receive(:suffix).and_return('suffix')
238
238
 
239
239
  expect(path.path_with_suffix).to eql('/the/pathsuffix')
240
240
  end
241
241
 
242
242
  context 'when using a specific format' do
243
243
  it 'might have a suffix with specified format' do
244
- path = Path.new(nil, nil, {})
245
- allow(path).to receive(:path) { '/the/path' }
246
- allow(path).to receive(:uses_specific_format?) { true }
247
- allow(path).to receive(:settings) { { format: :json } }
244
+ path = described_class.new(nil, nil, {})
245
+ allow(path).to receive(:path).and_return('/the/path')
246
+ allow(path).to receive(:uses_specific_format?).and_return(true)
247
+ allow(path).to receive(:settings).and_return({ format: :json })
248
248
 
249
249
  expect(path.path_with_suffix).to eql('/the/path(.json)')
250
250
  end
@@ -19,18 +19,18 @@ module Grape
19
19
  end
20
20
 
21
21
  describe Presenter do
22
+ subject { PresenterSpec::Dummy.new }
23
+
22
24
  describe 'represent' do
23
25
  let(:object_mock) do
24
26
  Object.new
25
27
  end
26
28
 
27
29
  it 'represent object' do
28
- expect(Presenter.represent(object_mock)).to eq object_mock
30
+ expect(described_class.represent(object_mock)).to eq object_mock
29
31
  end
30
32
  end
31
33
 
32
- subject { PresenterSpec::Dummy.new }
33
-
34
34
  describe 'present' do
35
35
  let(:hash_mock) do
36
36
  { key: :value }
@@ -38,8 +38,9 @@ module Grape
38
38
 
39
39
  describe 'instance' do
40
40
  before do
41
- subject.present hash_mock, with: Grape::Presenters::Presenter
41
+ subject.present hash_mock, with: described_class
42
42
  end
43
+
43
44
  it 'presents dummy hash' do
44
45
  expect(subject.body).to eq hash_mock
45
46
  end
@@ -56,8 +57,8 @@ module Grape
56
57
 
57
58
  describe 'instance' do
58
59
  before do
59
- subject.present hash_mock1, with: Grape::Presenters::Presenter
60
- subject.present hash_mock2, with: Grape::Presenters::Presenter
60
+ subject.present hash_mock1, with: described_class
61
+ subject.present hash_mock2, with: described_class
61
62
  end
62
63
 
63
64
  it 'presents both dummy presenter' do