grape 1.1.0 → 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Grape
4
+ module Validations
5
+ class SameAsValidator < Base
6
+ def validate_param!(attr_name, params)
7
+ confirmation = options_key?(:value) ? @option[:value] : @option
8
+ return if params[attr_name] == params[confirmation]
9
+ raise Grape::Exceptions::Validation.new(
10
+ params: [@scope.full_name(attr_name)],
11
+ message: build_message
12
+ )
13
+ end
14
+
15
+ private
16
+
17
+ def build_message
18
+ if options_key?(:message)
19
+ @option[:message]
20
+ else
21
+ format I18n.t(:same_as, scope: 'grape.errors.messages'), parameter: @option
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  module Validations
3
5
  class ValuesValidator < Base
4
- def initialize(attrs, options, required, scope, opts = {})
6
+ def initialize(attrs, options, required, scope, **opts)
5
7
  if options.is_a?(Hash)
6
8
  @excepts = options[:except]
7
9
  @values = options[:value]
@@ -24,17 +26,23 @@ module Grape
24
26
 
25
27
  def validate_param!(attr_name, params)
26
28
  return unless params.is_a?(Hash)
27
- return unless params[attr_name] || required_for_root_scope?
28
29
 
29
- param_array = params[attr_name].nil? ? [nil] : Array.wrap(params[attr_name])
30
+ val = params[attr_name]
31
+
32
+ return if val.nil? && !required_for_root_scope?
33
+
34
+ # don't forget that +false.blank?+ is true
35
+ return if val != false && val.blank? && @allow_blank
30
36
 
31
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: except_message \
37
+ param_array = val.nil? ? [nil] : Array.wrap(val)
38
+
39
+ raise validation_exception(attr_name, except_message) \
32
40
  unless check_excepts(param_array)
33
41
 
34
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: message(:values) \
42
+ raise validation_exception(attr_name, message(:values)) \
35
43
  unless check_values(param_array, attr_name)
36
44
 
37
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: message(:values) \
45
+ raise validation_exception(attr_name, message(:values)) \
38
46
  if @proc && !param_array.all? { |param| @proc.call(param) }
39
47
  end
40
48
 
@@ -66,6 +74,10 @@ module Grape
66
74
  def required_for_root_scope?
67
75
  @required && @scope.root?
68
76
  end
77
+
78
+ def validation_exception(attr_name, message)
79
+ Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message)
80
+ end
69
81
  end
70
82
  end
71
83
  end
data/lib/grape/version.rb CHANGED
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Grape
2
4
  # The current version of Grape.
3
- VERSION = '1.1.0'.freeze
5
+ VERSION = '1.5.3'
4
6
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Validations do
@@ -8,7 +10,7 @@ describe Grape::Validations do
8
10
  def validate_param!(attr_name, params)
9
11
  @option = params[:max].to_i if params.key?(:max)
10
12
  return if params[attr_name].length <= @option
11
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: "must be at the most #{@option} characters long"
13
+ raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: "must be at the most #{@option} characters long")
12
14
  end
13
15
  end
14
16
  end
@@ -87,7 +89,7 @@ describe Grape::Validations do
87
89
  module CustomValidationsSpec
88
90
  class WithMessageKey < Grape::Validations::PresenceValidator
89
91
  def validate_param!(attr_name, _params)
90
- raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: :presence
92
+ raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: :presence)
91
93
  end
92
94
  end
93
95
  end
@@ -126,7 +128,7 @@ describe Grape::Validations do
126
128
  return unless @option
127
129
  # check if user is admin or not
128
130
  # as an example get a token from request and check if it's admin or not
129
- raise Grape::Exceptions::Validation, params: @attrs, message: 'Can not set Admin only field.' unless request.headers['X-Access-Token'] == 'admin'
131
+ raise Grape::Exceptions::Validation.new(params: @attrs, message: 'Can not set Admin only field.') unless request.headers['X-Access-Token'] == 'admin'
130
132
  end
131
133
  end
