grape 1.2.5 → 1.3.1

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 (258) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +45 -0
  3. data/README.md +7 -6
  4. data/UPGRADING.md +43 -0
  5. data/grape.gemspec +10 -1
  6. data/lib/grape/api/helpers.rb +2 -0
  7. data/lib/grape/api/instance.rb +8 -6
  8. data/lib/grape/api.rb +4 -2
  9. data/lib/grape/config.rb +2 -0
  10. data/lib/grape/content_types.rb +34 -0
  11. data/lib/grape/cookies.rb +2 -0
  12. data/lib/grape/dsl/api.rb +2 -0
  13. data/lib/grape/dsl/callbacks.rb +2 -0
  14. data/lib/grape/dsl/configuration.rb +2 -0
  15. data/lib/grape/dsl/desc.rb +2 -0
  16. data/lib/grape/dsl/headers.rb +2 -0
  17. data/lib/grape/dsl/helpers.rb +4 -2
  18. data/lib/grape/dsl/inside_route.rb +15 -11
  19. data/lib/grape/dsl/logger.rb +2 -0
  20. data/lib/grape/dsl/middleware.rb +2 -0
  21. data/lib/grape/dsl/parameters.rb +8 -6
  22. data/lib/grape/dsl/request_response.rb +4 -2
  23. data/lib/grape/dsl/routing.rb +9 -5
  24. data/lib/grape/dsl/settings.rb +7 -1
  25. data/lib/grape/dsl/validations.rb +2 -0
  26. data/lib/grape/eager_load.rb +2 -0
  27. data/lib/grape/endpoint.rb +13 -7
  28. data/lib/grape/error_formatter/base.rb +2 -0
  29. data/lib/grape/error_formatter/json.rb +2 -0
  30. data/lib/grape/error_formatter/txt.rb +2 -0
  31. data/lib/grape/error_formatter/xml.rb +2 -0
  32. data/lib/grape/error_formatter.rb +3 -1
  33. data/lib/grape/exceptions/base.rb +11 -13
  34. data/lib/grape/exceptions/incompatible_option_values.rb +2 -0
  35. data/lib/grape/exceptions/invalid_accept_header.rb +2 -0
  36. data/lib/grape/exceptions/invalid_formatter.rb +2 -0
  37. data/lib/grape/exceptions/invalid_message_body.rb +2 -0
  38. data/lib/grape/exceptions/invalid_response.rb +2 -0
  39. data/lib/grape/exceptions/invalid_version_header.rb +2 -0
  40. data/lib/grape/exceptions/invalid_versioner_option.rb +2 -0
  41. data/lib/grape/exceptions/invalid_with_option_for_represent.rb +2 -0
  42. data/lib/grape/exceptions/method_not_allowed.rb +2 -0
  43. data/lib/grape/exceptions/missing_group_type.rb +2 -0
  44. data/lib/grape/exceptions/missing_mime_type.rb +2 -0
  45. data/lib/grape/exceptions/missing_option.rb +2 -0
  46. data/lib/grape/exceptions/missing_vendor_option.rb +2 -0
  47. data/lib/grape/exceptions/unknown_options.rb +2 -0
  48. data/lib/grape/exceptions/unknown_parameter.rb +2 -0
  49. data/lib/grape/exceptions/unknown_validator.rb +2 -0
  50. data/lib/grape/exceptions/unsupported_group_type.rb +2 -0
  51. data/lib/grape/exceptions/validation.rb +3 -1
  52. data/lib/grape/exceptions/validation_array_errors.rb +2 -0
  53. data/lib/grape/exceptions/validation_errors.rb +13 -12
  54. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +4 -3
  55. data/lib/grape/extensions/deep_mergeable_hash.rb +2 -0
  56. data/lib/grape/extensions/deep_symbolize_hash.rb +2 -0
  57. data/lib/grape/extensions/hash.rb +2 -0
  58. data/lib/grape/extensions/hashie/mash.rb +2 -0
  59. data/lib/grape/formatter/json.rb +2 -0
  60. data/lib/grape/formatter/serializable_hash.rb +2 -0
  61. data/lib/grape/formatter/txt.rb +2 -0
  62. data/lib/grape/formatter/xml.rb +2 -0
  63. data/lib/grape/formatter.rb +5 -3
  64. data/lib/grape/http/headers.rb +49 -18
  65. data/lib/grape/middleware/auth/base.rb +2 -0
  66. data/lib/grape/middleware/auth/dsl.rb +2 -0
  67. data/lib/grape/middleware/auth/strategies.rb +2 -0
  68. data/lib/grape/middleware/auth/strategy_info.rb +2 -0
  69. data/lib/grape/middleware/base.rb +5 -5
  70. data/lib/grape/middleware/error.rb +3 -1
  71. data/lib/grape/middleware/filter.rb +2 -0
  72. data/lib/grape/middleware/formatter.rb +5 -3
  73. data/lib/grape/middleware/globals.rb +2 -0
  74. data/lib/grape/middleware/helpers.rb +2 -0
  75. data/lib/grape/middleware/stack.rb +4 -1
  76. data/lib/grape/middleware/versioner/accept_version_header.rb +2 -0
  77. data/lib/grape/middleware/versioner/header.rb +5 -3
  78. data/lib/grape/middleware/versioner/param.rb +3 -1
  79. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -0
  80. data/lib/grape/middleware/versioner/path.rb +3 -1
  81. data/lib/grape/middleware/versioner.rb +2 -0
  82. data/lib/grape/namespace.rb +14 -2
  83. data/lib/grape/parser/json.rb +2 -0
  84. data/lib/grape/parser/xml.rb +2 -0
  85. data/lib/grape/parser.rb +3 -1
  86. data/lib/grape/path.rb +13 -1
  87. data/lib/grape/presenters/presenter.rb +2 -0
  88. data/lib/grape/request.rb +15 -8
  89. data/lib/grape/router/attribute_translator.rb +18 -8
  90. data/lib/grape/router/pattern.rb +20 -16
  91. data/lib/grape/router/route.rb +9 -4
  92. data/lib/grape/router.rb +26 -12
  93. data/lib/grape/serve_file/file_body.rb +2 -0
  94. data/lib/grape/serve_file/file_response.rb +2 -0
  95. data/lib/grape/serve_file/sendfile_response.rb +2 -0
  96. data/lib/grape/util/base_inheritable.rb +6 -0
  97. data/lib/grape/util/cache.rb +20 -0
  98. data/lib/grape/util/endpoint_configuration.rb +2 -0
  99. data/lib/grape/util/env.rb +19 -17
  100. data/lib/grape/util/inheritable_setting.rb +2 -0
  101. data/lib/grape/util/inheritable_values.rb +2 -0
  102. data/lib/grape/util/json.rb +2 -0
  103. data/lib/grape/util/lazy_block.rb +2 -0
  104. data/lib/grape/util/lazy_object.rb +43 -0
  105. data/lib/grape/util/lazy_value.rb +2 -0
  106. data/lib/grape/util/registrable.rb +2 -0
  107. data/lib/grape/util/reverse_stackable_values.rb +3 -1
  108. data/lib/grape/util/stackable_values.rb +9 -21
  109. data/lib/grape/util/strict_hash_configuration.rb +2 -0
  110. data/lib/grape/util/xml.rb +2 -0
  111. data/lib/grape/validations/attributes_iterator.rb +3 -3
  112. data/lib/grape/validations/multiple_attributes_iterator.rb +2 -0
  113. data/lib/grape/validations/params_scope.rb +24 -11
  114. data/lib/grape/validations/single_attribute_iterator.rb +13 -2
  115. data/lib/grape/validations/types/array_coercer.rb +56 -0
  116. data/lib/grape/validations/types/build_coercer.rb +49 -48
  117. data/lib/grape/validations/types/custom_type_coercer.rb +15 -49
  118. data/lib/grape/validations/types/custom_type_collection_coercer.rb +10 -25
  119. data/lib/grape/validations/types/dry_type_coercer.rb +41 -0
  120. data/lib/grape/validations/types/file.rb +11 -9
  121. data/lib/grape/validations/types/json.rb +11 -8
  122. data/lib/grape/validations/types/multiple_type_coercer.rb +14 -33
  123. data/lib/grape/validations/types/primitive_coercer.rb +61 -0
  124. data/lib/grape/validations/types/set_coercer.rb +38 -0
  125. data/lib/grape/validations/types/variant_collection_coercer.rb +4 -12
  126. data/lib/grape/validations/types.rb +7 -30
  127. data/lib/grape/validations/validator_factory.rb +2 -0
  128. data/lib/grape/validations/validators/all_or_none.rb +3 -1
  129. data/lib/grape/validations/validators/allow_blank.rb +3 -1
  130. data/lib/grape/validations/validators/as.rb +2 -0
  131. data/lib/grape/validations/validators/at_least_one_of.rb +3 -1
  132. data/lib/grape/validations/validators/base.rb +8 -5
  133. data/lib/grape/validations/validators/coerce.rb +44 -27
  134. data/lib/grape/validations/validators/default.rb +2 -0
  135. data/lib/grape/validations/validators/exactly_one_of.rb +6 -2
  136. data/lib/grape/validations/validators/except_values.rb +3 -1
  137. data/lib/grape/validations/validators/multiple_params_base.rb +2 -0
  138. data/lib/grape/validations/validators/mutual_exclusion.rb +3 -1
  139. data/lib/grape/validations/validators/presence.rb +3 -1
  140. data/lib/grape/validations/validators/regexp.rb +3 -1
  141. data/lib/grape/validations/validators/same_as.rb +6 -3
  142. data/lib/grape/validations/validators/values.rb +17 -5
  143. data/lib/grape/validations.rb +2 -0
  144. data/lib/grape/version.rb +3 -1
  145. data/lib/grape.rb +4 -5
  146. data/spec/grape/api/custom_validations_spec.rb +5 -3
  147. data/spec/grape/api/deeply_included_options_spec.rb +2 -0
  148. data/spec/grape/api/defines_boolean_in_params_spec.rb +5 -3
  149. data/spec/grape/api/inherited_helpers_spec.rb +2 -0
  150. data/spec/grape/api/instance_spec.rb +54 -0
  151. data/spec/grape/api/invalid_format_spec.rb +2 -0
  152. data/spec/grape/api/namespace_parameters_in_route_spec.rb +2 -0
  153. data/spec/grape/api/nested_helpers_spec.rb +2 -0
  154. data/spec/grape/api/optional_parameters_in_route_spec.rb +2 -0
  155. data/spec/grape/api/parameters_modification_spec.rb +3 -1
  156. data/spec/grape/api/patch_method_helpers_spec.rb +2 -0
  157. data/spec/grape/api/recognize_path_spec.rb +2 -0
  158. data/spec/grape/api/required_parameters_in_route_spec.rb +2 -0
  159. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +2 -0
  160. data/spec/grape/api/routes_with_requirements_spec.rb +2 -0
  161. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +2 -0
  162. data/spec/grape/api/shared_helpers_spec.rb +2 -0
  163. data/spec/grape/api_remount_spec.rb +2 -0
  164. data/spec/grape/api_spec.rb +34 -11
  165. data/spec/grape/config_spec.rb +2 -0
  166. data/spec/grape/dsl/callbacks_spec.rb +2 -0
  167. data/spec/grape/dsl/configuration_spec.rb +2 -0
  168. data/spec/grape/dsl/desc_spec.rb +2 -0
  169. data/spec/grape/dsl/headers_spec.rb +2 -0
  170. data/spec/grape/dsl/helpers_spec.rb +4 -2
  171. data/spec/grape/dsl/inside_route_spec.rb +2 -0
  172. data/spec/grape/dsl/logger_spec.rb +2 -0
  173. data/spec/grape/dsl/middleware_spec.rb +2 -0
  174. data/spec/grape/dsl/parameters_spec.rb +2 -0
  175. data/spec/grape/dsl/request_response_spec.rb +2 -0
  176. data/spec/grape/dsl/routing_spec.rb +2 -0
  177. data/spec/grape/dsl/settings_spec.rb +2 -0
  178. data/spec/grape/dsl/validations_spec.rb +2 -0
  179. data/spec/grape/endpoint_spec.rb +3 -1
  180. data/spec/grape/entity_spec.rb +2 -0
  181. data/spec/grape/exceptions/base_spec.rb +3 -1
  182. data/spec/grape/exceptions/body_parse_errors_spec.rb +2 -0
  183. data/spec/grape/exceptions/invalid_accept_header_spec.rb +2 -0
  184. data/spec/grape/exceptions/invalid_formatter_spec.rb +2 -0
  185. data/spec/grape/exceptions/invalid_response_spec.rb +2 -0
  186. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +2 -0
  187. data/spec/grape/exceptions/missing_mime_type_spec.rb +2 -0
  188. data/spec/grape/exceptions/missing_option_spec.rb +2 -0
  189. data/spec/grape/exceptions/unknown_options_spec.rb +2 -0
  190. data/spec/grape/exceptions/unknown_validator_spec.rb +2 -0
  191. data/spec/grape/exceptions/validation_errors_spec.rb +4 -2
  192. data/spec/grape/exceptions/validation_spec.rb +3 -1
  193. data/spec/grape/extensions/param_builders/hash_spec.rb +2 -0
  194. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +2 -0
  195. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +2 -0
  196. data/spec/grape/integration/global_namespace_function_spec.rb +2 -0
  197. data/spec/grape/integration/rack_sendfile_spec.rb +2 -0
  198. data/spec/grape/integration/rack_spec.rb +3 -1
  199. data/spec/grape/loading_spec.rb +2 -0
  200. data/spec/grape/middleware/auth/base_spec.rb +2 -0
  201. data/spec/grape/middleware/auth/dsl_spec.rb +2 -0
  202. data/spec/grape/middleware/auth/strategies_spec.rb +2 -0
  203. data/spec/grape/middleware/base_spec.rb +2 -0
  204. data/spec/grape/middleware/error_spec.rb +2 -0
  205. data/spec/grape/middleware/exception_spec.rb +3 -1
  206. data/spec/grape/middleware/formatter_spec.rb +19 -12
  207. data/spec/grape/middleware/globals_spec.rb +2 -0
  208. data/spec/grape/middleware/stack_spec.rb +11 -0
  209. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +3 -1
  210. data/spec/grape/middleware/versioner/header_spec.rb +3 -1
  211. data/spec/grape/middleware/versioner/param_spec.rb +3 -1
  212. data/spec/grape/middleware/versioner/path_spec.rb +3 -1
  213. data/spec/grape/middleware/versioner_spec.rb +2 -0
  214. data/spec/grape/named_api_spec.rb +2 -0
  215. data/spec/grape/parser_spec.rb +7 -5
  216. data/spec/grape/path_spec.rb +2 -0
  217. data/spec/grape/presenters/presenter_spec.rb +2 -0
  218. data/spec/grape/request_spec.rb +2 -0
  219. data/spec/grape/util/inheritable_setting_spec.rb +2 -0
  220. data/spec/grape/util/inheritable_values_spec.rb +2 -0
  221. data/spec/grape/util/reverse_stackable_values_spec.rb +2 -0
  222. data/spec/grape/util/stackable_values_spec.rb +3 -1
  223. data/spec/grape/util/strict_hash_configuration_spec.rb +2 -0
  224. data/spec/grape/validations/attributes_iterator_spec.rb +2 -0
  225. data/spec/grape/validations/instance_behaivour_spec.rb +5 -3
  226. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +2 -0
  227. data/spec/grape/validations/params_scope_spec.rb +3 -1
  228. data/spec/grape/validations/single_attribute_iterator_spec.rb +18 -4
  229. data/spec/grape/validations/types/primitive_coercer_spec.rb +75 -0
  230. data/spec/grape/validations/types_spec.rb +8 -35
  231. data/spec/grape/validations/validators/all_or_none_spec.rb +2 -0
  232. data/spec/grape/validations/validators/allow_blank_spec.rb +2 -0
  233. data/spec/grape/validations/validators/at_least_one_of_spec.rb +2 -0
  234. data/spec/grape/validations/validators/coerce_spec.rb +51 -110
  235. data/spec/grape/validations/validators/default_spec.rb +2 -0
  236. data/spec/grape/validations/validators/exactly_one_of_spec.rb +14 -12
  237. data/spec/grape/validations/validators/except_values_spec.rb +3 -1
  238. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +2 -0
  239. data/spec/grape/validations/validators/presence_spec.rb +30 -0
  240. data/spec/grape/validations/validators/regexp_spec.rb +2 -0
  241. data/spec/grape/validations/validators/same_as_spec.rb +2 -0
  242. data/spec/grape/validations/validators/values_spec.rb +29 -4
  243. data/spec/grape/validations_spec.rb +69 -15
  244. data/spec/integration/multi_json/json_spec.rb +2 -0
  245. data/spec/integration/multi_xml/xml_spec.rb +2 -0
  246. data/spec/shared/versioning_examples.rb +2 -0
  247. data/spec/spec_helper.rb +18 -0
  248. data/spec/support/basic_auth_encode_helpers.rb +2 -0
  249. data/spec/support/content_type_helpers.rb +2 -0
  250. data/spec/support/eager_load.rb +19 -0
  251. data/spec/support/endpoint_faker.rb +2 -0
  252. data/spec/support/file_streamer.rb +2 -0
  253. data/spec/support/integer_helpers.rb +2 -0
  254. data/spec/support/versioned_helpers.rb +4 -2
  255. metadata +126 -112
  256. data/lib/grape/extensions/deep_hash_with_indifferent_access.rb +0 -18
  257. data/lib/grape/util/content_types.rb +0 -26
  258. data/lib/grape/validations/types/virtus_collection_patch.rb +0 -16
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Extensions::Hash::ParamBuilder do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Extensions::Hashie::Mash::ParamBuilder do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # see https://github.com/ruby-grape/grape/issues/1348
2
4
 
