grape 1.1.0 → 1.5.3

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 (286) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +278 -44
  3. data/LICENSE +1 -1
  4. data/README.md +514 -69
  5. data/UPGRADING.md +424 -17
  6. data/grape.gemspec +13 -2
  7. data/lib/grape.rb +104 -71
  8. data/lib/grape/api.rb +138 -175
  9. data/lib/grape/api/helpers.rb +2 -0
  10. data/lib/grape/api/instance.rb +283 -0
  11. data/lib/grape/config.rb +34 -0
  12. data/lib/grape/content_types.rb +34 -0
  13. data/lib/grape/cookies.rb +2 -0
  14. data/lib/grape/dsl/api.rb +2 -0
  15. data/lib/grape/dsl/callbacks.rb +22 -0
  16. data/lib/grape/dsl/configuration.rb +2 -0
  17. data/lib/grape/dsl/desc.rb +41 -7
  18. data/lib/grape/dsl/headers.rb +2 -0
  19. data/lib/grape/dsl/helpers.rb +5 -2
  20. data/lib/grape/dsl/inside_route.rb +92 -49
  21. data/lib/grape/dsl/logger.rb +2 -0
  22. data/lib/grape/dsl/middleware.rb +9 -0
  23. data/lib/grape/dsl/parameters.rb +25 -14
  24. data/lib/grape/dsl/request_response.rb +4 -2
  25. data/lib/grape/dsl/routing.rb +17 -10
  26. data/lib/grape/dsl/settings.rb +7 -1
  27. data/lib/grape/dsl/validations.rb +24 -4
  28. data/lib/grape/eager_load.rb +20 -0
  29. data/lib/grape/endpoint.rb +59 -35
  30. data/lib/grape/error_formatter.rb +4 -2
  31. data/lib/grape/error_formatter/base.rb +2 -0
  32. data/lib/grape/error_formatter/json.rb +2 -0
  33. data/lib/grape/error_formatter/txt.rb +2 -0
  34. data/lib/grape/error_formatter/xml.rb +2 -0
  35. data/lib/grape/exceptions/base.rb +20 -14
  36. data/lib/grape/exceptions/empty_message_body.rb +11 -0
  37. data/lib/grape/exceptions/incompatible_option_values.rb +2 -0
  38. data/lib/grape/exceptions/invalid_accept_header.rb +2 -0
  39. data/lib/grape/exceptions/invalid_formatter.rb +2 -0
  40. data/lib/grape/exceptions/invalid_message_body.rb +2 -0
  41. data/lib/grape/exceptions/invalid_response.rb +11 -0
  42. data/lib/grape/exceptions/invalid_version_header.rb +2 -0
  43. data/lib/grape/exceptions/invalid_versioner_option.rb +2 -0
  44. data/lib/grape/exceptions/invalid_with_option_for_represent.rb +2 -0
  45. data/lib/grape/exceptions/method_not_allowed.rb +2 -0
  46. data/lib/grape/exceptions/missing_group_type.rb +2 -0
  47. data/lib/grape/exceptions/missing_mime_type.rb +2 -0
  48. data/lib/grape/exceptions/missing_option.rb +2 -0
  49. data/lib/grape/exceptions/missing_vendor_option.rb +2 -0
  50. data/lib/grape/exceptions/unknown_options.rb +2 -0
  51. data/lib/grape/exceptions/unknown_parameter.rb +2 -0
  52. data/lib/grape/exceptions/unknown_validator.rb +2 -0
  53. data/lib/grape/exceptions/unsupported_group_type.rb +2 -0
  54. data/lib/grape/exceptions/validation.rb +4 -2
  55. data/lib/grape/exceptions/validation_array_errors.rb +2 -0
  56. data/lib/grape/exceptions/validation_errors.rb +16 -13
  57. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +4 -3
  58. data/lib/grape/extensions/deep_mergeable_hash.rb +2 -0
  59. data/lib/grape/extensions/deep_symbolize_hash.rb +2 -0
  60. data/lib/grape/extensions/hash.rb +2 -0
  61. data/lib/grape/extensions/hashie/mash.rb +2 -0
  62. data/lib/grape/formatter.rb +5 -3
  63. data/lib/grape/formatter/json.rb +2 -0
  64. data/lib/grape/formatter/serializable_hash.rb +2 -0
  65. data/lib/grape/formatter/txt.rb +2 -0
  66. data/lib/grape/formatter/xml.rb +2 -0
  67. data/lib/grape/http/headers.rb +50 -18
  68. data/lib/grape/locale/en.yml +3 -1
  69. data/lib/grape/middleware/auth/base.rb +7 -7
  70. data/lib/grape/middleware/auth/dsl.rb +2 -0
  71. data/lib/grape/middleware/auth/strategies.rb +2 -0
  72. data/lib/grape/middleware/auth/strategy_info.rb +2 -0
  73. data/lib/grape/middleware/base.rb +10 -7
  74. data/lib/grape/middleware/error.rb +21 -16
  75. data/lib/grape/middleware/filter.rb +2 -0
  76. data/lib/grape/middleware/formatter.rb +8 -6
  77. data/lib/grape/middleware/globals.rb +2 -0
  78. data/lib/grape/middleware/helpers.rb +12 -0
  79. data/lib/grape/middleware/stack.rb +13 -3
  80. data/lib/grape/middleware/versioner.rb +2 -0
  81. data/lib/grape/middleware/versioner/accept_version_header.rb +2 -0
  82. data/lib/grape/middleware/versioner/header.rb +10 -8
  83. data/lib/grape/middleware/versioner/param.rb +3 -1
  84. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +4 -1
  85. data/lib/grape/middleware/versioner/path.rb +3 -1
  86. data/lib/grape/namespace.rb +14 -2
  87. data/lib/grape/parser.rb +4 -2
  88. data/lib/grape/parser/json.rb +3 -1
  89. data/lib/grape/parser/xml.rb +3 -1
  90. data/lib/grape/path.rb +15 -3
  91. data/lib/grape/presenters/presenter.rb +2 -0
  92. data/lib/grape/request.rb +19 -10
  93. data/lib/grape/router.rb +30 -29
  94. data/lib/grape/router/attribute_translator.rb +41 -8
  95. data/lib/grape/router/pattern.rb +20 -16
  96. data/lib/grape/router/route.rb +14 -28
  97. data/lib/grape/{serve_file → serve_stream}/file_body.rb +3 -1
  98. data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +3 -1
  99. data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +10 -8
  100. data/lib/grape/util/base_inheritable.rb +43 -0
  101. data/lib/grape/util/cache.rb +20 -0
  102. data/lib/grape/util/endpoint_configuration.rb +8 -0
  103. data/lib/grape/util/env.rb +19 -17
  104. data/lib/grape/util/inheritable_setting.rb +2 -0
  105. data/lib/grape/util/inheritable_values.rb +7 -25
  106. data/lib/grape/util/json.rb +2 -0
  107. data/lib/grape/util/lazy_block.rb +27 -0
  108. data/lib/grape/util/lazy_object.rb +43 -0
  109. data/lib/grape/util/lazy_value.rb +98 -0
  110. data/lib/grape/util/registrable.rb +2 -0
  111. data/lib/grape/util/reverse_stackable_values.rb +10 -35
  112. data/lib/grape/util/stackable_values.rb +21 -34
  113. data/lib/grape/util/strict_hash_configuration.rb +2 -0
  114. data/lib/grape/util/xml.rb +2 -0
  115. data/lib/grape/validations.rb +2 -0
  116. data/lib/grape/validations/attributes_iterator.rb +16 -6
  117. data/lib/grape/validations/multiple_attributes_iterator.rb +13 -0
  118. data/lib/grape/validations/params_scope.rb +51 -30
  119. data/lib/grape/validations/single_attribute_iterator.rb +24 -0
  120. data/lib/grape/validations/types.rb +13 -38
  121. data/lib/grape/validations/types/array_coercer.rb +65 -0
  122. data/lib/grape/validations/types/build_coercer.rb +47 -49
  123. data/lib/grape/validations/types/custom_type_coercer.rb +29 -51
  124. data/lib/grape/validations/types/custom_type_collection_coercer.rb +10 -25
  125. data/lib/grape/validations/types/dry_type_coercer.rb +76 -0
  126. data/lib/grape/validations/types/file.rb +22 -18
  127. data/lib/grape/validations/types/invalid_value.rb +24 -0
  128. data/lib/grape/validations/types/json.rb +46 -39
  129. data/lib/grape/validations/types/multiple_type_coercer.rb +14 -33
  130. data/lib/grape/validations/types/primitive_coercer.rb +67 -0
  131. data/lib/grape/validations/types/set_coercer.rb +40 -0
  132. data/lib/grape/validations/types/variant_collection_coercer.rb +5 -13
  133. data/lib/grape/validations/validator_factory.rb +8 -11
  134. data/lib/grape/validations/validators/all_or_none.rb +8 -13
  135. data/lib/grape/validations/validators/allow_blank.rb +3 -1
  136. data/lib/grape/validations/validators/as.rb +5 -4
  137. data/lib/grape/validations/validators/at_least_one_of.rb +7 -13
  138. data/lib/grape/validations/validators/base.rb +20 -16
  139. data/lib/grape/validations/validators/coerce.rb +46 -29
  140. data/lib/grape/validations/validators/default.rb +6 -6
  141. data/lib/grape/validations/validators/exactly_one_of.rb +10 -23
  142. data/lib/grape/validations/validators/except_values.rb +4 -2
  143. data/lib/grape/validations/validators/multiple_params_base.rb +17 -10
  144. data/lib/grape/validations/validators/mutual_exclusion.rb +8 -18
  145. data/lib/grape/validations/validators/presence.rb +3 -1
  146. data/lib/grape/validations/validators/regexp.rb +4 -2
  147. data/lib/grape/validations/validators/same_as.rb +26 -0
  148. data/lib/grape/validations/validators/values.rb +18 -6
  149. data/lib/grape/version.rb +3 -1
  150. data/spec/grape/api/custom_validations_spec.rb +5 -3
  151. data/spec/grape/api/deeply_included_options_spec.rb +2 -0
  152. data/spec/grape/api/defines_boolean_in_params_spec.rb +39 -0
  153. data/spec/grape/api/inherited_helpers_spec.rb +2 -0
  154. data/spec/grape/api/instance_spec.rb +104 -0
  155. data/spec/grape/api/invalid_format_spec.rb +2 -0
  156. data/spec/grape/api/namespace_parameters_in_route_spec.rb +2 -0
  157. data/spec/grape/api/nested_helpers_spec.rb +2 -0
  158. data/spec/grape/api/optional_parameters_in_route_spec.rb +2 -0
  159. data/spec/grape/api/parameters_modification_spec.rb +3 -1
  160. data/spec/grape/api/patch_method_helpers_spec.rb +2 -0
  161. data/spec/grape/api/recognize_path_spec.rb +2 -0
  162. data/spec/grape/api/required_parameters_in_route_spec.rb +2 -0
  163. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +2 -0
  164. data/spec/grape/api/routes_with_requirements_spec.rb +61 -0
  165. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +2 -0
  166. data/spec/grape/api/shared_helpers_spec.rb +2 -0
  167. data/spec/grape/api_remount_spec.rb +473 -0
  168. data/spec/grape/api_spec.rb +565 -12
  169. data/spec/grape/config_spec.rb +19 -0
  170. data/spec/grape/dsl/callbacks_spec.rb +2 -0
  171. data/spec/grape/dsl/configuration_spec.rb +2 -0
  172. data/spec/grape/dsl/desc_spec.rb +42 -16
  173. data/spec/grape/dsl/headers_spec.rb +2 -0
  174. data/spec/grape/dsl/helpers_spec.rb +4 -2
  175. data/spec/grape/dsl/inside_route_spec.rb +184 -33
  176. data/spec/grape/dsl/logger_spec.rb +2 -0
  177. data/spec/grape/dsl/middleware_spec.rb +10 -0
  178. data/spec/grape/dsl/parameters_spec.rb +2 -0
  179. data/spec/grape/dsl/request_response_spec.rb +2 -0
  180. data/spec/grape/dsl/routing_spec.rb +12 -0
  181. data/spec/grape/dsl/settings_spec.rb +2 -0
  182. data/spec/grape/dsl/validations_spec.rb +2 -0
  183. data/spec/grape/endpoint/declared_spec.rb +601 -0
  184. data/spec/grape/endpoint_spec.rb +53 -523
  185. data/spec/grape/entity_spec.rb +9 -1
  186. data/spec/grape/exceptions/base_spec.rb +67 -0
  187. data/spec/grape/exceptions/body_parse_errors_spec.rb +2 -0
  188. data/spec/grape/exceptions/invalid_accept_header_spec.rb +2 -0
  189. data/spec/grape/exceptions/invalid_formatter_spec.rb +2 -0
  190. data/spec/grape/exceptions/invalid_response_spec.rb +13 -0
  191. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +2 -0
  192. data/spec/grape/exceptions/missing_mime_type_spec.rb +2 -0
  193. data/spec/grape/exceptions/missing_option_spec.rb +2 -0
  194. data/spec/grape/exceptions/unknown_options_spec.rb +2 -0
  195. data/spec/grape/exceptions/unknown_validator_spec.rb +2 -0
  196. data/spec/grape/exceptions/validation_errors_spec.rb +8 -4
  197. data/spec/grape/exceptions/validation_spec.rb +3 -1
  198. data/spec/grape/extensions/param_builders/hash_spec.rb +2 -0
  199. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +2 -0
  200. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +2 -0
  201. data/spec/grape/integration/global_namespace_function_spec.rb +2 -0
  202. data/spec/grape/integration/rack_sendfile_spec.rb +14 -8
  203. data/spec/grape/integration/rack_spec.rb +25 -7
  204. data/spec/grape/loading_spec.rb +2 -0
  205. data/spec/grape/middleware/auth/base_spec.rb +2 -0
  206. data/spec/grape/middleware/auth/dsl_spec.rb +5 -3
  207. data/spec/grape/middleware/auth/strategies_spec.rb +3 -1
  208. data/spec/grape/middleware/base_spec.rb +10 -0
  209. data/spec/grape/middleware/error_spec.rb +3 -1
  210. data/spec/grape/middleware/exception_spec.rb +4 -2
  211. data/spec/grape/middleware/formatter_spec.rb +33 -16
  212. data/spec/grape/middleware/globals_spec.rb +2 -0
  213. data/spec/grape/middleware/stack_spec.rb +12 -0
  214. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +3 -1
  215. data/spec/grape/middleware/versioner/header_spec.rb +9 -1
  216. data/spec/grape/middleware/versioner/param_spec.rb +3 -1
  217. data/spec/grape/middleware/versioner/path_spec.rb +3 -1
  218. data/spec/grape/middleware/versioner_spec.rb +2 -0
  219. data/spec/grape/named_api_spec.rb +21 -0
  220. data/spec/grape/parser_spec.rb +7 -5
  221. data/spec/grape/path_spec.rb +6 -4
  222. data/spec/grape/presenters/presenter_spec.rb +2 -0
  223. data/spec/grape/request_spec.rb +26 -0
  224. data/spec/grape/util/inheritable_setting_spec.rb +2 -0
  225. data/spec/grape/util/inheritable_values_spec.rb +2 -0
  226. data/spec/grape/util/reverse_stackable_values_spec.rb +2 -0
  227. data/spec/grape/util/stackable_values_spec.rb +3 -1
  228. data/spec/grape/util/strict_hash_configuration_spec.rb +2 -0
  229. data/spec/grape/validations/attributes_iterator_spec.rb +2 -0
  230. data/spec/grape/validations/instance_behaivour_spec.rb +5 -3
  231. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +41 -0
  232. data/spec/grape/validations/params_scope_spec.rb +213 -9
  233. data/spec/grape/validations/single_attribute_iterator_spec.rb +58 -0
  234. data/spec/grape/validations/types/array_coercer_spec.rb +35 -0
  235. data/spec/grape/validations/types/primitive_coercer_spec.rb +135 -0
  236. data/spec/grape/validations/types/set_coercer_spec.rb +34 -0
  237. data/spec/grape/validations/types_spec.rb +9 -36
  238. data/spec/grape/validations/validators/all_or_none_spec.rb +140 -30
  239. data/spec/grape/validations/validators/allow_blank_spec.rb +2 -0
  240. data/spec/grape/validations/validators/at_least_one_of_spec.rb +175 -29
  241. data/spec/grape/validations/validators/coerce_spec.rb +476 -135
  242. data/spec/grape/validations/validators/default_spec.rb +172 -0
  243. data/spec/grape/validations/validators/exactly_one_of_spec.rb +204 -38
  244. data/spec/grape/validations/validators/except_values_spec.rb +4 -1
  245. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +186 -27
  246. data/spec/grape/validations/validators/presence_spec.rb +30 -0
  247. data/spec/grape/validations/validators/regexp_spec.rb +2 -0
  248. data/spec/grape/validations/validators/same_as_spec.rb +65 -0
  249. data/spec/grape/validations/validators/values_spec.rb +30 -5
  250. data/spec/grape/validations_spec.rb +388 -50
  251. data/spec/integration/eager_load/eager_load_spec.rb +15 -0
  252. data/spec/integration/multi_json/json_spec.rb +2 -0
  253. data/spec/integration/multi_xml/xml_spec.rb +2 -0
  254. data/spec/shared/versioning_examples.rb +22 -20
  255. data/spec/spec_helper.rb +12 -1
  256. data/spec/support/basic_auth_encode_helpers.rb +2 -0
  257. data/spec/support/chunks.rb +14 -0
  258. data/spec/support/content_type_helpers.rb +2 -0
  259. data/spec/support/eager_load.rb +19 -0
  260. data/spec/support/endpoint_faker.rb +2 -0
  261. data/spec/support/file_streamer.rb +2 -0
  262. data/spec/support/integer_helpers.rb +2 -0
  263. data/spec/support/versioned_helpers.rb +8 -8
  264. metadata +86 -48
  265. data/Appraisals +0 -32
  266. data/Dangerfile +0 -2
  267. data/Gemfile +0 -33
  268. data/Gemfile.lock +0 -231
  269. data/Guardfile +0 -10
  270. data/RELEASING.md +0 -111
  271. data/Rakefile +0 -25
  272. data/benchmark/simple.rb +0 -27
  273. data/benchmark/simple_with_type_coercer.rb +0 -22
  274. data/gemfiles/multi_json.gemfile +0 -35
  275. data/gemfiles/multi_xml.gemfile +0 -35
  276. data/gemfiles/rack_1.5.2.gemfile +0 -35
  277. data/gemfiles/rack_edge.gemfile +0 -35
  278. data/gemfiles/rails_3.gemfile +0 -36
  279. data/gemfiles/rails_4.gemfile +0 -35
  280. data/gemfiles/rails_5.gemfile +0 -35
  281. data/gemfiles/rails_edge.gemfile +0 -35
  282. data/lib/grape/extensions/deep_hash_with_indifferent_access.rb +0 -18
  283. data/lib/grape/util/content_types.rb +0 -26
  284. data/lib/grape/validations/types/virtus_collection_patch.rb +0 -16
  285. data/pkg/grape-0.17.0.gem +0 -0
  286. data/pkg/grape-0.19.0.gem +0 -0
