dry-validation 0.7.4 → 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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +9 -6
- data/CHANGELOG.md +58 -0
- data/Gemfile +3 -3
- data/benchmarks/benchmark_form_invalid.rb +64 -0
- data/benchmarks/benchmark_form_valid.rb +64 -0
- data/benchmarks/profile_schema_call_invalid.rb +20 -0
- data/benchmarks/profile_schema_call_valid.rb +20 -0
- data/benchmarks/profile_schema_definition.rb +14 -0
- data/benchmarks/profile_schema_messages_invalid.rb +20 -0
- data/benchmarks/suite.rb +5 -0
- data/config/errors.yml +12 -5
- data/dry-validation.gemspec +2 -2
- data/examples/basic.rb +2 -2
- data/examples/form.rb +2 -2
- data/examples/json.rb +2 -2
- data/examples/nested.rb +6 -6
- data/lib/dry/validation.rb +22 -3
- data/lib/dry/validation/deprecations.rb +23 -0
- data/lib/dry/validation/error_compiler.rb +31 -11
- data/lib/dry/validation/error_compiler/input.rb +44 -57
- data/lib/dry/validation/hint_compiler.rb +15 -7
- data/lib/dry/validation/input_processor_compiler.rb +13 -6
- data/lib/dry/validation/input_processor_compiler/form.rb +2 -0
- data/lib/dry/validation/input_processor_compiler/sanitizer.rb +1 -1
- data/lib/dry/validation/messages/abstract.rb +9 -1
- data/lib/dry/validation/predicate_registry.rb +101 -0
- data/lib/dry/validation/result.rb +8 -1
- data/lib/dry/validation/schema.rb +110 -44
- data/lib/dry/validation/schema/check.rb +4 -2
- data/lib/dry/validation/schema/deprecated.rb +31 -0
- data/lib/dry/validation/schema/dsl.rb +18 -11
- data/lib/dry/validation/schema/form.rb +1 -0
- data/lib/dry/validation/schema/json.rb +1 -0
- data/lib/dry/validation/schema/key.rb +23 -10
- data/lib/dry/validation/schema/rule.rb +81 -20
- data/lib/dry/validation/schema/value.rb +110 -25
- data/lib/dry/validation/version.rb +1 -1
- data/spec/fixtures/locales/en.yml +1 -0
- data/spec/fixtures/locales/pl.yml +1 -1
- data/spec/integration/custom_error_messages_spec.rb +2 -2
- data/spec/integration/custom_predicates_spec.rb +98 -15
- data/spec/integration/error_compiler_spec.rb +111 -96
- data/spec/integration/form/predicates/array_spec.rb +243 -0
- data/spec/integration/form/predicates/empty_spec.rb +263 -0
- data/spec/integration/form/predicates/eql_spec.rb +327 -0
- data/spec/integration/form/predicates/even_spec.rb +455 -0
- data/spec/integration/form/predicates/excluded_from_spec.rb +455 -0
- data/spec/integration/form/predicates/excludes_spec.rb +391 -0
- data/spec/integration/form/predicates/false_spec.rb +455 -0
- data/spec/integration/form/predicates/filled_spec.rb +467 -0
- data/spec/integration/form/predicates/format_spec.rb +454 -0
- data/spec/integration/form/predicates/gt_spec.rb +519 -0
- data/spec/integration/form/predicates/gteq_spec.rb +519 -0
- data/spec/integration/form/predicates/included_in_spec.rb +455 -0
- data/spec/integration/form/predicates/includes_spec.rb +391 -0
- data/spec/integration/form/predicates/key_spec.rb +75 -0
- data/spec/integration/form/predicates/lt_spec.rb +519 -0
- data/spec/integration/form/predicates/lteq_spec.rb +519 -0
- data/spec/integration/form/predicates/max_size_spec.rb +391 -0
- data/spec/integration/form/predicates/min_size_spec.rb +391 -0
- data/spec/integration/form/predicates/none_spec.rb +265 -0
- data/spec/integration/form/predicates/not_eql_spec.rb +327 -0
- data/spec/integration/form/predicates/odd_spec.rb +455 -0
- data/spec/integration/form/predicates/size/fixed_spec.rb +399 -0
- data/spec/integration/form/predicates/size/range_spec.rb +398 -0
- data/spec/integration/form/predicates/true_spec.rb +455 -0
- data/spec/integration/form/predicates/type_spec.rb +391 -0
- data/spec/integration/hints_spec.rb +90 -4
- data/spec/integration/injecting_rules_spec.rb +2 -2
- data/spec/integration/localized_error_messages_spec.rb +2 -2
- data/spec/integration/messages/i18n_spec.rb +3 -3
- data/spec/integration/optional_keys_spec.rb +3 -3
- data/spec/integration/schema/array_schema_spec.rb +49 -13
- data/spec/integration/schema/check_rules_spec.rb +6 -6
- data/spec/integration/schema/check_with_nested_el_spec.rb +3 -3
- data/spec/integration/schema/check_with_nth_el_spec.rb +1 -1
- data/spec/integration/schema/each_with_set_spec.rb +3 -3
- data/spec/integration/schema/extending_dsl_spec.rb +27 -0
- data/spec/integration/schema/form/explicit_types_spec.rb +182 -0
- data/spec/integration/schema/form_spec.rb +90 -18
- data/spec/integration/schema/hash_schema_spec.rb +47 -0
- data/spec/integration/schema/inheriting_schema_spec.rb +4 -4
- data/spec/integration/schema/input_processor_spec.rb +8 -8
- data/spec/integration/schema/json/explicit_types_spec.rb +157 -0
- data/spec/integration/schema/json_spec.rb +18 -18
- data/spec/integration/schema/macros/confirmation_spec.rb +1 -1
- data/spec/integration/schema/macros/each_spec.rb +177 -43
- data/spec/integration/schema/macros/{required_spec.rb → filled_spec.rb} +34 -6
- data/spec/integration/schema/macros/input_spec.rb +21 -0
- data/spec/integration/schema/macros/maybe_spec.rb +39 -2
- data/spec/integration/schema/macros/value_spec.rb +105 -0
- data/spec/integration/schema/macros/when_spec.rb +28 -8
- data/spec/integration/schema/nested_values_spec.rb +11 -8
- data/spec/integration/schema/not_spec.rb +2 -2
- data/spec/integration/schema/numbers_spec.rb +1 -1
- data/spec/integration/schema/option_with_default_spec.rb +1 -1
- data/spec/integration/schema/predicate_verification_spec.rb +9 -0
- data/spec/integration/schema/predicates/array_spec.rb +295 -0
- data/spec/integration/schema/predicates/custom_spec.rb +103 -0
- data/spec/integration/schema/predicates/empty_spec.rb +263 -0
- data/spec/integration/schema/predicates/eql_spec.rb +327 -0
- data/spec/integration/schema/predicates/even_spec.rb +455 -0
- data/spec/integration/schema/predicates/excluded_from_spec.rb +455 -0
- data/spec/integration/schema/predicates/excludes_spec.rb +391 -0
- data/spec/integration/schema/predicates/filled_spec.rb +467 -0
- data/spec/integration/schema/predicates/format_spec.rb +455 -0
- data/spec/integration/schema/predicates/gt_spec.rb +519 -0
- data/spec/integration/schema/predicates/gteq_spec.rb +519 -0
- data/spec/integration/schema/predicates/hash_spec.rb +69 -0
- data/spec/integration/schema/predicates/included_in_spec.rb +455 -0
- data/spec/integration/schema/predicates/includes_spec.rb +391 -0
- data/spec/integration/schema/predicates/key_spec.rb +88 -0
- data/spec/integration/schema/predicates/lt_spec.rb +520 -0
- data/spec/integration/schema/predicates/lteq_spec.rb +519 -0
- data/spec/integration/schema/predicates/max_size_spec.rb +391 -0
- data/spec/integration/schema/predicates/min_size_spec.rb +391 -0
- data/spec/integration/schema/predicates/none_spec.rb +265 -0
- data/spec/integration/schema/predicates/not_eql_spec.rb +391 -0
- data/spec/integration/schema/predicates/odd_spec.rb +455 -0
- data/spec/integration/schema/predicates/size/fixed_spec.rb +401 -0
- data/spec/integration/schema/predicates/size/range_spec.rb +399 -0
- data/spec/integration/schema/predicates/type_spec.rb +391 -0
- data/spec/integration/schema/reusing_schema_spec.rb +4 -4
- data/spec/integration/schema/using_types_spec.rb +24 -6
- data/spec/integration/schema/xor_spec.rb +2 -2
- data/spec/integration/schema_builders_spec.rb +15 -0
- data/spec/integration/schema_spec.rb +37 -12
- data/spec/shared/predicate_helper.rb +13 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/matchers.rb +38 -0
- data/spec/support/predicates_integration.rb +7 -0
- data/spec/unit/hint_compiler_spec.rb +10 -8
- data/spec/unit/input_processor_compiler/form_spec.rb +45 -43
- data/spec/unit/input_processor_compiler/json_spec.rb +37 -35
- data/spec/unit/predicate_registry_spec.rb +34 -0
- data/spec/unit/schema/key_spec.rb +12 -14
- data/spec/unit/schema/rule_spec.rb +4 -2
- data/spec/unit/schema/value_spec.rb +38 -121
- metadata +150 -16
- data/lib/dry/validation/schema/attr.rb +0 -15
- data/spec/integration/attr_spec.rb +0 -122
@@ -0,0 +1,47 @@
|
|
1
|
+
RSpec.describe Dry::Validation::Schema, 'for a hash' do
|
2
|
+
context 'without type specs' do
|
3
|
+
subject(:schema) do
|
4
|
+
Dry::Validation.Schema do
|
5
|
+
hash? do
|
6
|
+
required(:prefix).filled
|
7
|
+
required(:value).filled
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'applies its rules to array input' do
|
13
|
+
result = schema.(prefix: 1, value: 123)
|
14
|
+
|
15
|
+
expect(result).to be_success
|
16
|
+
|
17
|
+
result = schema.(prefix: 1, value: nil)
|
18
|
+
|
19
|
+
expect(result.messages).to eql(value: ["must be filled"])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'with type specs' do
|
24
|
+
subject(:schema) do
|
25
|
+
Dry::Validation.Form do
|
26
|
+
configure { config.type_specs = true }
|
27
|
+
|
28
|
+
hash? do
|
29
|
+
required(:prefix, :int).filled
|
30
|
+
required(:value, :int).filled
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'applies its rules to coerced array input' do
|
36
|
+
result = schema.(prefix: 1, value: '123')
|
37
|
+
|
38
|
+
expect(result).to be_success
|
39
|
+
|
40
|
+
expect(result.output).to eql(prefix: 1, value: 123)
|
41
|
+
|
42
|
+
result = schema.(prefix: 1, value: nil)
|
43
|
+
|
44
|
+
expect(result.messages).to eql(value: ["must be filled"])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -1,16 +1,16 @@
|
|
1
1
|
RSpec.describe 'Inheriting schema' do
|
2
2
|
subject(:schema) do
|
3
3
|
Dry::Validation.Schema(base_schema) do
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
required(:location).schema do
|
5
|
+
required(:lat).filled(:float?)
|
6
|
+
required(:lng).filled(:float?)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
11
|
let(:base_schema) do
|
12
12
|
Dry::Validation.Schema do
|
13
|
-
|
13
|
+
required(:city).filled
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -5,18 +5,18 @@ RSpec.describe Dry::Validation::Schema, 'setting input processor in schema' do
|
|
5
5
|
config.input_processor = :sanitizer
|
6
6
|
end
|
7
7
|
|
8
|
-
|
8
|
+
required(:email).filled
|
9
9
|
|
10
|
-
|
10
|
+
required(:age).maybe(:int?, gt?: 18)
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
required(:address).schema do
|
13
|
+
required(:city).filled
|
14
|
+
required(:street).filled
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
required(:phone_numbers).each do
|
18
|
+
required(:prefix).filled
|
19
|
+
required(:value).filled
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
RSpec.describe Dry::Validation::Schema::JSON, 'explicit types' do
|
2
|
+
context 'single type spec without rules' do
|
3
|
+
subject(:schema) do
|
4
|
+
Dry::Validation.JSON do
|
5
|
+
configure { config.type_specs = true }
|
6
|
+
required(:bdate, :date)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'uses json coercion' do
|
11
|
+
expect(schema.('bdate' => '2010-09-08').to_h).to eql(bdate: Date.new(2010, 9, 8))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'single type spec with rules' do
|
16
|
+
subject(:schema) do
|
17
|
+
Dry::Validation.JSON do
|
18
|
+
configure { config.type_specs = true }
|
19
|
+
required(:bdate, :date).value(:date?, gt?: Date.new(2009))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'applies rules to coerced value' do
|
24
|
+
expect(schema.(bdate: "2010-09-07").messages).to be_empty
|
25
|
+
expect(schema.(bdate: "2008-01-01").messages).to eql(bdate: ['must be greater than 2009-01-01'])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'sum type spec without rules' do
|
30
|
+
subject(:schema) do
|
31
|
+
Dry::Validation.JSON do
|
32
|
+
configure { config.type_specs = true }
|
33
|
+
required(:bdate, [:nil, :date])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'uses form coercion' do
|
38
|
+
expect(schema.('bdate' => '2010-09-08').to_h).to eql(bdate: Date.new(2010, 9, 8))
|
39
|
+
expect(schema.('bdate' => '').to_h).to eql(bdate: nil)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'sum type spec with rules' do
|
44
|
+
subject(:schema) do
|
45
|
+
Dry::Validation.JSON do
|
46
|
+
configure { config.type_specs = true }
|
47
|
+
required(:bdate, [:nil, :date]).maybe(:date?, gt?: Date.new(2008))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'applies rules to coerced value' do
|
52
|
+
expect(schema.(bdate: nil).messages).to be_empty
|
53
|
+
expect(schema.(bdate: "2010-09-07").messages).to be_empty
|
54
|
+
expect(schema.(bdate: "2008-01-01").messages).to eql(bdate: ['must be greater than 2008-01-01'])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'using a type object' do
|
59
|
+
subject(:schema) do
|
60
|
+
Dry::Validation.JSON do
|
61
|
+
configure { config.type_specs = true }
|
62
|
+
required(:bdate, Types::Json::Nil | Types::Json::Date)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'uses form coercion' do
|
67
|
+
expect(schema.('bdate' => '').to_h).to eql(bdate: nil)
|
68
|
+
expect(schema.('bdate' => '2010-09-08').to_h).to eql(bdate: Date.new(2010, 9, 8))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'nested schema' do
|
73
|
+
subject(:schema) do
|
74
|
+
Dry::Validation.JSON do
|
75
|
+
configure { config.type_specs = true }
|
76
|
+
|
77
|
+
required(:user).schema do
|
78
|
+
required(:email, :string)
|
79
|
+
required(:bdate, :date)
|
80
|
+
|
81
|
+
required(:address).schema do
|
82
|
+
required(:street, :string)
|
83
|
+
required(:city, :string)
|
84
|
+
required(:zipcode, :string)
|
85
|
+
|
86
|
+
required(:location).schema do
|
87
|
+
required(:lat, :float)
|
88
|
+
required(:lng, :float)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'uses form coercion for nested input' do
|
96
|
+
input = {
|
97
|
+
'user' => {
|
98
|
+
'email' => 'jane@doe.org',
|
99
|
+
'bdate' => '2010-09-08',
|
100
|
+
'address' => {
|
101
|
+
'street' => 'Street 1',
|
102
|
+
'city' => 'NYC',
|
103
|
+
'zipcode' => '1234',
|
104
|
+
'location' => { 'lat' => 1.23, 'lng' => 4.56 }
|
105
|
+
}
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
expect(schema.(input).to_h).to eql(
|
110
|
+
user: {
|
111
|
+
email: 'jane@doe.org',
|
112
|
+
bdate: Date.new(2010, 9, 8),
|
113
|
+
address: {
|
114
|
+
street: 'Street 1',
|
115
|
+
city: 'NYC',
|
116
|
+
zipcode: '1234',
|
117
|
+
location: { lat: 1.23, lng: 4.56 }
|
118
|
+
}
|
119
|
+
}
|
120
|
+
)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'nested schema with arrays' do
|
125
|
+
subject(:schema) do
|
126
|
+
Dry::Validation.JSON do
|
127
|
+
configure { config.type_specs = true }
|
128
|
+
|
129
|
+
required(:song).schema do
|
130
|
+
required(:title, :string)
|
131
|
+
|
132
|
+
required(:tags).each do
|
133
|
+
schema do
|
134
|
+
required(:name, :string)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'uses form coercion for nested input' do
|
142
|
+
input = {
|
143
|
+
'song' => {
|
144
|
+
'title' => 'dry-rb is awesome lala',
|
145
|
+
'tags' => [{ 'name' => 'red' }, { 'name' => 'blue' }]
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
expect(schema.(input).to_h).to eql(
|
150
|
+
song: {
|
151
|
+
title: 'dry-rb is awesome lala',
|
152
|
+
tags: [{ name: 'red' }, { name: 'blue' }]
|
153
|
+
}
|
154
|
+
)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -1,17 +1,23 @@
|
|
1
1
|
RSpec.describe Dry::Validation::Schema::JSON, 'defining a schema' do
|
2
2
|
subject(:schema) do
|
3
3
|
Dry::Validation.JSON do
|
4
|
-
|
4
|
+
configure do
|
5
|
+
def email?(value)
|
6
|
+
true
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
required(:email).filled
|
5
11
|
|
6
|
-
|
12
|
+
required(:age).maybe(:int?, gt?: 18)
|
7
13
|
|
8
|
-
|
9
|
-
|
10
|
-
|
14
|
+
required(:address).schema do
|
15
|
+
required(:city).filled
|
16
|
+
required(:street).filled
|
11
17
|
|
12
|
-
|
13
|
-
|
14
|
-
|
18
|
+
required(:loc).schema do
|
19
|
+
required(:lat).filled(:float?)
|
20
|
+
required(:lng).filled(:float?)
|
15
21
|
end
|
16
22
|
end
|
17
23
|
|
@@ -20,12 +26,6 @@ RSpec.describe Dry::Validation::Schema::JSON, 'defining a schema' do
|
|
20
26
|
optional(:phone_number).maybe(:int?, gt?: 0)
|
21
27
|
|
22
28
|
rule(:email_valid) { value(:email).email? }
|
23
|
-
|
24
|
-
configure do
|
25
|
-
def email?(value)
|
26
|
-
true
|
27
|
-
end
|
28
|
-
end
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -121,9 +121,9 @@ RSpec.describe Dry::Validation::Schema::JSON, 'defining a schema' do
|
|
121
121
|
describe 'with nested schema in a high-level rule' do
|
122
122
|
subject(:schema) do
|
123
123
|
Dry::Validation.JSON do
|
124
|
-
|
124
|
+
required(:address).maybe(:hash?)
|
125
125
|
|
126
|
-
|
126
|
+
required(:delivery).filled(:bool?)
|
127
127
|
|
128
128
|
rule(address: [:delivery, :address]) do |delivery, address|
|
129
129
|
delivery.true?.then(address.schema(AddressSchema))
|
@@ -133,8 +133,8 @@ RSpec.describe Dry::Validation::Schema::JSON, 'defining a schema' do
|
|
133
133
|
|
134
134
|
before do
|
135
135
|
AddressSchema = Dry::Validation.JSON do
|
136
|
-
|
137
|
-
|
136
|
+
required(:city).filled
|
137
|
+
required(:zipcode).filled(:int?)
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
@@ -1,43 +1,175 @@
|
|
1
1
|
RSpec.describe 'Macros #each' do
|
2
|
-
context
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
key(:songs).each do
|
7
|
-
key(:title).required
|
8
|
-
end
|
9
|
-
end
|
2
|
+
context "predicate without options" do
|
3
|
+
subject(:schema) do
|
4
|
+
Dry::Validation.Schema do
|
5
|
+
required(:foo).each(:filled?, :str?)
|
10
6
|
end
|
7
|
+
end
|
11
8
|
|
12
|
-
|
13
|
-
|
9
|
+
context 'with valid input' do
|
10
|
+
let(:input) { { foo: %w(a b c) } }
|
14
11
|
|
15
|
-
|
12
|
+
it 'is successful' do
|
13
|
+
expect(result).to be_successful
|
16
14
|
end
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
17
|
+
context 'with invalid input' do
|
18
|
+
let(:input) { { foo: [[1, 2], "", "foo"] } }
|
19
|
+
|
20
|
+
it 'is not successful' do
|
21
|
+
expect(result).to be_failing(0 => ["must be a string"], 1 => ["must be filled"])
|
20
22
|
end
|
23
|
+
end
|
21
24
|
|
22
|
-
|
23
|
-
|
25
|
+
context 'with invalid input type' do
|
26
|
+
let(:input) { { foo: nil } }
|
24
27
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
it 'is not successful' do
|
29
|
+
expect(result).to be_failing ["must be an array"]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "predicate with options" do
|
35
|
+
subject(:schema) do
|
36
|
+
Dry::Validation.Schema do
|
37
|
+
required(:foo).each(size?: 3)
|
31
38
|
end
|
32
39
|
end
|
33
40
|
|
41
|
+
context 'with valid input' do
|
42
|
+
let(:input) { { foo: [[1,2,3], "foo"] } }
|
43
|
+
|
44
|
+
it 'is successful' do
|
45
|
+
expect(result).to be_successful
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with invalid input' do
|
50
|
+
let(:input) { { foo: [[1,2], "foo"] } }
|
51
|
+
|
52
|
+
it 'is not successful' do
|
53
|
+
expect(result).to be_failing({0=>["size must be 3"]})
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'with invalid input type' do
|
58
|
+
let(:input) { { foo: nil } }
|
59
|
+
|
60
|
+
it 'is not successful' do
|
61
|
+
expect(result).to be_failing ["must be an array", "size must be 3"]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'with filled macro' do
|
67
|
+
subject(:schema) do
|
68
|
+
Dry::Validation.Schema do
|
69
|
+
required(:foo).filled(size?: 2) { each(:str?) }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'with valid input' do
|
74
|
+
let(:input) { { foo: %w(a b) } }
|
75
|
+
|
76
|
+
it 'is successful' do
|
77
|
+
expect(result).to be_successful
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context 'when value is not valid' do
|
82
|
+
let(:input) { { foo: ["foo"] } }
|
83
|
+
|
84
|
+
it 'is not successful' do
|
85
|
+
expect(result).to be_failing(["size must be 2"])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'when value has invalid elements' do
|
90
|
+
let(:input) { { foo: [:foo, "foo"] } }
|
91
|
+
|
92
|
+
it 'is not successful' do
|
93
|
+
expect(result).to be_failing(0 => ["must be a string"])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'with maybe macro' do
|
99
|
+
subject(:schema) do
|
100
|
+
Dry::Validation.Schema do
|
101
|
+
required(:foo).maybe { each(:str?) }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'with nil input' do
|
106
|
+
let(:input) { { foo: nil } }
|
107
|
+
|
108
|
+
it 'is successful' do
|
109
|
+
expect(result).to be_successful
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'with valid input' do
|
114
|
+
let(:input) { { foo: %w(a b c) } }
|
115
|
+
|
116
|
+
it 'is successful' do
|
117
|
+
expect(result).to be_successful
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'with invalid input' do
|
122
|
+
let(:input) { { foo: [:foo, "foo"] } }
|
123
|
+
|
124
|
+
it 'is not successful' do
|
125
|
+
expect(result).to be_failing(0 => ["must be a string"])
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'with external schema macro' do
|
131
|
+
subject(:schema) do
|
132
|
+
Dry::Validation.Schema do
|
133
|
+
required(:foo).each(FooSchema)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
before do
|
138
|
+
FooSchema = Dry::Validation.Schema do
|
139
|
+
required(:bar).filled(:str?)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
after do
|
144
|
+
Object.send(:remove_const, :FooSchema)
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'with valid input' do
|
148
|
+
let(:input) { { foo: [{ bar: "baz" }] } }
|
149
|
+
|
150
|
+
it 'is successful' do
|
151
|
+
expect(result).to be_successful
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'when value is not valid' do
|
156
|
+
let(:input) { { foo: [{ bar: 1 }] } }
|
157
|
+
|
158
|
+
it 'is not successful' do
|
159
|
+
# FIXME: our be_failing didn't work with such nested wow hash
|
160
|
+
expect(result.messages).to eql(foo: { 0 => { bar: ["must be a string"] } })
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context 'with a block' do
|
34
166
|
context 'with a nested schema' do
|
35
167
|
subject(:schema) do
|
36
168
|
Dry::Validation.Schema do
|
37
|
-
|
169
|
+
required(:songs).each do
|
38
170
|
schema do
|
39
|
-
|
40
|
-
|
171
|
+
required(:title).filled
|
172
|
+
required(:author).filled
|
41
173
|
end
|
42
174
|
end
|
43
175
|
end
|
@@ -76,31 +208,33 @@ RSpec.describe 'Macros #each' do
|
|
76
208
|
end
|
77
209
|
|
78
210
|
context 'with inferred predicates and a form schema' do
|
79
|
-
|
80
|
-
|
81
|
-
|
211
|
+
context "predicate w/o options" do
|
212
|
+
subject(:schema) do
|
213
|
+
Dry::Validation.Form do
|
214
|
+
required(:songs).each(:str?)
|
215
|
+
end
|
82
216
|
end
|
83
|
-
end
|
84
217
|
|
85
|
-
|
86
|
-
|
218
|
+
it 'passes when all elements are valid' do
|
219
|
+
songs = %w(hello world)
|
87
220
|
|
88
|
-
|
89
|
-
|
221
|
+
expect(schema.(songs: songs)).to be_success
|
222
|
+
end
|
90
223
|
|
91
|
-
|
92
|
-
|
93
|
-
|
224
|
+
it 'fails when value is not an array' do
|
225
|
+
expect(schema.(songs: 'oops').messages).to eql(songs: ['must be an array'])
|
226
|
+
end
|
94
227
|
|
95
|
-
|
96
|
-
|
228
|
+
it 'fails when not all elements are valid' do
|
229
|
+
songs = ['hello', nil, 2]
|
97
230
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
231
|
+
expect(schema.(songs: songs).messages).to eql(
|
232
|
+
songs: {
|
233
|
+
1 => ['must be a string'],
|
234
|
+
2 => ['must be a string']
|
235
|
+
}
|
236
|
+
)
|
237
|
+
end
|
104
238
|
end
|
105
239
|
end
|
106
240
|
end
|