3
5
  require 'spec_helper'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Rack::Sendfile do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Rack do
@@ -19,7 +21,7 @@ describe Rack do
19
21
  }
20
22
  env = Rack::MockRequest.env_for('/', options)
21
23
 
22
- expect(JSON.parse(app.call(env)[2].body.first)['params_keys']).to match_array('test')
24
+ expect(JSON.parse(read_chunks(app.call(env)[2]).join)['params_keys']).to match_array('test')
23
25
  ensure
24
26
  input.close
25
27
  input.unlink
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::API do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  require 'base64'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Middleware::Auth::DSL do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  require 'base64'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Middleware::Base do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  require 'grape-entity'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Middleware::Error do
@@ -53,7 +55,7 @@ describe Grape::Middleware::Error do
53
55
  class CustomErrorApp
54
56
  class << self
55
57
  def call(_env)
56
- raise CustomError, status: 400, message: 'failed validation'
58
+ raise CustomError.new(status: 400, message: 'failed validation')
57
59
  end
58
60
  end
59
61
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Middleware::Formatter do
@@ -41,7 +43,7 @@ describe Grape::Middleware::Formatter do
41
43
  end
42
44
 
43
45
  context 'xml' do
44
- let(:body) { 'string' }
46
+ let(:body) { +'string' }
45
47
  it 'calls #to_xml if the content type is xml' do
