dry-validation 0.13.3 → 1.7.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 +506 -95
- data/LICENSE +1 -1
- data/README.md +16 -12
- data/config/errors.yml +3 -88
- data/dry-validation.gemspec +37 -24
- data/lib/dry/validation/config.rb +24 -0
- data/lib/dry/validation/constants.rb +43 -0
- data/lib/dry/validation/contract/class_interface.rb +230 -0
- data/lib/dry/validation/contract.rb +171 -0
- data/lib/dry/validation/evaluator.rb +224 -0
- data/lib/dry/validation/extensions/hints.rb +67 -0
- data/lib/dry/validation/extensions/monads.rb +24 -8
- data/lib/dry/validation/extensions/predicates_as_macros.rb +75 -0
- data/lib/dry/validation/failures.rb +70 -0
- data/lib/dry/validation/function.rb +44 -0
- data/lib/dry/validation/macro.rb +38 -0
- data/lib/dry/validation/macros.rb +104 -0
- data/lib/dry/validation/message.rb +80 -80
- data/lib/dry/validation/message_set.rb +80 -105
- data/lib/dry/validation/messages/resolver.rb +131 -0
- data/lib/dry/validation/result.rb +183 -41
- data/lib/dry/validation/rule.rb +135 -0
- data/lib/dry/validation/schema_ext.rb +19 -0
- data/lib/dry/validation/values.rb +104 -0
- data/lib/dry/validation/version.rb +3 -1
- data/lib/dry/validation.rb +45 -28
- data/lib/dry-validation.rb +3 -1
- metadata +46 -344
- data/.codeclimate.yml +0 -17
- data/.gitignore +0 -9
- data/.rspec +0 -3
- data/.travis.yml +0 -29
- data/CONTRIBUTING.md +0 -31
- data/Gemfile +0 -25
- data/Rakefile +0 -22
- data/benchmarks/benchmark_form_invalid.rb +0 -64
- data/benchmarks/benchmark_form_valid.rb +0 -64
- data/benchmarks/benchmark_schema_invalid_huge.rb +0 -52
- data/benchmarks/profile_schema_call_invalid.rb +0 -20
- data/benchmarks/profile_schema_call_valid.rb +0 -20
- data/benchmarks/profile_schema_definition.rb +0 -14
- data/benchmarks/profile_schema_huge_invalid.rb +0 -30
- data/benchmarks/profile_schema_messages_invalid.rb +0 -20
- data/benchmarks/suite.rb +0 -5
- data/examples/basic.rb +0 -15
- data/examples/each.rb +0 -14
- data/examples/json.rb +0 -12
- data/examples/multiple.rb +0 -27
- data/examples/nested.rb +0 -22
- data/examples/params.rb +0 -11
- data/lib/dry/validation/compat/form.rb +0 -67
- data/lib/dry/validation/deprecations.rb +0 -24
- data/lib/dry/validation/executor.rb +0 -91
- data/lib/dry/validation/extensions/struct.rb +0 -32
- data/lib/dry/validation/extensions.rb +0 -7
- data/lib/dry/validation/input_processor_compiler/json.rb +0 -45
- data/lib/dry/validation/input_processor_compiler/params.rb +0 -49
- data/lib/dry/validation/input_processor_compiler/sanitizer.rb +0 -47
- data/lib/dry/validation/input_processor_compiler.rb +0 -137
- data/lib/dry/validation/message_compiler/visitor_opts.rb +0 -37
- data/lib/dry/validation/message_compiler.rb +0 -188
- data/lib/dry/validation/messages/abstract.rb +0 -119
- data/lib/dry/validation/messages/i18n.rb +0 -47
- data/lib/dry/validation/messages/namespaced.rb +0 -39
- data/lib/dry/validation/messages/yaml.rb +0 -61
- data/lib/dry/validation/messages.rb +0 -14
- data/lib/dry/validation/predicate_registry.rb +0 -115
- data/lib/dry/validation/predicates.rb +0 -19
- data/lib/dry/validation/schema/check.rb +0 -37
- data/lib/dry/validation/schema/class_interface.rb +0 -190
- data/lib/dry/validation/schema/deprecated.rb +0 -30
- data/lib/dry/validation/schema/dsl.rb +0 -118
- data/lib/dry/validation/schema/form.rb +0 -9
- data/lib/dry/validation/schema/json.rb +0 -21
- data/lib/dry/validation/schema/key.rb +0 -71
- data/lib/dry/validation/schema/params.rb +0 -22
- data/lib/dry/validation/schema/rule.rb +0 -202
- data/lib/dry/validation/schema/value.rb +0 -211
- data/lib/dry/validation/schema.rb +0 -126
- data/lib/dry/validation/schema_compiler.rb +0 -81
- data/lib/dry/validation/template.rb +0 -66
- data/lib/dry/validation/type_specs.rb +0 -70
- data/log/.gitkeep +0 -0
- data/spec/extensions/monads/result_spec.rb +0 -40
- data/spec/extensions/struct/schema_spec.rb +0 -32
- data/spec/fixtures/locales/en.yml +0 -8
- data/spec/fixtures/locales/pl.yml +0 -22
- data/spec/integration/custom_error_messages_spec.rb +0 -54
- data/spec/integration/custom_predicates_spec.rb +0 -228
- data/spec/integration/hints_spec.rb +0 -170
- data/spec/integration/injecting_rules_spec.rb +0 -30
- data/spec/integration/json/defining_base_schema_spec.rb +0 -41
- data/spec/integration/localized_error_messages_spec.rb +0 -72
- data/spec/integration/message_compiler_spec.rb +0 -405
- data/spec/integration/messages/i18n_spec.rb +0 -104
- data/spec/integration/optional_keys_spec.rb +0 -28
- data/spec/integration/params/predicates/array_spec.rb +0 -287
- data/spec/integration/params/predicates/empty_spec.rb +0 -263
- data/spec/integration/params/predicates/eql_spec.rb +0 -327
- data/spec/integration/params/predicates/even_spec.rb +0 -455
- data/spec/integration/params/predicates/excluded_from_spec.rb +0 -455
- data/spec/integration/params/predicates/excludes_spec.rb +0 -391
- data/spec/integration/params/predicates/false_spec.rb +0 -455
- data/spec/integration/params/predicates/filled_spec.rb +0 -467
- data/spec/integration/params/predicates/format_spec.rb +0 -454
- data/spec/integration/params/predicates/gt_spec.rb +0 -519
- data/spec/integration/params/predicates/gteq_spec.rb +0 -519
- data/spec/integration/params/predicates/included_in_spec.rb +0 -455
- data/spec/integration/params/predicates/includes_spec.rb +0 -391
- data/spec/integration/params/predicates/key_spec.rb +0 -67
- data/spec/integration/params/predicates/lt_spec.rb +0 -519
- data/spec/integration/params/predicates/lteq_spec.rb +0 -519
- data/spec/integration/params/predicates/max_size_spec.rb +0 -391
- data/spec/integration/params/predicates/min_size_spec.rb +0 -391
- data/spec/integration/params/predicates/none_spec.rb +0 -265
- data/spec/integration/params/predicates/not_eql_spec.rb +0 -327
- data/spec/integration/params/predicates/odd_spec.rb +0 -455
- data/spec/integration/params/predicates/size/fixed_spec.rb +0 -393
- data/spec/integration/params/predicates/size/range_spec.rb +0 -396
- data/spec/integration/params/predicates/true_spec.rb +0 -455
- data/spec/integration/params/predicates/type_spec.rb +0 -391
- data/spec/integration/result_spec.rb +0 -81
- data/spec/integration/schema/array_schema_spec.rb +0 -59
- data/spec/integration/schema/check_rules_spec.rb +0 -119
- data/spec/integration/schema/check_with_nested_el_spec.rb +0 -37
- data/spec/integration/schema/check_with_nth_el_spec.rb +0 -25
- data/spec/integration/schema/default_settings_spec.rb +0 -11
- data/spec/integration/schema/defining_base_schema_spec.rb +0 -41
- data/spec/integration/schema/dynamic_predicate_args_spec.rb +0 -43
- data/spec/integration/schema/each_with_set_spec.rb +0 -70
- data/spec/integration/schema/extending_dsl_spec.rb +0 -27
- data/spec/integration/schema/form_spec.rb +0 -236
- data/spec/integration/schema/hash_schema_spec.rb +0 -47
- data/spec/integration/schema/inheriting_schema_spec.rb +0 -31
- data/spec/integration/schema/input_processor_spec.rb +0 -46
- data/spec/integration/schema/json/explicit_types_spec.rb +0 -157
- data/spec/integration/schema/json_spec.rb +0 -163
- data/spec/integration/schema/macros/confirmation_spec.rb +0 -35
- data/spec/integration/schema/macros/each_spec.rb +0 -268
- data/spec/integration/schema/macros/filled_spec.rb +0 -87
- data/spec/integration/schema/macros/input_spec.rb +0 -139
- data/spec/integration/schema/macros/maybe_spec.rb +0 -99
- data/spec/integration/schema/macros/rule_spec.rb +0 -75
- data/spec/integration/schema/macros/value_spec.rb +0 -119
- data/spec/integration/schema/macros/when_spec.rb +0 -62
- data/spec/integration/schema/nested_schemas_spec.rb +0 -236
- data/spec/integration/schema/nested_values_spec.rb +0 -46
- data/spec/integration/schema/not_spec.rb +0 -34
- data/spec/integration/schema/numbers_spec.rb +0 -19
- data/spec/integration/schema/option_with_default_spec.rb +0 -64
- data/spec/integration/schema/or_spec.rb +0 -87
- data/spec/integration/schema/params/defining_base_schema_spec.rb +0 -41
- data/spec/integration/schema/params/explicit_types_spec.rb +0 -195
- data/spec/integration/schema/params_spec.rb +0 -234
- data/spec/integration/schema/predicate_verification_spec.rb +0 -9
- data/spec/integration/schema/predicates/array_spec.rb +0 -295
- data/spec/integration/schema/predicates/custom_spec.rb +0 -103
- data/spec/integration/schema/predicates/empty_spec.rb +0 -263
- data/spec/integration/schema/predicates/eql_spec.rb +0 -327
- data/spec/integration/schema/predicates/even_spec.rb +0 -455
- data/spec/integration/schema/predicates/excluded_from/array_spec.rb +0 -459
- data/spec/integration/schema/predicates/excluded_from/range_spec.rb +0 -459
- data/spec/integration/schema/predicates/excludes_spec.rb +0 -391
- data/spec/integration/schema/predicates/filled_spec.rb +0 -467
- data/spec/integration/schema/predicates/format_spec.rb +0 -455
- data/spec/integration/schema/predicates/gt_spec.rb +0 -519
- data/spec/integration/schema/predicates/gteq_spec.rb +0 -519
- data/spec/integration/schema/predicates/hash_spec.rb +0 -69
- data/spec/integration/schema/predicates/included_in/array_spec.rb +0 -459
- data/spec/integration/schema/predicates/included_in/range_spec.rb +0 -459
- data/spec/integration/schema/predicates/includes_spec.rb +0 -391
- data/spec/integration/schema/predicates/key_spec.rb +0 -88
- data/spec/integration/schema/predicates/lt_spec.rb +0 -520
- data/spec/integration/schema/predicates/lteq_spec.rb +0 -519
- data/spec/integration/schema/predicates/max_size_spec.rb +0 -391
- data/spec/integration/schema/predicates/min_size_spec.rb +0 -391
- data/spec/integration/schema/predicates/none_spec.rb +0 -265
- data/spec/integration/schema/predicates/not_eql_spec.rb +0 -391
- data/spec/integration/schema/predicates/odd_spec.rb +0 -455
- data/spec/integration/schema/predicates/size/fixed_spec.rb +0 -398
- data/spec/integration/schema/predicates/size/range_spec.rb +0 -395
- data/spec/integration/schema/predicates/type_spec.rb +0 -413
- data/spec/integration/schema/reusing_schema_spec.rb +0 -33
- data/spec/integration/schema/using_types_spec.rb +0 -135
- data/spec/integration/schema/validate_spec.rb +0 -120
- data/spec/integration/schema/xor_spec.rb +0 -35
- data/spec/integration/schema_builders_spec.rb +0 -17
- data/spec/integration/schema_spec.rb +0 -173
- data/spec/shared/message_compiler.rb +0 -11
- data/spec/shared/predicate_helper.rb +0 -15
- data/spec/shared/rule_compiler.rb +0 -8
- data/spec/spec_helper.rb +0 -62
- data/spec/support/define_struct.rb +0 -25
- data/spec/support/matchers.rb +0 -38
- data/spec/support/mutant.rb +0 -9
- data/spec/support/predicates_integration.rb +0 -7
- data/spec/unit/input_processor_compiler/json_spec.rb +0 -283
- data/spec/unit/input_processor_compiler/params_spec.rb +0 -328
- data/spec/unit/message_compiler/visit_failure_spec.rb +0 -38
- data/spec/unit/message_compiler/visit_spec.rb +0 -16
- data/spec/unit/message_compiler_spec.rb +0 -7
- data/spec/unit/predicate_registry_spec.rb +0 -34
- data/spec/unit/schema/key_spec.rb +0 -38
- data/spec/unit/schema/rule_spec.rb +0 -42
- data/spec/unit/schema/value_spec.rb +0 -131
- data/spec/unit/schema_spec.rb +0 -35
@@ -1,157 +0,0 @@
|
|
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,163 +0,0 @@
|
|
1
|
-
RSpec.describe Dry::Validation::Schema::JSON, 'defining a schema' do
|
2
|
-
subject(:schema) do
|
3
|
-
Dry::Validation.JSON do
|
4
|
-
configure do
|
5
|
-
def email?(value)
|
6
|
-
true
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
required(:email).filled
|
11
|
-
|
12
|
-
required(:age).maybe(:int?, gt?: 18)
|
13
|
-
|
14
|
-
required(:address).schema do
|
15
|
-
required(:city).filled
|
16
|
-
required(:street).filled
|
17
|
-
|
18
|
-
required(:loc).schema do
|
19
|
-
required(:lat).filled(:float?)
|
20
|
-
required(:lng).filled(:float?)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
optional(:password).maybe.confirmation
|
25
|
-
|
26
|
-
optional(:phone_number).maybe(:int?, gt?: 0)
|
27
|
-
|
28
|
-
rule(:email_valid) { value(:email).email? }
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
describe '#messages' do
|
33
|
-
it 'returns compiled error messages' do
|
34
|
-
result = schema.('email' => '', 'age' => 19)
|
35
|
-
|
36
|
-
expect(result.messages).to eql(
|
37
|
-
email: ['must be filled'],
|
38
|
-
address: ['is missing'],
|
39
|
-
)
|
40
|
-
|
41
|
-
expect(result.output).to eql(email: '', age: 19)
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'returns hints for nested data' do
|
45
|
-
result = schema.(
|
46
|
-
'email' => 'jane@doe.org',
|
47
|
-
'age' => 19,
|
48
|
-
'address' => {
|
49
|
-
'city' => '',
|
50
|
-
'street' => 'Street 1/2',
|
51
|
-
'loc' => { 'lat' => '123.456', 'lng' => '' }
|
52
|
-
}
|
53
|
-
)
|
54
|
-
|
55
|
-
expect(result.messages).to eql(
|
56
|
-
address: {
|
57
|
-
loc: { lat: ['must be a float'], lng: ['must be filled'] },
|
58
|
-
city: ['must be filled']
|
59
|
-
}
|
60
|
-
)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
describe '#call' do
|
65
|
-
it 'passes when attributes are valid' do
|
66
|
-
result = schema.(
|
67
|
-
'email' => 'jane@doe.org',
|
68
|
-
'age' => 19,
|
69
|
-
'address' => {
|
70
|
-
'city' => 'NYC',
|
71
|
-
'street' => 'Street 1/2',
|
72
|
-
'loc' => { 'lat' => 123.456, 'lng' => 456.123 }
|
73
|
-
}
|
74
|
-
)
|
75
|
-
|
76
|
-
expect(result).to be_success
|
77
|
-
|
78
|
-
expect(result.output).to eql(
|
79
|
-
email: 'jane@doe.org', age: 19,
|
80
|
-
address: {
|
81
|
-
city: 'NYC', street: 'Street 1/2',
|
82
|
-
loc: { lat: 123.456, lng: 456.123 }
|
83
|
-
}
|
84
|
-
)
|
85
|
-
end
|
86
|
-
|
87
|
-
it 'validates presence of an email and min age value' do
|
88
|
-
result = schema.('email' => '', 'age' => 18)
|
89
|
-
|
90
|
-
expect(result.messages).to eql(
|
91
|
-
address: ['is missing'],
|
92
|
-
age: ['must be greater than 18'],
|
93
|
-
email: ['must be filled']
|
94
|
-
)
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'handles optionals' do
|
98
|
-
result = schema.(
|
99
|
-
'email' => 'jane@doe.org',
|
100
|
-
'age' => 19,
|
101
|
-
'phone_number' => 12,
|
102
|
-
'address' => {
|
103
|
-
'city' => 'NYC',
|
104
|
-
'street' => 'Street 1/2',
|
105
|
-
'loc' => { 'lat' => 123.456, 'lng' => 456.123 }
|
106
|
-
}
|
107
|
-
)
|
108
|
-
|
109
|
-
expect(result).to be_success
|
110
|
-
|
111
|
-
expect(result.output).to eql(
|
112
|
-
email: 'jane@doe.org', age: 19, phone_number: 12,
|
113
|
-
address: {
|
114
|
-
city: 'NYC', street: 'Street 1/2',
|
115
|
-
loc: { lat: 123.456, lng: 456.123 }
|
116
|
-
}
|
117
|
-
)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
describe 'with nested schema in a high-level rule' do
|
122
|
-
subject(:schema) do
|
123
|
-
Dry::Validation.JSON do
|
124
|
-
required(:address).maybe(:hash?)
|
125
|
-
|
126
|
-
required(:delivery).filled(:bool?)
|
127
|
-
|
128
|
-
rule(address: [:delivery, :address]) do |delivery, address|
|
129
|
-
delivery.true?.then(address.schema(AddressSchema))
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
before do
|
135
|
-
AddressSchema = Dry::Validation.JSON do
|
136
|
-
required(:city).filled
|
137
|
-
required(:zipcode).filled(:int?)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
after do
|
142
|
-
Object.send(:remove_const, :AddressSchema)
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'succeeds when nested form schema succeeds' do
|
146
|
-
result = schema.(delivery: true, address: { city: 'NYC', zipcode: 123 })
|
147
|
-
expect(result).to be_success
|
148
|
-
end
|
149
|
-
|
150
|
-
it 'does not apply schema when there is no match' do
|
151
|
-
result = schema.(delivery: false, address: nil)
|
152
|
-
expect(result).to be_success
|
153
|
-
end
|
154
|
-
|
155
|
-
it 'fails when nested schema fails' do
|
156
|
-
result = schema.(delivery: true, address: { city: 'NYC', zipcode: 'foo' })
|
157
|
-
|
158
|
-
expect(result.messages).to eql(
|
159
|
-
address: { zipcode: ['must be an integer'] }
|
160
|
-
)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
RSpec.describe 'Macros #confirmation' do
|
2
|
-
describe 'with a maybe password with min-size specified' do
|
3
|
-
subject(:schema) do
|
4
|
-
Dry::Validation.Schema do
|
5
|
-
configure do
|
6
|
-
config.input_processor = :sanitizer
|
7
|
-
|
8
|
-
def self.messages
|
9
|
-
Messages.default.merge(
|
10
|
-
en: { errors: { password_confirmation: 'does not match' } }
|
11
|
-
)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
required(:password).maybe(min_size?: 3).confirmation
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'passes when values are equal' do
|
20
|
-
expect(schema.(password: 'foo', password_confirmation: 'foo')).to be_success
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'fails when source value is invalid' do
|
24
|
-
expect(schema.(password: 'fo', password_confirmation: nil).messages).to eql(
|
25
|
-
password: ['size cannot be less than 3']
|
26
|
-
)
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'fails when values are not equal' do
|
30
|
-
expect(schema.(password: 'foo', password_confirmation: 'fo').messages).to eql(
|
31
|
-
password_confirmation: ['does not match']
|
32
|
-
)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,268 +0,0 @@
|
|
1
|
-
RSpec.describe 'Macros #each' do
|
2
|
-
context "predicate without options" do
|
3
|
-
subject(:schema) do
|
4
|
-
Dry::Validation.Schema do
|
5
|
-
required(:foo).each(:filled?, :str?)
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
context 'with valid input' do
|
10
|
-
let(:input) { { foo: %w(a b c) } }
|
11
|
-
|
12
|
-
it 'is successful' do
|
13
|
-
expect(result).to be_successful
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
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"])
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
context 'with invalid input type' do
|
26
|
-
let(:input) { { foo: nil } }
|
27
|
-
|
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)
|
38
|
-
end
|
39
|
-
end
|
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"]
|
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
|
166
|
-
context 'with a nested schema' do
|
167
|
-
subject(:schema) do
|
168
|
-
Dry::Validation.Schema do
|
169
|
-
required(:songs).each do
|
170
|
-
schema do
|
171
|
-
required(:title).filled
|
172
|
-
required(:author).filled
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
it 'passes when all elements are valid' do
|
179
|
-
songs = [
|
180
|
-
{ title: 'Hello', author: 'Jane' },
|
181
|
-
{ title: 'World', author: 'Joe' }
|
182
|
-
]
|
183
|
-
|
184
|
-
expect(schema.(songs: songs)).to be_success
|
185
|
-
end
|
186
|
-
|
187
|
-
it 'fails when value is not an array' do
|
188
|
-
expect(schema.(songs: 'oops').messages).to eql(songs: ['must be an array'])
|
189
|
-
end
|
190
|
-
|
191
|
-
it 'fails when not all elements are valid' do
|
192
|
-
songs = [
|
193
|
-
{ title: 'Hello', author: 'Jane' },
|
194
|
-
{ title: nil, author: 'Joe' },
|
195
|
-
{ title: 'World', author: nil },
|
196
|
-
{ title: nil, author: nil }
|
197
|
-
]
|
198
|
-
|
199
|
-
expect(schema.(songs: songs).messages).to eql(
|
200
|
-
songs: {
|
201
|
-
1 => { title: ['must be filled'] },
|
202
|
-
2 => { author: ['must be filled'] },
|
203
|
-
3 => { title: ['must be filled'], author: ['must be filled'] }
|
204
|
-
}
|
205
|
-
)
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
context 'with inferred predicates and a form schema' do
|
211
|
-
context "predicate w/o options" do
|
212
|
-
subject(:schema) do
|
213
|
-
Dry::Validation.Params do
|
214
|
-
required(:songs).each(:str?)
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
it 'passes when all elements are valid' do
|
219
|
-
songs = %w(hello world)
|
220
|
-
|
221
|
-
expect(schema.(songs: songs)).to be_success
|
222
|
-
end
|
223
|
-
|
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
|
227
|
-
|
228
|
-
it 'fails when not all elements are valid' do
|
229
|
-
songs = ['hello', nil, 2]
|
230
|
-
|
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
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
context 'with a custom predicate' do
|
242
|
-
subject(:schema) do
|
243
|
-
Dry::Validation.Schema do
|
244
|
-
configure do
|
245
|
-
def self.messages
|
246
|
-
super.merge(en: { errors: { valid_content?: 'must have type key' }})
|
247
|
-
end
|
248
|
-
|
249
|
-
def valid_content?(content)
|
250
|
-
content.key?(:type)
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
required(:contents).each(:valid_content?)
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
it 'passes when all elements are valid' do
|
259
|
-
expect(schema.(contents: [{ type: 'foo' }, { type: 'bar' }]))
|
260
|
-
end
|
261
|
-
|
262
|
-
it 'fails when some elements are not valid' do
|
263
|
-
expect(schema.(contents: [{ type: 'foo' }, { oops: 'bar' }]).errors).to eql(
|
264
|
-
contents: { 1 => ['must have type key']}
|
265
|
-
)
|
266
|
-
end
|
267
|
-
end
|
268
|
-
end
|
@@ -1,87 +0,0 @@
|
|
1
|
-
RSpec.describe 'Macros #filled' do
|
2
|
-
describe 'with no args' do
|
3
|
-
subject(:schema) do
|
4
|
-
Dry::Validation.Schema do
|
5
|
-
required(:email).filled
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
it 'generates filled? rule' do
|
10
|
-
expect(schema.(email: '').messages).to eql(
|
11
|
-
email: ['must be filled']
|
12
|
-
)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
describe 'with a type specification' do
|
17
|
-
subject(:schema) do
|
18
|
-
Dry::Validation.Schema do
|
19
|
-
required(:age).filled(:int?)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'generates filled? & int? rule' do
|
24
|
-
expect(schema.(age: nil).messages).to eql(
|
25
|
-
age: ['must be filled']
|
26
|
-
)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe 'with a predicate with args' do
|
31
|
-
context 'with a flat arg' do
|
32
|
-
subject(:schema) do
|
33
|
-
Dry::Validation.Schema do
|
34
|
-
required(:age).filled(:int?, gt?: 18)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'generates filled? & int? & gt? rule' do
|
39
|
-
expect(schema.(age: nil).messages).to eql(
|
40
|
-
age: ['must be filled', 'must be greater than 18']
|
41
|
-
)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
context 'with a range arg' do
|
46
|
-
subject(:schema) do
|
47
|
-
Dry::Validation.Schema do
|
48
|
-
required(:age).filled(:int?, size?: 18..24)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'generates filled? & int? & size? rule' do
|
53
|
-
expect(schema.(age: nil).messages).to eql(
|
54
|
-
age: ['must be filled', 'size must be within 18 - 24']
|
55
|
-
)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
context 'with a block' do
|
60
|
-
subject(:schema) do
|
61
|
-
Dry::Validation.Schema do
|
62
|
-
required(:age).filled { int? & size?(18..24) }
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'generates filled? & int? & size? rule' do
|
67
|
-
expect(schema.(age: nil).messages).to eql(
|
68
|
-
age: ['must be filled', 'size must be within 18 - 24']
|
69
|
-
)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
context 'with a predicate and a block' do
|
74
|
-
subject(:schema) do
|
75
|
-
Dry::Validation.Schema do
|
76
|
-
required(:age).filled(:int?) { size?(18..24) }
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'generates filled? & int? & size? rule' do
|
81
|
-
expect(schema.(age: nil).messages).to eql(
|
82
|
-
age: ['must be filled', 'size must be within 18 - 24']
|
83
|
-
)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|