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.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +9 -6
  4. data/CHANGELOG.md +58 -0
  5. data/Gemfile +3 -3
  6. data/benchmarks/benchmark_form_invalid.rb +64 -0
  7. data/benchmarks/benchmark_form_valid.rb +64 -0
  8. data/benchmarks/profile_schema_call_invalid.rb +20 -0
  9. data/benchmarks/profile_schema_call_valid.rb +20 -0
  10. data/benchmarks/profile_schema_definition.rb +14 -0
  11. data/benchmarks/profile_schema_messages_invalid.rb +20 -0
  12. data/benchmarks/suite.rb +5 -0
  13. data/config/errors.yml +12 -5
  14. data/dry-validation.gemspec +2 -2
  15. data/examples/basic.rb +2 -2
  16. data/examples/form.rb +2 -2
  17. data/examples/json.rb +2 -2
  18. data/examples/nested.rb +6 -6
  19. data/lib/dry/validation.rb +22 -3
  20. data/lib/dry/validation/deprecations.rb +23 -0
  21. data/lib/dry/validation/error_compiler.rb +31 -11
  22. data/lib/dry/validation/error_compiler/input.rb +44 -57
  23. data/lib/dry/validation/hint_compiler.rb +15 -7
  24. data/lib/dry/validation/input_processor_compiler.rb +13 -6
  25. data/lib/dry/validation/input_processor_compiler/form.rb +2 -0
  26. data/lib/dry/validation/input_processor_compiler/sanitizer.rb +1 -1
  27. data/lib/dry/validation/messages/abstract.rb +9 -1
  28. data/lib/dry/validation/predicate_registry.rb +101 -0
  29. data/lib/dry/validation/result.rb +8 -1
  30. data/lib/dry/validation/schema.rb +110 -44
  31. data/lib/dry/validation/schema/check.rb +4 -2
  32. data/lib/dry/validation/schema/deprecated.rb +31 -0
  33. data/lib/dry/validation/schema/dsl.rb +18 -11
  34. data/lib/dry/validation/schema/form.rb +1 -0
  35. data/lib/dry/validation/schema/json.rb +1 -0
  36. data/lib/dry/validation/schema/key.rb +23 -10
  37. data/lib/dry/validation/schema/rule.rb +81 -20
  38. data/lib/dry/validation/schema/value.rb +110 -25
  39. data/lib/dry/validation/version.rb +1 -1
  40. data/spec/fixtures/locales/en.yml +1 -0
  41. data/spec/fixtures/locales/pl.yml +1 -1
  42. data/spec/integration/custom_error_messages_spec.rb +2 -2
  43. data/spec/integration/custom_predicates_spec.rb +98 -15
  44. data/spec/integration/error_compiler_spec.rb +111 -96
  45. data/spec/integration/form/predicates/array_spec.rb +243 -0
  46. data/spec/integration/form/predicates/empty_spec.rb +263 -0
  47. data/spec/integration/form/predicates/eql_spec.rb +327 -0
  48. data/spec/integration/form/predicates/even_spec.rb +455 -0
  49. data/spec/integration/form/predicates/excluded_from_spec.rb +455 -0
  50. data/spec/integration/form/predicates/excludes_spec.rb +391 -0
  51. data/spec/integration/form/predicates/false_spec.rb +455 -0
  52. data/spec/integration/form/predicates/filled_spec.rb +467 -0
  53. data/spec/integration/form/predicates/format_spec.rb +454 -0
  54. data/spec/integration/form/predicates/gt_spec.rb +519 -0
  55. data/spec/integration/form/predicates/gteq_spec.rb +519 -0
  56. data/spec/integration/form/predicates/included_in_spec.rb +455 -0
  57. data/spec/integration/form/predicates/includes_spec.rb +391 -0
  58. data/spec/integration/form/predicates/key_spec.rb +75 -0
  59. data/spec/integration/form/predicates/lt_spec.rb +519 -0
  60. data/spec/integration/form/predicates/lteq_spec.rb +519 -0
  61. data/spec/integration/form/predicates/max_size_spec.rb +391 -0
  62. data/spec/integration/form/predicates/min_size_spec.rb +391 -0
  63. data/spec/integration/form/predicates/none_spec.rb +265 -0
  64. data/spec/integration/form/predicates/not_eql_spec.rb +327 -0
  65. data/spec/integration/form/predicates/odd_spec.rb +455 -0
  66. data/spec/integration/form/predicates/size/fixed_spec.rb +399 -0
  67. data/spec/integration/form/predicates/size/range_spec.rb +398 -0
  68. data/spec/integration/form/predicates/true_spec.rb +455 -0
  69. data/spec/integration/form/predicates/type_spec.rb +391 -0
  70. data/spec/integration/hints_spec.rb +90 -4
  71. data/spec/integration/injecting_rules_spec.rb +2 -2
  72. data/spec/integration/localized_error_messages_spec.rb +2 -2
  73. data/spec/integration/messages/i18n_spec.rb +3 -3
  74. data/spec/integration/optional_keys_spec.rb +3 -3
  75. data/spec/integration/schema/array_schema_spec.rb +49 -13
  76. data/spec/integration/schema/check_rules_spec.rb +6 -6
  77. data/spec/integration/schema/check_with_nested_el_spec.rb +3 -3
  78. data/spec/integration/schema/check_with_nth_el_spec.rb +1 -1
  79. data/spec/integration/schema/each_with_set_spec.rb +3 -3
  80. data/spec/integration/schema/extending_dsl_spec.rb +27 -0
  81. data/spec/integration/schema/form/explicit_types_spec.rb +182 -0
  82. data/spec/integration/schema/form_spec.rb +90 -18
  83. data/spec/integration/schema/hash_schema_spec.rb +47 -0
  84. data/spec/integration/schema/inheriting_schema_spec.rb +4 -4
  85. data/spec/integration/schema/input_processor_spec.rb +8 -8
  86. data/spec/integration/schema/json/explicit_types_spec.rb +157 -0
  87. data/spec/integration/schema/json_spec.rb +18 -18
  88. data/spec/integration/schema/macros/confirmation_spec.rb +1 -1
  89. data/spec/integration/schema/macros/each_spec.rb +177 -43
  90. data/spec/integration/schema/macros/{required_spec.rb → filled_spec.rb} +34 -6
  91. data/spec/integration/schema/macros/input_spec.rb +21 -0
  92. data/spec/integration/schema/macros/maybe_spec.rb +39 -2
  93. data/spec/integration/schema/macros/value_spec.rb +105 -0
  94. data/spec/integration/schema/macros/when_spec.rb +28 -8
  95. data/spec/integration/schema/nested_values_spec.rb +11 -8
  96. data/spec/integration/schema/not_spec.rb +2 -2
  97. data/spec/integration/schema/numbers_spec.rb +1 -1
  98. data/spec/integration/schema/option_with_default_spec.rb +1 -1
  99. data/spec/integration/schema/predicate_verification_spec.rb +9 -0
  100. data/spec/integration/schema/predicates/array_spec.rb +295 -0
  101. data/spec/integration/schema/predicates/custom_spec.rb +103 -0
  102. data/spec/integration/schema/predicates/empty_spec.rb +263 -0
  103. data/spec/integration/schema/predicates/eql_spec.rb +327 -0
  104. data/spec/integration/schema/predicates/even_spec.rb +455 -0
  105. data/spec/integration/schema/predicates/excluded_from_spec.rb +455 -0
  106. data/spec/integration/schema/predicates/excludes_spec.rb +391 -0
  107. data/spec/integration/schema/predicates/filled_spec.rb +467 -0
  108. data/spec/integration/schema/predicates/format_spec.rb +455 -0
  109. data/spec/integration/schema/predicates/gt_spec.rb +519 -0
  110. data/spec/integration/schema/predicates/gteq_spec.rb +519 -0
  111. data/spec/integration/schema/predicates/hash_spec.rb +69 -0
  112. data/spec/integration/schema/predicates/included_in_spec.rb +455 -0
  113. data/spec/integration/schema/predicates/includes_spec.rb +391 -0
  114. data/spec/integration/schema/predicates/key_spec.rb +88 -0
  115. data/spec/integration/schema/predicates/lt_spec.rb +520 -0
  116. data/spec/integration/schema/predicates/lteq_spec.rb +519 -0
  117. data/spec/integration/schema/predicates/max_size_spec.rb +391 -0
  118. data/spec/integration/schema/predicates/min_size_spec.rb +391 -0
  119. data/spec/integration/schema/predicates/none_spec.rb +265 -0
  120. data/spec/integration/schema/predicates/not_eql_spec.rb +391 -0
  121. data/spec/integration/schema/predicates/odd_spec.rb +455 -0
  122. data/spec/integration/schema/predicates/size/fixed_spec.rb +401 -0
  123. data/spec/integration/schema/predicates/size/range_spec.rb +399 -0
  124. data/spec/integration/schema/predicates/type_spec.rb +391 -0
  125. data/spec/integration/schema/reusing_schema_spec.rb +4 -4
  126. data/spec/integration/schema/using_types_spec.rb +24 -6
  127. data/spec/integration/schema/xor_spec.rb +2 -2
  128. data/spec/integration/schema_builders_spec.rb +15 -0
  129. data/spec/integration/schema_spec.rb +37 -12
  130. data/spec/shared/predicate_helper.rb +13 -0
  131. data/spec/spec_helper.rb +10 -0
  132. data/spec/support/matchers.rb +38 -0
  133. data/spec/support/predicates_integration.rb +7 -0
  134. data/spec/unit/hint_compiler_spec.rb +10 -8
  135. data/spec/unit/input_processor_compiler/form_spec.rb +45 -43
  136. data/spec/unit/input_processor_compiler/json_spec.rb +37 -35
  137. data/spec/unit/predicate_registry_spec.rb +34 -0
  138. data/spec/unit/schema/key_spec.rb +12 -14
  139. data/spec/unit/schema/rule_spec.rb +4 -2
  140. data/spec/unit/schema/value_spec.rb +38 -121
  141. metadata +150 -16
  142. data/lib/dry/validation/schema/attr.rb +0 -15
  143. data/spec/integration/attr_spec.rb +0 -122