46
48
  body.instance_eval do
47
49
  def to_xml
@@ -194,19 +196,19 @@ describe Grape::Middleware::Formatter do
194
196
  subject.options[:content_types][:custom] = "don't care"
195
197
  subject.options[:formatters][:custom] = ->(_obj, _env) { 'CUSTOM FORMAT' }
196
198
  _, _, body = subject.call('PATH_INFO' => '/info.custom')
197
- expect(body.body).to eq(['CUSTOM FORMAT'])
199
+ expect(read_chunks(body)).to eq(['CUSTOM FORMAT'])
198
200
  end
199
201
  context 'default' do
200
202
  let(:body) { ['blah'] }
201
203
  it 'uses default json formatter' do
202
204
  _, _, body = subject.call('PATH_INFO' => '/info.json')
203
- expect(body.body).to eq(['["blah"]'])
205
+ expect(read_chunks(body)).to eq(['["blah"]'])
204
206
  end
205
207
  end
206
208
  it 'uses custom json formatter' do
207
209
  subject.options[:formatters][:json] = ->(_obj, _env) { 'CUSTOM JSON FORMAT' }
208
210
  _, _, body = subject.call('PATH_INFO' => '/info.json')
209
- expect(body.body).to eq(['CUSTOM JSON FORMAT'])
211
+ expect(read_chunks(body)).to eq(['CUSTOM JSON FORMAT'])
210
212
  end