132
134
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  module DeeplyIncludedOptionsSpec
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Grape::API::Instance do
6
+ describe 'boolean constant' do
7
+ module DefinesBooleanInstanceSpec
8
+ class API < Grape::API
9
+ params do
10
+ requires :message, type: Boolean
11
+ end
12
+ post :echo do
13
+ { class: params[:message].class.name, value: params[:message] }
14
+ end
15
+ end
16
+ end
17
+
18
+ def app
19
+ DefinesBooleanInstanceSpec::API
20
+ end
21
+
22
+ let(:expected_body) do
23
+ { class: 'TrueClass', value: true }.to_s
24
+ end
25
+
26
+ it 'sets Boolean as a type' do
27
+ post '/echo?message=true'
28
+ expect(last_response.status).to eq(201)
29
+ expect(last_response.body).to eq expected_body
30
+ end
31
+
32
+ context 'Params endpoint type' do
33
+ subject { DefinesBooleanInstanceSpec::API.new.router.map['POST'].first.options[:params]['message'][:type] }
34
+ it 'params type is a boolean' do
35
+ is_expected.to eq 'Grape::API::Boolean'
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::API::Helpers do
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'shared/versioning_examples'
5
+
6
+ describe Grape::API::Instance do
7
+ subject(:an_instance) do
8
+ Class.new(Grape::API::Instance) do
9
+ namespace :some_namespace do
10
+ get 'some_endpoint' do
11
+ 'success'
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ let(:root_api) do
18
+ to_mount = an_instance
19
+ Class.new(Grape::API) do
20
+ mount to_mount
21
+ end
22
+ end
23
+
24
+ def app
25
+ root_api
26
+ end
27
+
28
+ context 'when an instance is mounted on the root' do
29
+ it 'can call the instance endpoint' do
30
+ get '/some_namespace/some_endpoint'
31
+ expect(last_response.body).to eq 'success'
32
+ end
33
+ end
34
+
35
+ context 'when an instance is the root' do
36
+ let(:root_api) do
37
+ to_mount = an_instance
38
+ Class.new(Grape::API::Instance) do
39
+ mount to_mount
40
+ end
41
+ end
42
+
43
+ it 'can call the instance endpoint' do
44
+ get '/some_namespace/some_endpoint'
45
+ expect(last_response.body).to eq 'success'
46
+ end
47
+ end
48
+
49
+ context 'top level setting' do
50
+ it 'does not inherit settings from the superclass (Grape::API::Instance)' do
51
+ expect(an_instance.top_level_setting.parent).to be_nil
52
+ end
53
+ end
54
+
55
+ context 'with multiple moutes' do
56
+ let(:first) do
57
+ Class.new(Grape::API::Instance) do
58
+ namespace(:some_namespace) do
59
+ route :any, '*path' do
60
+ error!('Not found! (1)', 404)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ let(:second) do
66
+ Class.new(Grape::API::Instance) do
67
+ namespace(:another_namespace) do
68
+ route :any, '*path' do
69
+ error!('Not found! (2)', 404)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ let(:root_api) do
75
+ first_instance = first
76
+ second_instance = second
77
+ Class.new(Grape::API) do
78
+ mount first_instance
79
+ mount first_instance
80
+ mount second_instance
81
+ end
82
+ end
83
+
84
+ it 'does not raise a FrozenError on first instance' do
85
+ expect { patch '/some_namespace/anything' }.not_to \
86
+ raise_error
87
+ end
88
+
89
+ it 'responds the correct body at the first instance' do
90
+ patch '/some_namespace/anything'
91
+ expect(last_response.body).to eq 'Not found! (1)'
92
+ end
93
+
94
+ it 'does not raise a FrozenError on second instance' do
95
+ expect { get '/another_namespace/other' }.not_to \
96
+ raise_error
97
+ end
98
+
99
+ it 'responds the correct body at the second instance' do
100
+ get '/another_namespace/foobar'
101
+ expect(last_response.body).to eq 'Not found! (2)'
102
+ end
103
+ end
104
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Endpoint do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Endpoint do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::API::Helpers do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Endpoint do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Endpoint do
@@ -10,7 +12,7 @@ describe Grape::Endpoint do
10
12
  before do
11
13
  subject.namespace :test do
12
14
  params do
13
- optional :foo, default: '-abcdef'
15
+ optional :foo, default: +'-abcdef'
14
16
  end
15
17
  get do
16
18
  params[:foo].slice!(0)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::API::Helpers do
@@ -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
 
