grape 1.5.2 → 1.7.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 +75 -0
- data/CONTRIBUTING.md +2 -1
- data/README.md +152 -21
- data/UPGRADING.md +86 -2
- data/grape.gemspec +5 -5
- data/lib/grape/api/instance.rb +14 -18
- data/lib/grape/api.rb +18 -13
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dry_types.rb +12 -0
- data/lib/grape/dsl/api.rb +0 -2
- data/lib/grape/dsl/callbacks.rb +0 -2
- data/lib/grape/dsl/configuration.rb +0 -2
- data/lib/grape/dsl/desc.rb +2 -19
- data/lib/grape/dsl/headers.rb +5 -2
- data/lib/grape/dsl/helpers.rb +7 -7
- data/lib/grape/dsl/inside_route.rb +43 -30
- data/lib/grape/dsl/middleware.rb +4 -6
- data/lib/grape/dsl/parameters.rb +8 -10
- data/lib/grape/dsl/request_response.rb +9 -8
- data/lib/grape/dsl/routing.rb +6 -4
- data/lib/grape/dsl/settings.rb +5 -7
- data/lib/grape/dsl/validations.rb +0 -15
- data/lib/grape/endpoint.rb +21 -36
- data/lib/grape/error_formatter/json.rb +9 -7
- data/lib/grape/error_formatter/xml.rb +2 -6
- data/lib/grape/exceptions/base.rb +2 -2
- data/lib/grape/exceptions/empty_message_body.rb +11 -0
- data/lib/grape/exceptions/missing_group_type.rb +8 -1
- data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
- data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
- data/lib/grape/exceptions/validation.rb +1 -6
- data/lib/grape/formatter/json.rb +1 -0
- data/lib/grape/formatter/serializable_hash.rb +2 -1
- data/lib/grape/formatter/xml.rb +1 -0
- data/lib/grape/locale/en.yml +9 -8
- data/lib/grape/middleware/auth/dsl.rb +7 -2
- data/lib/grape/middleware/base.rb +3 -1
- data/lib/grape/middleware/error.rb +2 -2
- data/lib/grape/middleware/formatter.rb +4 -4
- data/lib/grape/middleware/stack.rb +2 -2
- data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
- data/lib/grape/middleware/versioner/header.rb +6 -4
- data/lib/grape/middleware/versioner/param.rb +1 -0
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
- data/lib/grape/middleware/versioner/path.rb +2 -0
- data/lib/grape/parser/json.rb +1 -1
- data/lib/grape/parser/xml.rb +1 -1
- data/lib/grape/path.rb +1 -0
- data/lib/grape/request.rb +5 -0
- data/lib/grape/router/pattern.rb +1 -1
- data/lib/grape/router/route.rb +2 -2
- data/lib/grape/router.rb +6 -0
- data/lib/grape/util/inheritable_setting.rb +1 -3
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/util/lazy_value.rb +3 -2
- data/lib/grape/util/strict_hash_configuration.rb +1 -1
- data/lib/grape/validations/attributes_doc.rb +58 -0
- data/lib/grape/validations/params_scope.rb +137 -78
- data/lib/grape/validations/types/array_coercer.rb +0 -2
- data/lib/grape/validations/types/custom_type_coercer.rb +1 -2
- data/lib/grape/validations/types/dry_type_coercer.rb +4 -8
- data/lib/grape/validations/types/json.rb +2 -1
- data/lib/grape/validations/types/primitive_coercer.rb +16 -8
- data/lib/grape/validations/types/set_coercer.rb +0 -2
- data/lib/grape/validations/types.rb +98 -30
- data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
- data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
- data/lib/grape/validations/validators/as_validator.rb +14 -0
- data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
- data/lib/grape/validations/validators/base.rb +82 -70
- data/lib/grape/validations/validators/coerce_validator.rb +75 -0
- data/lib/grape/validations/validators/default_validator.rb +51 -0
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
- data/lib/grape/validations/validators/except_values_validator.rb +24 -0
- data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
- data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
- data/lib/grape/validations/validators/presence_validator.rb +15 -0
- data/lib/grape/validations/validators/regexp_validator.rb +16 -0
- data/lib/grape/validations/validators/same_as_validator.rb +29 -0
- data/lib/grape/validations/validators/values_validator.rb +88 -0
- data/lib/grape/validations.rb +16 -6
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +70 -29
- data/spec/grape/api/custom_validations_spec.rb +116 -45
- data/spec/grape/api/deeply_included_options_spec.rb +3 -5
- data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -3
- data/spec/grape/api/documentation_spec.rb +59 -0
- data/spec/grape/api/inherited_helpers_spec.rb +0 -2
- data/spec/grape/api/instance_spec.rb +0 -1
- data/spec/grape/api/invalid_format_spec.rb +2 -2
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/nested_helpers_spec.rb +0 -2
- data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/parameters_modification_spec.rb +0 -2
- data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
- data/spec/grape/api/recognize_path_spec.rb +1 -3
- data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
- data/spec/grape/api/routes_with_requirements_spec.rb +8 -10
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -17
- data/spec/grape/api/shared_helpers_spec.rb +0 -2
- data/spec/grape/api_remount_spec.rb +16 -16
- data/spec/grape/api_spec.rb +527 -224
- data/spec/grape/config_spec.rb +0 -2
- data/spec/grape/dsl/callbacks_spec.rb +2 -3
- data/spec/grape/dsl/configuration_spec.rb +0 -2
- data/spec/grape/dsl/desc_spec.rb +0 -2
- data/spec/grape/dsl/headers_spec.rb +39 -11
- data/spec/grape/dsl/helpers_spec.rb +3 -4
- data/spec/grape/dsl/inside_route_spec.rb +16 -16
- data/spec/grape/dsl/logger_spec.rb +15 -19
- data/spec/grape/dsl/middleware_spec.rb +2 -3
- data/spec/grape/dsl/parameters_spec.rb +2 -2
- data/spec/grape/dsl/request_response_spec.rb +7 -8
- data/spec/grape/dsl/routing_spec.rb +11 -10
- data/spec/grape/dsl/settings_spec.rb +0 -2
- data/spec/grape/dsl/validations_spec.rb +0 -17
- data/spec/grape/endpoint/declared_spec.rb +261 -16
- data/spec/grape/endpoint_spec.rb +98 -57
- data/spec/grape/entity_spec.rb +22 -23
- data/spec/grape/exceptions/base_spec.rb +16 -2
- data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -2
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -24
- data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
- data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
- data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
- data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
- data/spec/grape/exceptions/missing_option_spec.rb +1 -3
- data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
- data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
- data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
- data/spec/grape/exceptions/validation_errors_spec.rb +13 -11
- data/spec/grape/exceptions/validation_spec.rb +5 -5
- data/spec/grape/extensions/param_builders/hash_spec.rb +7 -9
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -10
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -10
- data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
- data/spec/grape/integration/rack_sendfile_spec.rb +1 -3
- data/spec/grape/integration/rack_spec.rb +0 -2
- data/spec/grape/loading_spec.rb +8 -10
- data/spec/grape/middleware/auth/base_spec.rb +0 -1
- data/spec/grape/middleware/auth/dsl_spec.rb +15 -8
- data/spec/grape/middleware/auth/strategies_spec.rb +60 -22
- data/spec/grape/middleware/base_spec.rb +24 -17
- data/spec/grape/middleware/error_spec.rb +8 -3
- data/spec/grape/middleware/exception_spec.rb +111 -163
- data/spec/grape/middleware/formatter_spec.rb +27 -8
- data/spec/grape/middleware/globals_spec.rb +7 -6
- data/spec/grape/middleware/stack_spec.rb +14 -14
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -3
- data/spec/grape/middleware/versioner/header_spec.rb +30 -15
- data/spec/grape/middleware/versioner/param_spec.rb +7 -3
- data/spec/grape/middleware/versioner/path_spec.rb +5 -3
- data/spec/grape/middleware/versioner_spec.rb +1 -3
- data/spec/grape/named_api_spec.rb +0 -2
- data/spec/grape/parser_spec.rb +4 -2
- data/spec/grape/path_spec.rb +52 -54
- data/spec/grape/presenters/presenter_spec.rb +7 -8
- data/spec/grape/request_spec.rb +6 -6
- data/spec/grape/util/inheritable_setting_spec.rb +7 -8
- data/spec/grape/util/inheritable_values_spec.rb +3 -3
- data/spec/grape/util/reverse_stackable_values_spec.rb +3 -2
- data/spec/grape/util/stackable_values_spec.rb +7 -6
- data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
- data/spec/grape/validations/attributes_doc_spec.rb +153 -0
- data/spec/grape/validations/attributes_iterator_spec.rb +0 -2
- data/spec/grape/validations/instance_behaivour_spec.rb +9 -12
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -2
- data/spec/grape/validations/params_scope_spec.rb +361 -96
- data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -3
- data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
- data/spec/grape/validations/types/primitive_coercer_spec.rb +24 -9
- data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
- data/spec/grape/validations/types_spec.rb +36 -10
- data/spec/grape/validations/validators/all_or_none_spec.rb +50 -58
- data/spec/grape/validations/validators/allow_blank_spec.rb +135 -141
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -58
- data/spec/grape/validations/validators/coerce_spec.rb +99 -24
- data/spec/grape/validations/validators/default_spec.rb +72 -80
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -79
- data/spec/grape/validations/validators/except_values_spec.rb +3 -5
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -79
- data/spec/grape/validations/validators/presence_spec.rb +16 -3
- data/spec/grape/validations/validators/regexp_spec.rb +25 -33
- data/spec/grape/validations/validators/same_as_spec.rb +14 -22
- data/spec/grape/validations/validators/values_spec.rb +182 -179
- data/spec/grape/validations_spec.rb +149 -80
- data/spec/integration/eager_load/eager_load_spec.rb +2 -2
- data/spec/integration/multi_json/json_spec.rb +1 -3
- data/spec/integration/multi_xml/xml_spec.rb +1 -3
- data/spec/shared/versioning_examples.rb +12 -9
- data/spec/spec_helper.rb +21 -6
- data/spec/support/basic_auth_encode_helpers.rb +1 -1
- metadata +125 -115
- data/lib/grape/validations/validators/all_or_none.rb +0 -15
- data/lib/grape/validations/validators/allow_blank.rb +0 -18
- data/lib/grape/validations/validators/as.rb +0 -16
- data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
- data/lib/grape/validations/validators/coerce.rb +0 -91
- data/lib/grape/validations/validators/default.rb +0 -48
- data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
- data/lib/grape/validations/validators/except_values.rb +0 -22
- data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
- data/lib/grape/validations/validators/presence.rb +0 -12
- data/lib/grape/validations/validators/regexp.rb +0 -13
- data/lib/grape/validations/validators/same_as.rb +0 -26
- data/lib/grape/validations/validators/values.rb +0 -83
- data/spec/support/eager_load.rb +0 -19
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
3
|
describe Grape::Validations::ParamsScope do
|
6
4
|
subject do
|
7
5
|
Class.new(Grape::API)
|
@@ -11,86 +9,6 @@ describe Grape::Validations::ParamsScope do
|
|
11
9
|
subject
|
12
10
|
end
|
13
11
|
|
14
|
-
context 'setting a default' do
|
15
|
-
let(:documentation) { subject.routes.first.params }
|
16
|
-
|
17
|
-
context 'when the default value is truthy' do
|
18
|
-
before do
|
19
|
-
subject.params do
|
20
|
-
optional :int, type: Integer, default: 42
|
21
|
-
end
|
22
|
-
subject.get
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'adds documentation about the default value' do
|
26
|
-
expect(documentation).to have_key('int')
|
27
|
-
expect(documentation['int']).to have_key(:default)
|
28
|
-
expect(documentation['int'][:default]).to eq(42)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context 'when the default value is false' do
|
33
|
-
before do
|
34
|
-
subject.params do
|
35
|
-
optional :bool, type: Grape::API::Boolean, default: false
|
36
|
-
end
|
37
|
-
subject.get
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'adds documentation about the default value' do
|
41
|
-
expect(documentation).to have_key('bool')
|
42
|
-
expect(documentation['bool']).to have_key(:default)
|
43
|
-
expect(documentation['bool'][:default]).to eq(false)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
context 'when the default value is nil' do
|
48
|
-
before do
|
49
|
-
subject.params do
|
50
|
-
optional :object, type: Object, default: nil
|
51
|
-
end
|
52
|
-
subject.get
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'adds documentation about the default value' do
|
56
|
-
expect(documentation).to have_key('object')
|
57
|
-
expect(documentation['object']).to have_key(:default)
|
58
|
-
expect(documentation['object'][:default]).to eq(nil)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context 'without a default' do
|
64
|
-
before do
|
65
|
-
subject.params do
|
66
|
-
optional :object, type: Object
|
67
|
-
end
|
68
|
-
subject.get
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'does not add documentation for the default value' do
|
72
|
-
documentation = subject.routes.first.params
|
73
|
-
expect(documentation).to have_key('object')
|
74
|
-
expect(documentation['object']).not_to have_key(:default)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
context 'setting description' do
|
79
|
-
%i[desc description].each do |description_type|
|
80
|
-
it "allows setting #{description_type}" do
|
81
|
-
subject.params do
|
82
|
-
requires :int, type: Integer, description_type => 'My very nice integer'
|
83
|
-
end
|
84
|
-
subject.get '/single' do
|
85
|
-
'int works'
|
86
|
-
end
|
87
|
-
get '/single', int: 420
|
88
|
-
expect(last_response.status).to eq(200)
|
89
|
-
expect(last_response.body).to eq('int works')
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
12
|
context 'when using custom types' do
|
95
13
|
module ParamsScopeSpec
|
96
14
|
class CustomType
|
@@ -98,6 +16,7 @@ describe Grape::Validations::ParamsScope do
|
|
98
16
|
|
99
17
|
def self.parse(value)
|
100
18
|
raise if value == 'invalid'
|
19
|
+
|
101
20
|
new(value)
|
102
21
|
end
|
103
22
|
|
@@ -144,7 +63,7 @@ describe Grape::Validations::ParamsScope do
|
|
144
63
|
get '/renaming-coerced', foo: ' there we go '
|
145
64
|
|
146
65
|
expect(last_response.status).to eq(200)
|
147
|
-
expect(last_response.body).to eq('there we go
|
66
|
+
expect(last_response.body).to eq('-there we go')
|
148
67
|
end
|
149
68
|
|
150
69
|
it do
|
@@ -180,6 +99,28 @@ describe Grape::Validations::ParamsScope do
|
|
180
99
|
expect(last_response.status).to eq(200)
|
181
100
|
expect(last_response.body).to eq('{"baz":{"qux":"any"}}')
|
182
101
|
end
|
102
|
+
|
103
|
+
it 'renaming can be defined before default' do
|
104
|
+
subject.params do
|
105
|
+
optional :foo, as: :bar, default: 'before'
|
106
|
+
end
|
107
|
+
subject.get('/rename-before-default') { declared(params)[:bar] }
|
108
|
+
get '/rename-before-default'
|
109
|
+
|
110
|
+
expect(last_response.status).to eq(200)
|
111
|
+
expect(last_response.body).to eq('before')
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'renaming can be defined after default' do
|
115
|
+
subject.params do
|
116
|
+
optional :foo, default: 'after', as: :bar
|
117
|
+
end
|
118
|
+
subject.get('/rename-after-default') { declared(params)[:bar] }
|
119
|
+
get '/rename-after-default'
|
120
|
+
|
121
|
+
expect(last_response.status).to eq(200)
|
122
|
+
expect(last_response.body).to eq('after')
|
123
|
+
end
|
183
124
|
end
|
184
125
|
|
185
126
|
context 'array without coerce type explicitly given' do
|
@@ -269,7 +210,7 @@ describe Grape::Validations::ParamsScope do
|
|
269
210
|
it 'does not raise an exception' do
|
270
211
|
expect do
|
271
212
|
subject.params { optional :numbers, type: Array[Integer], values: 0..2, default: 0..2 }
|
272
|
-
end.
|
213
|
+
end.not_to raise_error
|
273
214
|
end
|
274
215
|
end
|
275
216
|
|
@@ -277,7 +218,7 @@ describe Grape::Validations::ParamsScope do
|
|
277
218
|
it 'does not raise an exception' do
|
278
219
|
expect do
|
279
220
|
subject.params { optional :numbers, type: Array[Integer], values: [0, 1, 2], default: [1, 0] }
|
280
|
-
end.
|
221
|
+
end.not_to raise_error
|
281
222
|
end
|
282
223
|
end
|
283
224
|
end
|
@@ -315,7 +256,7 @@ describe Grape::Validations::ParamsScope do
|
|
315
256
|
requires :b
|
316
257
|
end
|
317
258
|
end
|
318
|
-
end.to raise_error Grape::Exceptions::
|
259
|
+
end.to raise_error Grape::Exceptions::MissingGroupType
|
319
260
|
|
320
261
|
expect do
|
321
262
|
subject.params do
|
@@ -323,7 +264,7 @@ describe Grape::Validations::ParamsScope do
|
|
323
264
|
requires :b
|
324
265
|
end
|
325
266
|
end
|
326
|
-
end.to raise_error Grape::Exceptions::
|
267
|
+
end.to raise_error Grape::Exceptions::MissingGroupType
|
327
268
|
end
|
328
269
|
|
329
270
|
it 'allows Hash as type' do
|
@@ -383,7 +324,7 @@ describe Grape::Validations::ParamsScope do
|
|
383
324
|
requires :b
|
384
325
|
end
|
385
326
|
end
|
386
|
-
end.to raise_error Grape::Exceptions::
|
327
|
+
end.to raise_error Grape::Exceptions::UnsupportedGroupType
|
387
328
|
|
388
329
|
expect do
|
389
330
|
subject.params do
|
@@ -391,7 +332,7 @@ describe Grape::Validations::ParamsScope do
|
|
391
332
|
requires :b
|
392
333
|
end
|
393
334
|
end
|
394
|
-
end.to raise_error Grape::Exceptions::
|
335
|
+
end.to raise_error Grape::Exceptions::UnsupportedGroupType
|
395
336
|
end
|
396
337
|
end
|
397
338
|
|
@@ -501,7 +442,7 @@ describe Grape::Validations::ParamsScope do
|
|
501
442
|
requires :c
|
502
443
|
end
|
503
444
|
end
|
504
|
-
end.
|
445
|
+
end.not_to raise_error
|
505
446
|
end
|
506
447
|
|
507
448
|
it 'does not raise an error if when using nested given' do
|
@@ -517,7 +458,7 @@ describe Grape::Validations::ParamsScope do
|
|
517
458
|
end
|
518
459
|
end
|
519
460
|
end
|
520
|
-
end.
|
461
|
+
end.not_to raise_error
|
521
462
|
end
|
522
463
|
|
523
464
|
it 'allows nested dependent parameters' do
|
@@ -562,13 +503,13 @@ describe Grape::Validations::ParamsScope do
|
|
562
503
|
body = JSON.parse(last_response.body)
|
563
504
|
|
564
505
|
expect(body.keys).to include('c')
|
565
|
-
expect(body.keys).
|
506
|
+
expect(body.keys).not_to include('b')
|
566
507
|
end
|
567
508
|
|
568
509
|
it 'allows renaming of dependent on parameter' do
|
569
510
|
subject.params do
|
570
511
|
optional :a, as: :b
|
571
|
-
given
|
512
|
+
given a: ->(val) { val == 'x' } do
|
572
513
|
requires :c
|
573
514
|
end
|
574
515
|
end
|
@@ -582,7 +523,7 @@ describe Grape::Validations::ParamsScope do
|
|
582
523
|
expect(last_response.status).to eq 200
|
583
524
|
end
|
584
525
|
|
585
|
-
it '
|
526
|
+
it 'does not raise if the dependent parameter is not the renamed one' do
|
586
527
|
expect do
|
587
528
|
subject.params do
|
588
529
|
optional :a, as: :b
|
@@ -590,6 +531,17 @@ describe Grape::Validations::ParamsScope do
|
|
590
531
|
requires :c
|
591
532
|
end
|
592
533
|
end
|
534
|
+
end.not_to raise_error
|
535
|
+
end
|
536
|
+
|
537
|
+
it 'raises an error if the dependent parameter is the renamed one' do
|
538
|
+
expect do
|
539
|
+
subject.params do
|
540
|
+
optional :a, as: :b
|
541
|
+
given :b do
|
542
|
+
requires :c
|
543
|
+
end
|
544
|
+
end
|
593
545
|
end.to raise_error(Grape::Exceptions::UnknownParameter)
|
594
546
|
end
|
595
547
|
|
@@ -712,6 +664,317 @@ describe Grape::Validations::ParamsScope do
|
|
712
664
|
get '/nested', bar: { a: true, c: { b: 'yes' } }
|
713
665
|
expect(JSON.parse(last_response.body)).to eq('bar' => { 'a' => 'true', 'c' => { 'b' => 'yes' } })
|
714
666
|
end
|
667
|
+
|
668
|
+
context 'when the dependent parameter is not present #declared(params)' do
|
669
|
+
context 'lateral parameter' do
|
670
|
+
before do
|
671
|
+
[true, false].each do |evaluate_given|
|
672
|
+
subject.params do
|
673
|
+
optional :a
|
674
|
+
given :a do
|
675
|
+
optional :b
|
676
|
+
end
|
677
|
+
end
|
678
|
+
subject.get("/evaluate_given_#{evaluate_given}") { declared(params, evaluate_given: evaluate_given).to_json }
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
it 'evaluate_given_false' do
|
683
|
+
get '/evaluate_given_false', b: 'b'
|
684
|
+
expect(JSON.parse(last_response.body)).to eq('a' => nil, 'b' => 'b')
|
685
|
+
end
|
686
|
+
|
687
|
+
it 'evaluate_given_true' do
|
688
|
+
get '/evaluate_given_true', b: 'b'
|
689
|
+
expect(JSON.parse(last_response.body)).to eq('a' => nil)
|
690
|
+
end
|
691
|
+
end
|
692
|
+
|
693
|
+
context 'lateral hash parameter' do
|
694
|
+
before do
|
695
|
+
[true, false].each do |evaluate_given|
|
696
|
+
subject.params do
|
697
|
+
optional :a, values: %w[x y]
|
698
|
+
given a: ->(a) { a == 'x' } do
|
699
|
+
optional :b, type: Hash do
|
700
|
+
optional :c
|
701
|
+
end
|
702
|
+
optional :e
|
703
|
+
end
|
704
|
+
given a: ->(a) { a == 'y' } do
|
705
|
+
optional :b, type: Hash do
|
706
|
+
optional :d
|
707
|
+
end
|
708
|
+
optional :f
|
709
|
+
end
|
710
|
+
end
|
711
|
+
subject.get("/evaluate_given_#{evaluate_given}") { declared(params, evaluate_given: evaluate_given).to_json }
|
712
|
+
end
|
713
|
+
end
|
714
|
+
|
715
|
+
it 'evaluate_given_false' do
|
716
|
+
get '/evaluate_given_false', a: 'x'
|
717
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'x', 'b' => { 'd' => nil }, 'e' => nil, 'f' => nil)
|
718
|
+
|
719
|
+
get '/evaluate_given_false', a: 'y'
|
720
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'y', 'b' => { 'd' => nil }, 'e' => nil, 'f' => nil)
|
721
|
+
end
|
722
|
+
|
723
|
+
it 'evaluate_given_true' do
|
724
|
+
get '/evaluate_given_true', a: 'x'
|
725
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'x', 'b' => { 'c' => nil }, 'e' => nil)
|
726
|
+
|
727
|
+
get '/evaluate_given_true', a: 'y'
|
728
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'y', 'b' => { 'd' => nil }, 'f' => nil)
|
729
|
+
end
|
730
|
+
end
|
731
|
+
|
732
|
+
context 'lateral parameter within lateral hash parameter' do
|
733
|
+
before do
|
734
|
+
[true, false].each do |evaluate_given|
|
735
|
+
subject.params do
|
736
|
+
optional :a, values: %w[x y]
|
737
|
+
given a: ->(a) { a == 'x' } do
|
738
|
+
optional :b, type: Hash do
|
739
|
+
optional :c
|
740
|
+
given :c do
|
741
|
+
optional :g
|
742
|
+
optional :e, type: Hash do
|
743
|
+
optional :h
|
744
|
+
end
|
745
|
+
end
|
746
|
+
end
|
747
|
+
end
|
748
|
+
given a: ->(a) { a == 'y' } do
|
749
|
+
optional :b, type: Hash do
|
750
|
+
optional :d
|
751
|
+
given :d do
|
752
|
+
optional :f
|
753
|
+
optional :e, type: Hash do
|
754
|
+
optional :i
|
755
|
+
end
|
756
|
+
end
|
757
|
+
end
|
758
|
+
end
|
759
|
+
end
|
760
|
+
subject.get("/evaluate_given_#{evaluate_given}") { declared(params, evaluate_given: evaluate_given).to_json }
|
761
|
+
end
|
762
|
+
end
|
763
|
+
|
764
|
+
it 'evaluate_given_false' do
|
765
|
+
get '/evaluate_given_false', a: 'x'
|
766
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'x', 'b' => { 'd' => nil, 'f' => nil, 'e' => { 'i' => nil } })
|
767
|
+
|
768
|
+
get '/evaluate_given_false', a: 'x', b: { c: 'c' }
|
769
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'x', 'b' => { 'd' => nil, 'f' => nil, 'e' => { 'i' => nil } })
|
770
|
+
|
771
|
+
get '/evaluate_given_false', a: 'y'
|
772
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'y', 'b' => { 'd' => nil, 'f' => nil, 'e' => { 'i' => nil } })
|
773
|
+
|
774
|
+
get '/evaluate_given_false', a: 'y', b: { d: 'd' }
|
775
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'y', 'b' => { 'd' => 'd', 'f' => nil, 'e' => { 'i' => nil } })
|
776
|
+
end
|
777
|
+
|
778
|
+
it 'evaluate_given_true' do
|
779
|
+
get '/evaluate_given_true', a: 'x'
|
780
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'x', 'b' => { 'c' => nil })
|
781
|
+
|
782
|
+
get '/evaluate_given_true', a: 'x', b: { c: 'c' }
|
783
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'x', 'b' => { 'c' => 'c', 'g' => nil, 'e' => { 'h' => nil } })
|
784
|
+
|
785
|
+
get '/evaluate_given_true', a: 'y'
|
786
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'y', 'b' => { 'd' => nil })
|
787
|
+
|
788
|
+
get '/evaluate_given_true', a: 'y', b: { d: 'd' }
|
789
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'y', 'b' => { 'd' => 'd', 'f' => nil, 'e' => { 'i' => nil } })
|
790
|
+
end
|
791
|
+
end
|
792
|
+
|
793
|
+
context 'lateral parameter within an array param' do
|
794
|
+
before do
|
795
|
+
[true, false].each do |evaluate_given|
|
796
|
+
subject.params do
|
797
|
+
optional :array, type: Array do
|
798
|
+
optional :a
|
799
|
+
given :a do
|
800
|
+
optional :b
|
801
|
+
end
|
802
|
+
end
|
803
|
+
end
|
804
|
+
subject.post("/evaluate_given_#{evaluate_given}") do
|
805
|
+
declared(params, evaluate_given: evaluate_given).to_json
|
806
|
+
end
|
807
|
+
end
|
808
|
+
end
|
809
|
+
|
810
|
+
it 'evaluate_given_false' do
|
811
|
+
post '/evaluate_given_false', { array: [{ b: 'b' }, { a: 'a', b: 'b' }] }.to_json, 'CONTENT_TYPE' => 'application/json'
|
812
|
+
expect(JSON.parse(last_response.body)).to eq('array' => [{ 'a' => nil, 'b' => 'b' }, { 'a' => 'a', 'b' => 'b' }])
|
813
|
+
end
|
814
|
+
|
815
|
+
it 'evaluate_given_true' do
|
816
|
+
post '/evaluate_given_true', { array: [{ b: 'b' }, { a: 'a', b: 'b' }] }.to_json, 'CONTENT_TYPE' => 'application/json'
|
817
|
+
expect(JSON.parse(last_response.body)).to eq('array' => [{ 'a' => nil }, { 'a' => 'a', 'b' => 'b' }])
|
818
|
+
end
|
819
|
+
end
|
820
|
+
|
821
|
+
context 'nested given parameter' do
|
822
|
+
before do
|
823
|
+
[true, false].each do |evaluate_given|
|
824
|
+
subject.params do
|
825
|
+
optional :a
|
826
|
+
optional :c
|
827
|
+
given :a do
|
828
|
+
given :c do
|
829
|
+
optional :b
|
830
|
+
end
|
831
|
+
end
|
832
|
+
end
|
833
|
+
subject.post("/evaluate_given_#{evaluate_given}") do
|
834
|
+
declared(params, evaluate_given: evaluate_given).to_json
|
835
|
+
end
|
836
|
+
end
|
837
|
+
end
|
838
|
+
|
839
|
+
it 'evaluate_given_false' do
|
840
|
+
post '/evaluate_given_false', { a: 'a', b: 'b' }.to_json, 'CONTENT_TYPE' => 'application/json'
|
841
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'a', 'b' => 'b', 'c' => nil)
|
842
|
+
|
843
|
+
post '/evaluate_given_false', { c: 'c', b: 'b' }.to_json, 'CONTENT_TYPE' => 'application/json'
|
844
|
+
expect(JSON.parse(last_response.body)).to eq('a' => nil, 'b' => 'b', 'c' => 'c')
|
845
|
+
|
846
|
+
post '/evaluate_given_false', { a: 'a', c: 'c', b: 'b' }.to_json, 'CONTENT_TYPE' => 'application/json'
|
847
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'a', 'b' => 'b', 'c' => 'c')
|
848
|
+
end
|
849
|
+
|
850
|
+
it 'evaluate_given_true' do
|
851
|
+
post '/evaluate_given_true', { a: 'a', b: 'b' }.to_json, 'CONTENT_TYPE' => 'application/json'
|
852
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'a', 'c' => nil)
|
853
|
+
|
854
|
+
post '/evaluate_given_true', { c: 'c', b: 'b' }.to_json, 'CONTENT_TYPE' => 'application/json'
|
855
|
+
expect(JSON.parse(last_response.body)).to eq('a' => nil, 'c' => 'c')
|
856
|
+
|
857
|
+
post '/evaluate_given_true', { a: 'a', c: 'c', b: 'b' }.to_json, 'CONTENT_TYPE' => 'application/json'
|
858
|
+
expect(JSON.parse(last_response.body)).to eq('a' => 'a', 'b' => 'b', 'c' => 'c')
|
859
|
+
end
|
860
|
+
end
|
861
|
+
|
862
|
+
context 'nested given parameter within an array param' do
|
863
|
+
before do
|
864
|
+
[true, false].each do |evaluate_given|
|
865
|
+
subject.params do
|
866
|
+
optional :array, type: Array do
|
867
|
+
optional :a
|
868
|
+
optional :c
|
869
|
+
given :a do
|
870
|
+
given :c do
|
871
|
+
optional :b
|
872
|
+
end
|
873
|
+
end
|
874
|
+
end
|
875
|
+
end
|
876
|
+
subject.post("/evaluate_given_#{evaluate_given}") do
|
877
|
+
declared(params, evaluate_given: evaluate_given).to_json
|
878
|
+
end
|
879
|
+
end
|
880
|
+
end
|
881
|
+
|
882
|
+
let :evaluate_given_params do
|
883
|
+
{
|
884
|
+
array: [
|
885
|
+
{ a: 'a', b: 'b' },
|
886
|
+
{ c: 'c', b: 'b' },
|
887
|
+
{ a: 'a', c: 'c', b: 'b' }
|
888
|
+
]
|
889
|
+
}
|
890
|
+
end
|
891
|
+
|
892
|
+
it 'evaluate_given_false' do
|
893
|
+
post '/evaluate_given_false', evaluate_given_params.to_json, 'CONTENT_TYPE' => 'application/json'
|
894
|
+
expect(JSON.parse(last_response.body)).to eq('array' => [{ 'a' => 'a', 'b' => 'b', 'c' => nil }, { 'a' => nil, 'b' => 'b', 'c' => 'c' }, { 'a' => 'a', 'b' => 'b', 'c' => 'c' }])
|
895
|
+
end
|
896
|
+
|
897
|
+
it 'evaluate_given_true' do
|
898
|
+
post '/evaluate_given_true', evaluate_given_params.to_json, 'CONTENT_TYPE' => 'application/json'
|
899
|
+
expect(JSON.parse(last_response.body)).to eq('array' => [{ 'a' => 'a', 'c' => nil }, { 'a' => nil, 'c' => 'c' }, { 'a' => 'a', 'b' => 'b', 'c' => 'c' }])
|
900
|
+
end
|
901
|
+
end
|
902
|
+
|
903
|
+
context 'nested given parameter within a nested given parameter within an array param' do
|
904
|
+
before do
|
905
|
+
[true, false].each do |evaluate_given|
|
906
|
+
subject.params do
|
907
|
+
optional :array, type: Array do
|
908
|
+
optional :a
|
909
|
+
optional :c
|
910
|
+
given :a do
|
911
|
+
given :c do
|
912
|
+
optional :array, type: Array do
|
913
|
+
optional :a
|
914
|
+
optional :c
|
915
|
+
given :a do
|
916
|
+
given :c do
|
917
|
+
optional :b
|
918
|
+
end
|
919
|
+
end
|
920
|
+
end
|
921
|
+
end
|
922
|
+
end
|
923
|
+
end
|
924
|
+
end
|
925
|
+
subject.post("/evaluate_given_#{evaluate_given}") do
|
926
|
+
declared(params, evaluate_given: evaluate_given).to_json
|
927
|
+
end
|
928
|
+
end
|
929
|
+
end
|
930
|
+
|
931
|
+
let :evaluate_given_params do
|
932
|
+
{
|
933
|
+
array: [{
|
934
|
+
a: 'a',
|
935
|
+
c: 'c',
|
936
|
+
array: [
|
937
|
+
{ a: 'a', b: 'b' },
|
938
|
+
{ c: 'c', b: 'b' },
|
939
|
+
{ a: 'a', c: 'c', b: 'b' }
|
940
|
+
]
|
941
|
+
}]
|
942
|
+
}
|
943
|
+
end
|
944
|
+
|
945
|
+
it 'evaluate_given_false' do
|
946
|
+
expected_response_hash = {
|
947
|
+
'array' => [{
|
948
|
+
'a' => 'a',
|
949
|
+
'c' => 'c',
|
950
|
+
'array' => [
|
951
|
+
{ 'a' => 'a', 'b' => 'b', 'c' => nil },
|
952
|
+
{ 'a' => nil, 'c' => 'c', 'b' => 'b' },
|
953
|
+
{ 'a' => 'a', 'c' => 'c', 'b' => 'b' }
|
954
|
+
]
|
955
|
+
}]
|
956
|
+
}
|
957
|
+
post '/evaluate_given_false', evaluate_given_params.to_json, 'CONTENT_TYPE' => 'application/json'
|
958
|
+
expect(JSON.parse(last_response.body)).to eq(expected_response_hash)
|
959
|
+
end
|
960
|
+
|
961
|
+
it 'evaluate_given_true' do
|
962
|
+
expected_response_hash = {
|
963
|
+
'array' => [{
|
964
|
+
'a' => 'a',
|
965
|
+
'c' => 'c',
|
966
|
+
'array' => [
|
967
|
+
{ 'a' => 'a', 'c' => nil },
|
968
|
+
{ 'a' => nil, 'c' => 'c' },
|
969
|
+
{ 'a' => 'a', 'b' => 'b', 'c' => 'c' }
|
970
|
+
]
|
971
|
+
}]
|
972
|
+
}
|
973
|
+
post '/evaluate_given_true', evaluate_given_params.to_json, 'CONTENT_TYPE' => 'application/json'
|
974
|
+
expect(JSON.parse(last_response.body)).to eq(expected_response_hash)
|
975
|
+
end
|
976
|
+
end
|
977
|
+
end
|
715
978
|
end
|
716
979
|
|
717
980
|
context 'default value in given block' do
|
@@ -753,7 +1016,7 @@ describe Grape::Validations::ParamsScope do
|
|
753
1016
|
subject.get('/test') { 'ok' }
|
754
1017
|
end
|
755
1018
|
|
756
|
-
it '
|
1019
|
+
it 'passes none Hash params' do
|
757
1020
|
get '/test', foos: ['']
|
758
1021
|
expect(last_response.status).to eq(200)
|
759
1022
|
expect(last_response.body).to eq('ok')
|
@@ -929,6 +1192,7 @@ describe Grape::Validations::ParamsScope do
|
|
929
1192
|
expect(last_response.body).to eq('one is missing, two is missing, three is missing')
|
930
1193
|
end
|
931
1194
|
end
|
1195
|
+
|
932
1196
|
context 'when fail_fast is defined it stops the validation' do
|
933
1197
|
it 'of other params' do
|
934
1198
|
subject.params do
|
@@ -941,6 +1205,7 @@ describe Grape::Validations::ParamsScope do
|
|
941
1205
|
expect(last_response.status).to eq(400)
|
942
1206
|
expect(last_response.body).to eq('one is missing')
|
943
1207
|
end
|
1208
|
+
|
944
1209
|
it 'for a single param' do
|
945
1210
|
subject.params do
|
946
1211
|
requires :one, allow_blank: false, regexp: /[0-9]+/, fail_fast: true
|
@@ -991,7 +1256,7 @@ describe Grape::Validations::ParamsScope do
|
|
991
1256
|
end
|
992
1257
|
|
993
1258
|
it 'prioritizes parameter validation over group validation' do
|
994
|
-
expect(last_response.body).
|
1259
|
+
expect(last_response.body).not_to include('address is empty')
|
995
1260
|
end
|
996
1261
|
end
|
997
1262
|
end
|
@@ -1,10 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
3
|
describe Grape::Validations::SingleAttributeIterator do
|
6
4
|
describe '#each' do
|
7
5
|
subject(:iterator) { described_class.new(validator, scope, params) }
|
6
|
+
|
8
7
|
let(:scope) { Grape::Validations::ParamsScope.new(api: Class.new(Grape::API)) }
|
9
8
|
let(:validator) { double(attrs: %i[first second]) }
|
10
9
|
|
@@ -49,7 +48,7 @@ describe Grape::Validations::SingleAttributeIterator do
|
|
49
48
|
it 'marks params with skipped values' do
|
50
49
|
expect { |b| iterator.each(&b) }.to yield_successive_args(
|
51
50
|
[params[0], :first, false, true], [params[0], :second, false, true],
|
52
|
-
[params[1], :first, false, false], [params[1], :second, false, false]
|
51
|
+
[params[1], :first, false, false], [params[1], :second, false, false]
|
53
52
|
)
|
54
53
|
end
|
55
54
|
end
|