211
213
  end
212
214
 
@@ -377,12 +379,17 @@ describe Grape::Middleware::Formatter do
377
379
  end
378
380
 
379
381
  context 'send file' do
380
- let(:body) { Grape::ServeFile::FileResponse.new('file') }
381
- let(:app) { ->(_env) { [200, {}, body] } }
382
+ let(:file) { double(File) }
383
+ let(:file_body) { Grape::ServeFile::FileResponse.new(file) }
384
+ let(:app) { ->(_env) { [200, {}, file_body] } }
382
385
 
383
- it 'returns Grape::Uril::SendFileReponse' do
386
+ it 'returns a file response' do
387
+ expect(file).to receive(:each).and_yield('data')
384
388
  env = { 'PATH_INFO' => '/somewhere', 'HTTP_ACCEPT' => 'application/json' }
385
- expect(subject.call(env)).to be_a(Grape::ServeFile::SendfileResponse)
389
+ status, headers, body = subject.call(env)
390
+ expect(status).to be == 200
391
+ expect(headers).to be == { 'Content-Type' => 'application/json' }
392
+ expect(read_chunks(body)).to be == ['data']
386
393
  end
387
394
  end
388
395
 
@@ -395,17 +402,17 @@ describe Grape::Middleware::Formatter do
395
402
  let(:app) { ->(_env) { [200, {}, ['']] } }