@@ -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
@@ -128,7 +130,7 @@ describe Grape::Middleware::Error do
128
130
  subject do
129
131
  Rack::Builder.app do
130
132
  use Spec::Support::EndpointFaker
131
- use Grape::Middleware::Error, rescue_handlers: { NotImplementedError => -> { [200, {}, 'rescued'] } }
133
+ use Grape::Middleware::Error, rescue_handlers: { NotImplementedError => -> { Rack::Response.new('rescued', 200, {}) } }
132
134
  run ExceptionSpec::OtherExceptionApp
133
135
  end
134
136
  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,26 +196,32 @@ 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
 
213
215
  context 'no content responses' do
214
216
  let(:no_content_response) { ->(status) { [status, {}, ['']] } }
215
217
 
216
- Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.each do |status|
218
+ STATUSES_WITHOUT_BODY = if Gem::Version.new(Rack.release) >= Gem::Version.new('2.1.0')
219
+ Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.keys
220
+ else
221
+ Rack::Utils::STATUS_WITH_NO_ENTITY_BODY
222
+ end
223
+
224
+ STATUSES_WITHOUT_BODY.each do |status|
217
225
  it "does not modify a #{status} response" do
218
226
  expected_response = no_content_response[status]
219
227
  allow(app).to receive(:call).and_return(expected_response)
