dry-validation 0.5.0 → 0.6.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/.codeclimate.yml +16 -0
- data/CHANGELOG.md +23 -2
- data/Gemfile +1 -0
- data/config/errors.yml +2 -0
- data/dry-validation.gemspec +3 -3
- data/lib/dry/validation/error_compiler.rb +46 -10
- data/lib/dry/validation/hint_compiler.rb +5 -0
- data/lib/dry/validation/result.rb +5 -1
- data/lib/dry/validation/schema.rb +14 -11
- data/lib/dry/validation/schema/attr.rb +37 -0
- data/lib/dry/validation/schema/definition.rb +23 -5
- data/lib/dry/validation/schema/form.rb +16 -0
- data/lib/dry/validation/schema/key.rb +1 -1
- data/lib/dry/validation/schema/result.rb +11 -3
- data/lib/dry/validation/schema/rule.rb +23 -1
- data/lib/dry/validation/version.rb +1 -1
- data/spec/integration/error_compiler_spec.rb +3 -0
- data/spec/integration/injecting_rules_spec.rb +23 -0
- data/spec/integration/rule_groups_spec.rb +59 -0
- data/spec/integration/schema/attrs_spec.rb +38 -0
- data/spec/integration/schema/check_rules_spec.rb +63 -17
- data/spec/integration/schema/default_key_behavior_spec.rb +23 -0
- data/spec/integration/schema/grouped_rules_spec.rb +57 -0
- data/spec/integration/schema_spec.rb +175 -10
- data/spec/spec_helper.rb +5 -0
- data/spec/support/define_struct.rb +25 -0
- data/spec/unit/hint_compiler_spec.rb +18 -1
- data/spec/unit/input_type_compiler_spec.rb +2 -2
- data/spec/unit/schema/rule_spec.rb +4 -4
- data/spec/unit/schema/value_spec.rb +2 -2
- metadata +29 -5
@@ -9,6 +9,7 @@ RSpec.describe Dry::Validation::ErrorCompiler do
|
|
9
9
|
en: {
|
10
10
|
errors: {
|
11
11
|
key?: '+%{name}+ key is missing in the hash',
|
12
|
+
attr?: 'Object does not respond to the +%{name}+ attr',
|
12
13
|
rules: {
|
13
14
|
address: {
|
14
15
|
filled?: 'Please provide your address'
|
@@ -23,6 +24,7 @@ RSpec.describe Dry::Validation::ErrorCompiler do
|
|
23
24
|
let(:ast) do
|
24
25
|
[
|
25
26
|
[:error, [:input, [:name, nil, [[:key, [:name, [:predicate, [:key?, []]]]]]]]],
|
27
|
+
[:error, [:input, [:phone, nil, [[:attr, [:phone, [:predicate, [:attr?, []]]]]]]]],
|
26
28
|
[:error, [:input, [:age, 18, [[:val, [:age, [:predicate, [:gt?, [18]]]]]]]]],
|
27
29
|
[:error, [:input, [:email, "", [[:val, [:email, [:predicate, [:filled?, []]]]]]]]],
|
28
30
|
[:error, [:input, [:address, "", [[:val, [:address, [:predicate, [:filled?, []]]]]]]]]
|
@@ -32,6 +34,7 @@ RSpec.describe Dry::Validation::ErrorCompiler do
|
|
32
34
|
it 'converts error ast into another format' do
|
33
35
|
expect(error_compiler.(ast)).to eql(
|
34
36
|
name: [["+name+ key is missing in the hash"], nil],
|
37
|
+
phone: [["Object does not respond to the +phone+ attr"], nil],
|
35
38
|
age: [["age must be greater than 18"], 18],
|
36
39
|
email: [["email must be filled"], ''],
|
37
40
|
address: [["Please provide your address"], '']
|
@@ -0,0 +1,23 @@
|
|
1
|
+
RSpec.describe 'Schema / Injecting Rules' do
|
2
|
+
let(:validate) { schema.new(other.rules) }
|
3
|
+
|
4
|
+
let(:other) do
|
5
|
+
Class.new(Dry::Validation::Schema) do
|
6
|
+
key(:login) { |value| value.bool? }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:schema) do
|
11
|
+
Class.new(Dry::Validation::Schema) do
|
12
|
+
key(:email) { |email| email.none? | email.filled? }
|
13
|
+
|
14
|
+
rule(email: :filled?) { value(:login).true? > value(:email).filled? }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'appends rules from another schema' do
|
19
|
+
expect(validate.(login: true, email: 'jane@doe')).to be_empty
|
20
|
+
expect(validate.(login: false, email: nil)).to be_empty
|
21
|
+
expect(validate.(login: true, email: nil)).to_not be_empty
|
22
|
+
end
|
23
|
+
end
|
@@ -1,6 +1,14 @@
|
|
1
1
|
RSpec.describe Dry::Validation::Schema do
|
2
2
|
subject(:validation) { schema.new }
|
3
3
|
|
4
|
+
before do
|
5
|
+
def schema.messages
|
6
|
+
Messages.default.merge(
|
7
|
+
en: { errors: { password_confirmation: 'does not match' } }
|
8
|
+
)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
4
12
|
describe 'defining schema with rule groups' do
|
5
13
|
let(:schema) do
|
6
14
|
Class.new(Dry::Validation::Schema) do
|
@@ -24,6 +32,12 @@ RSpec.describe Dry::Validation::Schema do
|
|
24
32
|
])
|
25
33
|
end
|
26
34
|
|
35
|
+
it 'returns messages for a failed group rule' do
|
36
|
+
expect(validation.(password: 'foo', password_confirmation: 'bar').messages).to eql(
|
37
|
+
password_confirmation: [['does not match'], ['foo', 'bar']]
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
27
41
|
it 'returns errors for the dependent predicates, not the group rule, when any of the dependent predicates fail' do
|
28
42
|
expect(validation.(password: '', password_confirmation: '')).to match_array([
|
29
43
|
[:error, [:input, [:password, "", [[:val, [:password, [:predicate, [:filled?, []]]]]]]]],
|
@@ -31,5 +45,50 @@ RSpec.describe Dry::Validation::Schema do
|
|
31
45
|
])
|
32
46
|
end
|
33
47
|
end
|
48
|
+
|
49
|
+
describe 'confirmation' do
|
50
|
+
shared_examples_for 'confirmation behavior' do
|
51
|
+
it 'applies custom rules' do
|
52
|
+
expect(validation.(password: 'abcd').messages).to include(
|
53
|
+
password: [['password size cannot be less than 6'], 'abcd']
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'applies confirmation equality predicate' do
|
58
|
+
expect(validation.(password: 'abcdef', password_confirmation: 'abcd').messages).to include(
|
59
|
+
password_confirmation: [['does not match'], ['abcdef', 'abcd']]
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'skips default predicate' do
|
64
|
+
expect(validation.(password: '', password_confirmation: '').messages).to include(
|
65
|
+
password: [['password size cannot be less than 6'], ''],
|
66
|
+
password_confirmation: [['password_confirmation must be filled'], '']
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe 'custom predicates' do
|
72
|
+
let(:schema) do
|
73
|
+
Class.new(Dry::Validation::Schema) do
|
74
|
+
key(:password) { |value| value.min_size?(6) }
|
75
|
+
|
76
|
+
confirmation(:password)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it_behaves_like 'confirmation behavior'
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'custom predicates using shortcut options' do
|
84
|
+
let(:schema) do
|
85
|
+
Class.new(Dry::Validation::Schema) do
|
86
|
+
confirmation(:password, min_size: 6)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it_behaves_like 'confirmation behavior'
|
91
|
+
end
|
92
|
+
end
|
34
93
|
end
|
35
94
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
RSpec.describe Schema, 'defining schema with attrs' do
|
4
|
+
subject(:validation) { schema.new }
|
5
|
+
|
6
|
+
let(:schema) do
|
7
|
+
Class.new(Dry::Validation::Schema) do
|
8
|
+
attr(:email) { |email| email.filled? }
|
9
|
+
|
10
|
+
attr(:address) do |address|
|
11
|
+
address.attr(:city, &:filled?)
|
12
|
+
address.attr(:street, &:filled?)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#call' do
|
18
|
+
context 'when valid input' do
|
19
|
+
let(:input) do
|
20
|
+
struct_from_hash(email: "email@test.com", address: { city: 'NYC', street: 'Street 1/2' })
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should be valid' do
|
24
|
+
expect(validation.(input)).to be_empty
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when input does not have proper attributes' do
|
29
|
+
let(:input) do
|
30
|
+
struct_from_hash(name: "John", address: { country: 'US', street: 'Street 1/2' })
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should not be valid' do
|
34
|
+
expect(validation.(input)).to_not be_empty
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,28 +1,74 @@
|
|
1
|
-
RSpec.describe Schema, 'using
|
1
|
+
RSpec.describe Schema, 'using high-level rules' do
|
2
2
|
subject(:validate) { schema.new }
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
context 'composing rules' do
|
5
|
+
let(:schema) do
|
6
|
+
Class.new(Schema) do
|
7
|
+
def self.messages
|
8
|
+
Messages.default.merge(
|
9
|
+
en: { errors: { destiny: 'you must select either red or blue' } }
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
optional(:red, &:filled?)
|
14
|
+
optional(:blue, &:filled?)
|
15
|
+
|
16
|
+
rule(:destiny) { rule(:red) | rule(:blue) }
|
10
17
|
end
|
18
|
+
end
|
11
19
|
|
12
|
-
|
13
|
-
|
20
|
+
it 'passes when only red is filled' do
|
21
|
+
expect(validate.(red: '1')).to be_empty
|
22
|
+
end
|
14
23
|
|
15
|
-
|
24
|
+
it 'fails when red and blue are not filled ' do
|
25
|
+
expect(validate.(red: '', blue: '').messages[:destiny]).to eql(
|
26
|
+
[['you must select either red or blue'], '']
|
27
|
+
)
|
16
28
|
end
|
17
29
|
end
|
18
30
|
|
19
|
-
|
20
|
-
|
21
|
-
|
31
|
+
context 'composing specific predicates' do
|
32
|
+
let(:schema) do
|
33
|
+
Class.new(Schema) do
|
34
|
+
def self.messages
|
35
|
+
Messages.default.merge(
|
36
|
+
en: {
|
37
|
+
errors: {
|
38
|
+
email_presence: 'email must be present when login is set to true',
|
39
|
+
email_absence: 'email must not be present when login is set to false'
|
40
|
+
}
|
41
|
+
}
|
42
|
+
)
|
43
|
+
end
|
22
44
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
45
|
+
key(:login) { |login| login.bool? }
|
46
|
+
key(:email) { |email| email.none? | email.filled? }
|
47
|
+
|
48
|
+
rule(:email_presence) { value(:login).true?.then(value(:email).filled?) }
|
49
|
+
|
50
|
+
rule(:email_absence) { value(:login).false?.then(value(:email).none?) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'passes when login is false and email is nil' do
|
55
|
+
expect(validate.(login: false, email: nil)).to be_empty
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'fails when login is false and email is present' do
|
59
|
+
expect(validate.(login: false, email: 'jane@doe').messages[:email_absence]).to eql(
|
60
|
+
[['email must not be present when login is set to false'], nil]
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'passes when login is true and email is present' do
|
65
|
+
expect(validate.(login: true, email: 'jane@doe')).to be_empty
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'fails when login is true and email is not present' do
|
69
|
+
expect(validate.(login: true, email: nil).messages[:email_presence]).to eql(
|
70
|
+
[['email must be present when login is set to true'], nil]
|
71
|
+
)
|
72
|
+
end
|
27
73
|
end
|
28
74
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
RSpec.describe 'Schema::Form / Default key behavior' do
|
2
|
+
subject(:validate) { schema.new }
|
3
|
+
|
4
|
+
let(:schema) do
|
5
|
+
Class.new(Dry::Validation::Schema::Form) do
|
6
|
+
key(:name)
|
7
|
+
key(:age, &:int?)
|
8
|
+
optional(:address)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'applies filled? predicate by default' do
|
13
|
+
expect(validate.('name' => 'jane', 'age' => '21').params).to eql(
|
14
|
+
name: 'jane', age: 21
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'applies filled? predicate by default to optional key' do
|
19
|
+
expect(validate.('name' => 'jane', 'age' => '21', 'address' => 'Earth').params).to eql(
|
20
|
+
name: 'jane', age: 21, address: 'Earth'
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
RSpec.describe Schema, 'using high-level grouped rules' do
|
2
|
+
subject(:validate) { schema.new }
|
3
|
+
|
4
|
+
let(:schema) do
|
5
|
+
Class.new(Schema) do
|
6
|
+
def self.messages
|
7
|
+
Messages.default.merge(
|
8
|
+
en: {
|
9
|
+
errors: {
|
10
|
+
email: {
|
11
|
+
absence: 'email must not be selected',
|
12
|
+
presence: 'email must be selected',
|
13
|
+
format: 'this is not an email lol',
|
14
|
+
inclusion: 'sorry, did not expect this lol'
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
key(:email) { |email| email.none? | email.filled? }
|
22
|
+
key(:login) { |login| login.bool? }
|
23
|
+
|
24
|
+
rule(email: :absence) do
|
25
|
+
value(:login).false? > value(:email).none?
|
26
|
+
end
|
27
|
+
|
28
|
+
rule(email: :presence) do
|
29
|
+
value(:login).true? > value(:email).filled?
|
30
|
+
end
|
31
|
+
|
32
|
+
rule(email: :format) do
|
33
|
+
value(:email).filled? > value(:email).format?(/[a-z]@[a-z]/)
|
34
|
+
end
|
35
|
+
|
36
|
+
rule(email: :inclusion) do
|
37
|
+
value(:email).filled? > value(:email).inclusion?(%w[jane@doe])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'passes when login is true and email is present' do
|
43
|
+
expect(validate.(login: true, email: 'jane@doe').messages).to be_empty
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'fails when login is false and email is not present' do
|
47
|
+
expect(validate.(login: true, email: nil).messages).to_not be_empty
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'provides merged error messages' do
|
51
|
+
expect(validate.(login: true, email: 'not-an-email-lol').messages).to eql(
|
52
|
+
email: [
|
53
|
+
["sorry, did not expect this lol", "this is not an email lol"], nil
|
54
|
+
]
|
55
|
+
)
|
56
|
+
end
|
57
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
RSpec.describe Dry::Validation::Schema do
|
2
2
|
subject(:validation) { schema.new }
|
3
3
|
|
4
|
-
describe 'defining schema' do
|
4
|
+
describe 'defining key-based schema (hash-like)' do
|
5
5
|
let(:schema) do
|
6
6
|
Class.new(Dry::Validation::Schema) do
|
7
7
|
key(:email) { |email| email.filled? }
|
@@ -33,7 +33,7 @@ RSpec.describe Dry::Validation::Schema do
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
let(:
|
36
|
+
let(:input) do
|
37
37
|
{
|
38
38
|
email: 'jane@doe.org',
|
39
39
|
age: 19,
|
@@ -46,7 +46,7 @@ RSpec.describe Dry::Validation::Schema do
|
|
46
46
|
|
47
47
|
describe '#messages' do
|
48
48
|
it 'returns compiled error messages' do
|
49
|
-
expect(validation.(
|
49
|
+
expect(validation.(input.merge(email: '')).messages).to match_array([
|
50
50
|
[:email, [['email must be filled'], '']]
|
51
51
|
])
|
52
52
|
end
|
@@ -54,18 +54,18 @@ RSpec.describe Dry::Validation::Schema do
|
|
54
54
|
|
55
55
|
describe '#call' do
|
56
56
|
it 'passes when attributes are valid' do
|
57
|
-
expect(validation.(
|
57
|
+
expect(validation.(input)).to be_empty
|
58
58
|
end
|
59
59
|
|
60
60
|
it 'validates presence of an email and min age value' do
|
61
|
-
expect(validation.(
|
61
|
+
expect(validation.(input.merge(email: '', age: 18))).to match_array([
|
62
62
|
[:error, [:input, [:age, 18, [[:val, [:age, [:predicate, [:gt?, [18]]]]]]]]],
|
63
63
|
[:error, [:input, [:email, "", [[:val, [:email, [:predicate, [:filled?, []]]]]]]]]
|
64
64
|
])
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'validates presence of the email key and type of age value' do
|
68
|
-
expect(validation.(name: 'Jane', age: '18', address:
|
68
|
+
expect(validation.(name: 'Jane', age: '18', address: input[:address], phone_numbers: input[:phone_numbers])).to match_array([
|
69
69
|
[:error, [:input, [:age, "18", [[:val, [:age, [:predicate, [:int?, []]]]]]]]],
|
70
70
|
[:error, [:input, [:email, nil, [[:key, [:email, [:predicate, [:key?, [:email]]]]]]]]]
|
71
71
|
])
|
@@ -79,7 +79,7 @@ RSpec.describe Dry::Validation::Schema do
|
|
79
79
|
end
|
80
80
|
|
81
81
|
it 'validates presence of keys under address and min size of the city value' do
|
82
|
-
expect(validation.(
|
82
|
+
expect(validation.(input.merge(address: { city: 'NY' }))).to match_array([
|
83
83
|
[:error, [
|
84
84
|
:input, [
|
85
85
|
:address, {city: "NY"},
|
@@ -94,13 +94,13 @@ RSpec.describe Dry::Validation::Schema do
|
|
94
94
|
end
|
95
95
|
|
96
96
|
it 'validates address type' do
|
97
|
-
expect(validation.(
|
97
|
+
expect(validation.(input.merge(address: 'totally not a hash'))).to match_array([
|
98
98
|
[:error, [:input, [:address, "totally not a hash", [[:val, [:address, [:predicate, [:hash?, []]]]]]]]]
|
99
99
|
])
|
100
100
|
end
|
101
101
|
|
102
102
|
it 'validates address code and name values' do
|
103
|
-
expect(validation.(
|
103
|
+
expect(validation.(input.merge(address: input[:address].merge(country: { code: 'US', name: '' })))).to match_array([
|
104
104
|
[:error, [
|
105
105
|
:input, [
|
106
106
|
:address, {city: "NYC", street: "Street 1/2", country: {code: "US", name: ""}},
|
@@ -123,7 +123,7 @@ RSpec.describe Dry::Validation::Schema do
|
|
123
123
|
end
|
124
124
|
|
125
125
|
it 'validates each phone number' do
|
126
|
-
expect(validation.(
|
126
|
+
expect(validation.(input.merge(phone_numbers: ['123', 312]))).to match_array([
|
127
127
|
[:error, [
|
128
128
|
:input, [
|
129
129
|
:phone_numbers, ["123", 312],
|
@@ -142,4 +142,169 @@ RSpec.describe Dry::Validation::Schema do
|
|
142
142
|
end
|
143
143
|
end
|
144
144
|
end
|
145
|
+
|
146
|
+
describe 'defining attr-based schema (model-like)' do
|
147
|
+
let(:schema) do
|
148
|
+
Class.new(Dry::Validation::Schema) do
|
149
|
+
attr(:email) { |email| email.filled? }
|
150
|
+
|
151
|
+
attr(:age) do |age|
|
152
|
+
age.none? | (age.int? & age.gt?(18))
|
153
|
+
end
|
154
|
+
|
155
|
+
attr(:address) do |address|
|
156
|
+
address.attr(:city) do |city|
|
157
|
+
city.min_size?(3)
|
158
|
+
end
|
159
|
+
|
160
|
+
address.attr(:street) do |street|
|
161
|
+
street.filled?
|
162
|
+
end
|
163
|
+
|
164
|
+
address.attr(:country) do |country|
|
165
|
+
country.attr(:name, &:filled?)
|
166
|
+
country.attr(:code, &:filled?)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
attr(:phone_numbers) do |phone_numbers|
|
171
|
+
phone_numbers.array? { phone_numbers.each(&:str?) }
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
let(:input_data) do
|
177
|
+
{
|
178
|
+
email: 'jane@doe.org',
|
179
|
+
age: 19,
|
180
|
+
address: { city: 'NYC', street: 'Street 1/2', country: { code: 'US', name: 'USA' } },
|
181
|
+
phone_numbers: [
|
182
|
+
'123456', '234567'
|
183
|
+
]
|
184
|
+
}.freeze
|
185
|
+
end
|
186
|
+
|
187
|
+
def input(data = input_data)
|
188
|
+
struct_from_hash(data)
|
189
|
+
end
|
190
|
+
|
191
|
+
describe '#messages' do
|
192
|
+
it 'returns compiled error messages' do
|
193
|
+
expect(validation.(input(input_data.merge(email: ''))).messages).to match_array([
|
194
|
+
[:email, [["email must be filled"], '']]
|
195
|
+
])
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe '#call' do
|
200
|
+
it 'passes when attributes are valid' do
|
201
|
+
expect(validation.(input)).to be_empty
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'validates presence of an email and min age value' do
|
205
|
+
expect(validation.(input(input_data.merge(email: '', age: 18)))).to match_array([
|
206
|
+
[:error, [:input, [:age, 18, [[:val, [:age, [:predicate, [:gt?, [18]]]]]]]]],
|
207
|
+
[:error, [:input, [:email, "", [[:val, [:email, [:predicate, [:filled?, []]]]]]]]]
|
208
|
+
])
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'validates presence of the email attr and type of age value' do
|
212
|
+
input_object = input(input_data.reject { |k, v| k == :email }.merge(age: '18'))
|
213
|
+
|
214
|
+
expect(validation.(input_object)).to match_array([
|
215
|
+
[:error, [:input, [:age, "18", [[:val, [:age, [:predicate, [:int?, []]]]]]]]],
|
216
|
+
[:error, [:input, [:email, input_object, [[:attr, [:email, [:predicate, [:attr?, [:email]]]]]]]]]
|
217
|
+
])
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'validates presence of the address and phone_number keys' do
|
221
|
+
input_object = input(email: 'jane@doe.org', age: 19)
|
222
|
+
|
223
|
+
expect(validation.(input_object)).to match_array([
|
224
|
+
[:error, [
|
225
|
+
:input, [
|
226
|
+
:address, input_object,
|
227
|
+
[
|
228
|
+
[:attr, [:address, [:predicate, [:attr?, [:address]]]]]
|
229
|
+
]
|
230
|
+
]
|
231
|
+
]],
|
232
|
+
[:error, [
|
233
|
+
:input, [
|
234
|
+
:phone_numbers, input_object,
|
235
|
+
[
|
236
|
+
[:attr, [:phone_numbers, [:predicate, [:attr?, [:phone_numbers]]]]]
|
237
|
+
]
|
238
|
+
]
|
239
|
+
]]
|
240
|
+
])
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'validates presence of keys under address and min size of the city value' do
|
244
|
+
address = { city: 'NY' }
|
245
|
+
input_object = input(input_data.merge(address: address))
|
246
|
+
address_object = input_object.address.class.from_hash(address)
|
247
|
+
|
248
|
+
expect(validation.(input_object)).to match_array([
|
249
|
+
[:error, [
|
250
|
+
:input, [
|
251
|
+
:address, address_object,
|
252
|
+
[
|
253
|
+
[:input, [:city, "NY", [[:val, [:city, [:predicate, [:min_size?, [3]]]]]]]],
|
254
|
+
[:input, [:street, address_object, [[:attr, [:street, [:predicate, [:attr?, [:street]]]]]]]],
|
255
|
+
[:input, [:country, address_object, [[:attr, [:country, [:predicate, [:attr?, [:country]]]]]]]]
|
256
|
+
]
|
257
|
+
]
|
258
|
+
]]
|
259
|
+
])
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'validates address code and name values' do
|
263
|
+
input_object = input(input_data.merge(address: input_data[:address].merge(country: { code: 'US', name: '' })))
|
264
|
+
|
265
|
+
country_object = input_object.address.country.class.from_hash(code: "US", name: "")
|
266
|
+
|
267
|
+
expect(validation.(input_object)).to match_array([
|
268
|
+
[:error, [
|
269
|
+
:input, [
|
270
|
+
:address, input_object.address.class.from_hash(city: "NYC", street: "Street 1/2", country: country_object),
|
271
|
+
[
|
272
|
+
[
|
273
|
+
:input, [
|
274
|
+
:country, country_object, [
|
275
|
+
[
|
276
|
+
:input, [
|
277
|
+
:name, "", [[:val, [:name, [:predicate, [:filled?, []]]]]]
|
278
|
+
]
|
279
|
+
]
|
280
|
+
]
|
281
|
+
]
|
282
|
+
]
|
283
|
+
]
|
284
|
+
]
|
285
|
+
]]
|
286
|
+
])
|
287
|
+
end
|
288
|
+
|
289
|
+
it 'validates each phone number' do
|
290
|
+
input_object = input(input_data.merge(phone_numbers: ['123', 312]))
|
291
|
+
|
292
|
+
expect(validation.(input_object)).to match_array([
|
293
|
+
[:error, [
|
294
|
+
:input, [
|
295
|
+
:phone_numbers, ["123", 312],[
|
296
|
+
[
|
297
|
+
:input, [
|
298
|
+
:phone_numbers, 312, [
|
299
|
+
[:val, [:phone_numbers, [:predicate, [:str?, []]]]]
|
300
|
+
]
|
301
|
+
]
|
302
|
+
]
|
303
|
+
]
|
304
|
+
]
|
305
|
+
]]
|
306
|
+
])
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
145
310
|
end
|