396
403
  before do
397
404
  Grape::Formatter.register :invalid, InvalidFormatter
398
- Grape::ContentTypes::CONTENT_TYPES[:invalid] = 'application/x-invalid'
405
+ Grape::ContentTypes.register :invalid, 'application/x-invalid'
399
406
  end
400
407
  after do
401
- Grape::ContentTypes::CONTENT_TYPES.delete(:invalid)
408
+ Grape::ContentTypes.default_elements.delete(:invalid)
402
409
  Grape::Formatter.default_elements.delete(:invalid)
403
410
  end
404
411
 
405
412
  it 'returns response by invalid formatter' do
406
413
  env = { 'PATH_INFO' => '/hello.invalid', 'HTTP_ACCEPT' => 'application/x-invalid' }
407
- _, _, bodies = *subject.call(env)
408
- expect(bodies.body.first).to eq({ message: 'invalid' }.to_json)
414
+ _, _, body = *subject.call(env)
415
+ expect(read_chunks(body).join).to eq({ message: 'invalid' }.to_json)
409
416
  end
410
417
  end
411
418
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Middleware::Globals do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Middleware::Stack do
@@ -109,6 +111,15 @@ describe Grape::Middleware::Stack do
109
111
  expect(subject[1]).to eq(StackSpec::BlockMiddleware)