@@ -247,7 +255,7 @@ describe Grape::Middleware::Formatter do
247
255
  let(:content_type) { 'application/atom+xml' }
248
256
 
249
257
  it 'returns a 415 HTTP error status' do
250
- error = catch(:error) {
258
+ error = catch(:error) do
251
259
  subject.call(
252
260
  'PATH_INFO' => '/info',
253
261
  'REQUEST_METHOD' => method,
@@ -255,7 +263,7 @@ describe Grape::Middleware::Formatter do
255
263
  'rack.input' => io,
256
264
  'CONTENT_LENGTH' => io.length
257
265
  )
258
- }
266
+ end
259
267
  expect(error[:status]).to eq(415)
260
268
  expect(error[:message]).to eq("The provided content-type 'application/atom+xml' is not supported.")
261
269
  end
@@ -371,12 +379,17 @@ describe Grape::Middleware::Formatter do
371
379
  end
372
380
 
373
381
  context 'send file' do
374
- let(:body) { Grape::ServeFile::FileResponse.new('file') }
375
- let(:app) { ->(_env) { [200, {}, body] } }
382
+ let(:file) { double(File) }
383
+ let(:file_body) { Grape::ServeStream::StreamResponse.new(file) }
384
+ let(:app) { ->(_env) { [200, {}, file_body] } }
376
385
 
