grape 1.7.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -1
- data/CONTRIBUTING.md +1 -1
- data/README.md +30 -25
- data/UPGRADING.md +35 -0
- data/grape.gemspec +3 -6
- data/lib/grape/api.rb +2 -2
- data/lib/grape/content_types.rb +2 -8
- data/lib/grape/dsl/desc.rb +1 -1
- data/lib/grape/dsl/inside_route.rb +11 -11
- data/lib/grape/dsl/request_response.rb +2 -1
- data/lib/grape/dsl/settings.rb +2 -6
- data/lib/grape/endpoint.rb +28 -18
- data/lib/grape/error_formatter/base.rb +1 -1
- data/lib/grape/exceptions/base.rb +2 -2
- data/lib/grape/exceptions/missing_group_type.rb +1 -6
- data/lib/grape/exceptions/unsupported_group_type.rb +1 -6
- data/lib/grape/exceptions/validation_errors.rb +1 -6
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +3 -3
- data/lib/grape/extensions/hash.rb +4 -7
- data/lib/grape/extensions/hashie/mash.rb +3 -3
- data/lib/grape/formatter/serializable_hash.rb +7 -7
- data/lib/grape/http/headers.rb +12 -2
- data/lib/grape/middleware/auth/base.rb +1 -1
- data/lib/grape/middleware/auth/strategies.rb +1 -2
- data/lib/grape/middleware/error.rb +5 -5
- data/lib/grape/middleware/formatter.rb +6 -6
- data/lib/grape/middleware/versioner/header.rb +11 -19
- data/lib/grape/railtie.rb +9 -0
- data/lib/grape/request.rb +8 -2
- data/lib/grape/router/route.rb +1 -3
- data/lib/grape/util/lazy_value.rb +3 -11
- data/lib/grape/util/strict_hash_configuration.rb +3 -4
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/params_scope.rb +8 -2
- data/lib/grape/validations/single_attribute_iterator.rb +3 -1
- data/lib/grape/validations/types/custom_type_coercer.rb +2 -16
- data/lib/grape/validations/validators/base.rb +9 -20
- data/lib/grape/validations/validators/default_validator.rb +2 -20
- data/lib/grape/validations/validators/multiple_params_base.rb +4 -8
- data/lib/grape/validations/validators/values_validator.rb +14 -5
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +26 -5
- metadata +13 -253
- data/lib/grape/config.rb +0 -34
- data/lib/grape/extensions/deep_mergeable_hash.rb +0 -21
- data/lib/grape/extensions/deep_symbolize_hash.rb +0 -32
- data/spec/grape/api/custom_validations_spec.rb +0 -256
- data/spec/grape/api/deeply_included_options_spec.rb +0 -56
- data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -38
- data/spec/grape/api/documentation_spec.rb +0 -59
- data/spec/grape/api/inherited_helpers_spec.rb +0 -114
- data/spec/grape/api/instance_spec.rb +0 -103
- data/spec/grape/api/invalid_format_spec.rb +0 -45
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -38
- data/spec/grape/api/nested_helpers_spec.rb +0 -50
- data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -43
- data/spec/grape/api/parameters_modification_spec.rb +0 -41
- data/spec/grape/api/patch_method_helpers_spec.rb +0 -79
- data/spec/grape/api/recognize_path_spec.rb +0 -21
- data/spec/grape/api/required_parameters_in_route_spec.rb +0 -37
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -26
- data/spec/grape/api/routes_with_requirements_spec.rb +0 -59
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -41
- data/spec/grape/api/shared_helpers_spec.rb +0 -36
- data/spec/grape/api_remount_spec.rb +0 -473
- data/spec/grape/api_spec.rb +0 -4347
- data/spec/grape/config_spec.rb +0 -17
- data/spec/grape/dsl/callbacks_spec.rb +0 -45
- data/spec/grape/dsl/desc_spec.rb +0 -101
- data/spec/grape/dsl/headers_spec.rb +0 -62
- data/spec/grape/dsl/helpers_spec.rb +0 -100
- data/spec/grape/dsl/inside_route_spec.rb +0 -535
- data/spec/grape/dsl/logger_spec.rb +0 -24
- data/spec/grape/dsl/middleware_spec.rb +0 -60
- data/spec/grape/dsl/parameters_spec.rb +0 -180
- data/spec/grape/dsl/request_response_spec.rb +0 -206
- data/spec/grape/dsl/routing_spec.rb +0 -275
- data/spec/grape/dsl/settings_spec.rb +0 -261
- data/spec/grape/dsl/validations_spec.rb +0 -55
- data/spec/grape/endpoint/declared_spec.rb +0 -846
- data/spec/grape/endpoint_spec.rb +0 -1085
- data/spec/grape/entity_spec.rb +0 -336
- data/spec/grape/exceptions/base_spec.rb +0 -81
- data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -145
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +0 -358
- data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -15
- data/spec/grape/exceptions/invalid_response_spec.rb +0 -11
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +0 -15
- data/spec/grape/exceptions/missing_group_type_spec.rb +0 -21
- data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -17
- data/spec/grape/exceptions/missing_option_spec.rb +0 -15
- data/spec/grape/exceptions/unknown_options_spec.rb +0 -15
- data/spec/grape/exceptions/unknown_validator_spec.rb +0 -15
- data/spec/grape/exceptions/unsupported_group_type_spec.rb +0 -23
- data/spec/grape/exceptions/validation_errors_spec.rb +0 -92
- data/spec/grape/exceptions/validation_spec.rb +0 -19
- data/spec/grape/extensions/param_builders/hash_spec.rb +0 -83
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -105
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -79
- data/spec/grape/integration/global_namespace_function_spec.rb +0 -29
- data/spec/grape/integration/rack_sendfile_spec.rb +0 -48
- data/spec/grape/integration/rack_spec.rb +0 -51
- data/spec/grape/loading_spec.rb +0 -44
- data/spec/grape/middleware/auth/base_spec.rb +0 -31
- data/spec/grape/middleware/auth/dsl_spec.rb +0 -60
- data/spec/grape/middleware/auth/strategies_spec.rb +0 -120
- data/spec/grape/middleware/base_spec.rb +0 -221
- data/spec/grape/middleware/error_spec.rb +0 -85
- data/spec/grape/middleware/exception_spec.rb +0 -294
- data/spec/grape/middleware/formatter_spec.rb +0 -461
- data/spec/grape/middleware/globals_spec.rb +0 -30
- data/spec/grape/middleware/stack_spec.rb +0 -155
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -122
- data/spec/grape/middleware/versioner/header_spec.rb +0 -345
- data/spec/grape/middleware/versioner/param_spec.rb +0 -171
- data/spec/grape/middleware/versioner/path_spec.rb +0 -62
- data/spec/grape/middleware/versioner_spec.rb +0 -21
- data/spec/grape/named_api_spec.rb +0 -19
- data/spec/grape/parser_spec.rb +0 -86
- data/spec/grape/path_spec.rb +0 -252
- data/spec/grape/presenters/presenter_spec.rb +0 -71
- data/spec/grape/request_spec.rb +0 -136
- data/spec/grape/util/inheritable_setting_spec.rb +0 -242
- data/spec/grape/util/inheritable_values_spec.rb +0 -79
- data/spec/grape/util/reverse_stackable_values_spec.rb +0 -134
- data/spec/grape/util/stackable_values_spec.rb +0 -128
- data/spec/grape/util/strict_hash_configuration_spec.rb +0 -38
- data/spec/grape/validations/attributes_doc_spec.rb +0 -153
- data/spec/grape/validations/instance_behaivour_spec.rb +0 -43
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -40
- data/spec/grape/validations/params_scope_spec.rb +0 -1420
- data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -57
- data/spec/grape/validations/types/array_coercer_spec.rb +0 -33
- data/spec/grape/validations/types/primitive_coercer_spec.rb +0 -150
- data/spec/grape/validations/types/set_coercer_spec.rb +0 -32
- data/spec/grape/validations/types_spec.rb +0 -111
- data/spec/grape/validations/validators/all_or_none_spec.rb +0 -162
- data/spec/grape/validations/validators/allow_blank_spec.rb +0 -575
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -205
- data/spec/grape/validations/validators/coerce_spec.rb +0 -1261
- data/spec/grape/validations/validators/default_spec.rb +0 -463
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -233
- data/spec/grape/validations/validators/except_values_spec.rb +0 -192
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -214
- data/spec/grape/validations/validators/presence_spec.rb +0 -315
- data/spec/grape/validations/validators/regexp_spec.rb +0 -161
- data/spec/grape/validations/validators/same_as_spec.rb +0 -57
- data/spec/grape/validations/validators/values_spec.rb +0 -696
- data/spec/grape/validations/validators/zh-CN.yml +0 -10
- data/spec/grape/validations_spec.rb +0 -2029
- data/spec/integration/eager_load/eager_load_spec.rb +0 -15
- data/spec/integration/multi_json/json_spec.rb +0 -7
- data/spec/integration/multi_xml/xml_spec.rb +0 -7
- data/spec/shared/versioning_examples.rb +0 -215
- data/spec/spec_helper.rb +0 -52
- data/spec/support/basic_auth_encode_helpers.rb +0 -11
- data/spec/support/chunks.rb +0 -14
- data/spec/support/content_type_helpers.rb +0 -15
- data/spec/support/endpoint_faker.rb +0 -25
- data/spec/support/file_streamer.rb +0 -13
- data/spec/support/integer_helpers.rb +0 -13
- data/spec/support/versioned_helpers.rb +0 -55
@@ -1,57 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
describe Grape::Validations::SingleAttributeIterator do
|
4
|
-
describe '#each' do
|
5
|
-
subject(:iterator) { described_class.new(validator, scope, params) }
|
6
|
-
|
7
|
-
let(:scope) { Grape::Validations::ParamsScope.new(api: Class.new(Grape::API)) }
|
8
|
-
let(:validator) { double(attrs: %i[first second]) }
|
9
|
-
|
10
|
-
context 'when params is a hash' do
|
11
|
-
let(:params) do
|
12
|
-
{ first: 'string', second: 'string' }
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'yields params and every single attribute from the list' do
|
16
|
-
expect { |b| iterator.each(&b) }
|
17
|
-
.to yield_successive_args([params, :first, false, false], [params, :second, false, false])
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
context 'when params is an array' do
|
22
|
-
let(:params) do
|
23
|
-
[{ first: 'string1', second: 'string1' }, { first: 'string2', second: 'string2' }]
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'yields every single attribute from the list for each of the array elements' do
|
27
|
-
expect { |b| iterator.each(&b) }.to yield_successive_args(
|
28
|
-
[params[0], :first, false, false], [params[0], :second, false, false],
|
29
|
-
[params[1], :first, false, false], [params[1], :second, false, false]
|
30
|
-
)
|
31
|
-
end
|
32
|
-
|
33
|
-
context 'empty values' do
|
34
|
-
let(:params) { [{}, '', 10] }
|
35
|
-
|
36
|
-
it 'marks params with empty values' do
|
37
|
-
expect { |b| iterator.each(&b) }.to yield_successive_args(
|
38
|
-
[params[0], :first, true, false], [params[0], :second, true, false],
|
39
|
-
[params[1], :first, true, false], [params[1], :second, true, false],
|
40
|
-
[params[2], :first, false, false], [params[2], :second, false, false]
|
41
|
-
)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
context 'when missing optional value' do
|
46
|
-
let(:params) { [Grape::DSL::Parameters::EmptyOptionalValue, 10] }
|
47
|
-
|
48
|
-
it 'marks params with skipped values' do
|
49
|
-
expect { |b| iterator.each(&b) }.to yield_successive_args(
|
50
|
-
[params[0], :first, false, true], [params[0], :second, false, true],
|
51
|
-
[params[1], :first, false, false], [params[1], :second, false, false]
|
52
|
-
)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
describe Grape::Validations::Types::ArrayCoercer do
|
4
|
-
subject { described_class.new(type) }
|
5
|
-
|
6
|
-
describe '#call' do
|
7
|
-
context 'an array of primitives' do
|
8
|
-
let(:type) { Array[String] }
|
9
|
-
|
10
|
-
it 'coerces elements in the array' do
|
11
|
-
expect(subject.call([10, 20])).to eq(%w[10 20])
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
context 'an array of arrays' do
|
16
|
-
let(:type) { Array[Array[Integer]] }
|
17
|
-
|
18
|
-
it 'coerces elements in the nested array' do
|
19
|
-
expect(subject.call([%w[10 20]])).to eq([[10, 20]])
|
20
|
-
expect(subject.call([['10'], ['20']])).to eq([[10], [20]])
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'an array of sets' do
|
25
|
-
let(:type) { Array[Set[Integer]] }
|
26
|
-
|
27
|
-
it 'coerces elements in the nested set' do
|
28
|
-
expect(subject.call([%w[10 20]])).to eq([Set[10, 20]])
|
29
|
-
expect(subject.call([['10'], ['20']])).to eq([Set[10], Set[20]])
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,150 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
describe Grape::Validations::Types::PrimitiveCoercer do
|
4
|
-
subject { described_class.new(type, strict) }
|
5
|
-
|
6
|
-
let(:strict) { false }
|
7
|
-
|
8
|
-
describe '#call' do
|
9
|
-
context 'BigDecimal' do
|
10
|
-
let(:type) { BigDecimal }
|
11
|
-
|
12
|
-
it 'coerces to BigDecimal' do
|
13
|
-
expect(subject.call(5)).to eq(BigDecimal('5'))
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'coerces an empty string to nil' do
|
17
|
-
expect(subject.call('')).to be_nil
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
context 'Boolean' do
|
22
|
-
let(:type) { Grape::API::Boolean }
|
23
|
-
|
24
|
-
[true, 'true', 1].each do |val|
|
25
|
-
it "coerces '#{val}' to true" do
|
26
|
-
expect(subject.call(val)).to be(true)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
[false, 'false', 0].each do |val|
|
31
|
-
it "coerces '#{val}' to false" do
|
32
|
-
expect(subject.call(val)).to be(false)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'returns an error when the given value cannot be coerced' do
|
37
|
-
expect(subject.call(123)).to be_instance_of(Grape::Validations::Types::InvalidValue)
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'coerces an empty string to nil' do
|
41
|
-
expect(subject.call('')).to be_nil
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
context 'DateTime' do
|
46
|
-
let(:type) { DateTime }
|
47
|
-
|
48
|
-
it 'coerces an empty string to nil' do
|
49
|
-
expect(subject.call('')).to be_nil
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
context 'Float' do
|
54
|
-
let(:type) { Float }
|
55
|
-
|
56
|
-
it 'coerces an empty string to nil' do
|
57
|
-
expect(subject.call('')).to be_nil
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
context 'Integer' do
|
62
|
-
let(:type) { Integer }
|
63
|
-
|
64
|
-
it 'coerces an empty string to nil' do
|
65
|
-
expect(subject.call('')).to be_nil
|
66
|
-
end
|
67
|
-
|
68
|
-
it 'accepts non-nil value' do
|
69
|
-
expect(subject.call(42)).to be_a(Integer)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
context 'Numeric' do
|
74
|
-
let(:type) { Numeric }
|
75
|
-
|
76
|
-
it 'coerces an empty string to nil' do
|
77
|
-
expect(subject.call('')).to be_nil
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'accepts a non-nil value' do
|
81
|
-
expect(subject.call(42)).to be_a(Numeric) # in fact Integer
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
context 'Time' do
|
86
|
-
let(:type) { Time }
|
87
|
-
|
88
|
-
it 'coerces an empty string to nil' do
|
89
|
-
expect(subject.call('')).to be_nil
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
context 'String' do
|
94
|
-
let(:type) { String }
|
95
|
-
|
96
|
-
it 'coerces to String' do
|
97
|
-
expect(subject.call(10)).to eq('10')
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'does not coerce an empty string to nil' do
|
101
|
-
expect(subject.call('')).to eq('')
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
context 'Symbol' do
|
106
|
-
let(:type) { Symbol }
|
107
|
-
|
108
|
-
it 'coerces an empty string to nil' do
|
109
|
-
expect(subject.call('')).to be_nil
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
context 'a type unknown in Dry-types' do
|
114
|
-
let(:type) { Complex }
|
115
|
-
|
116
|
-
it 'raises error on init' do
|
117
|
-
expect(DryTypes::Params.constants).not_to include(type.name.to_sym)
|
118
|
-
expect { subject }.to raise_error(/type Complex should support coercion/)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
context 'the strict mode' do
|
123
|
-
let(:strict) { true }
|
124
|
-
|
125
|
-
context 'Boolean' do
|
126
|
-
let(:type) { Grape::API::Boolean }
|
127
|
-
|
128
|
-
it 'returns an error when the given value is not Boolean' do
|
129
|
-
expect(subject.call(1)).to be_instance_of(Grape::Validations::Types::InvalidValue)
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'returns a value as it is when the given value is Boolean' do
|
133
|
-
expect(subject.call(true)).to be(true)
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
context 'BigDecimal' do
|
138
|
-
let(:type) { BigDecimal }
|
139
|
-
|
140
|
-
it 'returns an error when the given value is not BigDecimal' do
|
141
|
-
expect(subject.call(1)).to be_instance_of(Grape::Validations::Types::InvalidValue)
|
142
|
-
end
|
143
|
-
|
144
|
-
it 'returns a value as it is when the given value is BigDecimal' do
|
145
|
-
expect(subject.call(BigDecimal('0'))).to eq(BigDecimal('0'))
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
describe Grape::Validations::Types::SetCoercer do
|
4
|
-
subject { described_class.new(type) }
|
5
|
-
|
6
|
-
describe '#call' do
|
7
|
-
context 'a set of primitives' do
|
8
|
-
let(:type) { Set[String] }
|
9
|
-
|
10
|
-
it 'coerces elements to the set' do
|
11
|
-
expect(subject.call([10, 20])).to eq(Set['10', '20'])
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
context 'a set of sets' do
|
16
|
-
let(:type) { Set[Set[Integer]] }
|
17
|
-
|
18
|
-
it 'coerces elements in the nested set' do
|
19
|
-
expect(subject.call([%w[10 20]])).to eq(Set[Set[10, 20]])
|
20
|
-
expect(subject.call([['10'], ['20']])).to eq(Set[Set[10], Set[20]])
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'a set of sets of arrays' do
|
25
|
-
let(:type) { Set[Set[Array[Integer]]] }
|
26
|
-
|
27
|
-
it 'coerces elements in the nested set' do
|
28
|
-
expect(subject.call([[['10'], ['20']]])).to eq(Set[Set[Array[10], Array[20]]])
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,111 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
describe Grape::Validations::Types do
|
4
|
-
module TypesSpec
|
5
|
-
class FooType
|
6
|
-
def self.parse(_); end
|
7
|
-
end
|
8
|
-
|
9
|
-
class BarType
|
10
|
-
def self.parse; end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
describe '::primitive?' do
|
15
|
-
[
|
16
|
-
Integer, Float, Numeric, BigDecimal,
|
17
|
-
Grape::API::Boolean, String, Symbol,
|
18
|
-
Date, DateTime, Time
|
19
|
-
].each do |type|
|
20
|
-
it "recognizes #{type} as a primitive" do
|
21
|
-
expect(described_class).to be_primitive(type)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'identifies unknown types' do
|
26
|
-
expect(described_class).not_to be_primitive(Object)
|
27
|
-
expect(described_class).not_to be_primitive(TypesSpec::FooType)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
describe '::structure?' do
|
32
|
-
[
|
33
|
-
Hash, Array, Set
|
34
|
-
].each do |type|
|
35
|
-
it "recognizes #{type} as a structure" do
|
36
|
-
expect(described_class).to be_structure(type)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
describe '::special?' do
|
42
|
-
[
|
43
|
-
JSON, Array[JSON], File, Rack::Multipart::UploadedFile
|
44
|
-
].each do |type|
|
45
|
-
it "provides special handling for #{type.inspect}" do
|
46
|
-
expect(described_class).to be_special(type)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
describe 'special types' do
|
52
|
-
subject { described_class::SPECIAL[type] }
|
53
|
-
|
54
|
-
context 'when JSON' do
|
55
|
-
let(:type) { JSON }
|
56
|
-
|
57
|
-
it { is_expected.to eq(Grape::Validations::Types::Json) }
|
58
|
-
end
|
59
|
-
|
60
|
-
context 'when Array[JSON]' do
|
61
|
-
let(:type) { Array[JSON] }
|
62
|
-
|
63
|
-
it { is_expected.to eq(Grape::Validations::Types::JsonArray) }
|
64
|
-
end
|
65
|
-
|
66
|
-
context 'when File' do
|
67
|
-
let(:type) { File }
|
68
|
-
|
69
|
-
it { is_expected.to eq(Grape::Validations::Types::File) }
|
70
|
-
end
|
71
|
-
|
72
|
-
context 'when Rack::Multipart::UploadedFile' do
|
73
|
-
let(:type) { Rack::Multipart::UploadedFile }
|
74
|
-
|
75
|
-
it { is_expected.to eq(Grape::Validations::Types::File) }
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
describe '::custom?' do
|
80
|
-
it 'returns false if the type does not respond to :parse' do
|
81
|
-
expect(described_class).not_to be_custom(Object)
|
82
|
-
end
|
83
|
-
|
84
|
-
it 'returns true if the type responds to :parse with one argument' do
|
85
|
-
expect(described_class).to be_custom(TypesSpec::FooType)
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'returns false if the type\'s #parse method takes other than one argument' do
|
89
|
-
expect(described_class).not_to be_custom(TypesSpec::BarType)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
describe '::build_coercer' do
|
94
|
-
it 'has internal cache variables' do
|
95
|
-
expect(described_class.instance_variable_get(:@__cache)).to be_a(Hash)
|
96
|
-
expect(described_class.instance_variable_get(:@__cache_write_lock)).to be_a(Mutex)
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'caches the result of the build_coercer method' do
|
100
|
-
original_cache = described_class.instance_variable_get(:@__cache)
|
101
|
-
described_class.instance_variable_set(:@__cache, {})
|
102
|
-
|
103
|
-
a_coercer = described_class.build_coercer(Array[String])
|
104
|
-
b_coercer = described_class.build_coercer(Array[String])
|
105
|
-
|
106
|
-
expect(a_coercer.object_id).to eq(b_coercer.object_id)
|
107
|
-
|
108
|
-
described_class.instance_variable_set(:@__cache, original_cache)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
@@ -1,162 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
describe Grape::Validations::Validators::AllOrNoneOfValidator do
|
4
|
-
let_it_be(:app) do
|
5
|
-
Class.new(Grape::API) do
|
6
|
-
rescue_from Grape::Exceptions::ValidationErrors do |e|
|
7
|
-
error!(e.errors.transform_keys! { |key| key.join(',') }, 400)
|
8
|
-
end
|
9
|
-
|
10
|
-
params do
|
11
|
-
optional :beer, :wine, type: Grape::API::Boolean
|
12
|
-
all_or_none_of :beer, :wine
|
13
|
-
end
|
14
|
-
post do
|
15
|
-
end
|
16
|
-
|
17
|
-
params do
|
18
|
-
optional :beer, :wine, :other, type: Grape::API::Boolean
|
19
|
-
all_or_none_of :beer, :wine
|
20
|
-
end
|
21
|
-
post 'mixed-params' do
|
22
|
-
end
|
23
|
-
|
24
|
-
params do
|
25
|
-
optional :beer, :wine, type: Grape::API::Boolean
|
26
|
-
all_or_none_of :beer, :wine, message: 'choose all or none'
|
27
|
-
end
|
28
|
-
post '/custom-message' do
|
29
|
-
end
|
30
|
-
|
31
|
-
params do
|
32
|
-
requires :item, type: Hash do
|
33
|
-
optional :beer, :wine, type: Grape::API::Boolean
|
34
|
-
all_or_none_of :beer, :wine
|
35
|
-
end
|
36
|
-
end
|
37
|
-
post '/nested-hash' do
|
38
|
-
end
|
39
|
-
|
40
|
-
params do
|
41
|
-
requires :items, type: Array do
|
42
|
-
optional :beer, :wine, type: Grape::API::Boolean
|
43
|
-
all_or_none_of :beer, :wine
|
44
|
-
end
|
45
|
-
end
|
46
|
-
post '/nested-array' do
|
47
|
-
end
|
48
|
-
|
49
|
-
params do
|
50
|
-
requires :items, type: Array do
|
51
|
-
requires :nested_items, type: Array do
|
52
|
-
optional :beer, :wine, type: Grape::API::Boolean
|
53
|
-
all_or_none_of :beer, :wine
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
post '/deeply-nested-array' do
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
describe '#validate!' do
|
63
|
-
subject(:validate) { post path, params }
|
64
|
-
|
65
|
-
context 'when all restricted params are present' do
|
66
|
-
let(:path) { '/' }
|
67
|
-
let(:params) { { beer: true, wine: true } }
|
68
|
-
|
69
|
-
it 'does not return a validation error' do
|
70
|
-
validate
|
71
|
-
expect(last_response.status).to eq 201
|
72
|
-
end
|
73
|
-
|
74
|
-
context 'mixed with other params' do
|
75
|
-
let(:path) { '/mixed-params' }
|
76
|
-
let(:params) { { beer: true, wine: true, other: true } }
|
77
|
-
|
78
|
-
it 'does not return a validation error' do
|
79
|
-
validate
|
80
|
-
expect(last_response.status).to eq 201
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
context 'when a subset of restricted params are present' do
|
86
|
-
let(:path) { '/' }
|
87
|
-
let(:params) { { beer: true } }
|
88
|
-
|
89
|
-
it 'returns a validation error' do
|
90
|
-
validate
|
91
|
-
expect(last_response.status).to eq 400
|
92
|
-
expect(JSON.parse(last_response.body)).to eq(
|
93
|
-
'beer,wine' => ['provide all or none of parameters']
|
94
|
-
)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
context 'when custom message is specified' do
|
99
|
-
let(:path) { '/custom-message' }
|
100
|
-
let(:params) { { beer: true } }
|
101
|
-
|
102
|
-
it 'returns a validation error' do
|
103
|
-
validate
|
104
|
-
expect(last_response.status).to eq 400
|
105
|
-
expect(JSON.parse(last_response.body)).to eq(
|
106
|
-
'beer,wine' => ['choose all or none']
|
107
|
-
)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
context 'when no restricted params are present' do
|
112
|
-
let(:path) { '/' }
|
113
|
-
let(:params) { { somethingelse: true } }
|
114
|
-
|
115
|
-
it 'does not return a validation error' do
|
116
|
-
validate
|
117
|
-
expect(last_response.status).to eq 201
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
context 'when restricted params are nested inside required hash' do
|
122
|
-
let(:path) { '/nested-hash' }
|
123
|
-
let(:params) { { item: { beer: true } } }
|
124
|
-
|
125
|
-
it 'returns a validation error with full names of the params' do
|
126
|
-
validate
|
127
|
-
expect(last_response.status).to eq 400
|
128
|
-
expect(JSON.parse(last_response.body)).to eq(
|
129
|
-
'item[beer],item[wine]' => ['provide all or none of parameters']
|
130
|
-
)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
context 'when mutually exclusive params are nested inside array' do
|
135
|
-
let(:path) { '/nested-array' }
|
136
|
-
let(:params) { { items: [{ beer: true, wine: true }, { wine: true }] } }
|
137
|
-
|
138
|
-
it 'returns a validation error with full names of the params' do
|
139
|
-
validate
|
140
|
-
expect(last_response.status).to eq 400
|
141
|
-
expect(JSON.parse(last_response.body)).to eq(
|
142
|
-
'items[1][beer],items[1][wine]' => ['provide all or none of parameters']
|
143
|
-
)
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
context 'when mutually exclusive params are deeply nested' do
|
148
|
-
let(:path) { '/deeply-nested-array' }
|
149
|
-
let(:params) { { items: [{ nested_items: [{ beer: true }] }] } }
|
150
|
-
|
151
|
-
it 'returns a validation error with full names of the params' do
|
152
|
-
validate
|
153
|
-
expect(last_response.status).to eq 400
|
154
|
-
expect(JSON.parse(last_response.body)).to eq(
|
155
|
-
'items[0][nested_items][0][beer],items[0][nested_items][0][wine]' => [
|
156
|
-
'provide all or none of parameters'
|
157
|
-
]
|
158
|
-
)
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|