110
112
  expect(subject[2]).to eq(StackSpec::BarMiddleware)
111
113
  end
114
+
115
+ context 'middleware spec with proc declaration exists' do
116
+ let(:middleware_spec_with_proc) { [:use, StackSpec::FooMiddleware, proc] }
117
+
118
+ it 'properly forwards spec arguments' do
119
+ expect(subject).to receive(:use).with(StackSpec::FooMiddleware)
120
+ subject.merge_with([middleware_spec_with_proc])
121
+ end
122
+ end
112
123
  end
113
124
 
114
125
  describe '#build' do
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Middleware::Versioner::AcceptVersionHeader do
4
6
  let(:app) { ->(env) { [200, env, env] } }
5
- subject { Grape::Middleware::Versioner::AcceptVersionHeader.new(app, @options || {}) }
7
+ subject { Grape::Middleware::Versioner::AcceptVersionHeader.new(app, **(@options || {})) }
6
8
 
7
9
  before do
8
10
  @options = {
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Middleware::Versioner::Header do
4
6
  let(:app) { ->(env) { [200, env, env] } }
5
- subject { Grape::Middleware::Versioner::Header.new(app, @options || {}) }
7
+ subject { Grape::Middleware::Versioner::Header.new(app, **(@options || {})) }
6
8
 
7
9
  before do
8
10
  @options = {
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Middleware::Versioner::Param do
4
6
  let(:app) { ->(env) { [200, env, env['api.version']] } }
5
7
  let(:options) { {} }
6
- subject { Grape::Middleware::Versioner::Param.new(app, options) }
8
+ subject { Grape::Middleware::Versioner::Param.new(app, **options) }
7
9
 
8
10
  it 'sets the API version based on the default param (apiver)' do
9
11
  env = Rack::MockRequest.env_for('/awesome', params: { 'apiver' => 'v1' })
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Middleware::Versioner::Path do
4
6
  let(:app) { ->(env) { [200, env, env['api.version']] } }
5
7
  let(:options) { {} }
6
- subject { Grape::Middleware::Versioner::Path.new(app, options) }
8
+ subject { Grape::Middleware::Versioner::Path.new(app, **options) }
7
9
 
8
10
  it 'sets the API version based on the first path' do
9
11
  expect(subject.call('PATH_INFO' => '/v1/awesome').last).to eq('v1')
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Middleware::Versioner do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe 'A named API' do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Parser do
@@ -15,11 +17,11 @@ describe Grape::Parser do
15
17
 
16
18
  describe '.parsers' do
17
19
  it 'returns an instance of Hash' do
18
- expect(subject.parsers({})).to be_an_instance_of(Hash)
20
+ expect(subject.parsers(**{})).to be_an_instance_of(Hash)
19
21
  end
20
22
 
21
23
  it 'includes built-in parsers' do
22
- expect(subject.parsers({})).to include(subject.builtin_parsers)
24
+ expect(subject.parsers(**{})).to include(subject.builtin_parsers)
23
25
  end
24
26
 
25
27
  context 'with :parsers option' do
@@ -33,7 +35,7 @@ describe Grape::Parser do
33
35
  let(:added_parser) { Class.new }
34
36
  before { subject.register :added, added_parser }
35
37
  it 'includes added parser' do
36
- expect(subject.parsers({})).to include(added: added_parser)
38
+ expect(subject.parsers(**{})).to include(added: added_parser)
37
39
  end
38
40
  end
39
41
  end
@@ -42,8 +44,8 @@ describe Grape::Parser do
42
44
  let(:options) { {} }
43
45
 
44
46
  it 'calls .parsers' do
45
- expect(subject).to receive(:parsers).with(options).and_return(subject.builtin_parsers)
46
- subject.parser_for(:json, options)
47
+ expect(subject).to receive(:parsers).with(any_args).and_return(subject.builtin_parsers)
48
+ subject.parser_for(:json, **options)
47
49
  end
48
50
 
49
51
  it 'returns parser correctly' do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Grape
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Grape
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module Grape
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  module Grape
3
5
  module Util
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  module Grape
3
5
  module Util
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  module Grape
3
5
  module Util
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  module Grape
3
5
  module Util
@@ -6,7 +8,7 @@ module Grape
6
8
  subject { StackableValues.new(parent) }
7
9
 
8
10
  describe '#keys' do
9
- it 'returns all key' do
11
+ it 'returns all keys' do
10
12
  subject[:some_thing] = :foo_bar
11
13
  subject[:some_thing_else] = :foo_bar
12
14
  expect(subject.keys).to eq %i[some_thing some_thing_else].sort
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
  module Grape
3
5
  module Util
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Validations::AttributesIterator do
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe 'Validator with instance variables' do
4
6
  let(:validator_type) do
5
7
  Class.new(Grape::Validations::Base) do
6
8
  def validate_param!(_attr_name, _params)
7
- if @instance_variable
8
- raise Grape::Exceptions::Validation, params: ['params'],
9
- message: 'This should never happen'
9
+ if instance_variable_defined?(:@instance_variable) && @instance_variable
10
+ raise Grape::Exceptions::Validation.new(params: ['params'],
11
+ message: 'This should never happen')
10
12
  end
11
13
  @instance_variable = true
12
14
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Validations::MultipleAttributesIterator do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Validations::ParamsScope do
@@ -30,7 +32,7 @@ describe Grape::Validations::ParamsScope do
30
32
  context 'when the default value is false' do
31
33
  before do
32
34
  subject.params do
33
- optional :bool, type: Virtus::Attribute::Boolean, default: false
35
+ optional :bool, type: Grape::API::Boolean, default: false
34
36
  end
35
37
  subject.get
36
38
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Validations::SingleAttributeIterator do
4
6
  describe '#each' do
5
7
  subject(:iterator) { described_class.new(validator, scope, params) }
6
8
  let(:scope) { Grape::Validations::ParamsScope.new(api: Class.new(Grape::API)) }
7
- let(:validator) { double(attrs: %i[first second third]) }
9
+ let(:validator) { double(attrs: %i[first second]) }
8
10
 
9
11
  context 'when params is a hash' do
10
12
  let(:params) do
@@ -13,7 +15,7 @@ describe Grape::Validations::SingleAttributeIterator do
13
15
 
14
16
  it 'yields params and every single attribute from the list' do
15
17
  expect { |b| iterator.each(&b) }
16
- .to yield_successive_args([params, :first], [params, :second], [params, :third])
18
+ .to yield_successive_args([params, :first, false], [params, :second, false])
17
19
  end
18
20
  end
19
21
 
@@ -24,10 +26,22 @@ describe Grape::Validations::SingleAttributeIterator do
24
26
 
25
27
  it 'yields every single attribute from the list for each of the array elements' do
26
28
  expect { |b| iterator.each(&b) }.to yield_successive_args(
27
- [params[0], :first], [params[0], :second], [params[0], :third],
28
- [params[1], :first], [params[1], :second], [params[1], :third]
29
+ [params[0], :first, false], [params[0], :second, false],
30
+ [params[1], :first, false], [params[1], :second, false]
29
31
  )
30
32
  end
33
+
34
+ context 'empty values' do
35
+ let(:params) { [{}, '', 10] }
36
+
37
+ it 'marks params with empty values' do
38
+ expect { |b| iterator.each(&b) }.to yield_successive_args(
39
+ [params[0], :first, true], [params[0], :second, true],
40
+ [params[1], :first, true], [params[1], :second, true],
41
+ [params[2], :first, false], [params[2], :second, false]
42
+ )
43
+ end
44
+ end
31
45
  end
32
46
  end
33
47
  end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Grape::Validations::Types::PrimitiveCoercer do
6
+ let(:strict) { false }
7
+
8
+ subject { described_class.new(type, strict) }
9
+
10
+ describe '.call' do
11
+ context 'Boolean' do
12
+ let(:type) { Grape::API::Boolean }
13
+
14
+ [true, 'true', 1].each do |val|
15
+ it "coerces '#{val}' to true" do
16
+ expect(subject.call(val)).to eq(true)
17
+ end
18
+ end
19
+
20
+ [false, 'false', 0].each do |val|
21
+ it "coerces '#{val}' to false" do
22
+ expect(subject.call(val)).to eq(false)
23
+ end
24
+ end
25
+
26
+ it 'returns an error when the given value cannot be coerced' do
27
+ expect(subject.call(123)).to be_instance_of(Grape::Validations::Types::InvalidValue)
28
+ end
29
+ end
30
+
31
+ context 'String' do
32
+ let(:type) { String }
33
+
34
+ it 'coerces to String' do
35
+ expect(subject.call(10)).to eq('10')
36
+ end
37
+ end
38
+
39
+ context 'BigDecimal' do
40
+ let(:type) { BigDecimal }
41
+
42
+ it 'coerces to BigDecimal' do
43
+ expect(subject.call(5)).to eq(BigDecimal(5))
44
+ end
45
+ end
46
+
47
+ context 'the strict mode' do
48
+ let(:strict) { true }
49
+
50
+ context 'Boolean' do
51
+ let(:type) { Grape::API::Boolean }
52
+
53
+ it 'returns an error when the given value is not Boolean' do
54
+ expect(subject.call(1)).to be_instance_of(Grape::Validations::Types::InvalidValue)
55
+ end
56
+
57
+ it 'returns a value as it is when the given value is Boolean' do
58
+ expect(subject.call(true)).to eq(true)
59
+ end
60
+ end
61
+
62
+ context 'BigDecimal' do
63
+ let(:type) { BigDecimal }
64
+
65
+ it 'returns an error when the given value is not BigDecimal' do
66
+ expect(subject.call(1)).to be_instance_of(Grape::Validations::Types::InvalidValue)
67
+ end
68
+
69
+ it 'returns a value as it is when the given value is BigDecimal' do
70
+ expect(subject.call(BigDecimal(0))).to eq(BigDecimal(0))
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Validations::Types do
@@ -11,29 +13,10 @@ describe Grape::Validations::Types do
11
13
  end
12
14
  end
13
15
 
14
- VirtusA = Virtus::Attribute.build(String)
15
-
16
- module VirtusModule
17
- include Virtus.module
18
- end
19
-
20
- class VirtusB
21
- include VirtusModule
22
- end
23
-
24
- class VirtusC
25
- include Virtus.model
26
- end
27
-
28
- MyAxiom = Axiom::Types::String.new do
29
- minimum_length 1
30
- maximum_length 30
31
- end
32
-
33
16
  describe '::primitive?' do
34
17
  [
35
18
  Integer, Float, Numeric, BigDecimal,
36
- Virtus::Attribute::Boolean, String, Symbol,
19
+ Grape::API::Boolean, String, Symbol,
37
20
  Date, DateTime, Time, Rack::Multipart::UploadedFile
38
21
  ].each do |type|
39
22
  it "recognizes #{type} as a primitive" do
@@ -57,16 +40,6 @@ describe Grape::Validations::Types do
57
40
  end
58
41
  end
59
42
 
60
- describe '::recognized?' do
61
- [
62
- VirtusA, VirtusB, VirtusC, MyAxiom
63
- ].each do |type|
64
- it "recognizes #{type}" do
65
- expect(described_class.recognized?(type)).to be_truthy
66
- end
67
- end
68
- end
69
-
70
43
  describe '::special?' do
71
44
  [
72
45
  JSON, Array[JSON], File, Rack::Multipart::UploadedFile
@@ -97,14 +70,14 @@ describe Grape::Validations::Types do
97
70
  expect(described_class.instance_variable_get(:@__cache_write_lock)).to be_a(Mutex)
98
71
  end
99
72
 
100
- it 'caches the result of the Virtus::Attribute.build method' do
73
+ it 'caches the result of the build_coercer method' do
101
74
  original_cache = described_class.instance_variable_get(:@__cache)
102
75
  described_class.instance_variable_set(:@__cache, {})
103
76
 
104
- coercer = 'TestCoercer'
105
- expect(Virtus::Attribute).to receive(:build).once.and_return(coercer)
106
- expect(described_class.build_coercer(Array[String])).to eq(coercer)
107
- expect(described_class.build_coercer(Array[String])).to eq(coercer)
77
+ a_coercer = described_class.build_coercer(Array[String])
78
+ b_coercer = described_class.build_coercer(Array[String])
79
+
80
+ expect(a_coercer.object_id).to eq(b_coercer.object_id)
108
81
 
109
82
  described_class.instance_variable_set(:@__cache, original_cache)
110
83
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Validations::AllOrNoneOfValidator do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Validations::AllowBlankValidator do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Validations::AtLeastOneOfValidator do