377
- it 'returns Grape::Uril::SendFileReponse' do
386
+ it 'returns a file response' do
387
+ expect(file).to receive(:each).and_yield('data')
378
388
  env = { 'PATH_INFO' => '/somewhere', 'HTTP_ACCEPT' => 'application/json' }
379
- 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']
380
393
  end
381
394
  end
382
395
 
@@ -389,13 +402,17 @@ describe Grape::Middleware::Formatter do
389
402
  let(:app) { ->(_env) { [200, {}, ['']] } }
390
403
  before do
391
404
  Grape::Formatter.register :invalid, InvalidFormatter
392
- Grape::ContentTypes::CONTENT_TYPES[:invalid] = 'application/x-invalid'
405
+ Grape::ContentTypes.register :invalid, 'application/x-invalid'
406
+ end
407
+ after do
408
+ Grape::ContentTypes.default_elements.delete(:invalid)
409
+ Grape::Formatter.default_elements.delete(:invalid)
393
410
  end
394
411
 
395
412
  it 'returns response by invalid formatter' do
396
413
  env = { 'PATH_INFO' => '/hello.invalid', 'HTTP_ACCEPT' => 'application/x-invalid' }
397
- _, _, bodies = *subject.call(env)
398
- 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)
399
416
  end
400
417
  end