3
5
  describe Grape::Endpoint do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::Endpoint do
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Grape::Endpoint do
6
+ subject { Class.new(Grape::API) }
7
+
8
+ def app
9
+ subject
10
+ end
11
+
12
+ context 'get' do
13
+ it 'routes to a namespace param with dots' do
14
+ subject.namespace ':ns_with_dots', requirements: { ns_with_dots: %r{[^\/]+} } do
15
+ get '/' do
16
+ params[:ns_with_dots]
17
+ end
18
+ end
19
+
20
+ get '/test.id.with.dots'
21
+ expect(last_response.status).to eq 200
22
+ expect(last_response.body).to eq 'test.id.with.dots'
23
+ end
24
+
25
+ it 'routes to a path with multiple params with dots' do
26
+ subject.get ':id_with_dots/:another_id_with_dots', requirements: { id_with_dots: %r{[^\/]+},
27
+ another_id_with_dots: %r{[^\/]+} } do
28
+ "#{params[:id_with_dots]}/#{params[:another_id_with_dots]}"
29
+ end
30
+
31
+ get '/test.id/test2.id'
32
+ expect(last_response.status).to eq 200
33
+ expect(last_response.body).to eq 'test.id/test2.id'
34
+ end
35
+
36
+ it 'routes to namespace and path params with dots, with overridden requirements' do
37
+ subject.namespace ':ns_with_dots', requirements: { ns_with_dots: %r{[^\/]+} } do
38
+ get ':another_id_with_dots', requirements: { ns_with_dots: %r{[^\/]+},
39
+ another_id_with_dots: %r{[^\/]+} } do
40
+ "#{params[:ns_with_dots]}/#{params[:another_id_with_dots]}"
41
+ end
42
+ end
43
+
44
+ get '/test.id/test2.id'
45
+ expect(last_response.status).to eq 200
46
+ expect(last_response.body).to eq 'test.id/test2.id'
47
+ end
48
+
49
+ it 'routes to namespace and path params with dots, with merged requirements' do
50
+ subject.namespace ':ns_with_dots', requirements: { ns_with_dots: %r{[^\/]+} } do
51
+ get ':another_id_with_dots', requirements: { another_id_with_dots: %r{[^\/]+} } do
52
+ "#{params[:ns_with_dots]}/#{params[:another_id_with_dots]}"
53
+ end
54
+ end
55
+
56
+ get '/test.id/test2.id'
57
+ expect(last_response.status).to eq 200
58
+ expect(last_response.body).to eq 'test.id/test2.id'
59
+ end
60
+ end
61
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::API::Helpers do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Grape::API::Helpers do
@@ -0,0 +1,473 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'shared/versioning_examples'
5
+
6
+ describe Grape::API do
7
+ subject(:a_remounted_api) { Class.new(Grape::API) }
8
+ let(:root_api) { Class.new(Grape::API) }
9
+
10
+ def app
11
+ root_api
12
+ end
13
+
14
+ describe 'remounting an API' do
15
+ context 'with a defined route' do
16
+ before do
17
+ a_remounted_api.get '/votes' do
18
+ '10 votes'
19
+ end
20
+ end
21
+
22
+ context 'when mounting one instance' do
23
+ before do
24
+ root_api.mount a_remounted_api
25
+ end
26
+
27
+ it 'can access the endpoint' do
28
+ get '/votes'
29
+ expect(last_response.body).to eql '10 votes'
30
+ end
31
+ end
32
+
33
+ context 'when mounting twice' do
34
+ before do
35
+ root_api.mount a_remounted_api => '/posts'
36
+ root_api.mount a_remounted_api => '/comments'
37
+ end
38
+
39
+ it 'can access the votes in both places' do
40
+ get '/posts/votes'
41
+ expect(last_response.body).to eql '10 votes'
42
+ get '/comments/votes'
43
+ expect(last_response.body).to eql '10 votes'
44
+ end
45
+ end
46
+
47
+ context 'when mounting on namespace' do
48
+ before do
49
+ stub_const('StaticRefToAPI', a_remounted_api)
50
+ root_api.namespace 'posts' do
51
+ mount StaticRefToAPI
52
+ end
53
+
54
+ root_api.namespace 'comments' do
55
+ mount StaticRefToAPI
56
+ end
57
+ end
58
+
59
+ it 'can access the votes in both places' do
60
+ get '/posts/votes'
61
+ expect(last_response.body).to eql '10 votes'
62
+ get '/comments/votes'
63
+ expect(last_response.body).to eql '10 votes'
64
+ end
65
+ end
66
+ end
67
+
68
+ describe 'with dynamic configuration' do
69
+ context 'when mounting an endpoint conditional on a configuration' do
70
+ subject(:a_remounted_api) do
71
+ Class.new(Grape::API) do
72
+ get 'always' do
73
+ 'success'
74
+ end
75
+
76
+ given configuration[:mount_sometimes] do
77
+ get 'sometimes' do
78
+ 'sometimes'
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ it 'mounts the endpoints only when configured to do so' do
85
+ root_api.mount({ a_remounted_api => 'with_conditional' }, with: { mount_sometimes: true })
86
+ root_api.mount({ a_remounted_api => 'without_conditional' }, with: { mount_sometimes: false })
87
+
88
+ get '/with_conditional/always'
89
+ expect(last_response.body).to eq 'success'
90
+
91
+ get '/with_conditional/sometimes'
92
+ expect(last_response.body).to eq 'sometimes'
93
+
94
+ get '/without_conditional/always'
95
+ expect(last_response.body).to eq 'success'
96
+
97
+ get '/without_conditional/sometimes'
98
+ expect(last_response.status).to eq 404
99
+ end
100
+ end
101
+
102
+ context 'when using an expression derived from a configuration' do
103
+ subject(:a_remounted_api) do
104
+ Class.new(Grape::API) do
105
+ get(mounted { "api_name_#{configuration[:api_name]}" }) do
106
+ 'success'
107
+ end
108
+ end
109
+ end
110
+
111
+ before do
112
+ root_api.mount a_remounted_api, with: {
113
+ api_name: 'a_name'
114
+ }
115
+ end
116
+
117
+ it 'mounts the endpoint with the name' do
118
+ get 'api_name_a_name'
119
+ expect(last_response.body).to eq 'success'
120
+ end
121
+
122
+ it 'does not mount the endpoint with a null name' do
123
+ get 'api_name_'
124
+ expect(last_response.body).not_to eq 'success'
125
+ end
126
+
127
+ context 'when the expression lives in a namespace' do
128
+ subject(:a_remounted_api) do
129
+ Class.new(Grape::API) do
130
+ namespace :base do
131
+ get(mounted { "api_name_#{configuration[:api_name]}" }) do
132
+ 'success'
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ it 'mounts the endpoint with the name' do
139
+ get 'base/api_name_a_name'
140
+ expect(last_response.body).to eq 'success'
141
+ end
142
+
143
+ it 'does not mount the endpoint with a null name' do
144
+ get 'base/api_name_'
145
+ expect(last_response.body).not_to eq 'success'
146
+ end
147
+ end
148
+ end
149
+
150
+ context 'when executing a standard block within a `mounted` block with all dynamic params' do
151
+ subject(:a_remounted_api) do
152
+ Class.new(Grape::API) do
153
+ mounted do
154
+ desc configuration[:description] do
155
+ headers configuration[:headers]
156
+ end
157
+ get configuration[:endpoint] do
158
+ configuration[:response]
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ let(:api_endpoint) { 'custom_endpoint' }
165
+ let(:api_response) { 'custom response' }
166
+ let(:endpoint_description) { 'this is a custom API' }
167
+ let(:headers) do
168
+ {
169
+ 'XAuthToken' => {
170
+ 'description' => 'Validates your identity',
171
+ 'required' => true
172
+ }
173
+ }
174
+ end
175
+
176
+ it 'mounts the API and obtains the description and headers definition' do
177
+ root_api.mount a_remounted_api, with: {
178
+ description: endpoint_description,
179
+ headers: headers,
180
+ endpoint: api_endpoint,
181
+ response: api_response
182
+ }
183
+ get api_endpoint
184
+ expect(last_response.body).to eq api_response
185
+ expect(a_remounted_api.instances.last.endpoints.first.options[:route_options][:description])
186
+ .to eq endpoint_description
187
+ expect(a_remounted_api.instances.last.endpoints.first.options[:route_options][:headers])
188
+ .to eq headers
189
+ end
190
+ end
191
+
192
+ context 'when executing a custom block on mount' do
193
+ subject(:a_remounted_api) do
194
+ Class.new(Grape::API) do
195
+ get 'always' do
196
+ 'success'
197
+ end
198
+
199
+ mounted do
200
+ configuration[:endpoints].each do |endpoint_name, endpoint_response|
201
+ get endpoint_name do
202
+ endpoint_response
203
+ end
204
+ end
205
+ end
206
+ end
207
+ end
208
+
209
+ it 'mounts the endpoints only when configured to do so' do
210
+ root_api.mount a_remounted_api, with: { endpoints: { 'api_name' => 'api_response' } }
211
+ get 'api_name'
212
+ expect(last_response.body).to eq 'api_response'
213
+ end
214
+ end
215
+
216
+ context 'when the configuration is part of the arguments of a method' do
217
+ subject(:a_remounted_api) do
218
+ Class.new(Grape::API) do
219
+ get configuration[:endpoint_name] do
220
+ 'success'
221
+ end
222
+ end
223
+ end
224
+
225
+ it 'mounts the endpoint in the location it is configured' do
226
+ root_api.mount a_remounted_api, with: { endpoint_name: 'some_location' }
227
+ get '/some_location'
228
+ expect(last_response.body).to eq 'success'
229
+
230
+ get '/different_location'
231
+ expect(last_response.status).to eq 404
232
+
233
+ root_api.mount a_remounted_api, with: { endpoint_name: 'new_location' }
234
+ get '/new_location'
235
+ expect(last_response.body).to eq 'success'
236
+ end
237
+
238
+ context 'when the configuration is the value in a key-arg pair' do
239
+ subject(:a_remounted_api) do
240
+ Class.new(Grape::API) do
241
+ version 'v1', using: :param, parameter: configuration[:version_param]
242
+ get 'endpoint' do
243
+ 'version 1'
244
+ end
245
+
246
+ version 'v2', using: :param, parameter: configuration[:version_param]
247
+ get 'endpoint' do
248
+ 'version 2'
249
+ end
250
+ end
251
+ end
252
+
253
+ it 'takes the param from the configuration' do
254
+ root_api.mount a_remounted_api, with: { version_param: 'param_name' }
255
+
256
+ get '/endpoint?param_name=v1'
257
+ expect(last_response.body).to eq 'version 1'
258
+
259
+ get '/endpoint?param_name=v2'
260
+ expect(last_response.body).to eq 'version 2'
261
+
262
+ get '/endpoint?wrong_param_name=v2'
263
+ expect(last_response.body).to eq 'version 1'
264
+ end
265
+ end
266
+ end
267
+
268
+ context 'on the DescSCope' do
269
+ subject(:a_remounted_api) do
270
+ Class.new(Grape::API) do
271
+ desc 'The description of this' do
272
+ tags ['not_configurable_tag', configuration[:a_configurable_tag]]
273
+ end
274
+ get 'location' do
275
+ 'success'
276
+ end
277
+ end
278
+ end
279
+
280
+ it 'mounts the endpoint with the appropiate tags' do
281
+ root_api.mount({ a_remounted_api => 'integer' }, with: { a_configurable_tag: 'a configured tag' })
282
+ end
283
+ end
284
+
285
+ context 'on the ParamScope' do
286
+ subject(:a_remounted_api) do
287
+ Class.new(Grape::API) do
288
+ params do
289
+ requires configuration[:required_param], type: configuration[:required_type]
290
+ end
291
+
292
+ get 'location' do
293
+ 'success'
294
+ end
295
+ end
296
+ end
297
+
298
+ it 'mounts the endpoint in the location it is configured' do
299
+ root_api.mount({ a_remounted_api => 'string' }, with: { required_param: 'param_key', required_type: String })
300
+ root_api.mount({ a_remounted_api => 'integer' }, with: { required_param: 'param_integer', required_type: Integer })
301
+
302
+ get '/string/location', param_key: 'a'
303
+ expect(last_response.body).to eq 'success'
304
+
305
+ get '/string/location', param_integer: 1
306
+ expect(last_response.status).to eq 400
307
+
308
+ get '/integer/location', param_integer: 1
309
+ expect(last_response.body).to eq 'success'
310
+
311
+ get '/integer/location', param_integer: 'a'
312
+ expect(last_response.status).to eq 400
313
+ end
314
+
315
+ context 'on dynamic checks' do
316
+ subject(:a_remounted_api) do
317
+ Class.new(Grape::API) do
318
+ params do
319
+ optional :restricted_values, values: -> { [configuration[:allowed_value], 'always'] }
320
+ end
321
+
322
+ get 'location' do
323
+ 'success'
324
+ end
325
+ end
326
+ end
327
+
328
+ it 'can read the configuration on lambdas' do
329
+ root_api.mount a_remounted_api, with: { allowed_value: 'sometimes' }
330
+ get '/location', restricted_values: 'always'
331
+ expect(last_response.body).to eq 'success'
332
+ get '/location', restricted_values: 'sometimes'
333
+ expect(last_response.body).to eq 'success'
334
+ get '/location', restricted_values: 'never'
335
+ expect(last_response.status).to eq 400
336
+ end
337
+ end
338
+ end
339
+
340
+ context 'when the configuration is read within a namespace' do
341
+ before do
342
+ a_remounted_api.namespace 'api' do
343
+ params do
344
+ requires configuration[:required_param]
345
+ end
346
+ get "/#{configuration[:path]}" do
347
+ '10 votes'
348
+ end
349
+ end
350
+ root_api.mount a_remounted_api, with: { path: 'votes', required_param: 'param_key' }
351
+ root_api.mount a_remounted_api, with: { path: 'scores', required_param: 'param_key' }
352
+ end
353
+
354
+ it 'will use the dynamic configuration on all routes' do
355
+ get 'api/votes', param_key: 'a'
356
+ expect(last_response.body).to eql '10 votes'
357
+ get 'api/scores', param_key: 'a'
358
+ expect(last_response.body).to eql '10 votes'
359
+ get 'api/votes'
360
+ expect(last_response.status).to eq 400
361
+ end
362
+ end
363
+
364
+ context 'a very complex configuration example' do
365
+ before do
366
+ top_level_api = Class.new(Grape::API) do
367
+ remounted_api = Class.new(Grape::API) do
368
+ get configuration[:endpoint_name] do
369
+ configuration[:response]
370
+ end
371
+ end
372
+
373
+ expression_namespace = mounted { configuration[:namespace].to_s * 2 }
374
+ given(mounted { configuration[:should_mount_expressed] != false }) do
375
+ namespace expression_namespace do
376
+ mount remounted_api, with: { endpoint_name: configuration[:endpoint_name], response: configuration[:endpoint_response] }
377
+ end
378
+ end
379
+ end
380
+ root_api.mount top_level_api, with: configuration_options
381
+ end
382
+
383
+ context 'when the namespace should be mounted' do
384
+ let(:configuration_options) do
385
+ {
386
+ should_mount_expressed: true,
387
+ namespace: 'bang',
388
+ endpoint_name: 'james',
389
+ endpoint_response: 'bond'
390
+ }
391
+ end
392
+
393
+ it 'gets a response' do
394
+ get 'bangbang/james'
395
+ expect(last_response.body).to eq 'bond'
396
+ end
397
+ end
398
+
399
+ context 'when should be mounted is nil' do
400
+ let(:configuration_options) do
401
+ {
402
+ should_mount_expressed: nil,
403
+ namespace: 'bang',
404
+ endpoint_name: 'james',
405
+ endpoint_response: 'bond'
406
+ }
407
+ end
408
+
409
+ it 'gets a response' do
410
+ get 'bangbang/james'
411
+ expect(last_response.body).to eq 'bond'
412
+ end
413
+ end
414
+
415
+ context 'when it should not be mounted' do
416
+ let(:configuration_options) do
417
+ {
418
+ should_mount_expressed: false,
419
+ namespace: 'bang',
420
+ endpoint_name: 'james',
421
+ endpoint_response: 'bond'
422
+ }
423
+ end
424
+
425
+ it 'gets a response' do
426
+ get 'bangbang/james'
427
+ expect(last_response.body).not_to eq 'bond'
428
+ end
429
+ end
430
+ end
431
+
432
+ context 'when the configuration is read in a helper' do
433
+ subject(:a_remounted_api) do
434
+ Class.new(Grape::API) do
435
+ helpers do
436
+ def printed_response
437
+ configuration[:some_value]
438
+ end
439
+ end
440
+
441
+ get 'location' do
442
+ printed_response
443
+ end
444
+ end
445
+ end
446
+
447
+ it 'will use the dynamic configuration on all routes' do
448
+ root_api.mount(a_remounted_api, with: { some_value: 'response value' })
449
+
450
+ get '/location'
451
+ expect(last_response.body).to eq 'response value'
452
+ end
453
+ end
454
+
455
+ context 'when the configuration is read within the response block' do
456
+ subject(:a_remounted_api) do
457
+ Class.new(Grape::API) do
458
+ get 'location' do
459
+ configuration[:some_value]
460
+ end
461
+ end
462
+ end
463
+
464
+ it 'will use the dynamic configuration on all routes' do
465
+ root_api.mount(a_remounted_api, with: { some_value: 'response value' })
466
+
467
+ get '/location'
468
+ expect(last_response.body).to eq 'response value'
469
+ end
470
+ end
471
+ end
472
+ end
473
+ end