@@ -0,0 +1,391 @@
1
+ RSpec.describe 'Predicates: Includes' do
2
+ context 'with required' do
3
+ subject(:schema) do
4
+ Dry::Validation.Schema do
5
+ required(:foo) { includes?(1) }
6
+ end
7
+ end
8
+
9
+ context 'with valid input' do
10
+ let(:input) { { foo: [1, 2, 3] } }
11
+
12
+ it 'is successful' do
13
+ expect(result).to be_successful
14
+ end
15
+ end
16
+
17
+ context 'with missing input' do
18
+ let(:input) { {} }
19
+
20
+ it 'is not successful' do
21
+ expect(result).to be_failing ['is missing', 'must include 1']
22
+ end
23
+ end
24
+
25
+ context 'with nil input' do
26
+ let(:input) { { foo: nil } }
27
+
28
+ it 'is not successful' do
29
+ expect(result).to be_failing ['must include 1']
30
+ end
31
+ end
32
+
33
+ context 'with blank input' do
34
+ let(:input) { { foo: '' } }
35
+
36
+ it 'is not successful' do
37
+ expect(result).to be_failing ['must include 1']
38
+ end
39
+ end
40
+
41
+ context 'with invalid input' do
42
+ let(:input) { { foo: [2, 3, 4] } }
43
+
44
+ it 'is not successful' do
45
+ expect(result).to be_failing ['must include 1']
46
+ end
47
+ end
48
+ end
49
+
50
+ context 'with optional' do
51
+ subject(:schema) do
52
+ Dry::Validation.Schema do
53
+ optional(:foo) { includes?(1) }
54
+ end
55
+ end
56
+
57
+ context 'with valid input' do
58
+ let(:input) { { foo: [1, 2, 3] } }
59
+
60
+ it 'is successful' do
61
+ expect(result).to be_successful
62
+ end
63
+ end
64
+
65
+ context 'with missing input' do
66
+ let(:input) { {} }
67
+
68
+ it 'is successful' do
69
+ expect(result).to be_successful
70
+ end
71
+ end
72
+
73
+ context 'with nil input' do
74
+ let(:input) { { foo: nil } }
75
+
76
+ it 'is not successful' do
77
+ expect(result).to be_failing ['must include 1']
78
+ end
79
+ end
80
+
81
+ context 'with blank input' do
82
+ let(:input) { { foo: '' } }
83
+
84
+ it 'is not successful' do
85
+ expect(result).to be_failing ['must include 1']
86
+ end
87
+ end
88
+
89
+ context 'with invalid input' do
90
+ let(:input) { { foo: [2, 3, 4] } }
91
+
92
+ it 'is not successful' do
93
+ expect(result).to be_failing ['must include 1']
94
+ end
95
+ end
96
+ end
97
+
98
+ context 'as macro' do
99
+ context 'with required' do
100
+ context 'with value' do
101
+ subject(:schema) do
102
+ Dry::Validation.Schema do
103
+ required(:foo).value(includes?: 1)
104
+ end
105
+ end
106
+
107
+ context 'with valid input' do
108
+ let(:input) { { foo: [1, 2, 3] } }
109
+
110
+ it 'is successful' do
111
+ expect(result).to be_successful
112
+ end
113
+ end
114
+
115
+ context 'with missing input' do
116
+ let(:input) { {} }
117
+
118
+ it 'is not successful' do
119
+ expect(result).to be_failing ['is missing', 'must include 1']
120
+ end
121
+ end
122
+
123
+ context 'with nil input' do
124
+ let(:input) { { foo: nil } }
125
+
126
+ it 'is not successful' do
127
+ expect(result).to be_failing ['must include 1']
128
+ end
129
+ end
130
+
131
+ context 'with blank input' do
132
+ let(:input) { { foo: '' } }
133
+
134
+ it 'is successful' do
135
+ expect(result).to be_failing ['must include 1']
136
+ end
137
+ end
138
+
139
+ context 'with invalid input' do
140
+ let(:input) { { foo: [2, 3, 4] } }
141
+
142
+ it 'is not successful' do
143
+ expect(result).to be_failing ['must include 1']
144
+ end
145
+ end
146
+ end
147
+
148
+ context 'with filled' do
149
+ subject(:schema) do
150
+ Dry::Validation.Schema do
151
+ required(:foo).filled(includes?: 1)
152
+ end
153
+ end
154
+
155
+ context 'with valid input' do
156
+ let(:input) { { foo: [1, 2, 3] } }
157
+
158
+ it 'is successful' do
159
+ expect(result).to be_successful
160
+ end
161
+ end
162
+
163
+ context 'with missing input' do
164
+ let(:input) { {} }
165
+
166
+ it 'is not successful' do
167
+ expect(result).to be_failing ['is missing', 'must include 1']
168
+ end
169
+ end
170
+
171
+ context 'with nil input' do
172
+ let(:input) { { foo: nil } }
173
+
174
+ it 'is not successful' do
175
+ expect(result).to be_failing ['must be filled', 'must include 1']
176
+ end
177
+ end
178
+
179
+ context 'with blank input' do
180
+ let(:input) { { foo: '' } }
181
+
182
+ it 'is not successful' do
183
+ expect(result).to be_failing ['must be filled', 'must include 1']
184
+ end
185
+ end
186
+
187
+ context 'with invalid input' do
188
+ let(:input) { { foo: [2, 3, 4] } }
189
+
190
+ it 'is not successful' do
191
+ expect(result).to be_failing ['must include 1']
192
+ end
193
+ end
194
+ end
195
+
196
+ context 'with maybe' do
197
+ subject(:schema) do
198
+ Dry::Validation.Schema do
199
+ required(:foo).maybe(includes?: 1)
200
+ end
201
+ end
202
+
203
+ context 'with valid input' do
204
+ let(:input) { { foo: [1, 2, 3] } }
205
+
206
+ it 'is successful' do
207
+ expect(result).to be_successful
208
+ end
209
+ end
210
+
211
+ context 'with missing input' do
212
+ let(:input) { {} }
213
+
214
+ it 'is not successful' do
215
+ expect(result).to be_failing ['is missing', 'must include 1']
216
+ end
217
+ end
218
+
219
+ context 'with nil input' do
220
+ let(:input) { { foo: nil } }
221
+
222
+ it 'is successful' do
223
+ expect(result).to be_successful
224
+ end
225
+ end
226
+
227
+ context 'with blank input' do
228
+ let(:input) { { foo: '' } }
229
+
230
+ it 'is successful' do
231
+ expect(result).to be_failing ['must include 1']
232
+ end
233
+ end
234
+
235
+ context 'with invalid input' do
236
+ let(:input) { { foo: [2, 3, 4] } }
237
+
238
+ it 'is not successful' do
239
+ expect(result).to be_failing ['must include 1']
240
+ end
241
+ end
242
+ end
243
+ end
244
+
245
+ context 'with optional' do
246
+ context 'with value' do
247
+ subject(:schema) do
248
+ Dry::Validation.Schema do
249
+ optional(:foo).value(includes?: 1)
250
+ end
251
+ end
252
+
253
+ context 'with valid input' do
254
+ let(:input) { { foo: [1, 2, 3] } }
255
+
256
+ it 'is successful' do
257
+ expect(result).to be_successful
258
+ end
259
+ end
260
+
261
+ context 'with missing input' do
262
+ let(:input) { {} }
263
+
264
+ it 'is successful' do
265
+ expect(result).to be_successful
266
+ end
267
+ end
268
+
269
+ context 'with nil input' do
270
+ let(:input) { { foo: nil } }
271
+
272
+ it 'is not successful' do
273
+ expect(result).to be_failing ['must include 1']
274
+ end
275
+ end
276
+
277
+ context 'with blank input' do
278
+ let(:input) { { foo: '' } }
279
+
280
+ it 'is successful' do
281
+ expect(result).to be_failing ['must include 1']
282
+ end
283
+ end
284
+
285
+ context 'with invalid input' do
286
+ let(:input) { { foo: [2, 3, 4] } }
287
+
288
+ it 'is not successful' do
289
+ expect(result).to be_failing ['must include 1']
290
+ end
291
+ end
292
+ end
293
+
294
+ context 'with filled' do
295
+ subject(:schema) do
296
+ Dry::Validation.Schema do
297
+ optional(:foo).filled(includes?: 1)
298
+ end
299
+ end
300
+
301
+ context 'with valid input' do
302
+ let(:input) { { foo: [1, 2, 3] } }
303
+
304
+ it 'is successful' do
305
+ expect(result).to be_successful
306
+ end
307
+ end
308
+
309
+ context 'with missing input' do
310
+ let(:input) { {} }
311
+
312
+ it 'is successful' do
313
+ expect(result).to be_successful
314
+ end
315
+ end
316
+
317
+ context 'with nil input' do
318
+ let(:input) { { foo: nil } }
319
+
320
+ it 'is not successful' do
321
+ expect(result).to be_failing ['must be filled', 'must include 1']
322
+ end
323
+ end
324
+
325
+ context 'with blank input' do
326
+ let(:input) { { foo: '' } }
327
+
328
+ it 'is not successful' do
329
+ expect(result).to be_failing ['must be filled', 'must include 1']
330
+ end
331
+ end
332
+
333
+ context 'with invalid input' do
334
+ let(:input) { { foo: [2, 3, 4] } }
335
+
336
+ it 'is not successful' do
337
+ expect(result).to be_failing ['must include 1']
338
+ end
339
+ end
340
+ end
341
+
342
+ context 'with maybe' do
343
+ subject(:schema) do
344
+ Dry::Validation.Schema do
345
+ optional(:foo).maybe(includes?: 1)
346
+ end
347
+ end
348
+
349
+ context 'with valid input' do
350
+ let(:input) { { foo: [1, 2, 3] } }
351
+
352
+ it 'is successful' do
353
+ expect(result).to be_successful
354
+ end
355
+ end
356
+
357
+ context 'with missing input' do
358
+ let(:input) { {} }
359
+
360
+ it 'is successful' do
361
+ expect(result).to be_successful
362
+ end
363
+ end
364
+
365
+ context 'with nil input' do
366
+ let(:input) { { foo: nil } }
367
+
368
+ it 'is successful' do
369
+ expect(result).to be_successful
370
+ end
371
+ end
372
+
373
+ context 'with blank input' do
374
+ let(:input) { { foo: '' } }
375
+
376
+ it 'is not successful' do
377
+ expect(result).to be_failing ['must include 1']
378
+ end
379
+ end
380
+
381
+ context 'with invalid input' do
382
+ let(:input) { { foo: [2, 3, 4] } }
383
+
384
+ it 'is not successful' do
385
+ expect(result).to be_failing ['must include 1']
386
+ end
387
+ end
388
+ end
389
+ end
390
+ end
391
+ end
@@ -0,0 +1,88 @@
1
+ #see: https://github.com/dry-rb/dry-validation/issues/127
2
+ RSpec.describe 'Predicates: Key' do
3
+ context 'inferred from required/optional macros' do
4
+ subject(:schema) do
5
+ Dry::Validation.Schema do
6
+ required(:foo).value(:str?)
7
+ optional(:bar).value(:int?)
8
+ end
9
+ end
10
+
11
+ it 'uses key? predicate for required' do
12
+ expect(schema.({}).messages(full: true)).to eql(foo: ['foo is missing'])
13
+ expect(schema.({}).messages).to eql(foo: ['is missing'])
14
+ end
15
+ end
16
+
17
+ context 'with required' do
18
+ it "should raise error" do
19
+ expect { Dry::Validation.Schema do
20
+ required(:foo) { key? }
21
+ end }.to raise_error InvalidSchemaError
22
+ end
23
+ end
24
+
25
+ context 'with optional' do
26
+ subject(:schema) do
27
+ it "should raise error" do
28
+ expect { Dry::Validation.Schema do
29
+ optional(:foo) { key? }
30
+ end }.to raise_error InvalidSchemaError
31
+ end
32
+ end
33
+ end
34
+
35
+ context 'as macro' do
36
+ context 'with required' do
37
+ context 'with value' do
38
+ it "should raise error" do
39
+ expect { Dry::Validation.Schema do
40
+ required(:foo).value(:key?)
41
+ end }.to raise_error InvalidSchemaError
42
+ end
43
+ end
44
+
45
+ context 'with filled' do
46
+ it "should raise error" do
47
+ expect { Dry::Validation.Schema do
48
+ required(:foo).filled(:key?)
49
+ end }.to raise_error InvalidSchemaError
50
+ end
51
+ end
52
+
53
+ context 'with maybe' do
54
+ it "should raise error" do
55
+ expect { Dry::Validation.Schema do
56
+ required(:foo).maybe(:key?)
57
+ end }.to raise_error InvalidSchemaError
58
+ end
59
+ end
60
+ end
61
+
62
+ context 'with optional' do
63
+ context 'with value' do
64
+ it "should raise error" do
65
+ expect { Dry::Validation.Schema do
66
+ optional(:foo).value(:key?)
67
+ end }.to raise_error InvalidSchemaError
68
+ end
69
+ end
70
+
71
+ context 'with filled' do
72
+ it "should raise error" do
73
+ expect { Dry::Validation.Schema do
74
+ optional(:foo).filled(:key?)
75
+ end }.to raise_error InvalidSchemaError
76
+ end
77
+ end
78
+
79
+ context 'with maybe' do
80
+ it "should raise error" do
81
+ expect { Dry::Validation.Schema do
82
+ optional(:foo).maybe(:key?)
83
+ end }.to raise_error InvalidSchemaError
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end