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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +278 -44
- data/LICENSE +1 -1
- data/README.md +514 -69
- data/UPGRADING.md +424 -17
- data/grape.gemspec +13 -2
- data/lib/grape.rb +104 -71
- data/lib/grape/api.rb +138 -175
- data/lib/grape/api/helpers.rb +2 -0
- data/lib/grape/api/instance.rb +283 -0
- data/lib/grape/config.rb +34 -0
- data/lib/grape/content_types.rb +34 -0
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dsl/api.rb +2 -0
- data/lib/grape/dsl/callbacks.rb +22 -0
- data/lib/grape/dsl/configuration.rb +2 -0
- data/lib/grape/dsl/desc.rb +41 -7
- data/lib/grape/dsl/headers.rb +2 -0
- data/lib/grape/dsl/helpers.rb +5 -2
- data/lib/grape/dsl/inside_route.rb +92 -49
- data/lib/grape/dsl/logger.rb +2 -0
- data/lib/grape/dsl/middleware.rb +9 -0
- data/lib/grape/dsl/parameters.rb +25 -14
- data/lib/grape/dsl/request_response.rb +4 -2
- data/lib/grape/dsl/routing.rb +17 -10
- data/lib/grape/dsl/settings.rb +7 -1
- data/lib/grape/dsl/validations.rb +24 -4
- data/lib/grape/eager_load.rb +20 -0
- data/lib/grape/endpoint.rb +59 -35
- data/lib/grape/error_formatter.rb +4 -2
- data/lib/grape/error_formatter/base.rb +2 -0
- data/lib/grape/error_formatter/json.rb +2 -0
- data/lib/grape/error_formatter/txt.rb +2 -0
- data/lib/grape/error_formatter/xml.rb +2 -0
- data/lib/grape/exceptions/base.rb +20 -14
- data/lib/grape/exceptions/empty_message_body.rb +11 -0
- data/lib/grape/exceptions/incompatible_option_values.rb +2 -0
- data/lib/grape/exceptions/invalid_accept_header.rb +2 -0
- data/lib/grape/exceptions/invalid_formatter.rb +2 -0
- data/lib/grape/exceptions/invalid_message_body.rb +2 -0
- data/lib/grape/exceptions/invalid_response.rb +11 -0
- data/lib/grape/exceptions/invalid_version_header.rb +2 -0
- data/lib/grape/exceptions/invalid_versioner_option.rb +2 -0
- data/lib/grape/exceptions/invalid_with_option_for_represent.rb +2 -0
- data/lib/grape/exceptions/method_not_allowed.rb +2 -0
- data/lib/grape/exceptions/missing_group_type.rb +2 -0
- data/lib/grape/exceptions/missing_mime_type.rb +2 -0
- data/lib/grape/exceptions/missing_option.rb +2 -0
- data/lib/grape/exceptions/missing_vendor_option.rb +2 -0
- data/lib/grape/exceptions/unknown_options.rb +2 -0
- data/lib/grape/exceptions/unknown_parameter.rb +2 -0
- data/lib/grape/exceptions/unknown_validator.rb +2 -0
- data/lib/grape/exceptions/unsupported_group_type.rb +2 -0
- data/lib/grape/exceptions/validation.rb +4 -2
- data/lib/grape/exceptions/validation_array_errors.rb +2 -0
- data/lib/grape/exceptions/validation_errors.rb +16 -13
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +4 -3
- data/lib/grape/extensions/deep_mergeable_hash.rb +2 -0
- data/lib/grape/extensions/deep_symbolize_hash.rb +2 -0
- data/lib/grape/extensions/hash.rb +2 -0
- data/lib/grape/extensions/hashie/mash.rb +2 -0
- data/lib/grape/formatter.rb +5 -3
- data/lib/grape/formatter/json.rb +2 -0
- data/lib/grape/formatter/serializable_hash.rb +2 -0
- data/lib/grape/formatter/txt.rb +2 -0
- data/lib/grape/formatter/xml.rb +2 -0
- data/lib/grape/http/headers.rb +50 -18
- data/lib/grape/locale/en.yml +3 -1
- data/lib/grape/middleware/auth/base.rb +7 -7
- data/lib/grape/middleware/auth/dsl.rb +2 -0
- data/lib/grape/middleware/auth/strategies.rb +2 -0
- data/lib/grape/middleware/auth/strategy_info.rb +2 -0
- data/lib/grape/middleware/base.rb +10 -7
- data/lib/grape/middleware/error.rb +21 -16
- data/lib/grape/middleware/filter.rb +2 -0
- data/lib/grape/middleware/formatter.rb +8 -6
- data/lib/grape/middleware/globals.rb +2 -0
- data/lib/grape/middleware/helpers.rb +12 -0
- data/lib/grape/middleware/stack.rb +13 -3
- data/lib/grape/middleware/versioner.rb +2 -0
- data/lib/grape/middleware/versioner/accept_version_header.rb +2 -0
- data/lib/grape/middleware/versioner/header.rb +10 -8
- data/lib/grape/middleware/versioner/param.rb +3 -1
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +4 -1
- data/lib/grape/middleware/versioner/path.rb +3 -1
- data/lib/grape/namespace.rb +14 -2
- data/lib/grape/parser.rb +4 -2
- data/lib/grape/parser/json.rb +3 -1
- data/lib/grape/parser/xml.rb +3 -1
- data/lib/grape/path.rb +15 -3
- data/lib/grape/presenters/presenter.rb +2 -0
- data/lib/grape/request.rb +19 -10
- data/lib/grape/router.rb +30 -29
- data/lib/grape/router/attribute_translator.rb +41 -8
- data/lib/grape/router/pattern.rb +20 -16
- data/lib/grape/router/route.rb +14 -28
- data/lib/grape/{serve_file → serve_stream}/file_body.rb +3 -1
- data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +3 -1
- data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +10 -8
- data/lib/grape/util/base_inheritable.rb +43 -0
- data/lib/grape/util/cache.rb +20 -0
- data/lib/grape/util/endpoint_configuration.rb +8 -0
- data/lib/grape/util/env.rb +19 -17
- data/lib/grape/util/inheritable_setting.rb +2 -0
- data/lib/grape/util/inheritable_values.rb +7 -25
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/util/lazy_block.rb +27 -0
- data/lib/grape/util/lazy_object.rb +43 -0
- data/lib/grape/util/lazy_value.rb +98 -0
- data/lib/grape/util/registrable.rb +2 -0
- data/lib/grape/util/reverse_stackable_values.rb +10 -35
- data/lib/grape/util/stackable_values.rb +21 -34
- data/lib/grape/util/strict_hash_configuration.rb +2 -0
- data/lib/grape/util/xml.rb +2 -0
- data/lib/grape/validations.rb +2 -0
- data/lib/grape/validations/attributes_iterator.rb +16 -6
- data/lib/grape/validations/multiple_attributes_iterator.rb +13 -0
- data/lib/grape/validations/params_scope.rb +51 -30
- data/lib/grape/validations/single_attribute_iterator.rb +24 -0
- data/lib/grape/validations/types.rb +13 -38
- data/lib/grape/validations/types/array_coercer.rb +65 -0
- data/lib/grape/validations/types/build_coercer.rb +47 -49
- data/lib/grape/validations/types/custom_type_coercer.rb +29 -51
- data/lib/grape/validations/types/custom_type_collection_coercer.rb +10 -25
- data/lib/grape/validations/types/dry_type_coercer.rb +76 -0
- data/lib/grape/validations/types/file.rb +22 -18
- data/lib/grape/validations/types/invalid_value.rb +24 -0
- data/lib/grape/validations/types/json.rb +46 -39
- data/lib/grape/validations/types/multiple_type_coercer.rb +14 -33
- data/lib/grape/validations/types/primitive_coercer.rb +67 -0
- data/lib/grape/validations/types/set_coercer.rb +40 -0
- data/lib/grape/validations/types/variant_collection_coercer.rb +5 -13
- data/lib/grape/validations/validator_factory.rb +8 -11
- data/lib/grape/validations/validators/all_or_none.rb +8 -13
- data/lib/grape/validations/validators/allow_blank.rb +3 -1
- data/lib/grape/validations/validators/as.rb +5 -4
- data/lib/grape/validations/validators/at_least_one_of.rb +7 -13
- data/lib/grape/validations/validators/base.rb +20 -16
- data/lib/grape/validations/validators/coerce.rb +46 -29
- data/lib/grape/validations/validators/default.rb +6 -6
- data/lib/grape/validations/validators/exactly_one_of.rb +10 -23
- data/lib/grape/validations/validators/except_values.rb +4 -2
- data/lib/grape/validations/validators/multiple_params_base.rb +17 -10
- data/lib/grape/validations/validators/mutual_exclusion.rb +8 -18
- data/lib/grape/validations/validators/presence.rb +3 -1
- data/lib/grape/validations/validators/regexp.rb +4 -2
- data/lib/grape/validations/validators/same_as.rb +26 -0
- data/lib/grape/validations/validators/values.rb +18 -6
- data/lib/grape/version.rb +3 -1
- data/spec/grape/api/custom_validations_spec.rb +5 -3
- data/spec/grape/api/deeply_included_options_spec.rb +2 -0
- data/spec/grape/api/defines_boolean_in_params_spec.rb +39 -0
- data/spec/grape/api/inherited_helpers_spec.rb +2 -0
- data/spec/grape/api/instance_spec.rb +104 -0
- data/spec/grape/api/invalid_format_spec.rb +2 -0
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +2 -0
- data/spec/grape/api/nested_helpers_spec.rb +2 -0
- data/spec/grape/api/optional_parameters_in_route_spec.rb +2 -0
- data/spec/grape/api/parameters_modification_spec.rb +3 -1
- data/spec/grape/api/patch_method_helpers_spec.rb +2 -0
- data/spec/grape/api/recognize_path_spec.rb +2 -0
- data/spec/grape/api/required_parameters_in_route_spec.rb +2 -0
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +2 -0
- data/spec/grape/api/routes_with_requirements_spec.rb +61 -0
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +2 -0
- data/spec/grape/api/shared_helpers_spec.rb +2 -0
- data/spec/grape/api_remount_spec.rb +473 -0
- data/spec/grape/api_spec.rb +565 -12
- data/spec/grape/config_spec.rb +19 -0
- data/spec/grape/dsl/callbacks_spec.rb +2 -0
- data/spec/grape/dsl/configuration_spec.rb +2 -0
- data/spec/grape/dsl/desc_spec.rb +42 -16
- data/spec/grape/dsl/headers_spec.rb +2 -0
- data/spec/grape/dsl/helpers_spec.rb +4 -2
- data/spec/grape/dsl/inside_route_spec.rb +184 -33
- data/spec/grape/dsl/logger_spec.rb +2 -0
- data/spec/grape/dsl/middleware_spec.rb +10 -0
- data/spec/grape/dsl/parameters_spec.rb +2 -0
- data/spec/grape/dsl/request_response_spec.rb +2 -0
- data/spec/grape/dsl/routing_spec.rb +12 -0
- data/spec/grape/dsl/settings_spec.rb +2 -0
- data/spec/grape/dsl/validations_spec.rb +2 -0
- data/spec/grape/endpoint/declared_spec.rb +601 -0
- data/spec/grape/endpoint_spec.rb +53 -523
- data/spec/grape/entity_spec.rb +9 -1
- data/spec/grape/exceptions/base_spec.rb +67 -0
- data/spec/grape/exceptions/body_parse_errors_spec.rb +2 -0
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +2 -0
- data/spec/grape/exceptions/invalid_formatter_spec.rb +2 -0
- data/spec/grape/exceptions/invalid_response_spec.rb +13 -0
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +2 -0
- data/spec/grape/exceptions/missing_mime_type_spec.rb +2 -0
- data/spec/grape/exceptions/missing_option_spec.rb +2 -0
- data/spec/grape/exceptions/unknown_options_spec.rb +2 -0
- data/spec/grape/exceptions/unknown_validator_spec.rb +2 -0
- data/spec/grape/exceptions/validation_errors_spec.rb +8 -4
- data/spec/grape/exceptions/validation_spec.rb +3 -1
- data/spec/grape/extensions/param_builders/hash_spec.rb +2 -0
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +2 -0
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +2 -0
- data/spec/grape/integration/global_namespace_function_spec.rb +2 -0
- data/spec/grape/integration/rack_sendfile_spec.rb +14 -8
- data/spec/grape/integration/rack_spec.rb +25 -7
- data/spec/grape/loading_spec.rb +2 -0
- data/spec/grape/middleware/auth/base_spec.rb +2 -0
- data/spec/grape/middleware/auth/dsl_spec.rb +5 -3
- data/spec/grape/middleware/auth/strategies_spec.rb +3 -1
- data/spec/grape/middleware/base_spec.rb +10 -0
- data/spec/grape/middleware/error_spec.rb +3 -1
- data/spec/grape/middleware/exception_spec.rb +4 -2
- data/spec/grape/middleware/formatter_spec.rb +33 -16
- data/spec/grape/middleware/globals_spec.rb +2 -0
- data/spec/grape/middleware/stack_spec.rb +12 -0
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +3 -1
- data/spec/grape/middleware/versioner/header_spec.rb +9 -1
- data/spec/grape/middleware/versioner/param_spec.rb +3 -1
- data/spec/grape/middleware/versioner/path_spec.rb +3 -1
- data/spec/grape/middleware/versioner_spec.rb +2 -0
- data/spec/grape/named_api_spec.rb +21 -0
- data/spec/grape/parser_spec.rb +7 -5
- data/spec/grape/path_spec.rb +6 -4
- data/spec/grape/presenters/presenter_spec.rb +2 -0
- data/spec/grape/request_spec.rb +26 -0
- data/spec/grape/util/inheritable_setting_spec.rb +2 -0
- data/spec/grape/util/inheritable_values_spec.rb +2 -0
- data/spec/grape/util/reverse_stackable_values_spec.rb +2 -0
- data/spec/grape/util/stackable_values_spec.rb +3 -1
- data/spec/grape/util/strict_hash_configuration_spec.rb +2 -0
- data/spec/grape/validations/attributes_iterator_spec.rb +2 -0
- data/spec/grape/validations/instance_behaivour_spec.rb +5 -3
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +41 -0
- data/spec/grape/validations/params_scope_spec.rb +213 -9
- data/spec/grape/validations/single_attribute_iterator_spec.rb +58 -0
- data/spec/grape/validations/types/array_coercer_spec.rb +35 -0
- data/spec/grape/validations/types/primitive_coercer_spec.rb +135 -0
- data/spec/grape/validations/types/set_coercer_spec.rb +34 -0
- data/spec/grape/validations/types_spec.rb +9 -36
- data/spec/grape/validations/validators/all_or_none_spec.rb +140 -30
- data/spec/grape/validations/validators/allow_blank_spec.rb +2 -0
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +175 -29
- data/spec/grape/validations/validators/coerce_spec.rb +476 -135
- data/spec/grape/validations/validators/default_spec.rb +172 -0
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +204 -38
- data/spec/grape/validations/validators/except_values_spec.rb +4 -1
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +186 -27
- data/spec/grape/validations/validators/presence_spec.rb +30 -0
- data/spec/grape/validations/validators/regexp_spec.rb +2 -0
- data/spec/grape/validations/validators/same_as_spec.rb +65 -0
- data/spec/grape/validations/validators/values_spec.rb +30 -5
- data/spec/grape/validations_spec.rb +388 -50
- data/spec/integration/eager_load/eager_load_spec.rb +15 -0
- data/spec/integration/multi_json/json_spec.rb +2 -0
- data/spec/integration/multi_xml/xml_spec.rb +2 -0
- data/spec/shared/versioning_examples.rb +22 -20
- data/spec/spec_helper.rb +12 -1
- data/spec/support/basic_auth_encode_helpers.rb +2 -0
- data/spec/support/chunks.rb +14 -0
- data/spec/support/content_type_helpers.rb +2 -0
- data/spec/support/eager_load.rb +19 -0
- data/spec/support/endpoint_faker.rb +2 -0
- data/spec/support/file_streamer.rb +2 -0
- data/spec/support/integer_helpers.rb +2 -0
- data/spec/support/versioned_helpers.rb +8 -8
- metadata +86 -48
- data/Appraisals +0 -32
- data/Dangerfile +0 -2
- data/Gemfile +0 -33
- data/Gemfile.lock +0 -231
- data/Guardfile +0 -10
- data/RELEASING.md +0 -111
- data/Rakefile +0 -25
- data/benchmark/simple.rb +0 -27
- data/benchmark/simple_with_type_coercer.rb +0 -22
- data/gemfiles/multi_json.gemfile +0 -35
- data/gemfiles/multi_xml.gemfile +0 -35
- data/gemfiles/rack_1.5.2.gemfile +0 -35
- data/gemfiles/rack_edge.gemfile +0 -35
- data/gemfiles/rails_3.gemfile +0 -36
- data/gemfiles/rails_4.gemfile +0 -35
- data/gemfiles/rails_5.gemfile +0 -35
- data/gemfiles/rails_edge.gemfile +0 -35
- data/lib/grape/extensions/deep_hash_with_indifferent_access.rb +0 -18
- data/lib/grape/util/content_types.rb +0 -26
- data/lib/grape/validations/types/virtus_collection_patch.rb +0 -16
- data/pkg/grape-0.17.0.gem +0 -0
- 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
|
-
|
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
|
-
|
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
|
42
|
+
raise validation_exception(attr_name, message(:values)) \
|
35
43
|
unless check_values(param_array, attr_name)
|
36
44
|
|
37
|
-
raise
|
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,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
|
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
|
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
|
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
|
@@ -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
|
@@ -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
|
@@ -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)
|
@@ -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
|
@@ -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
|