grape 1.8.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +65 -1
- data/README.md +377 -334
- data/UPGRADING.md +231 -6
- data/grape.gemspec +6 -10
- data/lib/grape/api/instance.rb +13 -10
- data/lib/grape/api.rb +17 -8
- data/lib/grape/content_types.rb +0 -2
- data/lib/grape/cookies.rb +2 -1
- data/lib/grape/dry_types.rb +0 -2
- data/lib/grape/dsl/desc.rb +23 -21
- data/lib/grape/dsl/headers.rb +1 -1
- data/lib/grape/dsl/inside_route.rb +47 -22
- data/lib/grape/dsl/parameters.rb +4 -3
- data/lib/grape/dsl/routing.rb +20 -4
- data/lib/grape/dsl/validations.rb +13 -0
- data/lib/grape/endpoint.rb +15 -10
- data/lib/grape/{util/env.rb → env.rb} +0 -5
- data/lib/grape/error_formatter/txt.rb +11 -10
- data/lib/grape/exceptions/base.rb +3 -3
- data/lib/grape/exceptions/missing_group_type.rb +1 -1
- data/lib/grape/exceptions/unsupported_group_type.rb +1 -1
- data/lib/grape/exceptions/validation.rb +0 -2
- data/lib/grape/exceptions/validation_array_errors.rb +1 -0
- data/lib/grape/exceptions/validation_errors.rb +1 -3
- data/lib/grape/extensions/hash.rb +5 -1
- data/lib/grape/http/headers.rb +18 -24
- data/lib/grape/{util/json.rb → json.rb} +1 -3
- data/lib/grape/locale/en.yml +3 -0
- data/lib/grape/middleware/auth/base.rb +0 -2
- data/lib/grape/middleware/auth/dsl.rb +0 -2
- data/lib/grape/middleware/auth/strategies.rb +1 -2
- data/lib/grape/middleware/base.rb +0 -2
- data/lib/grape/middleware/error.rb +55 -50
- data/lib/grape/middleware/formatter.rb +21 -18
- data/lib/grape/middleware/globals.rb +1 -3
- data/lib/grape/middleware/stack.rb +2 -3
- data/lib/grape/middleware/versioner/accept_version_header.rb +0 -2
- data/lib/grape/middleware/versioner/header.rb +17 -163
- data/lib/grape/middleware/versioner/param.rb +2 -4
- data/lib/grape/middleware/versioner/path.rb +1 -3
- data/lib/grape/namespace.rb +3 -4
- data/lib/grape/path.rb +24 -29
- data/lib/grape/railtie.rb +9 -0
- data/lib/grape/request.rb +3 -5
- data/lib/grape/router/base_route.rb +39 -0
- data/lib/grape/router/greedy_route.rb +20 -0
- data/lib/grape/router/pattern.rb +39 -30
- data/lib/grape/router/route.rb +22 -59
- data/lib/grape/router.rb +30 -36
- data/lib/grape/util/accept/header.rb +19 -0
- data/lib/grape/util/accept_header_handler.rb +105 -0
- data/lib/grape/util/base_inheritable.rb +4 -4
- data/lib/grape/util/cache.rb +0 -3
- data/lib/grape/util/endpoint_configuration.rb +1 -1
- data/lib/grape/util/header.rb +13 -0
- data/lib/grape/util/inheritable_values.rb +0 -2
- data/lib/grape/util/lazy/block.rb +29 -0
- data/lib/grape/util/lazy/object.rb +45 -0
- data/lib/grape/util/lazy/value.rb +38 -0
- data/lib/grape/util/lazy/value_array.rb +21 -0
- data/lib/grape/util/lazy/value_enumerable.rb +34 -0
- data/lib/grape/util/lazy/value_hash.rb +21 -0
- data/lib/grape/util/media_type.rb +70 -0
- data/lib/grape/util/reverse_stackable_values.rb +1 -6
- data/lib/grape/util/stackable_values.rb +1 -6
- data/lib/grape/util/strict_hash_configuration.rb +3 -3
- data/lib/grape/validations/attributes_doc.rb +38 -36
- data/lib/grape/validations/contract_scope.rb +71 -0
- data/lib/grape/validations/params_scope.rb +10 -9
- data/lib/grape/validations/types/array_coercer.rb +0 -2
- data/lib/grape/validations/types/build_coercer.rb +69 -71
- data/lib/grape/validations/types/dry_type_coercer.rb +1 -11
- data/lib/grape/validations/types/json.rb +0 -2
- data/lib/grape/validations/types/primitive_coercer.rb +0 -2
- data/lib/grape/validations/types/set_coercer.rb +0 -3
- data/lib/grape/validations/types.rb +0 -3
- data/lib/grape/validations/validators/base.rb +2 -1
- data/lib/grape/validations/validators/default_validator.rb +5 -1
- data/lib/grape/validations/validators/length_validator.rb +42 -0
- data/lib/grape/validations/validators/values_validator.rb +8 -3
- data/lib/grape/validations.rb +3 -7
- data/lib/grape/version.rb +1 -1
- data/lib/grape/{util/xml.rb → xml.rb} +1 -1
- data/lib/grape.rb +38 -269
- metadata +33 -274
- data/lib/grape/eager_load.rb +0 -20
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +0 -24
- data/lib/grape/router/attribute_translator.rb +0 -63
- data/lib/grape/util/lazy_block.rb +0 -27
- data/lib/grape/util/lazy_object.rb +0 -43
- data/lib/grape/util/lazy_value.rb +0 -91
- data/spec/grape/api/custom_validations_spec.rb +0 -213
- 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 -509
- data/spec/grape/api_spec.rb +0 -4356
- data/spec/grape/dsl/callbacks_spec.rb +0 -45
- data/spec/grape/dsl/desc_spec.rb +0 -98
- 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 -531
- 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 -225
- 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 -185
- 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 -17
- 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 -19
- 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/grape_spec.rb +0 -9
- 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 -126
- 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 -38
- data/spec/grape/validations/params_scope_spec.rb +0 -1420
- data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -56
- 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/base_spec.rb +0 -38
- 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 -733
- data/spec/grape/validations/validators/zh-CN.yml +0 -10
- data/spec/grape/validations_spec.rb +0 -2030
- 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/deprecated_class_examples.rb +0 -16
- 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,1420 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
describe Grape::Validations::ParamsScope do
|
4
|
-
subject do
|
5
|
-
Class.new(Grape::API)
|
6
|
-
end
|
7
|
-
|
8
|
-
def app
|
9
|
-
subject
|
10
|
-
end
|
11
|
-
|
12
|
-
context 'when using custom types' do
|
13
|
-
module ParamsScopeSpec
|
14
|
-
class CustomType
|
15
|
-
attr_reader :value
|
16
|
-
|
17
|
-
def self.parse(value)
|
18
|
-
raise if value == 'invalid'
|
19
|
-
|
20
|
-
new(value)
|
21
|
-
end
|
22
|
-
|
23
|
-
def initialize(value)
|
24
|
-
@value = value
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'coerces the parameter via the type\'s parse method' do
|
30
|
-
subject.params do
|
31
|
-
requires :foo, type: ParamsScopeSpec::CustomType
|
32
|
-
end
|
33
|
-
subject.get('/types') { params[:foo].value }
|
34
|
-
|
35
|
-
get '/types', foo: 'valid'
|
36
|
-
expect(last_response.status).to eq(200)
|
37
|
-
expect(last_response.body).to eq('valid')
|
38
|
-
|
39
|
-
get '/types', foo: 'invalid'
|
40
|
-
expect(last_response.status).to eq(400)
|
41
|
-
expect(last_response.body).to match(/foo is invalid/)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
context 'param renaming' do
|
46
|
-
it do
|
47
|
-
subject.params do
|
48
|
-
requires :foo, as: :bar
|
49
|
-
optional :super, as: :hiper
|
50
|
-
end
|
51
|
-
subject.get('/renaming') { "#{declared(params)['bar']}-#{declared(params)['hiper']}" }
|
52
|
-
get '/renaming', foo: 'any', super: 'any2'
|
53
|
-
|
54
|
-
expect(last_response.status).to eq(200)
|
55
|
-
expect(last_response.body).to eq('any-any2')
|
56
|
-
end
|
57
|
-
|
58
|
-
it do
|
59
|
-
subject.params do
|
60
|
-
requires :foo, as: :bar, type: String, coerce_with: ->(c) { c.strip }
|
61
|
-
end
|
62
|
-
subject.get('/renaming-coerced') { "#{params['bar']}-#{params['foo']}" }
|
63
|
-
get '/renaming-coerced', foo: ' there we go '
|
64
|
-
|
65
|
-
expect(last_response.status).to eq(200)
|
66
|
-
expect(last_response.body).to eq('-there we go')
|
67
|
-
end
|
68
|
-
|
69
|
-
it do
|
70
|
-
subject.params do
|
71
|
-
requires :foo, as: :bar, allow_blank: false
|
72
|
-
end
|
73
|
-
subject.get('/renaming-not-blank') {}
|
74
|
-
get '/renaming-not-blank', foo: ''
|
75
|
-
|
76
|
-
expect(last_response.status).to eq(400)
|
77
|
-
expect(last_response.body).to eq('foo is empty')
|
78
|
-
end
|
79
|
-
|
80
|
-
it do
|
81
|
-
subject.params do
|
82
|
-
requires :foo, as: :bar, allow_blank: false
|
83
|
-
end
|
84
|
-
subject.get('/renaming-not-blank-with-value') {}
|
85
|
-
get '/renaming-not-blank-with-value', foo: 'any'
|
86
|
-
|
87
|
-
expect(last_response.status).to eq(200)
|
88
|
-
end
|
89
|
-
|
90
|
-
it do
|
91
|
-
subject.params do
|
92
|
-
requires :foo, as: :baz, type: Hash do
|
93
|
-
requires :bar, as: :qux
|
94
|
-
end
|
95
|
-
end
|
96
|
-
subject.get('/nested-renaming') { declared(params).to_json }
|
97
|
-
get '/nested-renaming', foo: { bar: 'any' }
|
98
|
-
|
99
|
-
expect(last_response.status).to eq(200)
|
100
|
-
expect(last_response.body).to eq('{"baz":{"qux":"any"}}')
|
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
|
124
|
-
end
|
125
|
-
|
126
|
-
context 'array without coerce type explicitly given' do
|
127
|
-
it 'sets the type based on first element' do
|
128
|
-
subject.params do
|
129
|
-
requires :periods, type: Array, values: -> { %w[day month] }
|
130
|
-
end
|
131
|
-
subject.get('/required') { 'required works' }
|
132
|
-
|
133
|
-
get '/required', periods: %w[day month]
|
134
|
-
expect(last_response.status).to eq(200)
|
135
|
-
expect(last_response.body).to eq('required works')
|
136
|
-
end
|
137
|
-
|
138
|
-
it 'fails to call API without Array type' do
|
139
|
-
subject.params do
|
140
|
-
requires :periods, type: Array, values: -> { %w[day month] }
|
141
|
-
end
|
142
|
-
subject.get('/required') { 'required works' }
|
143
|
-
|
144
|
-
get '/required', periods: 'day'
|
145
|
-
expect(last_response.status).to eq(400)
|
146
|
-
expect(last_response.body).to eq('periods is invalid')
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'raises exception when values are of different type' do
|
150
|
-
expect do
|
151
|
-
subject.params { requires :numbers, type: Array, values: [1, 'definitely not a number', 3] }
|
152
|
-
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
153
|
-
end
|
154
|
-
|
155
|
-
it 'raises exception when range values have different endpoint types' do
|
156
|
-
expect do
|
157
|
-
subject.params { requires :numbers, type: Array, values: 0.0..10 }
|
158
|
-
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
context 'coercing values validation with proc' do
|
163
|
-
it 'allows the proc to pass validation without checking' do
|
164
|
-
subject.params { requires :numbers, type: Integer, values: -> { [0, 1, 2] } }
|
165
|
-
|
166
|
-
subject.post('/required') { 'coercion with proc works' }
|
167
|
-
post '/required', numbers: '1'
|
168
|
-
expect(last_response.status).to eq(201)
|
169
|
-
expect(last_response.body).to eq('coercion with proc works')
|
170
|
-
end
|
171
|
-
|
172
|
-
it 'allows the proc to pass validation without checking in value' do
|
173
|
-
subject.params { requires :numbers, type: Integer, values: { value: -> { [0, 1, 2] } } }
|
174
|
-
|
175
|
-
subject.post('/required') { 'coercion with proc works' }
|
176
|
-
post '/required', numbers: '1'
|
177
|
-
expect(last_response.status).to eq(201)
|
178
|
-
expect(last_response.body).to eq('coercion with proc works')
|
179
|
-
end
|
180
|
-
|
181
|
-
it 'allows the proc to pass validation without checking in except' do
|
182
|
-
subject.params { requires :numbers, type: Integer, values: { except: -> { [0, 1, 2] } } }
|
183
|
-
|
184
|
-
subject.post('/required') { 'coercion with proc works' }
|
185
|
-
post '/required', numbers: '10'
|
186
|
-
expect(last_response.status).to eq(201)
|
187
|
-
expect(last_response.body).to eq('coercion with proc works')
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
context 'with range values' do
|
192
|
-
context "when left range endpoint isn't #kind_of? the type" do
|
193
|
-
it 'raises exception' do
|
194
|
-
expect do
|
195
|
-
subject.params { requires :latitude, type: Integer, values: -90.0..90 }
|
196
|
-
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
context "when right range endpoint isn't #kind_of? the type" do
|
201
|
-
it 'raises exception' do
|
202
|
-
expect do
|
203
|
-
subject.params { requires :latitude, type: Integer, values: -90..90.0 }
|
204
|
-
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
context 'when the default is an array' do
|
209
|
-
context 'and is the entire range of allowed values' do
|
210
|
-
it 'does not raise an exception' do
|
211
|
-
expect do
|
212
|
-
subject.params { optional :numbers, type: Array[Integer], values: 0..2, default: 0..2 }
|
213
|
-
end.not_to raise_error
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
context 'and is a subset of allowed values' do
|
218
|
-
it 'does not raise an exception' do
|
219
|
-
expect do
|
220
|
-
subject.params { optional :numbers, type: Array[Integer], values: [0, 1, 2], default: [1, 0] }
|
221
|
-
end.not_to raise_error
|
222
|
-
end
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
context 'when both range endpoints are #kind_of? the type' do
|
227
|
-
it 'accepts values in the range' do
|
228
|
-
subject.params do
|
229
|
-
requires :letter, type: String, values: 'a'..'z'
|
230
|
-
end
|
231
|
-
subject.get('/letter') { params[:letter] }
|
232
|
-
|
233
|
-
get '/letter', letter: 'j'
|
234
|
-
expect(last_response.status).to eq(200)
|
235
|
-
expect(last_response.body).to eq('j')
|
236
|
-
end
|
237
|
-
|
238
|
-
it 'rejects values outside the range' do
|
239
|
-
subject.params do
|
240
|
-
requires :letter, type: String, values: 'a'..'z'
|
241
|
-
end
|
242
|
-
subject.get('/letter') { params[:letter] }
|
243
|
-
|
244
|
-
get '/letter', letter: 'J'
|
245
|
-
expect(last_response.status).to eq(400)
|
246
|
-
expect(last_response.body).to eq('letter does not have a valid value')
|
247
|
-
end
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
context 'parameters in group' do
|
252
|
-
it 'errors when no type is provided' do
|
253
|
-
expect do
|
254
|
-
subject.params do
|
255
|
-
group :a do
|
256
|
-
requires :b
|
257
|
-
end
|
258
|
-
end
|
259
|
-
end.to raise_error Grape::Exceptions::MissingGroupType
|
260
|
-
|
261
|
-
expect do
|
262
|
-
subject.params do
|
263
|
-
optional :a do
|
264
|
-
requires :b
|
265
|
-
end
|
266
|
-
end
|
267
|
-
end.to raise_error Grape::Exceptions::MissingGroupType
|
268
|
-
end
|
269
|
-
|
270
|
-
it 'allows Hash as type' do
|
271
|
-
subject.params do
|
272
|
-
group :a, type: Hash do
|
273
|
-
requires :b
|
274
|
-
end
|
275
|
-
end
|
276
|
-
subject.get('/group') { 'group works' }
|
277
|
-
get '/group', a: { b: true }
|
278
|
-
expect(last_response.status).to eq(200)
|
279
|
-
expect(last_response.body).to eq('group works')
|
280
|
-
|
281
|
-
subject.params do
|
282
|
-
optional :a, type: Hash do
|
283
|
-
requires :b
|
284
|
-
end
|
285
|
-
end
|
286
|
-
get '/optional_type_hash'
|
287
|
-
end
|
288
|
-
|
289
|
-
it 'allows Array as type' do
|
290
|
-
subject.params do
|
291
|
-
group :a, type: Array do
|
292
|
-
requires :b
|
293
|
-
end
|
294
|
-
end
|
295
|
-
subject.get('/group') { 'group works' }
|
296
|
-
get '/group', a: [{ b: true }]
|
297
|
-
expect(last_response.status).to eq(200)
|
298
|
-
expect(last_response.body).to eq('group works')
|
299
|
-
|
300
|
-
subject.params do
|
301
|
-
optional :a, type: Array do
|
302
|
-
requires :b
|
303
|
-
end
|
304
|
-
end
|
305
|
-
get '/optional_type_array'
|
306
|
-
end
|
307
|
-
|
308
|
-
it 'handles missing optional Array type' do
|
309
|
-
subject.params do
|
310
|
-
optional :a, type: Array do
|
311
|
-
requires :b
|
312
|
-
end
|
313
|
-
end
|
314
|
-
subject.get('/test') { declared(params).to_json }
|
315
|
-
get '/test'
|
316
|
-
expect(last_response.status).to eq(200)
|
317
|
-
expect(last_response.body).to eq('{"a":[]}')
|
318
|
-
end
|
319
|
-
|
320
|
-
it 'errors with an unsupported type' do
|
321
|
-
expect do
|
322
|
-
subject.params do
|
323
|
-
group :a, type: Set do
|
324
|
-
requires :b
|
325
|
-
end
|
326
|
-
end
|
327
|
-
end.to raise_error Grape::Exceptions::UnsupportedGroupType
|
328
|
-
|
329
|
-
expect do
|
330
|
-
subject.params do
|
331
|
-
optional :a, type: Set do
|
332
|
-
requires :b
|
333
|
-
end
|
334
|
-
end
|
335
|
-
end.to raise_error Grape::Exceptions::UnsupportedGroupType
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
context 'when validations are dependent on a parameter' do
|
340
|
-
before do
|
341
|
-
subject.params do
|
342
|
-
optional :a
|
343
|
-
given :a do
|
344
|
-
requires :b
|
345
|
-
end
|
346
|
-
end
|
347
|
-
subject.get('/test') { declared(params).to_json }
|
348
|
-
end
|
349
|
-
|
350
|
-
it 'applies the validations only if the parameter is present' do
|
351
|
-
get '/test'
|
352
|
-
expect(last_response.status).to eq(200)
|
353
|
-
|
354
|
-
get '/test', a: true
|
355
|
-
expect(last_response.status).to eq(400)
|
356
|
-
expect(last_response.body).to eq('b is missing')
|
357
|
-
|
358
|
-
get '/test', a: true, b: true
|
359
|
-
expect(last_response.status).to eq(200)
|
360
|
-
end
|
361
|
-
|
362
|
-
it 'applies the validations of multiple parameters' do
|
363
|
-
subject.params do
|
364
|
-
optional :a, :b
|
365
|
-
given :a, :b do
|
366
|
-
requires :c
|
367
|
-
end
|
368
|
-
end
|
369
|
-
subject.get('/multiple') { declared(params).to_json }
|
370
|
-
|
371
|
-
get '/multiple'
|
372
|
-
expect(last_response.status).to eq(200)
|
373
|
-
|
374
|
-
get '/multiple', a: true
|
375
|
-
expect(last_response.status).to eq(200)
|
376
|
-
|
377
|
-
get '/multiple', b: true
|
378
|
-
expect(last_response.status).to eq(200)
|
379
|
-
|
380
|
-
get '/multiple', a: true, b: true
|
381
|
-
expect(last_response.status).to eq(400)
|
382
|
-
expect(last_response.body).to eq('c is missing')
|
383
|
-
|
384
|
-
get '/multiple', a: true, b: true, c: true
|
385
|
-
expect(last_response.status).to eq(200)
|
386
|
-
end
|
387
|
-
|
388
|
-
it 'applies only the appropriate validation' do
|
389
|
-
subject.params do
|
390
|
-
optional :a
|
391
|
-
optional :b
|
392
|
-
mutually_exclusive :a, :b
|
393
|
-
given :a do
|
394
|
-
requires :c, type: String
|
395
|
-
end
|
396
|
-
given :b do
|
397
|
-
requires :c, type: Integer
|
398
|
-
end
|
399
|
-
end
|
400
|
-
subject.get('/multiple') { declared(params).to_json }
|
401
|
-
|
402
|
-
get '/multiple'
|
403
|
-
expect(last_response.status).to eq(200)
|
404
|
-
|
405
|
-
get '/multiple', a: true, c: 'test'
|
406
|
-
expect(last_response.status).to eq(200)
|
407
|
-
expect(JSON.parse(last_response.body).symbolize_keys).to eq a: 'true', b: nil, c: 'test'
|
408
|
-
|
409
|
-
get '/multiple', b: true, c: '3'
|
410
|
-
expect(last_response.status).to eq(200)
|
411
|
-
expect(JSON.parse(last_response.body).symbolize_keys).to eq a: nil, b: 'true', c: 3
|
412
|
-
|
413
|
-
get '/multiple', a: true
|
414
|
-
expect(last_response.status).to eq(400)
|
415
|
-
expect(last_response.body).to eq('c is missing')
|
416
|
-
|
417
|
-
get '/multiple', b: true
|
418
|
-
expect(last_response.status).to eq(400)
|
419
|
-
expect(last_response.body).to eq('c is missing')
|
420
|
-
|
421
|
-
get '/multiple', a: true, b: true, c: 'test'
|
422
|
-
expect(last_response.status).to eq(400)
|
423
|
-
expect(last_response.body).to eq('a, b are mutually exclusive, c is invalid')
|
424
|
-
end
|
425
|
-
|
426
|
-
it 'raises an error if the dependent parameter was never specified' do
|
427
|
-
expect do
|
428
|
-
subject.params do
|
429
|
-
given :c do
|
430
|
-
end
|
431
|
-
end
|
432
|
-
end.to raise_error(Grape::Exceptions::UnknownParameter)
|
433
|
-
end
|
434
|
-
|
435
|
-
it 'does not raise an error if the dependent parameter is a Hash' do
|
436
|
-
expect do
|
437
|
-
subject.params do
|
438
|
-
optional :a, type: Hash do
|
439
|
-
requires :b
|
440
|
-
end
|
441
|
-
given :a do
|
442
|
-
requires :c
|
443
|
-
end
|
444
|
-
end
|
445
|
-
end.not_to raise_error
|
446
|
-
end
|
447
|
-
|
448
|
-
it 'does not raise an error if when using nested given' do
|
449
|
-
expect do
|
450
|
-
subject.params do
|
451
|
-
optional :a, type: Hash do
|
452
|
-
requires :b
|
453
|
-
end
|
454
|
-
given :a do
|
455
|
-
requires :c
|
456
|
-
given :c do
|
457
|
-
requires :d
|
458
|
-
end
|
459
|
-
end
|
460
|
-
end
|
461
|
-
end.not_to raise_error
|
462
|
-
end
|
463
|
-
|
464
|
-
it 'allows nested dependent parameters' do
|
465
|
-
subject.params do
|
466
|
-
optional :a
|
467
|
-
given a: ->(val) { val == 'a' } do
|
468
|
-
optional :b
|
469
|
-
given b: ->(val) { val == 'b' } do
|
470
|
-
optional :c
|
471
|
-
given c: ->(val) { val == 'c' } do
|
472
|
-
requires :d
|
473
|
-
end
|
474
|
-
end
|
475
|
-
end
|
476
|
-
end
|
477
|
-
subject.get('/') { declared(params).to_json }
|
478
|
-
|
479
|
-
get '/'
|
480
|
-
expect(last_response.status).to eq 200
|
481
|
-
|
482
|
-
get '/', a: 'a', b: 'b', c: 'c'
|
483
|
-
expect(last_response.status).to eq 400
|
484
|
-
expect(last_response.body).to eq 'd is missing'
|
485
|
-
|
486
|
-
get '/', a: 'a', b: 'b', c: 'c', d: 'd'
|
487
|
-
expect(last_response.status).to eq 200
|
488
|
-
expect(last_response.body).to eq({ a: 'a', b: 'b', c: 'c', d: 'd' }.to_json)
|
489
|
-
end
|
490
|
-
|
491
|
-
it 'allows renaming of dependent parameters' do
|
492
|
-
subject.params do
|
493
|
-
optional :a
|
494
|
-
given :a do
|
495
|
-
requires :b, as: :c
|
496
|
-
end
|
497
|
-
end
|
498
|
-
|
499
|
-
subject.get('/multiple') { declared(params).to_json }
|
500
|
-
|
501
|
-
get '/multiple', a: 'a', b: 'b'
|
502
|
-
|
503
|
-
body = JSON.parse(last_response.body)
|
504
|
-
|
505
|
-
expect(body.keys).to include('c')
|
506
|
-
expect(body.keys).not_to include('b')
|
507
|
-
end
|
508
|
-
|
509
|
-
it 'allows renaming of dependent on parameter' do
|
510
|
-
subject.params do
|
511
|
-
optional :a, as: :b
|
512
|
-
given a: ->(val) { val == 'x' } do
|
513
|
-
requires :c
|
514
|
-
end
|
515
|
-
end
|
516
|
-
subject.get('/') { declared(params) }
|
517
|
-
|
518
|
-
get '/', a: 'x'
|
519
|
-
expect(last_response.status).to eq 400
|
520
|
-
expect(last_response.body).to eq 'c is missing'
|
521
|
-
|
522
|
-
get '/', a: 'y'
|
523
|
-
expect(last_response.status).to eq 200
|
524
|
-
end
|
525
|
-
|
526
|
-
it 'does not raise if the dependent parameter is not the renamed one' do
|
527
|
-
expect do
|
528
|
-
subject.params do
|
529
|
-
optional :a, as: :b
|
530
|
-
given :a do
|
531
|
-
requires :c
|
532
|
-
end
|
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
|
545
|
-
end.to raise_error(Grape::Exceptions::UnknownParameter)
|
546
|
-
end
|
547
|
-
|
548
|
-
it 'does not validate nested requires when given is false' do
|
549
|
-
subject.params do
|
550
|
-
requires :a, type: String, allow_blank: false, values: %w[x y z]
|
551
|
-
given a: ->(val) { val == 'x' } do
|
552
|
-
requires :inner1, type: Hash, allow_blank: false do
|
553
|
-
requires :foo, type: Integer, allow_blank: false
|
554
|
-
end
|
555
|
-
end
|
556
|
-
given a: ->(val) { val == 'y' } do
|
557
|
-
requires :inner2, type: Hash, allow_blank: false do
|
558
|
-
requires :bar, type: Integer, allow_blank: false
|
559
|
-
requires :baz, type: Array, allow_blank: false do
|
560
|
-
requires :baz_category, type: String, allow_blank: false
|
561
|
-
end
|
562
|
-
end
|
563
|
-
end
|
564
|
-
given a: ->(val) { val == 'z' } do
|
565
|
-
requires :inner3, type: Array, allow_blank: false do
|
566
|
-
requires :bar, type: Integer, allow_blank: false
|
567
|
-
requires :baz, type: Array, allow_blank: false do
|
568
|
-
requires :baz_category, type: String, allow_blank: false
|
569
|
-
end
|
570
|
-
end
|
571
|
-
end
|
572
|
-
end
|
573
|
-
subject.get('/varying') { declared(params).to_json }
|
574
|
-
|
575
|
-
get '/varying', a: 'x', inner1: { foo: 1 }
|
576
|
-
expect(last_response.status).to eq(200)
|
577
|
-
|
578
|
-
get '/varying', a: 'y', inner2: { bar: 2, baz: [{ baz_category: 'barstools' }] }
|
579
|
-
expect(last_response.status).to eq(200)
|
580
|
-
|
581
|
-
get '/varying', a: 'y', inner2: { bar: 2, baz: [{ unrelated: 'yep' }] }
|
582
|
-
expect(last_response.status).to eq(400)
|
583
|
-
|
584
|
-
get '/varying', a: 'z', inner3: [{ bar: 3, baz: [{ baz_category: 'barstools' }] }]
|
585
|
-
expect(last_response.status).to eq(200)
|
586
|
-
end
|
587
|
-
|
588
|
-
it 'detect unmet nested dependency' do
|
589
|
-
subject.params do
|
590
|
-
requires :a, type: String, allow_blank: false, values: %w[x y z]
|
591
|
-
given a: ->(val) { val == 'z' } do
|
592
|
-
requires :inner3, type: Array, allow_blank: false do
|
593
|
-
requires :bar, type: String, allow_blank: false
|
594
|
-
given bar: ->(val) { val == 'b' } do
|
595
|
-
requires :baz, type: Array do
|
596
|
-
optional :baz_category, type: String
|
597
|
-
end
|
598
|
-
end
|
599
|
-
given bar: ->(val) { val == 'c' } do
|
600
|
-
requires :baz, type: Array do
|
601
|
-
requires :baz_category, type: String
|
602
|
-
end
|
603
|
-
end
|
604
|
-
end
|
605
|
-
end
|
606
|
-
end
|
607
|
-
subject.get('/nested-dependency') { declared(params).to_json }
|
608
|
-
|
609
|
-
get '/nested-dependency', a: 'z', inner3: [{ bar: 'c', baz: [{ unrelated: 'nope' }] }]
|
610
|
-
expect(last_response.status).to eq(400)
|
611
|
-
expect(last_response.body).to eq 'inner3[0][baz][0][baz_category] is missing'
|
612
|
-
end
|
613
|
-
|
614
|
-
it 'includes the parameter within #declared(params)' do
|
615
|
-
get '/test', a: true, b: true
|
616
|
-
|
617
|
-
expect(JSON.parse(last_response.body)).to eq('a' => 'true', 'b' => 'true')
|
618
|
-
end
|
619
|
-
|
620
|
-
it 'returns a sensible error message within a nested context' do
|
621
|
-
subject.params do
|
622
|
-
requires :bar, type: Hash do
|
623
|
-
optional :a
|
624
|
-
given :a do
|
625
|
-
requires :b
|
626
|
-
end
|
627
|
-
end
|
628
|
-
end
|
629
|
-
subject.get('/nested') { 'worked' }
|
630
|
-
|
631
|
-
get '/nested', bar: { a: true }
|
632
|
-
expect(last_response.status).to eq(400)
|
633
|
-
expect(last_response.body).to eq('bar[b] is missing')
|
634
|
-
end
|
635
|
-
|
636
|
-
it 'includes the nested parameter within #declared(params)' do
|
637
|
-
subject.params do
|
638
|
-
requires :bar, type: Hash do
|
639
|
-
optional :a
|
640
|
-
given :a do
|
641
|
-
requires :b
|
642
|
-
end
|
643
|
-
end
|
644
|
-
end
|
645
|
-
subject.get('/nested') { declared(params).to_json }
|
646
|
-
|
647
|
-
get '/nested', bar: { a: true, b: 'yes' }
|
648
|
-
expect(JSON.parse(last_response.body)).to eq('bar' => { 'a' => 'true', 'b' => 'yes' })
|
649
|
-
end
|
650
|
-
|
651
|
-
it 'includes level 2 nested parameters outside the given within #declared(params)' do
|
652
|
-
subject.params do
|
653
|
-
requires :bar, type: Hash do
|
654
|
-
optional :a
|
655
|
-
given :a do
|
656
|
-
requires :c, type: Hash do
|
657
|
-
requires :b
|
658
|
-
end
|
659
|
-
end
|
660
|
-
end
|
661
|
-
end
|
662
|
-
subject.get('/nested') { declared(params).to_json }
|
663
|
-
|
664
|
-
get '/nested', bar: { a: true, c: { b: 'yes' } }
|
665
|
-
expect(JSON.parse(last_response.body)).to eq('bar' => { 'a' => 'true', 'c' => { 'b' => 'yes' } })
|
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
|
978
|
-
end
|
979
|
-
|
980
|
-
context 'default value in given block' do
|
981
|
-
before do
|
982
|
-
subject.params do
|
983
|
-
optional :a, values: %w[a b]
|
984
|
-
given a: ->(val) { val == 'a' } do
|
985
|
-
optional :b, default: 'default'
|
986
|
-
end
|
987
|
-
end
|
988
|
-
subject.get('/') { params.to_json }
|
989
|
-
end
|
990
|
-
|
991
|
-
context 'when dependency meets' do
|
992
|
-
it 'sets default value for dependent parameter' do
|
993
|
-
get '/', a: 'a'
|
994
|
-
expect(last_response.body).to eq({ a: 'a', b: 'default' }.to_json)
|
995
|
-
end
|
996
|
-
end
|
997
|
-
|
998
|
-
context 'when dependency does not meet' do
|
999
|
-
it 'does not set default value for dependent parameter' do
|
1000
|
-
get '/', a: 'b'
|
1001
|
-
expect(last_response.body).to eq({ a: 'b' }.to_json)
|
1002
|
-
end
|
1003
|
-
end
|
1004
|
-
end
|
1005
|
-
|
1006
|
-
context 'when validations are dependent on a parameter within an array param' do
|
1007
|
-
before do
|
1008
|
-
subject.params do
|
1009
|
-
requires :foos, type: Array do
|
1010
|
-
optional :foo
|
1011
|
-
given :foo do
|
1012
|
-
requires :bar
|
1013
|
-
end
|
1014
|
-
end
|
1015
|
-
end
|
1016
|
-
subject.get('/test') { 'ok' }
|
1017
|
-
end
|
1018
|
-
|
1019
|
-
it 'passes none Hash params' do
|
1020
|
-
get '/test', foos: ['']
|
1021
|
-
expect(last_response.status).to eq(200)
|
1022
|
-
expect(last_response.body).to eq('ok')
|
1023
|
-
end
|
1024
|
-
end
|
1025
|
-
|
1026
|
-
context 'when validations are dependent on a parameter within an array param within #declared(params).to_json' do
|
1027
|
-
before do
|
1028
|
-
subject.params do
|
1029
|
-
requires :foos, type: Array do
|
1030
|
-
optional :foo_type, :baz_type
|
1031
|
-
given :foo_type do
|
1032
|
-
requires :bar
|
1033
|
-
end
|
1034
|
-
end
|
1035
|
-
end
|
1036
|
-
subject.post('/test') { declared(params).to_json }
|
1037
|
-
end
|
1038
|
-
|
1039
|
-
it 'applies the constraint within each value' do
|
1040
|
-
post '/test',
|
1041
|
-
{ foos: [{ foo_type: 'a' }, { baz_type: 'c' }] }.to_json,
|
1042
|
-
'CONTENT_TYPE' => 'application/json'
|
1043
|
-
|
1044
|
-
expect(last_response.status).to eq(400)
|
1045
|
-
expect(last_response.body).to eq('foos[0][bar] is missing')
|
1046
|
-
end
|
1047
|
-
end
|
1048
|
-
|
1049
|
-
context 'when validations are dependent on a parameter with specific value' do
|
1050
|
-
# build test cases from all combinations of declarations and options
|
1051
|
-
a_decls = %i[optional requires]
|
1052
|
-
a_options = [{}, { values: %w[x y z] }]
|
1053
|
-
b_options = [{}, { type: String }, { allow_blank: false }, { type: String, allow_blank: false }]
|
1054
|
-
combinations = a_decls.product(a_options, b_options)
|
1055
|
-
combinations.each_with_index do |combination, i|
|
1056
|
-
a_decl, a_opts, b_opts = combination
|
1057
|
-
|
1058
|
-
context "(case #{i})" do
|
1059
|
-
before do
|
1060
|
-
# puts "a_decl: #{a_decl}, a_opts: #{a_opts}, b_opts: #{b_opts}"
|
1061
|
-
subject.params do
|
1062
|
-
send a_decl, :a, **a_opts
|
1063
|
-
given(a: ->(val) { val == 'x' }) { requires :b, **b_opts }
|
1064
|
-
given(a: ->(val) { val == 'y' }) { requires :c, **b_opts }
|
1065
|
-
end
|
1066
|
-
subject.get('/test') { declared(params).to_json }
|
1067
|
-
end
|
1068
|
-
|
1069
|
-
if a_decl == :optional
|
1070
|
-
it 'skips validation when base param is missing' do
|
1071
|
-
get '/test'
|
1072
|
-
expect(last_response.status).to eq(200)
|
1073
|
-
end
|
1074
|
-
end
|
1075
|
-
|
1076
|
-
it 'skips validation when base param does not have a specified value' do
|
1077
|
-
get '/test', a: 'z'
|
1078
|
-
expect(last_response.status).to eq(200)
|
1079
|
-
|
1080
|
-
get '/test', a: 'z', b: ''
|
1081
|
-
expect(last_response.status).to eq(200)
|
1082
|
-
end
|
1083
|
-
|
1084
|
-
it 'applies the validation when base param has the specific value' do
|
1085
|
-
get '/test', a: 'x'
|
1086
|
-
expect(last_response.status).to eq(400)
|
1087
|
-
expect(last_response.body).to include('b is missing')
|
1088
|
-
|
1089
|
-
get '/test', a: 'x', b: true
|
1090
|
-
expect(last_response.status).to eq(200)
|
1091
|
-
|
1092
|
-
get '/test', a: 'x', b: true, c: ''
|
1093
|
-
expect(last_response.status).to eq(200)
|
1094
|
-
end
|
1095
|
-
|
1096
|
-
it 'includes the parameter within #declared(params)' do
|
1097
|
-
get '/test', a: 'x', b: true
|
1098
|
-
expect(JSON.parse(last_response.body)).to eq('a' => 'x', 'b' => 'true', 'c' => nil)
|
1099
|
-
end
|
1100
|
-
end
|
1101
|
-
end
|
1102
|
-
end
|
1103
|
-
|
1104
|
-
it 'raises an error if the dependent parameter was never specified' do
|
1105
|
-
expect do
|
1106
|
-
subject.params do
|
1107
|
-
given :c do
|
1108
|
-
end
|
1109
|
-
end
|
1110
|
-
end.to raise_error(Grape::Exceptions::UnknownParameter)
|
1111
|
-
end
|
1112
|
-
|
1113
|
-
it 'returns a sensible error message within a nested context' do
|
1114
|
-
subject.params do
|
1115
|
-
requires :bar, type: Hash do
|
1116
|
-
optional :a
|
1117
|
-
given a: ->(val) { val == 'x' } do
|
1118
|
-
requires :b
|
1119
|
-
end
|
1120
|
-
end
|
1121
|
-
end
|
1122
|
-
subject.get('/nested') { 'worked' }
|
1123
|
-
|
1124
|
-
get '/nested', bar: { a: 'x' }
|
1125
|
-
expect(last_response.status).to eq(400)
|
1126
|
-
expect(last_response.body).to eq('bar[b] is missing')
|
1127
|
-
end
|
1128
|
-
|
1129
|
-
it 'includes the nested parameter within #declared(params)' do
|
1130
|
-
subject.params do
|
1131
|
-
requires :bar, type: Hash do
|
1132
|
-
optional :a
|
1133
|
-
given a: ->(val) { val == 'x' } do
|
1134
|
-
requires :b
|
1135
|
-
end
|
1136
|
-
end
|
1137
|
-
end
|
1138
|
-
subject.get('/nested') { declared(params).to_json }
|
1139
|
-
|
1140
|
-
get '/nested', bar: { a: 'x', b: 'yes' }
|
1141
|
-
expect(JSON.parse(last_response.body)).to eq('bar' => { 'a' => 'x', 'b' => 'yes' })
|
1142
|
-
end
|
1143
|
-
|
1144
|
-
it 'includes level 2 nested parameters outside the given within #declared(params)' do
|
1145
|
-
subject.params do
|
1146
|
-
requires :bar, type: Hash do
|
1147
|
-
optional :a
|
1148
|
-
given a: ->(val) { val == 'x' } do
|
1149
|
-
requires :c, type: Hash do
|
1150
|
-
requires :b
|
1151
|
-
end
|
1152
|
-
end
|
1153
|
-
end
|
1154
|
-
end
|
1155
|
-
subject.get('/nested') { declared(params).to_json }
|
1156
|
-
|
1157
|
-
get '/nested', bar: { a: 'x', c: { b: 'yes' } }
|
1158
|
-
expect(JSON.parse(last_response.body)).to eq('bar' => { 'a' => 'x', 'c' => { 'b' => 'yes' } })
|
1159
|
-
end
|
1160
|
-
|
1161
|
-
it 'includes deeply nested parameters within #declared(params)' do
|
1162
|
-
subject.params do
|
1163
|
-
requires :arr1, type: Array do
|
1164
|
-
requires :hash1, type: Hash do
|
1165
|
-
requires :arr2, type: Array do
|
1166
|
-
requires :hash2, type: Hash do
|
1167
|
-
requires :something, type: String
|
1168
|
-
end
|
1169
|
-
end
|
1170
|
-
end
|
1171
|
-
end
|
1172
|
-
end
|
1173
|
-
subject.get('/nested_deep') { declared(params).to_json }
|
1174
|
-
|
1175
|
-
get '/nested_deep', arr1: [{ hash1: { arr2: [{ hash2: { something: 'value' } }] } }]
|
1176
|
-
expect(last_response.status).to eq(200)
|
1177
|
-
expect(JSON.parse(last_response.body)).to eq('arr1' => [{ 'hash1' => { 'arr2' => [{ 'hash2' => { 'something' => 'value' } }] } }])
|
1178
|
-
end
|
1179
|
-
|
1180
|
-
context 'failing fast' do
|
1181
|
-
context 'when fail_fast is not defined' do
|
1182
|
-
it 'does not stop validation' do
|
1183
|
-
subject.params do
|
1184
|
-
requires :one
|
1185
|
-
requires :two
|
1186
|
-
requires :three
|
1187
|
-
end
|
1188
|
-
subject.get('/fail-fast') { declared(params).to_json }
|
1189
|
-
|
1190
|
-
get '/fail-fast'
|
1191
|
-
expect(last_response.status).to eq(400)
|
1192
|
-
expect(last_response.body).to eq('one is missing, two is missing, three is missing')
|
1193
|
-
end
|
1194
|
-
end
|
1195
|
-
|
1196
|
-
context 'when fail_fast is defined it stops the validation' do
|
1197
|
-
it 'of other params' do
|
1198
|
-
subject.params do
|
1199
|
-
requires :one, fail_fast: true
|
1200
|
-
requires :two
|
1201
|
-
end
|
1202
|
-
subject.get('/fail-fast') { declared(params).to_json }
|
1203
|
-
|
1204
|
-
get '/fail-fast'
|
1205
|
-
expect(last_response.status).to eq(400)
|
1206
|
-
expect(last_response.body).to eq('one is missing')
|
1207
|
-
end
|
1208
|
-
|
1209
|
-
it 'for a single param' do
|
1210
|
-
subject.params do
|
1211
|
-
requires :one, allow_blank: false, regexp: /[0-9]+/, fail_fast: true
|
1212
|
-
end
|
1213
|
-
subject.get('/fail-fast') { declared(params).to_json }
|
1214
|
-
|
1215
|
-
get '/fail-fast', one: ''
|
1216
|
-
expect(last_response.status).to eq(400)
|
1217
|
-
expect(last_response.body).to eq('one is empty')
|
1218
|
-
end
|
1219
|
-
end
|
1220
|
-
end
|
1221
|
-
|
1222
|
-
context 'when params have group attributes' do
|
1223
|
-
context 'with validations' do
|
1224
|
-
before do
|
1225
|
-
subject.params do
|
1226
|
-
with(allow_blank: false) do
|
1227
|
-
requires :id
|
1228
|
-
optional :name
|
1229
|
-
optional :address, allow_blank: true
|
1230
|
-
end
|
1231
|
-
end
|
1232
|
-
subject.get('test')
|
1233
|
-
end
|
1234
|
-
|
1235
|
-
context 'when data is invalid' do
|
1236
|
-
before do
|
1237
|
-
get 'test', id: '', name: ''
|
1238
|
-
end
|
1239
|
-
|
1240
|
-
it 'returns a validation error' do
|
1241
|
-
expect(last_response.status).to eq(400)
|
1242
|
-
end
|
1243
|
-
|
1244
|
-
it 'applies group validations for every parameter' do
|
1245
|
-
expect(last_response.body).to eq('id is empty, name is empty')
|
1246
|
-
end
|
1247
|
-
end
|
1248
|
-
|
1249
|
-
context 'when parameter has the same validator as a group' do
|
1250
|
-
before do
|
1251
|
-
get 'test', id: 'id', address: ''
|
1252
|
-
end
|
1253
|
-
|
1254
|
-
it 'returns a successful response' do
|
1255
|
-
expect(last_response.status).to eq(200)
|
1256
|
-
end
|
1257
|
-
|
1258
|
-
it 'prioritizes parameter validation over group validation' do
|
1259
|
-
expect(last_response.body).not_to include('address is empty')
|
1260
|
-
end
|
1261
|
-
end
|
1262
|
-
end
|
1263
|
-
|
1264
|
-
context 'with types' do
|
1265
|
-
before do
|
1266
|
-
subject.params do
|
1267
|
-
with(type: Date) do
|
1268
|
-
requires :created_at
|
1269
|
-
end
|
1270
|
-
end
|
1271
|
-
subject.get('test') { params[:created_at] }
|
1272
|
-
end
|
1273
|
-
|
1274
|
-
context 'when invalid date provided' do
|
1275
|
-
before do
|
1276
|
-
get 'test', created_at: 'not_a_date'
|
1277
|
-
end
|
1278
|
-
|
1279
|
-
it 'responds with HTTP error' do
|
1280
|
-
expect(last_response.status).to eq(400)
|
1281
|
-
end
|
1282
|
-
|
1283
|
-
it 'returns a validation error' do
|
1284
|
-
expect(last_response.body).to eq('created_at is invalid')
|
1285
|
-
end
|
1286
|
-
end
|
1287
|
-
|
1288
|
-
context 'when created_at receives a valid date' do
|
1289
|
-
before do
|
1290
|
-
get 'test', created_at: '2016-01-01'
|
1291
|
-
end
|
1292
|
-
|
1293
|
-
it 'returns a successful response' do
|
1294
|
-
expect(last_response.status).to eq(200)
|
1295
|
-
end
|
1296
|
-
|
1297
|
-
it 'returns a date' do
|
1298
|
-
expect(last_response.body).to eq('2016-01-01')
|
1299
|
-
end
|
1300
|
-
end
|
1301
|
-
end
|
1302
|
-
|
1303
|
-
context 'with several group attributes' do
|
1304
|
-
before do
|
1305
|
-
subject.params do
|
1306
|
-
with(values: [1]) do
|
1307
|
-
requires :id, type: Integer
|
1308
|
-
end
|
1309
|
-
|
1310
|
-
with(allow_blank: false) do
|
1311
|
-
optional :address, type: String
|
1312
|
-
end
|
1313
|
-
|
1314
|
-
requires :name
|
1315
|
-
end
|
1316
|
-
subject.get('test')
|
1317
|
-
end
|
1318
|
-
|
1319
|
-
context 'when data is invalid' do
|
1320
|
-
before do
|
1321
|
-
get 'test', id: 2, address: ''
|
1322
|
-
end
|
1323
|
-
|
1324
|
-
it 'responds with HTTP error' do
|
1325
|
-
expect(last_response.status).to eq(400)
|
1326
|
-
end
|
1327
|
-
|
1328
|
-
it 'returns a validation error' do
|
1329
|
-
expect(last_response.body).to eq('id does not have a valid value, address is empty, name is missing')
|
1330
|
-
end
|
1331
|
-
end
|
1332
|
-
|
1333
|
-
context 'when correct data is provided' do
|
1334
|
-
before do
|
1335
|
-
get 'test', id: 1, address: 'Some street', name: 'John'
|
1336
|
-
end
|
1337
|
-
|
1338
|
-
it 'returns a successful response' do
|
1339
|
-
expect(last_response.status).to eq(200)
|
1340
|
-
end
|
1341
|
-
end
|
1342
|
-
end
|
1343
|
-
|
1344
|
-
context 'with nested groups' do
|
1345
|
-
before do
|
1346
|
-
subject.params do
|
1347
|
-
with(type: Integer) do
|
1348
|
-
requires :id
|
1349
|
-
|
1350
|
-
with(type: Date) do
|
1351
|
-
requires :created_at
|
1352
|
-
optional :updated_at
|
1353
|
-
end
|
1354
|
-
end
|
1355
|
-
end
|
1356
|
-
subject.get('test')
|
1357
|
-
end
|
1358
|
-
|
1359
|
-
context 'when data is invalid' do
|
1360
|
-
before do
|
1361
|
-
get 'test', id: 'wrong', created_at: 'not_a_date', updated_at: '2016-01-01'
|
1362
|
-
end
|
1363
|
-
|
1364
|
-
it 'responds with HTTP error' do
|
1365
|
-
expect(last_response.status).to eq(400)
|
1366
|
-
end
|
1367
|
-
|
1368
|
-
it 'returns a validation error' do
|
1369
|
-
expect(last_response.body).to eq('id is invalid, created_at is invalid')
|
1370
|
-
end
|
1371
|
-
end
|
1372
|
-
|
1373
|
-
context 'when correct data is provided' do
|
1374
|
-
before do
|
1375
|
-
get 'test', id: 1, created_at: '2016-01-01'
|
1376
|
-
end
|
1377
|
-
|
1378
|
-
it 'returns a successful response' do
|
1379
|
-
expect(last_response.status).to eq(200)
|
1380
|
-
end
|
1381
|
-
end
|
1382
|
-
end
|
1383
|
-
end
|
1384
|
-
|
1385
|
-
context 'with exactly_one_of validation for optional parameters within an Hash param' do
|
1386
|
-
before do
|
1387
|
-
subject.params do
|
1388
|
-
optional :memo, type: Hash do
|
1389
|
-
optional :text, type: String
|
1390
|
-
optional :custom_body, type: Hash, coerce_with: JSON
|
1391
|
-
exactly_one_of :text, :custom_body
|
1392
|
-
end
|
1393
|
-
end
|
1394
|
-
subject.get('test')
|
1395
|
-
end
|
1396
|
-
|
1397
|
-
context 'when correct data is provided' do
|
1398
|
-
it 'returns a successful response' do
|
1399
|
-
get 'test', memo: {}
|
1400
|
-
expect(last_response.status).to eq(200)
|
1401
|
-
|
1402
|
-
get 'test', memo: { text: 'HOGEHOGE' }
|
1403
|
-
expect(last_response.status).to eq(200)
|
1404
|
-
|
1405
|
-
get 'test', memo: { custom_body: '{ "xxx": "yyy" }' }
|
1406
|
-
expect(last_response.status).to eq(200)
|
1407
|
-
end
|
1408
|
-
end
|
1409
|
-
|
1410
|
-
context 'when invalid data is provided' do
|
1411
|
-
it 'returns a failure response' do
|
1412
|
-
get 'test', memo: { text: 'HOGEHOGE', custom_body: '{ "xxx": "yyy" }' }
|
1413
|
-
expect(last_response.status).to eq(400)
|
1414
|
-
|
1415
|
-
get 'test', memo: '{ "custom_body": "HOGE" }'
|
1416
|
-
expect(last_response.status).to eq(400)
|
1417
|
-
end
|
1418
|
-
end
|
1419
|
-
end
|
1420
|
-
end
|