401
418
 
@@ -407,7 +424,7 @@ describe Grape::Middleware::Formatter do
407
424
  parsers: { json: ->(_object, _env) { raise StandardError, 'fail' } }
408
425
  )
409
426
  io = StringIO.new('{invalid}')
410
- error = catch(:error) {
427
+ error = catch(:error) do
411
428
  subject.call(
412
429
  'PATH_INFO' => '/info',
413
430
  'REQUEST_METHOD' => 'POST',
@@ -415,7 +432,7 @@ describe Grape::Middleware::Formatter do
415
432
  'rack.input' => io,
416
433
  'CONTENT_LENGTH' => io.length
417
434
  )
418
- }
435
+ end
419
436
 
420
437
  expect(error[:message]).to eq 'fail'
421
438
  expect(error[:backtrace].size).to be >= 1
@@ -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
@@ -6,6 +8,7 @@ describe Grape::Middleware::Stack do
6
8
  class BarMiddleware; end
7
9
  class BlockMiddleware
8
10
  attr_reader :block
11
+
9
12
  def initialize(&block)
10
13
  @block = block
11
14
  end
@@ -109,6 +112,15 @@ describe Grape::Middleware::Stack do
109
112
  expect(subject[1]).to eq(StackSpec::BlockMiddleware)
