grape 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grape might be problematic. Click here for more details.
- checksums.yaml +5 -13
- data/.rubocop.yml +6 -6
- data/.travis.yml +11 -2
- data/CHANGELOG.md +23 -1
- data/Gemfile +11 -10
- data/Guardfile +5 -6
- data/README.md +194 -13
- data/UPGRADING.md +3 -3
- data/grape.gemspec +1 -1
- data/grape.png +0 -0
- data/lib/grape/api.rb +21 -13
- data/lib/grape/endpoint.rb +31 -13
- data/lib/grape/exceptions/validation.rb +2 -2
- data/lib/grape/locale/en.yml +2 -0
- data/lib/grape/middleware/auth/oauth2.rb +69 -65
- data/lib/grape/middleware/error.rb +4 -2
- data/lib/grape/middleware/formatter.rb +2 -2
- data/lib/grape/middleware/versioner/accept_version_header.rb +1 -1
- data/lib/grape/middleware/versioner/header.rb +3 -3
- data/lib/grape/util/hash_stack.rb +1 -1
- data/lib/grape/validations.rb +22 -8
- data/lib/grape/validations/default.rb +1 -1
- 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 +1 -1
- data/lib/grape/validations/regexp.rb +2 -1
- data/lib/grape/validations/values.rb +7 -1
- data/lib/grape/version.rb +1 -1
- data/spec/grape/api_spec.rb +390 -333
- data/spec/grape/endpoint_spec.rb +129 -99
- data/spec/grape/entity_spec.rb +47 -27
- data/spec/grape/exceptions/invalid_formatter_spec.rb +1 -1
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -1
- data/spec/grape/exceptions/missing_mime_type_spec.rb +2 -2
- data/spec/grape/exceptions/missing_option_spec.rb +1 -1
- data/spec/grape/exceptions/unknown_options_spec.rb +1 -1
- data/spec/grape/exceptions/unknown_validator_spec.rb +1 -1
- data/spec/grape/middleware/auth/basic_spec.rb +3 -3
- data/spec/grape/middleware/auth/digest_spec.rb +4 -4
- data/spec/grape/middleware/auth/oauth2_spec.rb +11 -11
- data/spec/grape/middleware/base_spec.rb +9 -9
- data/spec/grape/middleware/error_spec.rb +4 -4
- data/spec/grape/middleware/exception_spec.rb +17 -17
- data/spec/grape/middleware/formatter_spec.rb +38 -38
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +11 -11
- data/spec/grape/middleware/versioner/header_spec.rb +39 -39
- data/spec/grape/middleware/versioner/param_spec.rb +10 -10
- data/spec/grape/middleware/versioner/path_spec.rb +7 -7
- data/spec/grape/middleware/versioner_spec.rb +4 -4
- data/spec/grape/path_spec.rb +6 -6
- data/spec/grape/util/hash_stack_spec.rb +22 -22
- data/spec/grape/validations/coerce_spec.rb +34 -34
- data/spec/grape/validations/default_spec.rb +16 -16
- 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 +34 -34
- data/spec/grape/validations/regexp_spec.rb +11 -4
- data/spec/grape/validations/values_spec.rb +34 -20
- data/spec/grape/validations_spec.rb +300 -147
- data/spec/shared/versioning_examples.rb +18 -18
- data/spec/spec_helper.rb +2 -1
- metadata +81 -38
@@ -74,50 +74,50 @@ describe Grape::Validations::DefaultValidator do
|
|
74
74
|
|
75
75
|
it 'set default value for optional param' do
|
76
76
|
get("/")
|
77
|
-
last_response.status.
|
78
|
-
last_response.body.
|
77
|
+
expect(last_response.status).to eq(200)
|
78
|
+
expect(last_response.body).to eq({ id: nil, type: 'default-type' }.to_json)
|
79
79
|
end
|
80
80
|
|
81
81
|
it 'set default values for optional params' do
|
82
82
|
get("/user")
|
83
|
-
last_response.status.
|
84
|
-
last_response.body.
|
83
|
+
expect(last_response.status).to eq(200)
|
84
|
+
expect(last_response.body).to eq({ type1: 'default-type1', type2: 'default-type2' }.to_json)
|
85
85
|
end
|
86
86
|
|
87
87
|
it 'set default values for missing params in the request' do
|
88
88
|
get("/user?type2=value2")
|
89
|
-
last_response.status.
|
90
|
-
last_response.body.
|
89
|
+
expect(last_response.status).to eq(200)
|
90
|
+
expect(last_response.body).to eq({ type1: 'default-type1', type2: 'value2' }.to_json)
|
91
91
|
end
|
92
92
|
|
93
93
|
it 'set default values for optional params and allow to use required fields in the same time' do
|
94
94
|
get("/message?id=1")
|
95
|
-
last_response.status.
|
96
|
-
last_response.body.
|
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
97
|
end
|
98
98
|
|
99
99
|
it 'sets lambda based defaults at the time of call' do
|
100
100
|
get("/numbers")
|
101
|
-
last_response.status.
|
101
|
+
expect(last_response.status).to eq(200)
|
102
102
|
before = JSON.parse(last_response.body)
|
103
103
|
get("/numbers")
|
104
|
-
last_response.status.
|
104
|
+
expect(last_response.status).to eq(200)
|
105
105
|
after = JSON.parse(last_response.body)
|
106
106
|
|
107
|
-
before['non_random_number'].
|
108
|
-
before['random_number'].
|
107
|
+
expect(before['non_random_number']).to eq(after['non_random_number'])
|
108
|
+
expect(before['random_number']).not_to eq(after['random_number'])
|
109
109
|
end
|
110
110
|
|
111
111
|
it 'set default values for optional grouped params' do
|
112
112
|
get('/group')
|
113
|
-
last_response.status.
|
114
|
-
last_response.body.
|
113
|
+
expect(last_response.status).to eq(200)
|
114
|
+
expect(last_response.body).to eq({ foo_bar: 'foo-bar' }.to_json)
|
115
115
|
end
|
116
116
|
|
117
117
|
it 'sets default values for grouped arrays' do
|
118
118
|
get('/array?array[][name]=name&array[][name]=name2&array[][with_default]=bar2')
|
119
|
-
last_response.status.
|
120
|
-
last_response.body.
|
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
121
|
end
|
122
122
|
|
123
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
|
@@ -61,82 +61,82 @@ describe Grape::Validations::PresenceValidator do
|
|
61
61
|
|
62
62
|
it 'does not validate for any params' do
|
63
63
|
get "/bacons"
|
64
|
-
last_response.status.
|
65
|
-
last_response.body.
|
64
|
+
expect(last_response.status).to eq(200)
|
65
|
+
expect(last_response.body).to eq("All the bacon".to_json)
|
66
66
|
end
|
67
67
|
|
68
68
|
it 'validates id' do
|
69
69
|
post '/'
|
70
|
-
last_response.status.
|
71
|
-
last_response.body.
|
70
|
+
expect(last_response.status).to eq(400)
|
71
|
+
expect(last_response.body).to eq('{"error":"id is missing"}')
|
72
72
|
|
73
73
|
io = StringIO.new('{"id" : "a56b"}')
|
74
74
|
post '/', {}, 'rack.input' => io, 'CONTENT_TYPE' => 'application/json', 'CONTENT_LENGTH' => io.length
|
75
|
-
last_response.body.
|
76
|
-
last_response.status.
|
75
|
+
expect(last_response.body).to eq('{"error":"id is invalid"}')
|
76
|
+
expect(last_response.status).to eq(400)
|
77
77
|
|
78
78
|
io = StringIO.new('{"id" : 56}')
|
79
79
|
post '/', {}, 'rack.input' => io, 'CONTENT_TYPE' => 'application/json', 'CONTENT_LENGTH' => io.length
|
80
|
-
last_response.body.
|
81
|
-
last_response.status.
|
80
|
+
expect(last_response.body).to eq('{"ret":56}')
|
81
|
+
expect(last_response.status).to eq(201)
|
82
82
|
end
|
83
83
|
|
84
84
|
it 'validates name, company' do
|
85
85
|
get '/'
|
86
|
-
last_response.status.
|
87
|
-
last_response.body.
|
86
|
+
expect(last_response.status).to eq(400)
|
87
|
+
expect(last_response.body).to eq('{"error":"name is missing"}')
|
88
88
|
|
89
89
|
get '/', name: "Bob"
|
90
|
-
last_response.status.
|
91
|
-
last_response.body.
|
90
|
+
expect(last_response.status).to eq(400)
|
91
|
+
expect(last_response.body).to eq('{"error":"company is missing"}')
|
92
92
|
|
93
93
|
get '/', name: "Bob", company: "TestCorp"
|
94
|
-
last_response.status.
|
95
|
-
last_response.body.
|
94
|
+
expect(last_response.status).to eq(200)
|
95
|
+
expect(last_response.body).to eq("Hello".to_json)
|
96
96
|
end
|
97
97
|
|
98
98
|
it 'validates nested parameters' do
|
99
99
|
get '/nested'
|
100
|
-
last_response.status.
|
101
|
-
last_response.body.
|
100
|
+
expect(last_response.status).to eq(400)
|
101
|
+
expect(last_response.body).to eq('{"error":"user is missing, user[first_name] is missing, user[last_name] is missing"}')
|
102
102
|
|
103
103
|
get '/nested', user: { first_name: "Billy" }
|
104
|
-
last_response.status.
|
105
|
-
last_response.body.
|
104
|
+
expect(last_response.status).to eq(400)
|
105
|
+
expect(last_response.body).to eq('{"error":"user[last_name] is missing"}')
|
106
106
|
|
107
107
|
get '/nested', user: { first_name: "Billy", last_name: "Bob" }
|
108
|
-
last_response.status.
|
109
|
-
last_response.body.
|
108
|
+
expect(last_response.status).to eq(200)
|
109
|
+
expect(last_response.body).to eq("Nested".to_json)
|
110
110
|
end
|
111
111
|
|
112
112
|
it 'validates triple nested parameters' do
|
113
113
|
get '/nested_triple'
|
114
|
-
last_response.status.
|
115
|
-
last_response.body.
|
114
|
+
expect(last_response.status).to eq(400)
|
115
|
+
expect(last_response.body).to include '{"error":"admin is missing'
|
116
116
|
|
117
117
|
get '/nested_triple', user: { first_name: "Billy" }
|
118
|
-
last_response.status.
|
119
|
-
last_response.body.
|
118
|
+
expect(last_response.status).to eq(400)
|
119
|
+
expect(last_response.body).to include '{"error":"admin is missing'
|
120
120
|
|
121
121
|
get '/nested_triple', admin: { super: { first_name: "Billy" } }
|
122
|
-
last_response.status.
|
123
|
-
last_response.body.
|
122
|
+
expect(last_response.status).to eq(400)
|
123
|
+
expect(last_response.body).to eq('{"error":"admin[admin_name] is missing, admin[super][user] is missing, admin[super][user][first_name] is missing, admin[super][user][last_name] is missing"}')
|
124
124
|
|
125
125
|
get '/nested_triple', super: { user: { first_name: "Billy", last_name: "Bob" } }
|
126
|
-
last_response.status.
|
127
|
-
last_response.body.
|
126
|
+
expect(last_response.status).to eq(400)
|
127
|
+
expect(last_response.body).to include '{"error":"admin is missing'
|
128
128
|
|
129
129
|
get '/nested_triple', admin: { super: { user: { first_name: "Billy" } } }
|
130
|
-
last_response.status.
|
131
|
-
last_response.body.
|
130
|
+
expect(last_response.status).to eq(400)
|
131
|
+
expect(last_response.body).to eq('{"error":"admin[admin_name] is missing, admin[super][user][last_name] is missing"}')
|
132
132
|
|
133
133
|
get '/nested_triple', admin: { admin_name: 'admin', super: { user: { first_name: "Billy" } } }
|
134
|
-
last_response.status.
|
135
|
-
last_response.body.
|
134
|
+
expect(last_response.status).to eq(400)
|
135
|
+
expect(last_response.body).to eq('{"error":"admin[super][user][last_name] is missing"}')
|
136
136
|
|
137
137
|
get '/nested_triple', admin: { admin_name: 'admin', super: { user: { first_name: "Billy", last_name: "Bob" } } }
|
138
|
-
last_response.status.
|
139
|
-
last_response.body.
|
138
|
+
expect(last_response.status).to eq(200)
|
139
|
+
expect(last_response.body).to eq("Nested triple".to_json)
|
140
140
|
end
|
141
141
|
|
142
142
|
end
|
@@ -20,14 +20,21 @@ describe Grape::Validations::RegexpValidator do
|
|
20
20
|
ValidationsSpec::RegexpValidatorSpec::API
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
context 'invalid input' do
|
24
|
+
it 'refuses inapppopriate' do
|
25
|
+
get '/', name: "invalid name"
|
26
|
+
expect(last_response.status).to eq(400)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'refuses nil' do
|
30
|
+
get '/', name: nil
|
31
|
+
expect(last_response.status).to eq(400)
|
32
|
+
end
|
26
33
|
end
|
27
34
|
|
28
35
|
it 'accepts valid input' do
|
29
36
|
get '/', name: "bob"
|
30
|
-
last_response.status.
|
37
|
+
expect(last_response.status).to eq(200)
|
31
38
|
end
|
32
39
|
|
33
40
|
end
|
@@ -49,6 +49,13 @@ describe Grape::Validations::ValuesValidator do
|
|
49
49
|
get '/values/coercion' do
|
50
50
|
{ type: params[:type] }
|
51
51
|
end
|
52
|
+
|
53
|
+
params do
|
54
|
+
optional :optional do
|
55
|
+
requires :type, values: ["a", "b"]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
get '/optional_with_required_values'
|
52
59
|
end
|
53
60
|
end
|
54
61
|
end
|
@@ -59,54 +66,61 @@ describe Grape::Validations::ValuesValidator do
|
|
59
66
|
|
60
67
|
it 'allows a valid value for a parameter' do
|
61
68
|
get("/", type: 'valid-type1')
|
62
|
-
last_response.status.
|
63
|
-
last_response.body.
|
69
|
+
expect(last_response.status).to eq 200
|
70
|
+
expect(last_response.body).to eq({ type: "valid-type1" }.to_json)
|
64
71
|
end
|
65
72
|
|
66
73
|
it 'does not allow an invalid value for a parameter' do
|
67
74
|
get("/", type: 'invalid-type')
|
68
|
-
last_response.status.
|
69
|
-
last_response.body.
|
75
|
+
expect(last_response.status).to eq 400
|
76
|
+
expect(last_response.body).to eq({ error: "type does not have a valid value" }.to_json)
|
70
77
|
end
|
71
78
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
79
|
+
context 'nil value for a parameter' do
|
80
|
+
it 'does not allow for root params scope' do
|
81
|
+
get("/", type: nil)
|
82
|
+
expect(last_response.status).to eq 400
|
83
|
+
expect(last_response.body).to eq({ error: "type does not have a valid value" }.to_json)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'allows for a required param in child scope' do
|
87
|
+
get('/optional_with_required_values')
|
88
|
+
expect(last_response.status).to eq 200
|
89
|
+
end
|
76
90
|
end
|
77
91
|
|
78
92
|
it 'allows a valid default value' do
|
79
93
|
get("/default/valid")
|
80
|
-
last_response.status.
|
81
|
-
last_response.body.
|
94
|
+
expect(last_response.status).to eq 200
|
95
|
+
expect(last_response.body).to eq({ type: "valid-type2" }.to_json)
|
82
96
|
end
|
83
97
|
|
84
98
|
it 'allows a proc for values' do
|
85
99
|
get('/lambda', type: 'valid-type1')
|
86
|
-
last_response.status.
|
87
|
-
last_response.body.
|
100
|
+
expect(last_response.status).to eq 200
|
101
|
+
expect(last_response.body).to eq({ type: "valid-type1" }.to_json)
|
88
102
|
end
|
89
103
|
|
90
104
|
it 'does not validate updated values without proc' do
|
91
105
|
ValuesModel.add_value('valid-type4')
|
92
106
|
|
93
107
|
get('/', type: 'valid-type4')
|
94
|
-
last_response.status.
|
95
|
-
last_response.body.
|
108
|
+
expect(last_response.status).to eq 400
|
109
|
+
expect(last_response.body).to eq({ error: "type does not have a valid value" }.to_json)
|
96
110
|
end
|
97
111
|
|
98
112
|
it 'validates against values in a proc' do
|
99
113
|
ValuesModel.add_value('valid-type4')
|
100
114
|
|
101
115
|
get('/lambda', type: 'valid-type4')
|
102
|
-
last_response.status.
|
103
|
-
last_response.body.
|
116
|
+
expect(last_response.status).to eq 200
|
117
|
+
expect(last_response.body).to eq({ type: "valid-type4" }.to_json)
|
104
118
|
end
|
105
119
|
|
106
120
|
it 'does not allow an invalid value for a parameter using lambda' do
|
107
121
|
get("/lambda", type: 'invalid-type')
|
108
|
-
last_response.status.
|
109
|
-
last_response.body.
|
122
|
+
expect(last_response.status).to eq 400
|
123
|
+
expect(last_response.body).to eq({ error: "type does not have a valid value" }.to_json)
|
110
124
|
end
|
111
125
|
|
112
126
|
it 'raises IncompatibleOptionValues on an invalid default value' do
|
@@ -125,8 +139,8 @@ describe Grape::Validations::ValuesValidator do
|
|
125
139
|
|
126
140
|
it 'allows values to be a kind of the coerced type not just an instance of it' do
|
127
141
|
get("/values/coercion", type: 10)
|
128
|
-
last_response.status.
|
129
|
-
last_response.body.
|
142
|
+
expect(last_response.status).to eq 200
|
143
|
+
expect(last_response.body).to eq({ type: 10 }.to_json)
|
130
144
|
end
|
131
145
|
|
132
146
|
it 'raises IncompatibleOptionValues when values contains a value that is not a kind of the type' do
|