grape 1.7.1 → 2.0.0
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 +37 -1
- data/CONTRIBUTING.md +1 -1
- data/README.md +30 -25
- data/UPGRADING.md +35 -0
- data/grape.gemspec +3 -6
- data/lib/grape/api.rb +2 -2
- data/lib/grape/content_types.rb +2 -8
- data/lib/grape/dsl/desc.rb +1 -1
- data/lib/grape/dsl/inside_route.rb +11 -11
- data/lib/grape/dsl/request_response.rb +2 -1
- data/lib/grape/dsl/settings.rb +2 -6
- data/lib/grape/endpoint.rb +28 -18
- data/lib/grape/error_formatter/base.rb +1 -1
- data/lib/grape/exceptions/base.rb +2 -2
- data/lib/grape/exceptions/missing_group_type.rb +1 -6
- data/lib/grape/exceptions/unsupported_group_type.rb +1 -6
- data/lib/grape/exceptions/validation_errors.rb +1 -6
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +3 -3
- data/lib/grape/extensions/hash.rb +4 -7
- data/lib/grape/extensions/hashie/mash.rb +3 -3
- data/lib/grape/formatter/serializable_hash.rb +7 -7
- data/lib/grape/http/headers.rb +12 -2
- data/lib/grape/middleware/auth/base.rb +1 -1
- data/lib/grape/middleware/auth/strategies.rb +1 -2
- data/lib/grape/middleware/error.rb +5 -5
- data/lib/grape/middleware/formatter.rb +6 -6
- data/lib/grape/middleware/versioner/header.rb +11 -19
- data/lib/grape/railtie.rb +9 -0
- data/lib/grape/request.rb +8 -2
- data/lib/grape/router/route.rb +1 -3
- data/lib/grape/util/lazy_value.rb +3 -11
- data/lib/grape/util/strict_hash_configuration.rb +3 -4
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/params_scope.rb +8 -2
- data/lib/grape/validations/single_attribute_iterator.rb +3 -1
- data/lib/grape/validations/types/custom_type_coercer.rb +2 -16
- data/lib/grape/validations/validators/base.rb +9 -20
- data/lib/grape/validations/validators/default_validator.rb +2 -20
- data/lib/grape/validations/validators/multiple_params_base.rb +4 -8
- data/lib/grape/validations/validators/values_validator.rb +14 -5
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +26 -5
- metadata +13 -253
- data/lib/grape/config.rb +0 -34
- data/lib/grape/extensions/deep_mergeable_hash.rb +0 -21
- data/lib/grape/extensions/deep_symbolize_hash.rb +0 -32
- data/spec/grape/api/custom_validations_spec.rb +0 -256
- data/spec/grape/api/deeply_included_options_spec.rb +0 -56
- data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -38
- data/spec/grape/api/documentation_spec.rb +0 -59
- data/spec/grape/api/inherited_helpers_spec.rb +0 -114
- data/spec/grape/api/instance_spec.rb +0 -103
- data/spec/grape/api/invalid_format_spec.rb +0 -45
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -38
- data/spec/grape/api/nested_helpers_spec.rb +0 -50
- data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -43
- data/spec/grape/api/parameters_modification_spec.rb +0 -41
- data/spec/grape/api/patch_method_helpers_spec.rb +0 -79
- data/spec/grape/api/recognize_path_spec.rb +0 -21
- data/spec/grape/api/required_parameters_in_route_spec.rb +0 -37
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -26
- data/spec/grape/api/routes_with_requirements_spec.rb +0 -59
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -41
- data/spec/grape/api/shared_helpers_spec.rb +0 -36
- data/spec/grape/api_remount_spec.rb +0 -473
- data/spec/grape/api_spec.rb +0 -4347
- data/spec/grape/config_spec.rb +0 -17
- data/spec/grape/dsl/callbacks_spec.rb +0 -45
- data/spec/grape/dsl/desc_spec.rb +0 -101
- data/spec/grape/dsl/headers_spec.rb +0 -62
- data/spec/grape/dsl/helpers_spec.rb +0 -100
- data/spec/grape/dsl/inside_route_spec.rb +0 -535
- data/spec/grape/dsl/logger_spec.rb +0 -24
- data/spec/grape/dsl/middleware_spec.rb +0 -60
- data/spec/grape/dsl/parameters_spec.rb +0 -180
- data/spec/grape/dsl/request_response_spec.rb +0 -206
- data/spec/grape/dsl/routing_spec.rb +0 -275
- data/spec/grape/dsl/settings_spec.rb +0 -261
- data/spec/grape/dsl/validations_spec.rb +0 -55
- data/spec/grape/endpoint/declared_spec.rb +0 -846
- data/spec/grape/endpoint_spec.rb +0 -1085
- data/spec/grape/entity_spec.rb +0 -336
- data/spec/grape/exceptions/base_spec.rb +0 -81
- data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -145
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -358
- data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -15
- data/spec/grape/exceptions/invalid_response_spec.rb +0 -11
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +0 -15
- data/spec/grape/exceptions/missing_group_type_spec.rb +0 -21
- data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -17
- data/spec/grape/exceptions/missing_option_spec.rb +0 -15
- data/spec/grape/exceptions/unknown_options_spec.rb +0 -15
- data/spec/grape/exceptions/unknown_validator_spec.rb +0 -15
- data/spec/grape/exceptions/unsupported_group_type_spec.rb +0 -23
- data/spec/grape/exceptions/validation_errors_spec.rb +0 -92
- data/spec/grape/exceptions/validation_spec.rb +0 -19
- data/spec/grape/extensions/param_builders/hash_spec.rb +0 -83
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -105
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -79
- data/spec/grape/integration/global_namespace_function_spec.rb +0 -29
- data/spec/grape/integration/rack_sendfile_spec.rb +0 -48
- data/spec/grape/integration/rack_spec.rb +0 -51
- data/spec/grape/loading_spec.rb +0 -44
- data/spec/grape/middleware/auth/base_spec.rb +0 -31
- data/spec/grape/middleware/auth/dsl_spec.rb +0 -60
- data/spec/grape/middleware/auth/strategies_spec.rb +0 -120
- data/spec/grape/middleware/base_spec.rb +0 -221
- data/spec/grape/middleware/error_spec.rb +0 -85
- data/spec/grape/middleware/exception_spec.rb +0 -294
- data/spec/grape/middleware/formatter_spec.rb +0 -461
- data/spec/grape/middleware/globals_spec.rb +0 -30
- data/spec/grape/middleware/stack_spec.rb +0 -155
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -122
- data/spec/grape/middleware/versioner/header_spec.rb +0 -345
- data/spec/grape/middleware/versioner/param_spec.rb +0 -171
- data/spec/grape/middleware/versioner/path_spec.rb +0 -62
- data/spec/grape/middleware/versioner_spec.rb +0 -21
- data/spec/grape/named_api_spec.rb +0 -19
- data/spec/grape/parser_spec.rb +0 -86
- data/spec/grape/path_spec.rb +0 -252
- data/spec/grape/presenters/presenter_spec.rb +0 -71
- data/spec/grape/request_spec.rb +0 -136
- data/spec/grape/util/inheritable_setting_spec.rb +0 -242
- data/spec/grape/util/inheritable_values_spec.rb +0 -79
- data/spec/grape/util/reverse_stackable_values_spec.rb +0 -134
- data/spec/grape/util/stackable_values_spec.rb +0 -128
- data/spec/grape/util/strict_hash_configuration_spec.rb +0 -38
- data/spec/grape/validations/attributes_doc_spec.rb +0 -153
- data/spec/grape/validations/instance_behaivour_spec.rb +0 -43
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -40
- data/spec/grape/validations/params_scope_spec.rb +0 -1420
- data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -57
- data/spec/grape/validations/types/array_coercer_spec.rb +0 -33
- data/spec/grape/validations/types/primitive_coercer_spec.rb +0 -150
- data/spec/grape/validations/types/set_coercer_spec.rb +0 -32
- data/spec/grape/validations/types_spec.rb +0 -111
- data/spec/grape/validations/validators/all_or_none_spec.rb +0 -162
- data/spec/grape/validations/validators/allow_blank_spec.rb +0 -575
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -205
- data/spec/grape/validations/validators/coerce_spec.rb +0 -1261
- data/spec/grape/validations/validators/default_spec.rb +0 -463
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -233
- data/spec/grape/validations/validators/except_values_spec.rb +0 -192
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -214
- data/spec/grape/validations/validators/presence_spec.rb +0 -315
- data/spec/grape/validations/validators/regexp_spec.rb +0 -161
- data/spec/grape/validations/validators/same_as_spec.rb +0 -57
- data/spec/grape/validations/validators/values_spec.rb +0 -696
- data/spec/grape/validations/validators/zh-CN.yml +0 -10
- data/spec/grape/validations_spec.rb +0 -2029
- data/spec/integration/eager_load/eager_load_spec.rb +0 -15
- data/spec/integration/multi_json/json_spec.rb +0 -7
- data/spec/integration/multi_xml/xml_spec.rb +0 -7
- data/spec/shared/versioning_examples.rb +0 -215
- data/spec/spec_helper.rb +0 -52
- data/spec/support/basic_auth_encode_helpers.rb +0 -11
- data/spec/support/chunks.rb +0 -14
- data/spec/support/content_type_helpers.rb +0 -15
- data/spec/support/endpoint_faker.rb +0 -25
- data/spec/support/file_streamer.rb +0 -13
- data/spec/support/integer_helpers.rb +0 -13
- data/spec/support/versioned_helpers.rb +0 -55
@@ -1,696 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
describe Grape::Validations::Validators::ValuesValidator do
|
4
|
-
let_it_be(:values_model) do
|
5
|
-
Class.new do
|
6
|
-
DEFAULT_VALUES = %w[valid-type1 valid-type2 valid-type3].freeze
|
7
|
-
DEFAULT_EXCEPTS = %w[invalid-type1 invalid-type2 invalid-type3].freeze
|
8
|
-
|
9
|
-
class << self
|
10
|
-
def values
|
11
|
-
@values ||= []
|
12
|
-
[DEFAULT_VALUES + @values].flatten.uniq
|
13
|
-
end
|
14
|
-
|
15
|
-
def add_value(value)
|
16
|
-
@values ||= []
|
17
|
-
@values << value
|
18
|
-
end
|
19
|
-
|
20
|
-
def excepts
|
21
|
-
@excepts ||= []
|
22
|
-
[DEFAULT_EXCEPTS + @excepts].flatten.uniq
|
23
|
-
end
|
24
|
-
|
25
|
-
def add_except(except)
|
26
|
-
@excepts ||= []
|
27
|
-
@excepts << except
|
28
|
-
end
|
29
|
-
|
30
|
-
def include?(value)
|
31
|
-
values.include?(value)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
before do
|
38
|
-
stub_const('ValuesModel', values_model)
|
39
|
-
end
|
40
|
-
|
41
|
-
let_it_be(:app) do
|
42
|
-
ValuesModel = values_model
|
43
|
-
Class.new(Grape::API) do
|
44
|
-
default_format :json
|
45
|
-
|
46
|
-
resources :custom_message do
|
47
|
-
params do
|
48
|
-
requires :type, values: { value: ValuesModel.values, message: 'value does not include in values' }
|
49
|
-
end
|
50
|
-
get '/' do
|
51
|
-
{ type: params[:type] }
|
52
|
-
end
|
53
|
-
|
54
|
-
params do
|
55
|
-
optional :type, values: { value: -> { ValuesModel.values }, message: 'value does not include in values' }, default: 'valid-type2'
|
56
|
-
end
|
57
|
-
get '/lambda' do
|
58
|
-
{ type: params[:type] }
|
59
|
-
end
|
60
|
-
|
61
|
-
params do
|
62
|
-
requires :type, values: { except: ValuesModel.excepts, except_message: 'value is on exclusions list', message: 'default exclude message' }
|
63
|
-
end
|
64
|
-
get '/exclude/exclude_message'
|
65
|
-
|
66
|
-
params do
|
67
|
-
requires :type, values: { except: -> { ValuesModel.excepts }, except_message: 'value is on exclusions list' }
|
68
|
-
end
|
69
|
-
get '/exclude/lambda/exclude_message'
|
70
|
-
|
71
|
-
params do
|
72
|
-
requires :type, values: { except: ValuesModel.excepts, message: 'default exclude message' }
|
73
|
-
end
|
74
|
-
get '/exclude/fallback_message'
|
75
|
-
end
|
76
|
-
|
77
|
-
params do
|
78
|
-
requires :type, values: ValuesModel.values
|
79
|
-
end
|
80
|
-
get '/' do
|
81
|
-
{ type: params[:type] }
|
82
|
-
end
|
83
|
-
|
84
|
-
params do
|
85
|
-
requires :type, values: []
|
86
|
-
end
|
87
|
-
get '/empty'
|
88
|
-
|
89
|
-
params do
|
90
|
-
optional :type, values: { value: ValuesModel.values }, default: 'valid-type2'
|
91
|
-
end
|
92
|
-
get '/default/hash/valid' do
|
93
|
-
{ type: params[:type] }
|
94
|
-
end
|
95
|
-
|
96
|
-
params do
|
97
|
-
optional :type, values: ValuesModel.values, default: 'valid-type2'
|
98
|
-
end
|
99
|
-
get '/default/valid' do
|
100
|
-
{ type: params[:type] }
|
101
|
-
end
|
102
|
-
|
103
|
-
params do
|
104
|
-
optional :type, values: { except: ValuesModel.excepts }, default: 'valid-type2'
|
105
|
-
end
|
106
|
-
get '/default/except' do
|
107
|
-
{ type: params[:type] }
|
108
|
-
end
|
109
|
-
|
110
|
-
params do
|
111
|
-
optional :type, values: -> { ValuesModel.values }, default: 'valid-type2'
|
112
|
-
end
|
113
|
-
get '/lambda' do
|
114
|
-
{ type: params[:type] }
|
115
|
-
end
|
116
|
-
|
117
|
-
params do
|
118
|
-
optional :type, type: Integer, values: 1..
|
119
|
-
end
|
120
|
-
get '/endless' do
|
121
|
-
{ type: params[:type] }
|
122
|
-
end
|
123
|
-
|
124
|
-
params do
|
125
|
-
requires :type, values: ->(v) { ValuesModel.include? v }
|
126
|
-
end
|
127
|
-
get '/lambda_val' do
|
128
|
-
{ type: params[:type] }
|
129
|
-
end
|
130
|
-
|
131
|
-
params do
|
132
|
-
requires :number, type: Integer, values: ->(v) { v > 0 }
|
133
|
-
end
|
134
|
-
get '/lambda_int_val' do
|
135
|
-
{ number: params[:number] }
|
136
|
-
end
|
137
|
-
|
138
|
-
params do
|
139
|
-
requires :type, values: -> { [] }
|
140
|
-
end
|
141
|
-
get '/empty_lambda'
|
142
|
-
|
143
|
-
params do
|
144
|
-
optional :type, values: ValuesModel.values, default: -> { ValuesModel.values.sample }
|
145
|
-
end
|
146
|
-
get '/default_lambda' do
|
147
|
-
{ type: params[:type] }
|
148
|
-
end
|
149
|
-
|
150
|
-
params do
|
151
|
-
optional :type, values: -> { ValuesModel.values }, default: -> { ValuesModel.values.sample }
|
152
|
-
end
|
153
|
-
get '/default_and_values_lambda' do
|
154
|
-
{ type: params[:type] }
|
155
|
-
end
|
156
|
-
|
157
|
-
params do
|
158
|
-
optional :type, type: Grape::API::Boolean, desc: 'A boolean', values: [true]
|
159
|
-
end
|
160
|
-
get '/values/optional_boolean' do
|
161
|
-
{ type: params[:type] }
|
162
|
-
end
|
163
|
-
|
164
|
-
params do
|
165
|
-
requires :type, type: Integer, desc: 'An integer', values: [10, 11], default: 10
|
166
|
-
end
|
167
|
-
get '/values/coercion' do
|
168
|
-
{ type: params[:type] }
|
169
|
-
end
|
170
|
-
|
171
|
-
params do
|
172
|
-
requires :type, type: Array[Integer], desc: 'An integer', values: [10, 11], default: 10
|
173
|
-
end
|
174
|
-
get '/values/array_coercion' do
|
175
|
-
{ type: params[:type] }
|
176
|
-
end
|
177
|
-
|
178
|
-
params do
|
179
|
-
optional :optional, type: Array do
|
180
|
-
requires :type, values: %w[a b]
|
181
|
-
end
|
182
|
-
end
|
183
|
-
get '/optional_with_required_values'
|
184
|
-
|
185
|
-
params do
|
186
|
-
requires :type, values: { except: ValuesModel.excepts }
|
187
|
-
end
|
188
|
-
get '/except/exclusive' do
|
189
|
-
{ type: params[:type] }
|
190
|
-
end
|
191
|
-
|
192
|
-
params do
|
193
|
-
requires :type, type: String, values: { except: ValuesModel.excepts }
|
194
|
-
end
|
195
|
-
get '/except/exclusive/type' do
|
196
|
-
{ type: params[:type] }
|
197
|
-
end
|
198
|
-
|
199
|
-
params do
|
200
|
-
requires :type, values: { except: -> { ValuesModel.excepts } }
|
201
|
-
end
|
202
|
-
get '/except/exclusive/lambda' do
|
203
|
-
{ type: params[:type] }
|
204
|
-
end
|
205
|
-
|
206
|
-
params do
|
207
|
-
requires :type, type: String, values: { except: -> { ValuesModel.excepts } }
|
208
|
-
end
|
209
|
-
get '/except/exclusive/lambda/type' do
|
210
|
-
{ type: params[:type] }
|
211
|
-
end
|
212
|
-
|
213
|
-
params do
|
214
|
-
requires :type, type: Integer, values: { except: -> { [3, 4, 5] } }
|
215
|
-
end
|
216
|
-
get '/except/exclusive/lambda/coercion' do
|
217
|
-
{ type: params[:type] }
|
218
|
-
end
|
219
|
-
|
220
|
-
params do
|
221
|
-
requires :type, type: Integer, values: { value: 1..5, except: [3] }
|
222
|
-
end
|
223
|
-
get '/mixed/value/except' do
|
224
|
-
{ type: params[:type] }
|
225
|
-
end
|
226
|
-
|
227
|
-
params do
|
228
|
-
optional :optional, type: Array[String], values: %w[a b c]
|
229
|
-
end
|
230
|
-
put '/optional_with_array_of_string_values'
|
231
|
-
|
232
|
-
params do
|
233
|
-
requires :type, values: { proc: ->(v) { ValuesModel.include? v } }
|
234
|
-
end
|
235
|
-
get '/proc' do
|
236
|
-
{ type: params[:type] }
|
237
|
-
end
|
238
|
-
|
239
|
-
params do
|
240
|
-
requires :type, values: { proc: ->(v) { ValuesModel.include? v }, message: 'failed check' }
|
241
|
-
end
|
242
|
-
get '/proc/message'
|
243
|
-
|
244
|
-
params do
|
245
|
-
optional :name, type: String, values: %w[a b], allow_blank: true
|
246
|
-
end
|
247
|
-
get '/allow_blank'
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
context 'with a custom validation message' do
|
252
|
-
it 'allows a valid value for a parameter' do
|
253
|
-
get('/custom_message', type: 'valid-type1')
|
254
|
-
expect(last_response.status).to eq 200
|
255
|
-
expect(last_response.body).to eq({ type: 'valid-type1' }.to_json)
|
256
|
-
end
|
257
|
-
|
258
|
-
it 'does not allow an invalid value for a parameter' do
|
259
|
-
get('/custom_message', type: 'invalid-type')
|
260
|
-
expect(last_response.status).to eq 400
|
261
|
-
expect(last_response.body).to eq({ error: 'type value does not include in values' }.to_json)
|
262
|
-
end
|
263
|
-
|
264
|
-
it 'validates against values in a proc' do
|
265
|
-
ValuesModel.add_value('valid-type4')
|
266
|
-
|
267
|
-
get('/custom_message/lambda', type: 'valid-type4')
|
268
|
-
expect(last_response.status).to eq 200
|
269
|
-
expect(last_response.body).to eq({ type: 'valid-type4' }.to_json)
|
270
|
-
end
|
271
|
-
|
272
|
-
it 'does not allow an invalid value for a parameter using lambda' do
|
273
|
-
get('/custom_message/lambda', type: 'invalid-type')
|
274
|
-
expect(last_response.status).to eq 400
|
275
|
-
expect(last_response.body).to eq({ error: 'type value does not include in values' }.to_json)
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
context 'with a custom exclude validation message' do
|
280
|
-
it 'does not allow an invalid value for a parameter' do
|
281
|
-
get('/custom_message/exclude/exclude_message', type: 'invalid-type1')
|
282
|
-
expect(last_response.status).to eq 400
|
283
|
-
expect(last_response.body).to eq({ error: 'type value is on exclusions list' }.to_json)
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
context 'with a custom exclude validation message' do
|
288
|
-
it 'does not allow an invalid value for a parameter' do
|
289
|
-
get('/custom_message/exclude/lambda/exclude_message', type: 'invalid-type1')
|
290
|
-
expect(last_response.status).to eq 400
|
291
|
-
expect(last_response.body).to eq({ error: 'type value is on exclusions list' }.to_json)
|
292
|
-
end
|
293
|
-
end
|
294
|
-
|
295
|
-
context 'exclude with a standard custom validation message' do
|
296
|
-
it 'does not allow an invalid value for a parameter' do
|
297
|
-
get('/custom_message/exclude/fallback_message', type: 'invalid-type1')
|
298
|
-
expect(last_response.status).to eq 400
|
299
|
-
expect(last_response.body).to eq({ error: 'type default exclude message' }.to_json)
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
it 'allows a valid value for a parameter' do
|
304
|
-
get('/', type: 'valid-type1')
|
305
|
-
expect(last_response.status).to eq 200
|
306
|
-
expect(last_response.body).to eq({ type: 'valid-type1' }.to_json)
|
307
|
-
end
|
308
|
-
|
309
|
-
it 'does not allow an invalid value for a parameter' do
|
310
|
-
get('/', type: 'invalid-type')
|
311
|
-
expect(last_response.status).to eq 400
|
312
|
-
expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
|
313
|
-
end
|
314
|
-
|
315
|
-
it 'rejects all values if values is an empty array' do
|
316
|
-
get('/empty', type: 'invalid-type')
|
317
|
-
expect(last_response.status).to eq 400
|
318
|
-
expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
|
319
|
-
end
|
320
|
-
|
321
|
-
context 'nil value for a parameter' do
|
322
|
-
it 'does not allow for root params scope' do
|
323
|
-
get('/', type: nil)
|
324
|
-
expect(last_response.status).to eq 400
|
325
|
-
expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
|
326
|
-
end
|
327
|
-
|
328
|
-
it 'allows for a required param in child scope' do
|
329
|
-
get('/optional_with_required_values')
|
330
|
-
expect(last_response.status).to eq 200
|
331
|
-
end
|
332
|
-
|
333
|
-
it 'accepts for an optional param with a list of values' do
|
334
|
-
put('/optional_with_array_of_string_values', optional: nil)
|
335
|
-
expect(last_response.status).to eq 200
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
it 'allows a valid default value' do
|
340
|
-
get('/default/valid')
|
341
|
-
expect(last_response.status).to eq 200
|
342
|
-
expect(last_response.body).to eq({ type: 'valid-type2' }.to_json)
|
343
|
-
end
|
344
|
-
|
345
|
-
it 'allows a default value with except' do
|
346
|
-
get('/default/except')
|
347
|
-
expect(last_response.status).to eq 200
|
348
|
-
expect(last_response.body).to eq({ type: 'valid-type2' }.to_json)
|
349
|
-
end
|
350
|
-
|
351
|
-
it 'allows a valid default value' do
|
352
|
-
get('/default/hash/valid')
|
353
|
-
expect(last_response.status).to eq 200
|
354
|
-
expect(last_response.body).to eq({ type: 'valid-type2' }.to_json)
|
355
|
-
end
|
356
|
-
|
357
|
-
it 'allows a proc for values' do
|
358
|
-
get('/lambda', type: 'valid-type1')
|
359
|
-
expect(last_response.status).to eq 200
|
360
|
-
expect(last_response.body).to eq({ type: 'valid-type1' }.to_json)
|
361
|
-
end
|
362
|
-
|
363
|
-
it 'does not validate updated values without proc' do
|
364
|
-
ValuesModel.add_value('valid-type4')
|
365
|
-
get('/', type: 'valid-type4')
|
366
|
-
expect(last_response.status).to eq 400
|
367
|
-
expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
|
368
|
-
end
|
369
|
-
|
370
|
-
it 'validates against values in a proc' do
|
371
|
-
ValuesModel.add_value('valid-type4')
|
372
|
-
|
373
|
-
get('/lambda', type: 'valid-type4')
|
374
|
-
expect(last_response.status).to eq 200
|
375
|
-
expect(last_response.body).to eq({ type: 'valid-type4' }.to_json)
|
376
|
-
end
|
377
|
-
|
378
|
-
it 'does not allow an invalid value for a parameter using lambda' do
|
379
|
-
get('/lambda', type: 'invalid-type')
|
380
|
-
expect(last_response.status).to eq 400
|
381
|
-
expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
|
382
|
-
end
|
383
|
-
|
384
|
-
it 'validates against values in an endless range', if: ActiveSupport::VERSION::MAJOR >= 6 do
|
385
|
-
get('/endless', type: 10)
|
386
|
-
expect(last_response.status).to eq 200
|
387
|
-
expect(last_response.body).to eq({ type: 10 }.to_json)
|
388
|
-
end
|
389
|
-
|
390
|
-
it 'does not allow an invalid value for a parameter using an endless range', if: ActiveSupport::VERSION::MAJOR >= 6 do
|
391
|
-
get('/endless', type: 0)
|
392
|
-
expect(last_response.status).to eq 400
|
393
|
-
expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
|
394
|
-
end
|
395
|
-
|
396
|
-
it 'does not allow non-numeric string value for int value using lambda' do
|
397
|
-
get('/lambda_int_val', number: 'foo')
|
398
|
-
expect(last_response.status).to eq 400
|
399
|
-
expect(last_response.body).to eq({ error: 'number is invalid, number does not have a valid value' }.to_json)
|
400
|
-
end
|
401
|
-
|
402
|
-
it 'does not allow nil for int value using lambda' do
|
403
|
-
get('/lambda_int_val', number: nil)
|
404
|
-
expect(last_response.status).to eq 400
|
405
|
-
expect(last_response.body).to eq({ error: 'number does not have a valid value' }.to_json)
|
406
|
-
end
|
407
|
-
|
408
|
-
it 'allows numeric string for int value using lambda' do
|
409
|
-
get('/lambda_int_val', number: '3')
|
410
|
-
expect(last_response.status).to eq 200
|
411
|
-
expect(last_response.body).to eq({ number: 3 }.to_json)
|
412
|
-
end
|
413
|
-
|
414
|
-
it 'allows value using lambda' do
|
415
|
-
get('/lambda_val', type: 'valid-type1')
|
416
|
-
expect(last_response.status).to eq 200
|
417
|
-
expect(last_response.body).to eq({ type: 'valid-type1' }.to_json)
|
418
|
-
end
|
419
|
-
|
420
|
-
it 'does not allow invalid value using lambda' do
|
421
|
-
get('/lambda_val', type: 'invalid-type')
|
422
|
-
expect(last_response.status).to eq 400
|
423
|
-
expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
|
424
|
-
end
|
425
|
-
|
426
|
-
it 'validates against an empty array in a proc' do
|
427
|
-
get('/empty_lambda', type: 'any')
|
428
|
-
expect(last_response.status).to eq 400
|
429
|
-
expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
|
430
|
-
end
|
431
|
-
|
432
|
-
it 'validates default value from proc' do
|
433
|
-
get('/default_lambda')
|
434
|
-
expect(last_response.status).to eq 200
|
435
|
-
end
|
436
|
-
|
437
|
-
it 'validates default value from proc against values in a proc' do
|
438
|
-
get('/default_and_values_lambda')
|
439
|
-
expect(last_response.status).to eq 200
|
440
|
-
end
|
441
|
-
|
442
|
-
it 'raises IncompatibleOptionValues on an invalid default value from proc' do
|
443
|
-
subject = Class.new(Grape::API)
|
444
|
-
expect do
|
445
|
-
subject.params { optional :type, values: %w[valid-type1 valid-type2 valid-type3], default: "#{ValuesModel.values.sample}_invalid" }
|
446
|
-
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
447
|
-
end
|
448
|
-
|
449
|
-
it 'raises IncompatibleOptionValues on an invalid default value' do
|
450
|
-
subject = Class.new(Grape::API)
|
451
|
-
expect do
|
452
|
-
subject.params { optional :type, values: %w[valid-type1 valid-type2 valid-type3], default: 'invalid-type' }
|
453
|
-
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
454
|
-
end
|
455
|
-
|
456
|
-
it 'raises IncompatibleOptionValues when type is incompatible with values array' do
|
457
|
-
subject = Class.new(Grape::API)
|
458
|
-
expect do
|
459
|
-
subject.params { optional :type, values: %w[valid-type1 valid-type2 valid-type3], type: Symbol }
|
460
|
-
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
461
|
-
end
|
462
|
-
|
463
|
-
context 'boolean values' do
|
464
|
-
it 'allows a value from the list' do
|
465
|
-
get('/values/optional_boolean', type: true)
|
466
|
-
|
467
|
-
expect(last_response.status).to eq 200
|
468
|
-
expect(last_response.body).to eq({ type: true }.to_json)
|
469
|
-
end
|
470
|
-
|
471
|
-
it 'rejects a value which is not in the list' do
|
472
|
-
get('/values/optional_boolean', type: false)
|
473
|
-
|
474
|
-
expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
|
475
|
-
end
|
476
|
-
end
|
477
|
-
|
478
|
-
it 'allows values to be a kind of the coerced type not just an instance of it' do
|
479
|
-
get('/values/coercion', type: 10)
|
480
|
-
expect(last_response.status).to eq 200
|
481
|
-
expect(last_response.body).to eq({ type: 10 }.to_json)
|
482
|
-
end
|
483
|
-
|
484
|
-
it 'allows values to be a kind of the coerced type in an array' do
|
485
|
-
get('/values/array_coercion', type: [10])
|
486
|
-
expect(last_response.status).to eq 200
|
487
|
-
expect(last_response.body).to eq({ type: [10] }.to_json)
|
488
|
-
end
|
489
|
-
|
490
|
-
it 'raises IncompatibleOptionValues when values contains a value that is not a kind of the type' do
|
491
|
-
subject = Class.new(Grape::API)
|
492
|
-
expect do
|
493
|
-
subject.params { requires :type, values: [10.5, 11], type: Integer }
|
494
|
-
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
495
|
-
end
|
496
|
-
|
497
|
-
it 'raises IncompatibleOptionValues when except contains a value that is not a kind of the type' do
|
498
|
-
subject = Class.new(Grape::API)
|
499
|
-
expect do
|
500
|
-
subject.params { requires :type, values: { except: [10.5, 11] }, type: Integer }
|
501
|
-
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
502
|
-
end
|
503
|
-
|
504
|
-
it 'allows a blank value when the allow_blank option is true' do
|
505
|
-
get 'allow_blank', name: nil
|
506
|
-
expect(last_response.status).to eq(200)
|
507
|
-
|
508
|
-
get 'allow_blank', name: ''
|
509
|
-
expect(last_response.status).to eq(200)
|
510
|
-
end
|
511
|
-
|
512
|
-
context 'with a lambda values' do
|
513
|
-
subject do
|
514
|
-
Class.new(Grape::API) do
|
515
|
-
params do
|
516
|
-
optional :type, type: String, values: -> { [SecureRandom.uuid] }, default: -> { SecureRandom.uuid }
|
517
|
-
end
|
518
|
-
get '/random_values'
|
519
|
-
end
|
520
|
-
end
|
521
|
-
|
522
|
-
def app
|
523
|
-
subject
|
524
|
-
end
|
525
|
-
|
526
|
-
before do
|
527
|
-
expect(SecureRandom).to receive(:uuid).and_return('foo').once
|
528
|
-
end
|
529
|
-
|
530
|
-
it 'only evaluates values dynamically with each request' do
|
531
|
-
get '/random_values', type: 'foo'
|
532
|
-
expect(last_response.status).to eq 200
|
533
|
-
end
|
534
|
-
|
535
|
-
it 'chooses default' do
|
536
|
-
get '/random_values'
|
537
|
-
expect(last_response.status).to eq 200
|
538
|
-
end
|
539
|
-
end
|
540
|
-
|
541
|
-
context 'with a range of values' do
|
542
|
-
subject(:app) do
|
543
|
-
Class.new(Grape::API) do
|
544
|
-
params do
|
545
|
-
optional :value, type: Float, values: 0.0..10.0
|
546
|
-
end
|
547
|
-
get '/value' do
|
548
|
-
{ value: params[:value] }.to_json
|
549
|
-
end
|
550
|
-
|
551
|
-
params do
|
552
|
-
optional :values, type: Array[Float], values: 0.0..10.0
|
553
|
-
end
|
554
|
-
get '/values' do
|
555
|
-
{ values: params[:values] }.to_json
|
556
|
-
end
|
557
|
-
end
|
558
|
-
end
|
559
|
-
|
560
|
-
it 'allows a single value inside of the range' do
|
561
|
-
get('/value', value: 5.2)
|
562
|
-
expect(last_response.status).to eq 200
|
563
|
-
expect(last_response.body).to eq({ value: 5.2 }.to_json)
|
564
|
-
end
|
565
|
-
|
566
|
-
it 'allows an array of values inside of the range' do
|
567
|
-
get('/values', values: [8.6, 7.5, 3, 0.9])
|
568
|
-
expect(last_response.status).to eq 200
|
569
|
-
expect(last_response.body).to eq({ values: [8.6, 7.5, 3.0, 0.9] }.to_json)
|
570
|
-
end
|
571
|
-
|
572
|
-
it 'rejects a single value outside the range' do
|
573
|
-
get('/value', value: 'a')
|
574
|
-
expect(last_response.status).to eq 400
|
575
|
-
expect(last_response.body).to eq('value is invalid, value does not have a valid value')
|
576
|
-
end
|
577
|
-
|
578
|
-
it 'rejects an array of values if any of them are outside the range' do
|
579
|
-
get('/values', values: [8.6, 75, 3, 0.9])
|
580
|
-
expect(last_response.status).to eq 400
|
581
|
-
expect(last_response.body).to eq('values does not have a valid value')
|
582
|
-
end
|
583
|
-
end
|
584
|
-
|
585
|
-
context 'exclusive excepts' do
|
586
|
-
it 'allows any other value outside excepts' do
|
587
|
-
get '/except/exclusive', type: 'value'
|
588
|
-
expect(last_response.status).to eq 200
|
589
|
-
expect(last_response.body).to eq({ type: 'value' }.to_json)
|
590
|
-
end
|
591
|
-
|
592
|
-
it 'allows any other value outside excepts when type is included' do
|
593
|
-
get '/except/exclusive/type', type: 'value'
|
594
|
-
expect(last_response.status).to eq 200
|
595
|
-
expect(last_response.body).to eq({ type: 'value' }.to_json)
|
596
|
-
end
|
597
|
-
|
598
|
-
it 'rejects values that matches except' do
|
599
|
-
get '/except/exclusive', type: 'invalid-type1'
|
600
|
-
expect(last_response.status).to eq 400
|
601
|
-
expect(last_response.body).to eq({ error: 'type has a value not allowed' }.to_json)
|
602
|
-
end
|
603
|
-
|
604
|
-
it 'rejects an array of values if any of them matches except' do
|
605
|
-
get '/except/exclusive', type: %w[valid1 valid2 invalid-type1 valid4]
|
606
|
-
expect(last_response.status).to eq 400
|
607
|
-
expect(last_response.body).to eq({ error: 'type has a value not allowed' }.to_json)
|
608
|
-
end
|
609
|
-
end
|
610
|
-
|
611
|
-
context 'exclusive excepts with lambda' do
|
612
|
-
it 'allows any other value outside excepts when type is included' do
|
613
|
-
get '/except/exclusive/lambda/type', type: 'value'
|
614
|
-
expect(last_response.status).to eq 200
|
615
|
-
expect(last_response.body).to eq({ type: 'value' }.to_json)
|
616
|
-
end
|
617
|
-
|
618
|
-
it 'allows any other value outside excepts' do
|
619
|
-
get '/except/exclusive/lambda', type: 'value'
|
620
|
-
expect(last_response.status).to eq 200
|
621
|
-
expect(last_response.body).to eq({ type: 'value' }.to_json)
|
622
|
-
end
|
623
|
-
|
624
|
-
it 'rejects values that matches except' do
|
625
|
-
get '/except/exclusive/lambda', type: 'invalid-type1'
|
626
|
-
expect(last_response.status).to eq 400
|
627
|
-
expect(last_response.body).to eq({ error: 'type has a value not allowed' }.to_json)
|
628
|
-
end
|
629
|
-
end
|
630
|
-
|
631
|
-
context 'exclusive excepts with lambda and coercion' do
|
632
|
-
it 'allows any other value outside excepts' do
|
633
|
-
get '/except/exclusive/lambda/coercion', type: '10010000'
|
634
|
-
expect(last_response.status).to eq 200
|
635
|
-
expect(last_response.body).to eq({ type: 10_010_000 }.to_json)
|
636
|
-
end
|
637
|
-
|
638
|
-
it 'rejects values that matches except' do
|
639
|
-
get '/except/exclusive/lambda/coercion', type: '3'
|
640
|
-
expect(last_response.status).to eq 400
|
641
|
-
expect(last_response.body).to eq({ error: 'type has a value not allowed' }.to_json)
|
642
|
-
end
|
643
|
-
end
|
644
|
-
|
645
|
-
context 'with mixed values and excepts' do
|
646
|
-
it 'allows value, but not in except' do
|
647
|
-
get '/mixed/value/except', type: 2
|
648
|
-
expect(last_response.status).to eq 200
|
649
|
-
expect(last_response.body).to eq({ type: 2 }.to_json)
|
650
|
-
end
|
651
|
-
|
652
|
-
it 'rejects except' do
|
653
|
-
get '/mixed/value/except', type: 3
|
654
|
-
expect(last_response.status).to eq 400
|
655
|
-
expect(last_response.body).to eq({ error: 'type has a value not allowed' }.to_json)
|
656
|
-
end
|
657
|
-
|
658
|
-
it 'rejects outside except and outside value' do
|
659
|
-
get '/mixed/value/except', type: 10
|
660
|
-
expect(last_response.status).to eq 400
|
661
|
-
expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
|
662
|
-
end
|
663
|
-
end
|
664
|
-
|
665
|
-
context 'custom validation using proc' do
|
666
|
-
it 'accepts a single valid value' do
|
667
|
-
get '/proc', type: 'valid-type1'
|
668
|
-
expect(last_response.status).to eq 200
|
669
|
-
expect(last_response.body).to eq({ type: 'valid-type1' }.to_json)
|
670
|
-
end
|
671
|
-
|
672
|
-
it 'accepts multiple valid values' do
|
673
|
-
get '/proc', type: %w[valid-type1 valid-type3]
|
674
|
-
expect(last_response.status).to eq 200
|
675
|
-
expect(last_response.body).to eq({ type: %w[valid-type1 valid-type3] }.to_json)
|
676
|
-
end
|
677
|
-
|
678
|
-
it 'rejects a single invalid value' do
|
679
|
-
get '/proc', type: 'invalid-type1'
|
680
|
-
expect(last_response.status).to eq 400
|
681
|
-
expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
|
682
|
-
end
|
683
|
-
|
684
|
-
it 'rejects an invalid value among valid ones' do
|
685
|
-
get '/proc', type: %w[valid-type1 invalid-type1 valid-type3]
|
686
|
-
expect(last_response.status).to eq 400
|
687
|
-
expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
|
688
|
-
end
|
689
|
-
|
690
|
-
it 'uses supplied message' do
|
691
|
-
get '/proc/message', type: 'invalid-type1'
|
692
|
-
expect(last_response.status).to eq 400
|
693
|
-
expect(last_response.body).to eq({ error: 'type failed check' }.to_json)
|
694
|
-
end
|
695
|
-
end
|
696
|
-
end
|