110
113
  expect(subject[2]).to eq(StackSpec::BarMiddleware)
111
114
  end
115
+
116
+ context 'middleware spec with proc declaration exists' do
117
+ let(:middleware_spec_with_proc) { [:use, StackSpec::FooMiddleware, proc] }
118
+
119
+ it 'properly forwards spec arguments' do
120
+ expect(subject).to receive(:use).with(StackSpec::FooMiddleware)
121
+ subject.merge_with([middleware_spec_with_proc])
122
+ end
123
+ end
112
124
  end
113
125
 
114
126
  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 = {
@@ -160,6 +162,12 @@ describe Grape::Middleware::Versioner::Header do
160
162
  expect(subject.call({}).first).to eq(200)
161
163
  end
162
164
 
165
+ it 'succeeds if :strict is set to false and given an invalid header' do
166
+ @options[:version_options][:strict] = false
167
+ expect(subject.call('HTTP_ACCEPT' => 'yaml').first).to eq(200)
168
+ expect(subject.call({}).first).to eq(200)
169
+ end
170
+
163
171
  context 'when :strict is set' do
164
172
  before do
165
173
  @options[:versions] = ['v1']
@@ -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
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'A named API' do
6
+ subject(:api_name) { NamedAPI.endpoints.last.options[:for].to_s }
7
+
8
+ let(:api) do
9
+ Class.new(Grape::API) do
10
+ get 'test' do
11
+ 'response'
12
+ end
13
+ end
14
+ end
15
+
16
+ before { stub_const('NamedAPI', api) }
17
+
18
+ it 'can access the name of the API' do
19
+ expect(api_name).to eq 'NamedAPI'
20
+ end
21
+ end
@@ -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
@@ -85,12 +87,12 @@ module Grape
85
87
  describe '#namespace?' do
86
88
  it 'is false when the namespace is nil' do
87
89
  path = Path.new(anything, nil, anything)
88
- expect(path.namespace?).to be nil
90
+ expect(path.namespace?).to be_falsey
89
91
  end
90
92
 
91
93
  it 'is false when the namespace starts with whitespace' do
92
94
  path = Path.new(anything, ' /foo', anything)
93
- expect(path.namespace?).to be nil
95
+ expect(path.namespace?).to be_falsey
94
96
  end
95
97
 
96
98
  it 'is false when the namespace is the root path' do
@@ -107,12 +109,12 @@ module Grape
107
109
  describe '#path?' do
108
110
  it 'is false when the path is nil' do
109
111
  path = Path.new(nil, anything, anything)
110
- expect(path.path?).to be nil
112
+ expect(path.path?).to be_falsey
111
113
  end
112
114
 
113
115
  it 'is false when the path starts with whitespace' do
114
116
  path = Path.new(' /foo', anything, anything)
115
- expect(path.path?).to be nil
117
+ expect(path.path?).to be_falsey
116
118
  end
117
119
 
118
120
  it 'is false when the path is the root path' 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
@@ -62,6 +64,30 @@ module Grape
62
64
  end
63
65
  end
64
66
 
67
+ describe 'when the param_builder is set to Hashie' do
68
+ before do
69
+ Grape.configure do |config|
70
+ config.param_builder = Grape::Extensions::Hashie::Mash::ParamBuilder
71
+ end
72
+ end
73
+
74
+ after do
75
+ Grape.config.reset
76
+ end
77
+
78
+ subject(:request_params) { Grape::Request.new(env, **opts).params }
79
+
80
+ context 'when the API does not include a specific param builder' do
81
+ let(:opts) { {} }
82
+ it { is_expected.to be_a(Hashie::Mash) }
83
+ end
84
+
85
+ context 'when the API includes a specific param builder' do
86
+ let(:opts) { { build_params_with: Grape::Extensions::Hash::ParamBuilder } }
87
+ it { is_expected.to be_a(Hash) }
88
+ end
89
+ end
90
+
65
91
  describe '#headers' do
66
92
  let(:options) do
67
93
  default_options.merge(request_headers)
@@ -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