grape-security 0.8.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 +7 -0
- data/.gitignore +45 -0
- data/.rspec +2 -0
- data/.rubocop.yml +70 -0
- data/.travis.yml +18 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +314 -0
- data/CONTRIBUTING.md +118 -0
- data/Gemfile +21 -0
- data/Guardfile +14 -0
- data/LICENSE +20 -0
- data/README.md +1777 -0
- data/RELEASING.md +105 -0
- data/Rakefile +69 -0
- data/UPGRADING.md +124 -0
- data/grape-security.gemspec +39 -0
- data/grape.png +0 -0
- data/lib/grape.rb +99 -0
- data/lib/grape/api.rb +646 -0
- data/lib/grape/cookies.rb +39 -0
- data/lib/grape/endpoint.rb +533 -0
- data/lib/grape/error_formatter/base.rb +31 -0
- data/lib/grape/error_formatter/json.rb +15 -0
- data/lib/grape/error_formatter/txt.rb +16 -0
- data/lib/grape/error_formatter/xml.rb +15 -0
- data/lib/grape/exceptions/base.rb +66 -0
- data/lib/grape/exceptions/incompatible_option_values.rb +10 -0
- data/lib/grape/exceptions/invalid_formatter.rb +10 -0
- data/lib/grape/exceptions/invalid_versioner_option.rb +10 -0
- data/lib/grape/exceptions/invalid_with_option_for_represent.rb +10 -0
- data/lib/grape/exceptions/missing_mime_type.rb +10 -0
- data/lib/grape/exceptions/missing_option.rb +10 -0
- data/lib/grape/exceptions/missing_vendor_option.rb +10 -0
- data/lib/grape/exceptions/unknown_options.rb +10 -0
- data/lib/grape/exceptions/unknown_validator.rb +10 -0
- data/lib/grape/exceptions/validation.rb +26 -0
- data/lib/grape/exceptions/validation_errors.rb +43 -0
- data/lib/grape/formatter/base.rb +31 -0
- data/lib/grape/formatter/json.rb +12 -0
- data/lib/grape/formatter/serializable_hash.rb +35 -0
- data/lib/grape/formatter/txt.rb +11 -0
- data/lib/grape/formatter/xml.rb +12 -0
- data/lib/grape/http/request.rb +26 -0
- data/lib/grape/locale/en.yml +32 -0
- data/lib/grape/middleware/auth/base.rb +30 -0
- data/lib/grape/middleware/auth/basic.rb +13 -0
- data/lib/grape/middleware/auth/digest.rb +13 -0
- data/lib/grape/middleware/auth/oauth2.rb +83 -0
- data/lib/grape/middleware/base.rb +62 -0
- data/lib/grape/middleware/error.rb +89 -0
- data/lib/grape/middleware/filter.rb +17 -0
- data/lib/grape/middleware/formatter.rb +150 -0
- data/lib/grape/middleware/globals.rb +13 -0
- data/lib/grape/middleware/versioner.rb +32 -0
- data/lib/grape/middleware/versioner/accept_version_header.rb +67 -0
- data/lib/grape/middleware/versioner/header.rb +132 -0
- data/lib/grape/middleware/versioner/param.rb +42 -0
- data/lib/grape/middleware/versioner/path.rb +52 -0
- data/lib/grape/namespace.rb +23 -0
- data/lib/grape/parser/base.rb +29 -0
- data/lib/grape/parser/json.rb +11 -0
- data/lib/grape/parser/xml.rb +11 -0
- data/lib/grape/path.rb +70 -0
- data/lib/grape/route.rb +27 -0
- data/lib/grape/util/content_types.rb +18 -0
- data/lib/grape/util/deep_merge.rb +23 -0
- data/lib/grape/util/hash_stack.rb +120 -0
- data/lib/grape/validations.rb +322 -0
- data/lib/grape/validations/coerce.rb +63 -0
- data/lib/grape/validations/default.rb +25 -0
- data/lib/grape/validations/exactly_one_of.rb +26 -0
- data/lib/grape/validations/mutual_exclusion.rb +25 -0
- data/lib/grape/validations/presence.rb +16 -0
- data/lib/grape/validations/regexp.rb +12 -0
- data/lib/grape/validations/values.rb +23 -0
- data/lib/grape/version.rb +3 -0
- data/spec/grape/api_spec.rb +2571 -0
- data/spec/grape/endpoint_spec.rb +784 -0
- data/spec/grape/entity_spec.rb +324 -0
- data/spec/grape/exceptions/invalid_formatter_spec.rb +18 -0
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +18 -0
- data/spec/grape/exceptions/missing_mime_type_spec.rb +18 -0
- data/spec/grape/exceptions/missing_option_spec.rb +18 -0
- data/spec/grape/exceptions/unknown_options_spec.rb +18 -0
- data/spec/grape/exceptions/unknown_validator_spec.rb +18 -0
- data/spec/grape/exceptions/validation_errors_spec.rb +19 -0
- data/spec/grape/middleware/auth/basic_spec.rb +31 -0
- data/spec/grape/middleware/auth/digest_spec.rb +47 -0
- data/spec/grape/middleware/auth/oauth2_spec.rb +135 -0
- data/spec/grape/middleware/base_spec.rb +58 -0
- data/spec/grape/middleware/error_spec.rb +45 -0
- data/spec/grape/middleware/exception_spec.rb +184 -0
- data/spec/grape/middleware/formatter_spec.rb +258 -0
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +121 -0
- data/spec/grape/middleware/versioner/header_spec.rb +302 -0
- data/spec/grape/middleware/versioner/param_spec.rb +58 -0
- data/spec/grape/middleware/versioner/path_spec.rb +44 -0
- data/spec/grape/middleware/versioner_spec.rb +22 -0
- data/spec/grape/path_spec.rb +229 -0
- data/spec/grape/util/hash_stack_spec.rb +132 -0
- data/spec/grape/validations/coerce_spec.rb +208 -0
- data/spec/grape/validations/default_spec.rb +123 -0
- data/spec/grape/validations/exactly_one_of_spec.rb +71 -0
- data/spec/grape/validations/mutual_exclusion_spec.rb +61 -0
- data/spec/grape/validations/presence_spec.rb +142 -0
- data/spec/grape/validations/regexp_spec.rb +40 -0
- data/spec/grape/validations/values_spec.rb +152 -0
- data/spec/grape/validations/zh-CN.yml +10 -0
- data/spec/grape/validations_spec.rb +994 -0
- data/spec/shared/versioning_examples.rb +121 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/basic_auth_encode_helpers.rb +3 -0
- data/spec/support/content_type_helpers.rb +11 -0
- data/spec/support/versioned_helpers.rb +50 -0
- metadata +421 -0
@@ -0,0 +1,208 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Grape::Validations::CoerceValidator do
|
5
|
+
subject do
|
6
|
+
Class.new(Grape::API)
|
7
|
+
end
|
8
|
+
|
9
|
+
def app
|
10
|
+
subject
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'coerce' do
|
14
|
+
|
15
|
+
context "i18n" do
|
16
|
+
|
17
|
+
after :each do
|
18
|
+
I18n.locale = :en
|
19
|
+
end
|
20
|
+
|
21
|
+
it "i18n error on malformed input" do
|
22
|
+
I18n.load_path << File.expand_path('../zh-CN.yml', __FILE__)
|
23
|
+
I18n.reload!
|
24
|
+
I18n.locale = 'zh-CN'.to_sym
|
25
|
+
subject.params do
|
26
|
+
requires :age, type: Integer
|
27
|
+
end
|
28
|
+
subject.get '/single' do
|
29
|
+
'int works'
|
30
|
+
end
|
31
|
+
|
32
|
+
get '/single', age: '43a'
|
33
|
+
expect(last_response.status).to eq(400)
|
34
|
+
expect(last_response.body).to eq('年龄格式不正确')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'gives an english fallback error when default locale message is blank' do
|
38
|
+
I18n.locale = 'pt-BR'.to_sym
|
39
|
+
subject.params do
|
40
|
+
requires :age, type: Integer
|
41
|
+
end
|
42
|
+
subject.get '/single' do
|
43
|
+
'int works'
|
44
|
+
end
|
45
|
+
|
46
|
+
get '/single', age: '43a'
|
47
|
+
expect(last_response.status).to eq(400)
|
48
|
+
expect(last_response.body).to eq('age is invalid')
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'error on malformed input' do
|
54
|
+
subject.params do
|
55
|
+
requires :int, type: Integer
|
56
|
+
end
|
57
|
+
subject.get '/single' do
|
58
|
+
'int works'
|
59
|
+
end
|
60
|
+
|
61
|
+
get '/single', int: '43a'
|
62
|
+
expect(last_response.status).to eq(400)
|
63
|
+
expect(last_response.body).to eq('int is invalid')
|
64
|
+
|
65
|
+
get '/single', int: '43'
|
66
|
+
expect(last_response.status).to eq(200)
|
67
|
+
expect(last_response.body).to eq('int works')
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'error on malformed input (Array)' do
|
71
|
+
subject.params do
|
72
|
+
requires :ids, type: Array[Integer]
|
73
|
+
end
|
74
|
+
subject.get '/array' do
|
75
|
+
'array int works'
|
76
|
+
end
|
77
|
+
|
78
|
+
get 'array', ids: ['1', '2', 'az']
|
79
|
+
expect(last_response.status).to eq(400)
|
80
|
+
expect(last_response.body).to eq('ids is invalid')
|
81
|
+
|
82
|
+
get 'array', ids: ['1', '2', '890']
|
83
|
+
expect(last_response.status).to eq(200)
|
84
|
+
expect(last_response.body).to eq('array int works')
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'complex objects' do
|
88
|
+
module CoerceValidatorSpec
|
89
|
+
class User
|
90
|
+
include Virtus.model
|
91
|
+
attribute :id, Integer
|
92
|
+
attribute :name, String
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'error on malformed input for complex objects' do
|
97
|
+
subject.params do
|
98
|
+
requires :user, type: CoerceValidatorSpec::User
|
99
|
+
end
|
100
|
+
subject.get '/user' do
|
101
|
+
'complex works'
|
102
|
+
end
|
103
|
+
|
104
|
+
get '/user', user: "32"
|
105
|
+
expect(last_response.status).to eq(400)
|
106
|
+
expect(last_response.body).to eq('user is invalid')
|
107
|
+
|
108
|
+
get '/user', user: { id: 32, name: 'Bob' }
|
109
|
+
expect(last_response.status).to eq(200)
|
110
|
+
expect(last_response.body).to eq('complex works')
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'coerces' do
|
115
|
+
it 'Integer' do
|
116
|
+
subject.params do
|
117
|
+
requires :int, coerce: Integer
|
118
|
+
end
|
119
|
+
subject.get '/int' do
|
120
|
+
params[:int].class
|
121
|
+
end
|
122
|
+
|
123
|
+
get '/int', int: "45"
|
124
|
+
expect(last_response.status).to eq(200)
|
125
|
+
expect(last_response.body).to eq('Integer')
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'Array of Integers' do
|
129
|
+
subject.params do
|
130
|
+
requires :arry, coerce: Array[Integer]
|
131
|
+
end
|
132
|
+
subject.get '/array' do
|
133
|
+
params[:arry][0].class
|
134
|
+
end
|
135
|
+
|
136
|
+
get '/array', arry: ['1', '2', '3']
|
137
|
+
expect(last_response.status).to eq(200)
|
138
|
+
expect(last_response.body).to eq('Integer')
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'Array of Bools' do
|
142
|
+
subject.params do
|
143
|
+
requires :arry, coerce: Array[Virtus::Attribute::Boolean]
|
144
|
+
end
|
145
|
+
subject.get '/array' do
|
146
|
+
params[:arry][0].class
|
147
|
+
end
|
148
|
+
|
149
|
+
get 'array', arry: [1, 0]
|
150
|
+
expect(last_response.status).to eq(200)
|
151
|
+
expect(last_response.body).to eq('TrueClass')
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'Bool' do
|
155
|
+
subject.params do
|
156
|
+
requires :bool, coerce: Virtus::Attribute::Boolean
|
157
|
+
end
|
158
|
+
subject.get '/bool' do
|
159
|
+
params[:bool].class
|
160
|
+
end
|
161
|
+
|
162
|
+
get '/bool', bool: 1
|
163
|
+
expect(last_response.status).to eq(200)
|
164
|
+
expect(last_response.body).to eq('TrueClass')
|
165
|
+
|
166
|
+
get '/bool', bool: 0
|
167
|
+
expect(last_response.status).to eq(200)
|
168
|
+
expect(last_response.body).to eq('FalseClass')
|
169
|
+
|
170
|
+
get '/bool', bool: 'false'
|
171
|
+
expect(last_response.status).to eq(200)
|
172
|
+
expect(last_response.body).to eq('FalseClass')
|
173
|
+
|
174
|
+
get '/bool', bool: 'true'
|
175
|
+
expect(last_response.status).to eq(200)
|
176
|
+
expect(last_response.body).to eq('TrueClass')
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'file' do
|
180
|
+
subject.params do
|
181
|
+
requires :file, coerce: Rack::Multipart::UploadedFile
|
182
|
+
end
|
183
|
+
subject.post '/upload' do
|
184
|
+
params[:file].filename
|
185
|
+
end
|
186
|
+
|
187
|
+
post '/upload', file: Rack::Test::UploadedFile.new(__FILE__)
|
188
|
+
expect(last_response.status).to eq(201)
|
189
|
+
expect(last_response.body).to eq(File.basename(__FILE__).to_s)
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'Nests integers' do
|
193
|
+
subject.params do
|
194
|
+
requires :integers, type: Hash do
|
195
|
+
requires :int, coerce: Integer
|
196
|
+
end
|
197
|
+
end
|
198
|
+
subject.get '/int' do
|
199
|
+
params[:integers][:int].class
|
200
|
+
end
|
201
|
+
|
202
|
+
get '/int', integers: { int: "45" }
|
203
|
+
expect(last_response.status).to eq(200)
|
204
|
+
expect(last_response.body).to eq('Integer')
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Grape::Validations::DefaultValidator do
|
4
|
+
|
5
|
+
module ValidationsSpec
|
6
|
+
module DefaultValidatorSpec
|
7
|
+
class API < Grape::API
|
8
|
+
default_format :json
|
9
|
+
|
10
|
+
params do
|
11
|
+
optional :id
|
12
|
+
optional :type, default: 'default-type'
|
13
|
+
end
|
14
|
+
get '/' do
|
15
|
+
{ id: params[:id], type: params[:type] }
|
16
|
+
end
|
17
|
+
|
18
|
+
params do
|
19
|
+
optional :type1, default: 'default-type1'
|
20
|
+
optional :type2, default: 'default-type2'
|
21
|
+
end
|
22
|
+
get '/user' do
|
23
|
+
{ type1: params[:type1], type2: params[:type2] }
|
24
|
+
end
|
25
|
+
|
26
|
+
params do
|
27
|
+
requires :id
|
28
|
+
optional :type1, default: 'default-type1'
|
29
|
+
optional :type2, default: 'default-type2'
|
30
|
+
end
|
31
|
+
|
32
|
+
get '/message' do
|
33
|
+
{ id: params[:id], type1: params[:type1], type2: params[:type2] }
|
34
|
+
end
|
35
|
+
|
36
|
+
params do
|
37
|
+
optional :random, default: -> { Random.rand }
|
38
|
+
optional :not_random, default: Random.rand
|
39
|
+
end
|
40
|
+
get '/numbers' do
|
41
|
+
{ random_number: params[:random], non_random_number: params[:non_random_number] }
|
42
|
+
end
|
43
|
+
|
44
|
+
params do
|
45
|
+
# NOTE: The :foo parameter could be made required with json body
|
46
|
+
# params, and then an empty hash would be valid. With query parameters
|
47
|
+
# it must be optional if it isn't provided at all, as otherwise
|
48
|
+
# the validaton for the Hash itself fails because there is no such
|
49
|
+
# thing as an empty hash.
|
50
|
+
optional :foo, type: Hash do
|
51
|
+
optional :bar, default: 'foo-bar'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
get '/group' do
|
55
|
+
{ foo_bar: params[:foo][:bar] }
|
56
|
+
end
|
57
|
+
|
58
|
+
params do
|
59
|
+
optional :array, type: Array do
|
60
|
+
requires :name
|
61
|
+
optional :with_default, default: 'default'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
get '/array' do
|
65
|
+
{ array: params[:array] }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def app
|
72
|
+
ValidationsSpec::DefaultValidatorSpec::API
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'set default value for optional param' do
|
76
|
+
get("/")
|
77
|
+
expect(last_response.status).to eq(200)
|
78
|
+
expect(last_response.body).to eq({ id: nil, type: 'default-type' }.to_json)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'set default values for optional params' do
|
82
|
+
get("/user")
|
83
|
+
expect(last_response.status).to eq(200)
|
84
|
+
expect(last_response.body).to eq({ type1: 'default-type1', type2: 'default-type2' }.to_json)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'set default values for missing params in the request' do
|
88
|
+
get("/user?type2=value2")
|
89
|
+
expect(last_response.status).to eq(200)
|
90
|
+
expect(last_response.body).to eq({ type1: 'default-type1', type2: 'value2' }.to_json)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'set default values for optional params and allow to use required fields in the same time' do
|
94
|
+
get("/message?id=1")
|
95
|
+
expect(last_response.status).to eq(200)
|
96
|
+
expect(last_response.body).to eq({ id: '1', type1: 'default-type1', type2: 'default-type2' }.to_json)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'sets lambda based defaults at the time of call' do
|
100
|
+
get("/numbers")
|
101
|
+
expect(last_response.status).to eq(200)
|
102
|
+
before = JSON.parse(last_response.body)
|
103
|
+
get("/numbers")
|
104
|
+
expect(last_response.status).to eq(200)
|
105
|
+
after = JSON.parse(last_response.body)
|
106
|
+
|
107
|
+
expect(before['non_random_number']).to eq(after['non_random_number'])
|
108
|
+
expect(before['random_number']).not_to eq(after['random_number'])
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'set default values for optional grouped params' do
|
112
|
+
get('/group')
|
113
|
+
expect(last_response.status).to eq(200)
|
114
|
+
expect(last_response.body).to eq({ foo_bar: 'foo-bar' }.to_json)
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'sets default values for grouped arrays' do
|
118
|
+
get('/array?array[][name]=name&array[][name]=name2&array[][with_default]=bar2')
|
119
|
+
expect(last_response.status).to eq(200)
|
120
|
+
expect(last_response.body).to eq({ array: [{ name: "name", with_default: "default" }, { name: "name2", with_default: "bar2" }] }.to_json)
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Grape::Validations::ExactlyOneOfValidator do
|
4
|
+
describe '#validate!' do
|
5
|
+
let(:scope) do
|
6
|
+
Struct.new(:opts) do
|
7
|
+
def params(arg); end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
let(:exactly_one_of_params) { [:beer, :wine, :grapefruit] }
|
11
|
+
let(:validator) { described_class.new(exactly_one_of_params, {}, false, scope.new) }
|
12
|
+
|
13
|
+
context 'when all restricted params are present' do
|
14
|
+
let(:params) { { beer: true, wine: true, grapefruit: true } }
|
15
|
+
|
16
|
+
it 'raises a validation exception' do
|
17
|
+
expect {
|
18
|
+
validator.validate! params
|
19
|
+
}.to raise_error(Grape::Exceptions::Validation)
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'mixed with other params' do
|
23
|
+
let(:mixed_params) { params.merge!(other: true, andanother: true) }
|
24
|
+
|
25
|
+
it 'still raises a validation exception' do
|
26
|
+
expect {
|
27
|
+
validator.validate! mixed_params
|
28
|
+
}.to raise_error(Grape::Exceptions::Validation)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when a subset of restricted params are present' do
|
34
|
+
let(:params) { { beer: true, grapefruit: true } }
|
35
|
+
|
36
|
+
it 'raises a validation exception' do
|
37
|
+
expect {
|
38
|
+
validator.validate! params
|
39
|
+
}.to raise_error(Grape::Exceptions::Validation)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'when params keys come as strings' do
|
44
|
+
let(:params) { { 'beer' => true, 'grapefruit' => true } }
|
45
|
+
|
46
|
+
it 'raises a validation exception' do
|
47
|
+
expect {
|
48
|
+
validator.validate! params
|
49
|
+
}.to raise_error(Grape::Exceptions::Validation)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when none of the restricted params is selected' do
|
54
|
+
let(:params) { { somethingelse: true } }
|
55
|
+
|
56
|
+
it 'raises a validation exception' do
|
57
|
+
expect {
|
58
|
+
validator.validate! params
|
59
|
+
}.to raise_error(Grape::Exceptions::Validation)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when exactly one of the restricted params is selected' do
|
64
|
+
let(:params) { { beer: true, somethingelse: true } }
|
65
|
+
|
66
|
+
it 'params' do
|
67
|
+
expect(validator.validate!(params)).to eql params
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Grape::Validations::MutualExclusionValidator do
|
4
|
+
describe '#validate!' do
|
5
|
+
let(:scope) do
|
6
|
+
Struct.new(:opts) do
|
7
|
+
def params(arg); end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
let(:mutually_exclusive_params) { [:beer, :wine, :grapefruit] }
|
11
|
+
let(:validator) { described_class.new(mutually_exclusive_params, {}, false, scope.new) }
|
12
|
+
|
13
|
+
context 'when all mutually exclusive params are present' do
|
14
|
+
let(:params) { { beer: true, wine: true, grapefruit: true } }
|
15
|
+
|
16
|
+
it 'raises a validation exception' do
|
17
|
+
expect {
|
18
|
+
validator.validate! params
|
19
|
+
}.to raise_error(Grape::Exceptions::Validation)
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'mixed with other params' do
|
23
|
+
let(:mixed_params) { params.merge!(other: true, andanother: true) }
|
24
|
+
|
25
|
+
it 'still raises a validation exception' do
|
26
|
+
expect {
|
27
|
+
validator.validate! mixed_params
|
28
|
+
}.to raise_error(Grape::Exceptions::Validation)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when a subset of mutually exclusive params are present' do
|
34
|
+
let(:params) { { beer: true, grapefruit: true } }
|
35
|
+
|
36
|
+
it 'raises a validation exception' do
|
37
|
+
expect {
|
38
|
+
validator.validate! params
|
39
|
+
}.to raise_error(Grape::Exceptions::Validation)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'when params keys come as strings' do
|
44
|
+
let(:params) { { 'beer' => true, 'grapefruit' => true } }
|
45
|
+
|
46
|
+
it 'raises a validation exception' do
|
47
|
+
expect {
|
48
|
+
validator.validate! params
|
49
|
+
}.to raise_error(Grape::Exceptions::Validation)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when no mutually exclusive params are present' do
|
54
|
+
let(:params) { { beer: true, somethingelse: true } }
|
55
|
+
|
56
|
+
it 'params' do
|
57
|
+
expect(validator.validate!(params)).to eql params
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|