grape 1.3.3 → 1.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +111 -2
- data/CONTRIBUTING.md +2 -1
- data/README.md +135 -23
- data/UPGRADING.md +237 -46
- data/grape.gemspec +5 -5
- data/lib/grape/api/instance.rb +34 -42
- data/lib/grape/api.rb +21 -16
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dsl/callbacks.rb +1 -1
- data/lib/grape/dsl/desc.rb +3 -5
- data/lib/grape/dsl/headers.rb +5 -2
- data/lib/grape/dsl/helpers.rb +8 -5
- data/lib/grape/dsl/inside_route.rb +72 -53
- data/lib/grape/dsl/middleware.rb +4 -4
- data/lib/grape/dsl/parameters.rb +11 -7
- data/lib/grape/dsl/request_response.rb +9 -6
- data/lib/grape/dsl/routing.rb +8 -9
- data/lib/grape/dsl/settings.rb +5 -5
- data/lib/grape/dsl/validations.rb +18 -1
- data/lib/grape/eager_load.rb +1 -1
- data/lib/grape/endpoint.rb +29 -42
- data/lib/grape/error_formatter/json.rb +2 -6
- data/lib/grape/error_formatter/xml.rb +2 -6
- data/lib/grape/exceptions/empty_message_body.rb +11 -0
- data/lib/grape/exceptions/validation.rb +2 -3
- data/lib/grape/exceptions/validation_errors.rb +1 -1
- 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 +1 -1
- data/lib/grape/middleware/auth/base.rb +3 -3
- data/lib/grape/middleware/auth/dsl.rb +7 -1
- data/lib/grape/middleware/base.rb +6 -3
- data/lib/grape/middleware/error.rb +11 -13
- data/lib/grape/middleware/formatter.rb +7 -7
- data/lib/grape/middleware/stack.rb +10 -3
- 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 +4 -1
- data/lib/grape/router/attribute_translator.rb +3 -3
- data/lib/grape/router/pattern.rb +1 -1
- data/lib/grape/router/route.rb +2 -2
- data/lib/grape/router.rb +31 -30
- data/lib/grape/{serve_file → serve_stream}/file_body.rb +1 -1
- data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +1 -1
- data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +8 -8
- data/lib/grape/util/base_inheritable.rb +2 -2
- data/lib/grape/util/inheritable_setting.rb +1 -3
- data/lib/grape/util/lazy_value.rb +4 -2
- data/lib/grape/util/strict_hash_configuration.rb +1 -1
- data/lib/grape/validations/attributes_iterator.rb +8 -0
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/params_scope.rb +97 -62
- data/lib/grape/validations/single_attribute_iterator.rb +1 -1
- data/lib/grape/validations/types/custom_type_coercer.rb +16 -3
- data/lib/grape/validations/types/dry_type_coercer.rb +1 -1
- data/lib/grape/validations/types/invalid_value.rb +24 -0
- data/lib/grape/validations/types/json.rb +2 -1
- data/lib/grape/validations/types/primitive_coercer.rb +4 -5
- data/lib/grape/validations/types.rb +1 -4
- data/lib/grape/validations/validator_factory.rb +1 -1
- data/lib/grape/validations/validators/all_or_none.rb +8 -5
- data/lib/grape/validations/validators/allow_blank.rb +9 -7
- data/lib/grape/validations/validators/as.rb +6 -8
- data/lib/grape/validations/validators/at_least_one_of.rb +7 -4
- data/lib/grape/validations/validators/base.rb +74 -69
- data/lib/grape/validations/validators/coerce.rb +63 -76
- data/lib/grape/validations/validators/default.rb +36 -34
- data/lib/grape/validations/validators/exactly_one_of.rb +9 -6
- data/lib/grape/validations/validators/except_values.rb +13 -11
- data/lib/grape/validations/validators/multiple_params_base.rb +24 -19
- data/lib/grape/validations/validators/mutual_exclusion.rb +8 -5
- data/lib/grape/validations/validators/presence.rb +7 -4
- data/lib/grape/validations/validators/regexp.rb +8 -5
- data/lib/grape/validations/validators/same_as.rb +18 -15
- data/lib/grape/validations/validators/values.rb +61 -56
- data/lib/grape/validations.rb +6 -0
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +7 -3
- data/spec/grape/api/custom_validations_spec.rb +77 -45
- data/spec/grape/api/deeply_included_options_spec.rb +3 -3
- data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
- data/spec/grape/api/invalid_format_spec.rb +2 -0
- data/spec/grape/api/recognize_path_spec.rb +1 -1
- data/spec/grape/api/routes_with_requirements_spec.rb +8 -8
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
- data/spec/grape/api_remount_spec.rb +25 -19
- data/spec/grape/api_spec.rb +576 -211
- data/spec/grape/dsl/callbacks_spec.rb +2 -1
- data/spec/grape/dsl/headers_spec.rb +39 -9
- data/spec/grape/dsl/helpers_spec.rb +3 -2
- data/spec/grape/dsl/inside_route_spec.rb +185 -34
- data/spec/grape/dsl/logger_spec.rb +16 -18
- data/spec/grape/dsl/middleware_spec.rb +2 -1
- data/spec/grape/dsl/parameters_spec.rb +2 -0
- data/spec/grape/dsl/request_response_spec.rb +1 -0
- data/spec/grape/dsl/routing_spec.rb +10 -7
- data/spec/grape/endpoint/declared_spec.rb +848 -0
- data/spec/grape/endpoint_spec.rb +77 -589
- data/spec/grape/entity_spec.rb +29 -23
- data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
- data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
- data/spec/grape/exceptions/validation_spec.rb +5 -3
- data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
- data/spec/grape/integration/rack_sendfile_spec.rb +13 -9
- data/spec/grape/loading_spec.rb +8 -8
- data/spec/grape/middleware/auth/dsl_spec.rb +15 -6
- data/spec/grape/middleware/auth/strategies_spec.rb +61 -21
- data/spec/grape/middleware/base_spec.rb +24 -15
- data/spec/grape/middleware/error_spec.rb +3 -3
- data/spec/grape/middleware/exception_spec.rb +111 -161
- data/spec/grape/middleware/formatter_spec.rb +28 -7
- data/spec/grape/middleware/globals_spec.rb +7 -4
- data/spec/grape/middleware/stack_spec.rb +15 -12
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
- data/spec/grape/middleware/versioner/header_spec.rb +14 -13
- data/spec/grape/middleware/versioner/param_spec.rb +7 -1
- data/spec/grape/middleware/versioner/path_spec.rb +5 -1
- data/spec/grape/middleware/versioner_spec.rb +1 -1
- data/spec/grape/parser_spec.rb +4 -0
- data/spec/grape/path_spec.rb +52 -52
- data/spec/grape/presenters/presenter_spec.rb +7 -6
- data/spec/grape/request_spec.rb +6 -4
- data/spec/grape/util/inheritable_setting_spec.rb +7 -7
- data/spec/grape/util/inheritable_values_spec.rb +3 -2
- data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
- data/spec/grape/util/stackable_values_spec.rb +7 -5
- data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +14 -3
- data/spec/grape/validations/params_scope_spec.rb +72 -10
- data/spec/grape/validations/single_attribute_iterator_spec.rb +18 -6
- data/spec/grape/validations/types/primitive_coercer_spec.rb +63 -7
- data/spec/grape/validations/types_spec.rb +8 -8
- data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
- data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
- data/spec/grape/validations/validators/coerce_spec.rb +248 -33
- data/spec/grape/validations/validators/default_spec.rb +121 -78
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
- data/spec/grape/validations/validators/except_values_spec.rb +4 -3
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
- data/spec/grape/validations/validators/presence_spec.rb +16 -1
- data/spec/grape/validations/validators/regexp_spec.rb +25 -31
- data/spec/grape/validations/validators/same_as_spec.rb +14 -20
- data/spec/grape/validations/validators/values_spec.rb +183 -178
- data/spec/grape/validations_spec.rb +342 -29
- data/spec/integration/eager_load/eager_load_spec.rb +15 -0
- data/spec/integration/multi_json/json_spec.rb +1 -1
- data/spec/integration/multi_xml/xml_spec.rb +1 -1
- data/spec/shared/versioning_examples.rb +32 -29
- data/spec/spec_helper.rb +12 -12
- data/spec/support/basic_auth_encode_helpers.rb +1 -1
- data/spec/support/chunks.rb +14 -0
- data/spec/support/versioned_helpers.rb +4 -6
- metadata +110 -102
data/spec/grape/request_spec.rb
CHANGED
@@ -21,7 +21,7 @@ module Grape
|
|
21
21
|
let(:env) { default_env }
|
22
22
|
|
23
23
|
let(:request) do
|
24
|
-
|
24
|
+
described_class.new(env)
|
25
25
|
end
|
26
26
|
|
27
27
|
describe '#params' do
|
@@ -38,7 +38,7 @@ module Grape
|
|
38
38
|
|
39
39
|
context 'when build_params_with: Grape::Extensions::Hash::ParamBuilder is specified' do
|
40
40
|
let(:request) do
|
41
|
-
|
41
|
+
described_class.new(env, build_params_with: Grape::Extensions::Hash::ParamBuilder)
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'returns symbolized params' do
|
@@ -65,6 +65,8 @@ module Grape
|
|
65
65
|
end
|
66
66
|
|
67
67
|
describe 'when the param_builder is set to Hashie' do
|
68
|
+
subject(:request_params) { described_class.new(env, **opts).params }
|
69
|
+
|
68
70
|
before do
|
69
71
|
Grape.configure do |config|
|
70
72
|
config.param_builder = Grape::Extensions::Hashie::Mash::ParamBuilder
|
@@ -75,15 +77,15 @@ module Grape
|
|
75
77
|
Grape.config.reset
|
76
78
|
end
|
77
79
|
|
78
|
-
subject(:request_params) { Grape::Request.new(env, opts).params }
|
79
|
-
|
80
80
|
context 'when the API does not include a specific param builder' do
|
81
81
|
let(:opts) { {} }
|
82
|
+
|
82
83
|
it { is_expected.to be_a(Hashie::Mash) }
|
83
84
|
end
|
84
85
|
|
85
86
|
context 'when the API includes a specific param builder' do
|
86
87
|
let(:opts) { { build_params_with: Grape::Extensions::Hash::ParamBuilder } }
|
88
|
+
|
87
89
|
it { is_expected.to be_a(Hash) }
|
88
90
|
end
|
89
91
|
end
|
@@ -4,12 +4,12 @@ require 'spec_helper'
|
|
4
4
|
module Grape
|
5
5
|
module Util
|
6
6
|
describe InheritableSetting do
|
7
|
-
before
|
8
|
-
|
7
|
+
before do
|
8
|
+
described_class.reset_global!
|
9
9
|
end
|
10
10
|
|
11
11
|
let(:parent) do
|
12
|
-
|
12
|
+
described_class.new.tap do |settings|
|
13
13
|
settings.global[:global_thing] = :global_foo_bar
|
14
14
|
settings.namespace[:namespace_thing] = :namespace_foo_bar
|
15
15
|
settings.namespace_inheritable[:namespace_inheritable_thing] = :namespace_inheritable_foo_bar
|
@@ -20,7 +20,7 @@ module Grape
|
|
20
20
|
end
|
21
21
|
|
22
22
|
let(:other_parent) do
|
23
|
-
|
23
|
+
described_class.new.tap do |settings|
|
24
24
|
settings.namespace[:namespace_thing] = :namespace_foo_bar_other
|
25
25
|
settings.namespace_inheritable[:namespace_inheritable_thing] = :namespace_inheritable_foo_bar_other
|
26
26
|
settings.namespace_stackable[:namespace_stackable_thing] = :namespace_stackable_foo_bar_other
|
@@ -29,7 +29,7 @@ module Grape
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
before
|
32
|
+
before do
|
33
33
|
subject.inherit_from parent
|
34
34
|
end
|
35
35
|
|
@@ -50,7 +50,7 @@ module Grape
|
|
50
50
|
expect(parent.global[:global_thing]).to eq :global_new_foo_bar
|
51
51
|
end
|
52
52
|
|
53
|
-
it '
|
53
|
+
it 'handles different parents' do
|
54
54
|
subject.global[:global_thing] = :global_new_foo_bar
|
55
55
|
|
56
56
|
subject.inherit_from other_parent
|
@@ -89,7 +89,7 @@ module Grape
|
|
89
89
|
expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
|
90
90
|
end
|
91
91
|
|
92
|
-
it '
|
92
|
+
it 'handles different parents' do
|
93
93
|
expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
|
94
94
|
|
95
95
|
subject.inherit_from other_parent
|
@@ -4,8 +4,9 @@ require 'spec_helper'
|
|
4
4
|
module Grape
|
5
5
|
module Util
|
6
6
|
describe InheritableValues do
|
7
|
-
|
8
|
-
|
7
|
+
subject { described_class.new(parent) }
|
8
|
+
|
9
|
+
let(:parent) { described_class.new }
|
9
10
|
|
10
11
|
describe '#delete' do
|
11
12
|
it 'deletes a key' do
|
@@ -4,9 +4,10 @@ require 'spec_helper'
|
|
4
4
|
module Grape
|
5
5
|
module Util
|
6
6
|
describe ReverseStackableValues do
|
7
|
-
let(:parent) { described_class.new }
|
8
7
|
subject { described_class.new(parent) }
|
9
8
|
|
9
|
+
let(:parent) { described_class.new }
|
10
|
+
|
10
11
|
describe '#keys' do
|
11
12
|
it 'returns all keys' do
|
12
13
|
subject[:some_thing] = :foo_bar
|
@@ -102,6 +103,7 @@ module Grape
|
|
102
103
|
|
103
104
|
describe '#clone' do
|
104
105
|
let(:obj_cloned) { subject.clone }
|
106
|
+
|
105
107
|
it 'copies all values' do
|
106
108
|
parent = described_class.new
|
107
109
|
child = described_class.new parent
|
@@ -4,8 +4,9 @@ require 'spec_helper'
|
|
4
4
|
module Grape
|
5
5
|
module Util
|
6
6
|
describe StackableValues do
|
7
|
-
|
8
|
-
|
7
|
+
subject { described_class.new(parent) }
|
8
|
+
|
9
|
+
let(:parent) { described_class.new }
|
9
10
|
|
10
11
|
describe '#keys' do
|
11
12
|
it 'returns all keys' do
|
@@ -99,10 +100,11 @@ module Grape
|
|
99
100
|
|
100
101
|
describe '#clone' do
|
101
102
|
let(:obj_cloned) { subject.clone }
|
103
|
+
|
102
104
|
it 'copies all values' do
|
103
|
-
parent =
|
104
|
-
child =
|
105
|
-
grandchild =
|
105
|
+
parent = described_class.new
|
106
|
+
child = described_class.new parent
|
107
|
+
grandchild = described_class.new child
|
106
108
|
|
107
109
|
parent[:some_thing] = :foo
|
108
110
|
child[:some_thing] = %i[bar more]
|
@@ -4,7 +4,7 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe 'Validator with instance variables' do
|
6
6
|
let(:validator_type) do
|
7
|
-
Class.new(Grape::Validations::Base) do
|
7
|
+
Class.new(Grape::Validations::Validators::Base) do
|
8
8
|
def validate_param!(_attr_name, _params)
|
9
9
|
if instance_variable_defined?(:@instance_variable) && @instance_variable
|
10
10
|
raise Grape::Exceptions::Validation.new(params: ['params'],
|
@@ -14,15 +14,6 @@ describe 'Validator with instance variables' do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
18
|
-
before do
|
19
|
-
Grape::Validations.register_validator('instance_validator', validator_type)
|
20
|
-
end
|
21
|
-
|
22
|
-
after do
|
23
|
-
Grape::Validations.deregister_validator('instance_validator')
|
24
|
-
end
|
25
|
-
|
26
17
|
let(:app) do
|
27
18
|
Class.new(Grape::API) do
|
28
19
|
params do
|
@@ -35,6 +26,14 @@ describe 'Validator with instance variables' do
|
|
35
26
|
end
|
36
27
|
end
|
37
28
|
|
29
|
+
before do
|
30
|
+
Grape::Validations.register_validator('instance_validator', validator_type)
|
31
|
+
end
|
32
|
+
|
33
|
+
after do
|
34
|
+
Grape::Validations.deregister_validator('instance_validator')
|
35
|
+
end
|
36
|
+
|
38
37
|
it 'passes validation every time' do
|
39
38
|
expect(validator_type).to receive(:new).exactly(4).times.and_call_original
|
40
39
|
|
@@ -5,6 +5,7 @@ require 'spec_helper'
|
|
5
5
|
describe Grape::Validations::MultipleAttributesIterator do
|
6
6
|
describe '#each' do
|
7
7
|
subject(:iterator) { described_class.new(validator, scope, params) }
|
8
|
+
|
8
9
|
let(:scope) { Grape::Validations::ParamsScope.new(api: Class.new(Grape::API)) }
|
9
10
|
let(:validator) { double(attrs: %i[first second third]) }
|
10
11
|
|
@@ -13,8 +14,8 @@ describe Grape::Validations::MultipleAttributesIterator do
|
|
13
14
|
{ first: 'string', second: 'string' }
|
14
15
|
end
|
15
16
|
|
16
|
-
it 'yields the whole params hash without the list of attrs' do
|
17
|
-
expect { |b| iterator.each(&b) }.to yield_with_args(params)
|
17
|
+
it 'yields the whole params hash and the skipped flag without the list of attrs' do
|
18
|
+
expect { |b| iterator.each(&b) }.to yield_with_args(params, false)
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
@@ -24,7 +25,17 @@ describe Grape::Validations::MultipleAttributesIterator do
|
|
24
25
|
end
|
25
26
|
|
26
27
|
it 'yields each element of the array without the list of attrs' do
|
27
|
-
expect { |b| iterator.each(&b) }.to yield_successive_args(params[0], params[1])
|
28
|
+
expect { |b| iterator.each(&b) }.to yield_successive_args([params[0], false], [params[1], false])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when params is empty optional placeholder' do
|
33
|
+
let(:params) do
|
34
|
+
[Grape::DSL::Parameters::EmptyOptionalValue, { first: 'string2', second: 'string2' }]
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'yields each element of the array without the list of attrs' do
|
38
|
+
expect { |b| iterator.each(&b) }.to yield_successive_args([Grape::DSL::Parameters::EmptyOptionalValue, true], [params[1], false])
|
28
39
|
end
|
29
40
|
end
|
30
41
|
end
|
@@ -98,6 +98,7 @@ describe Grape::Validations::ParamsScope do
|
|
98
98
|
|
99
99
|
def self.parse(value)
|
100
100
|
raise if value == 'invalid'
|
101
|
+
|
101
102
|
new(value)
|
102
103
|
end
|
103
104
|
|
@@ -144,7 +145,7 @@ describe Grape::Validations::ParamsScope do
|
|
144
145
|
get '/renaming-coerced', foo: ' there we go '
|
145
146
|
|
146
147
|
expect(last_response.status).to eq(200)
|
147
|
-
expect(last_response.body).to eq('there we go
|
148
|
+
expect(last_response.body).to eq('-there we go')
|
148
149
|
end
|
149
150
|
|
150
151
|
it do
|
@@ -180,6 +181,28 @@ describe Grape::Validations::ParamsScope do
|
|
180
181
|
expect(last_response.status).to eq(200)
|
181
182
|
expect(last_response.body).to eq('{"baz":{"qux":"any"}}')
|
182
183
|
end
|
184
|
+
|
185
|
+
it 'renaming can be defined before default' do
|
186
|
+
subject.params do
|
187
|
+
optional :foo, as: :bar, default: 'before'
|
188
|
+
end
|
189
|
+
subject.get('/rename-before-default') { declared(params)[:bar] }
|
190
|
+
get '/rename-before-default'
|
191
|
+
|
192
|
+
expect(last_response.status).to eq(200)
|
193
|
+
expect(last_response.body).to eq('before')
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'renaming can be defined after default' do
|
197
|
+
subject.params do
|
198
|
+
optional :foo, default: 'after', as: :bar
|
199
|
+
end
|
200
|
+
subject.get('/rename-after-default') { declared(params)[:bar] }
|
201
|
+
get '/rename-after-default'
|
202
|
+
|
203
|
+
expect(last_response.status).to eq(200)
|
204
|
+
expect(last_response.body).to eq('after')
|
205
|
+
end
|
183
206
|
end
|
184
207
|
|
185
208
|
context 'array without coerce type explicitly given' do
|
@@ -269,7 +292,7 @@ describe Grape::Validations::ParamsScope do
|
|
269
292
|
it 'does not raise an exception' do
|
270
293
|
expect do
|
271
294
|
subject.params { optional :numbers, type: Array[Integer], values: 0..2, default: 0..2 }
|
272
|
-
end.
|
295
|
+
end.not_to raise_error
|
273
296
|
end
|
274
297
|
end
|
275
298
|
|
@@ -277,7 +300,7 @@ describe Grape::Validations::ParamsScope do
|
|
277
300
|
it 'does not raise an exception' do
|
278
301
|
expect do
|
279
302
|
subject.params { optional :numbers, type: Array[Integer], values: [0, 1, 2], default: [1, 0] }
|
280
|
-
end.
|
303
|
+
end.not_to raise_error
|
281
304
|
end
|
282
305
|
end
|
283
306
|
end
|
@@ -501,7 +524,7 @@ describe Grape::Validations::ParamsScope do
|
|
501
524
|
requires :c
|
502
525
|
end
|
503
526
|
end
|
504
|
-
end.
|
527
|
+
end.not_to raise_error
|
505
528
|
end
|
506
529
|
|
507
530
|
it 'does not raise an error if when using nested given' do
|
@@ -517,7 +540,7 @@ describe Grape::Validations::ParamsScope do
|
|
517
540
|
end
|
518
541
|
end
|
519
542
|
end
|
520
|
-
end.
|
543
|
+
end.not_to raise_error
|
521
544
|
end
|
522
545
|
|
523
546
|
it 'allows nested dependent parameters' do
|
@@ -562,13 +585,13 @@ describe Grape::Validations::ParamsScope do
|
|
562
585
|
body = JSON.parse(last_response.body)
|
563
586
|
|
564
587
|
expect(body.keys).to include('c')
|
565
|
-
expect(body.keys).
|
588
|
+
expect(body.keys).not_to include('b')
|
566
589
|
end
|
567
590
|
|
568
591
|
it 'allows renaming of dependent on parameter' do
|
569
592
|
subject.params do
|
570
593
|
optional :a, as: :b
|
571
|
-
given
|
594
|
+
given a: ->(val) { val == 'x' } do
|
572
595
|
requires :c
|
573
596
|
end
|
574
597
|
end
|
@@ -582,7 +605,7 @@ describe Grape::Validations::ParamsScope do
|
|
582
605
|
expect(last_response.status).to eq 200
|
583
606
|
end
|
584
607
|
|
585
|
-
it '
|
608
|
+
it 'does not raise if the dependent parameter is not the renamed one' do
|
586
609
|
expect do
|
587
610
|
subject.params do
|
588
611
|
optional :a, as: :b
|
@@ -590,6 +613,17 @@ describe Grape::Validations::ParamsScope do
|
|
590
613
|
requires :c
|
591
614
|
end
|
592
615
|
end
|
616
|
+
end.not_to raise_error
|
617
|
+
end
|
618
|
+
|
619
|
+
it 'raises an error if the dependent parameter is the renamed one' do
|
620
|
+
expect do
|
621
|
+
subject.params do
|
622
|
+
optional :a, as: :b
|
623
|
+
given :b do
|
624
|
+
requires :c
|
625
|
+
end
|
626
|
+
end
|
593
627
|
end.to raise_error(Grape::Exceptions::UnknownParameter)
|
594
628
|
end
|
595
629
|
|
@@ -633,6 +667,32 @@ describe Grape::Validations::ParamsScope do
|
|
633
667
|
expect(last_response.status).to eq(200)
|
634
668
|
end
|
635
669
|
|
670
|
+
it 'detect unmet nested dependency' do
|
671
|
+
subject.params do
|
672
|
+
requires :a, type: String, allow_blank: false, values: %w[x y z]
|
673
|
+
given a: ->(val) { val == 'z' } do
|
674
|
+
requires :inner3, type: Array, allow_blank: false do
|
675
|
+
requires :bar, type: String, allow_blank: false
|
676
|
+
given bar: ->(val) { val == 'b' } do
|
677
|
+
requires :baz, type: Array do
|
678
|
+
optional :baz_category, type: String
|
679
|
+
end
|
680
|
+
end
|
681
|
+
given bar: ->(val) { val == 'c' } do
|
682
|
+
requires :baz, type: Array do
|
683
|
+
requires :baz_category, type: String
|
684
|
+
end
|
685
|
+
end
|
686
|
+
end
|
687
|
+
end
|
688
|
+
end
|
689
|
+
subject.get('/nested-dependency') { declared(params).to_json }
|
690
|
+
|
691
|
+
get '/nested-dependency', a: 'z', inner3: [{ bar: 'c', baz: [{ unrelated: 'nope' }] }]
|
692
|
+
expect(last_response.status).to eq(400)
|
693
|
+
expect(last_response.body).to eq 'inner3[0][baz][0][baz_category] is missing'
|
694
|
+
end
|
695
|
+
|
636
696
|
it 'includes the parameter within #declared(params)' do
|
637
697
|
get '/test', a: true, b: true
|
638
698
|
|
@@ -727,7 +787,7 @@ describe Grape::Validations::ParamsScope do
|
|
727
787
|
subject.get('/test') { 'ok' }
|
728
788
|
end
|
729
789
|
|
730
|
-
it '
|
790
|
+
it 'passes none Hash params' do
|
731
791
|
get '/test', foos: ['']
|
732
792
|
expect(last_response.status).to eq(200)
|
733
793
|
expect(last_response.body).to eq('ok')
|
@@ -903,6 +963,7 @@ describe Grape::Validations::ParamsScope do
|
|
903
963
|
expect(last_response.body).to eq('one is missing, two is missing, three is missing')
|
904
964
|
end
|
905
965
|
end
|
966
|
+
|
906
967
|
context 'when fail_fast is defined it stops the validation' do
|
907
968
|
it 'of other params' do
|
908
969
|
subject.params do
|
@@ -915,6 +976,7 @@ describe Grape::Validations::ParamsScope do
|
|
915
976
|
expect(last_response.status).to eq(400)
|
916
977
|
expect(last_response.body).to eq('one is missing')
|
917
978
|
end
|
979
|
+
|
918
980
|
it 'for a single param' do
|
919
981
|
subject.params do
|
920
982
|
requires :one, allow_blank: false, regexp: /[0-9]+/, fail_fast: true
|
@@ -965,7 +1027,7 @@ describe Grape::Validations::ParamsScope do
|
|
965
1027
|
end
|
966
1028
|
|
967
1029
|
it 'prioritizes parameter validation over group validation' do
|
968
|
-
expect(last_response.body).
|
1030
|
+
expect(last_response.body).not_to include('address is empty')
|
969
1031
|
end
|
970
1032
|
end
|
971
1033
|
end
|
@@ -5,6 +5,7 @@ require 'spec_helper'
|
|
5
5
|
describe Grape::Validations::SingleAttributeIterator do
|
6
6
|
describe '#each' do
|
7
7
|
subject(:iterator) { described_class.new(validator, scope, params) }
|
8
|
+
|
8
9
|
let(:scope) { Grape::Validations::ParamsScope.new(api: Class.new(Grape::API)) }
|
9
10
|
let(:validator) { double(attrs: %i[first second]) }
|
10
11
|
|
@@ -15,7 +16,7 @@ describe Grape::Validations::SingleAttributeIterator do
|
|
15
16
|
|
16
17
|
it 'yields params and every single attribute from the list' do
|
17
18
|
expect { |b| iterator.each(&b) }
|
18
|
-
.to yield_successive_args([params, :first, false], [params, :second, false])
|
19
|
+
.to yield_successive_args([params, :first, false, false], [params, :second, false, false])
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
@@ -26,8 +27,8 @@ describe Grape::Validations::SingleAttributeIterator do
|
|
26
27
|
|
27
28
|
it 'yields every single attribute from the list for each of the array elements' do
|
28
29
|
expect { |b| iterator.each(&b) }.to yield_successive_args(
|
29
|
-
[params[0], :first, false], [params[0], :second, false],
|
30
|
-
[params[1], :first, false], [params[1], :second, false]
|
30
|
+
[params[0], :first, false, false], [params[0], :second, false, false],
|
31
|
+
[params[1], :first, false, false], [params[1], :second, false, false]
|
31
32
|
)
|
32
33
|
end
|
33
34
|
|
@@ -36,9 +37,20 @@ describe Grape::Validations::SingleAttributeIterator do
|
|
36
37
|
|
37
38
|
it 'marks params with empty values' do
|
38
39
|
expect { |b| iterator.each(&b) }.to yield_successive_args(
|
39
|
-
[params[0], :first, true], [params[0], :second, true],
|
40
|
-
[params[1], :first, true], [params[1], :second, true],
|
41
|
-
[params[2], :first, false], [params[2], :second, false]
|
40
|
+
[params[0], :first, true, false], [params[0], :second, true, false],
|
41
|
+
[params[1], :first, true, false], [params[1], :second, true, false],
|
42
|
+
[params[2], :first, false, false], [params[2], :second, false, false]
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when missing optional value' do
|
48
|
+
let(:params) { [Grape::DSL::Parameters::EmptyOptionalValue, 10] }
|
49
|
+
|
50
|
+
it 'marks params with skipped values' do
|
51
|
+
expect { |b| iterator.each(&b) }.to yield_successive_args(
|
52
|
+
[params[0], :first, false, true], [params[0], :second, false, true],
|
53
|
+
[params[1], :first, false, false], [params[1], :second, false, false]
|
42
54
|
)
|
43
55
|
end
|
44
56
|
end
|
@@ -3,11 +3,23 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe Grape::Validations::Types::PrimitiveCoercer do
|
6
|
-
let(:strict) { false }
|
7
|
-
|
8
6
|
subject { described_class.new(type, strict) }
|
9
7
|
|
8
|
+
let(:strict) { false }
|
9
|
+
|
10
10
|
describe '#call' do
|
11
|
+
context 'BigDecimal' do
|
12
|
+
let(:type) { BigDecimal }
|
13
|
+
|
14
|
+
it 'coerces to BigDecimal' do
|
15
|
+
expect(subject.call(5)).to eq(BigDecimal('5'))
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'coerces an empty string to nil' do
|
19
|
+
expect(subject.call('')).to be_nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
11
23
|
context 'Boolean' do
|
12
24
|
let(:type) { Grape::API::Boolean }
|
13
25
|
|
@@ -32,19 +44,63 @@ describe Grape::Validations::Types::PrimitiveCoercer do
|
|
32
44
|
end
|
33
45
|
end
|
34
46
|
|
47
|
+
context 'DateTime' do
|
48
|
+
let(:type) { DateTime }
|
49
|
+
|
50
|
+
it 'coerces an empty string to nil' do
|
51
|
+
expect(subject.call('')).to be_nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'Float' do
|
56
|
+
let(:type) { Float }
|
57
|
+
|
58
|
+
it 'coerces an empty string to nil' do
|
59
|
+
expect(subject.call('')).to be_nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'Integer' do
|
64
|
+
let(:type) { Integer }
|
65
|
+
|
66
|
+
it 'coerces an empty string to nil' do
|
67
|
+
expect(subject.call('')).to be_nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'Numeric' do
|
72
|
+
let(:type) { Numeric }
|
73
|
+
|
74
|
+
it 'coerces an empty string to nil' do
|
75
|
+
expect(subject.call('')).to be_nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'Time' do
|
80
|
+
let(:type) { Time }
|
81
|
+
|
82
|
+
it 'coerces an empty string to nil' do
|
83
|
+
expect(subject.call('')).to be_nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
35
87
|
context 'String' do
|
36
88
|
let(:type) { String }
|
37
89
|
|
38
90
|
it 'coerces to String' do
|
39
91
|
expect(subject.call(10)).to eq('10')
|
40
92
|
end
|
93
|
+
|
94
|
+
it 'does not coerce an empty string to nil' do
|
95
|
+
expect(subject.call('')).to eq('')
|
96
|
+
end
|
41
97
|
end
|
42
98
|
|
43
|
-
context '
|
44
|
-
let(:type) {
|
99
|
+
context 'Symbol' do
|
100
|
+
let(:type) { Symbol }
|
45
101
|
|
46
|
-
it 'coerces to
|
47
|
-
expect(subject.call(
|
102
|
+
it 'coerces an empty string to nil' do
|
103
|
+
expect(subject.call('')).to be_nil
|
48
104
|
end
|
49
105
|
end
|
50
106
|
|
@@ -71,7 +127,7 @@ describe Grape::Validations::Types::PrimitiveCoercer do
|
|
71
127
|
end
|
72
128
|
|
73
129
|
it 'returns a value as it is when the given value is BigDecimal' do
|
74
|
-
expect(subject.call(BigDecimal(0))).to eq(BigDecimal(0))
|
130
|
+
expect(subject.call(BigDecimal('0'))).to eq(BigDecimal('0'))
|
75
131
|
end
|
76
132
|
end
|
77
133
|
end
|
@@ -20,13 +20,13 @@ describe Grape::Validations::Types do
|
|
20
20
|
Date, DateTime, Time
|
21
21
|
].each do |type|
|
22
22
|
it "recognizes #{type} as a primitive" do
|
23
|
-
expect(described_class.
|
23
|
+
expect(described_class).to be_primitive(type)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'identifies unknown types' do
|
28
|
-
expect(described_class.
|
29
|
-
expect(described_class.
|
28
|
+
expect(described_class).not_to be_primitive(Object)
|
29
|
+
expect(described_class).not_to be_primitive(TypesSpec::FooType)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
@@ -35,7 +35,7 @@ describe Grape::Validations::Types do
|
|
35
35
|
Hash, Array, Set
|
36
36
|
].each do |type|
|
37
37
|
it "recognizes #{type} as a structure" do
|
38
|
-
expect(described_class.
|
38
|
+
expect(described_class).to be_structure(type)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -45,22 +45,22 @@ describe Grape::Validations::Types do
|
|
45
45
|
JSON, Array[JSON], File, Rack::Multipart::UploadedFile
|
46
46
|
].each do |type|
|
47
47
|
it "provides special handling for #{type.inspect}" do
|
48
|
-
expect(described_class.
|
48
|
+
expect(described_class).to be_special(type)
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
53
|
describe '::custom?' do
|
54
54
|
it 'returns false if the type does not respond to :parse' do
|
55
|
-
expect(described_class.
|
55
|
+
expect(described_class).not_to be_custom(Object)
|
56
56
|
end
|
57
57
|
|
58
58
|
it 'returns true if the type responds to :parse with one argument' do
|
59
|
-
expect(described_class.
|
59
|
+
expect(described_class).to be_custom(TypesSpec::FooType)
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'returns false if the type\'s #parse method takes other than one argument' do
|
63
|
-
expect(described_class.
|
63
|
+
expect(described_class).not_to be_custom(TypesSpec::BarType)
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|