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,454 @@
1
+ RSpec.describe 'Predicates: Format' do
2
+ context 'with required' do
3
+ subject(:schema) do
4
+ Dry::Validation.Form do
5
+ required(:foo) { str? & format?(/bar/) }
6
+ end
7
+ end
8
+
9
+ context 'with valid input' do
10
+ let(:input) { { 'foo' => 'bar baz' } }
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', 'is in invalid format']
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 be a string', 'is in invalid format']
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 ['is in invalid format']
38
+ end
39
+ end
40
+
41
+ context 'with invalid type' do
42
+ let(:input) { { 'foo' => { 'a' => '1' } } }
43
+
44
+ it 'raises error' do
45
+ expect(result).to be_failing ['must be a string', 'is in invalid format']
46
+ end
47
+ end
48
+
49
+ context 'with invalid input' do
50
+ let(:input) { { 'foo' => 'wat' } }
51
+
52
+ it 'is not successful' do
53
+ expect(result).to be_failing ['is in invalid format']
54
+ end
55
+ end
56
+ end
57
+
58
+ context 'with optional' do
59
+ subject(:schema) do
60
+ Dry::Validation.Form do
61
+ optional(:foo) { str? & format?(/bar/) }
62
+ end
63
+ end
64
+
65
+ context 'with valid input' do
66
+ let(:input) { { 'foo' => 'bar baz' } }
67
+
68
+ it 'is successful' do
69
+ expect(result).to be_successful
70
+ end
71
+ end
72
+
73
+ context 'with missing input' do
74
+ let(:input) { {} }
75
+
76
+ it 'is successful' do
77
+ expect(result).to be_successful
78
+ end
79
+ end
80
+
81
+ context 'with nil input' do
82
+ let(:input) { { 'foo' => nil } }
83
+
84
+ it 'is not successful' do
85
+ expect(result).to be_failing ["must be a string", "is in invalid format"]
86
+ end
87
+ end
88
+
89
+ context 'with blank input' do
90
+ let(:input) { { 'foo' => '' } }
91
+
92
+ it 'is not successful' do
93
+ expect(result).to be_failing ['is in invalid format']
94
+ end
95
+ end
96
+
97
+ context 'with invalid type' do
98
+ let(:input) { { 'foo' => { 'a' => '1' } } }
99
+
100
+ it 'raises error' do
101
+ expect(result).to be_failing ['must be a string', 'is in invalid format']
102
+ end
103
+ end
104
+
105
+ context 'with invalid input' do
106
+ let(:input) { { 'foo' => 'wat' } }
107
+
108
+ it 'is not successful' do
109
+ expect(result).to be_failing ['is in invalid format']
110
+ end
111
+ end
112
+ end
113
+
114
+ context 'as macro' do
115
+ context 'with required' do
116
+ context 'with value' do
117
+ subject(:schema) do
118
+ Dry::Validation.Form do
119
+ required(:foo).value(:str?, format?: /bar/)
120
+ end
121
+ end
122
+
123
+ context 'with valid input' do
124
+ let(:input) { { 'foo' => 'bar baz' } }
125
+
126
+ it 'is successful' do
127
+ expect(result).to be_successful
128
+ end
129
+ end
130
+
131
+ context 'with missing input' do
132
+ let(:input) { {} }
133
+
134
+ it 'is not successful' do
135
+ expect(result).to be_failing ['is missing', 'is in invalid format']
136
+ end
137
+ end
138
+
139
+ context 'with nil input' do
140
+ let(:input) { { 'foo' => nil } }
141
+
142
+ it 'is not successful' do
143
+ expect(result).to be_failing ['must be a string', 'is in invalid format']
144
+ end
145
+ end
146
+
147
+ context 'with blank input' do
148
+ let(:input) { { 'foo' => '' } }
149
+
150
+ it 'is not successful' do
151
+ expect(result).to be_failing ['is in invalid format']
152
+ end
153
+ end
154
+
155
+ context 'with invalid type' do
156
+ let(:input) { { 'foo' => { 'a' => '1' } } }
157
+
158
+ it 'raises error' do
159
+ expect(result).to be_failing ['must be a string', 'is in invalid format']
160
+ end
161
+ end
162
+
163
+ context 'with invalid input' do
164
+ let(:input) { { 'foo' => 'wat' } }
165
+
166
+ it 'is not successful' do
167
+ expect(result).to be_failing ['is in invalid format']
168
+ end
169
+ end
170
+ end
171
+
172
+ context 'with filled' do
173
+ subject(:schema) do
174
+ Dry::Validation.Form do
175
+ required(:foo).filled(:str?, format?: /bar/)
176
+ end
177
+ end
178
+
179
+ context 'with valid input' do
180
+ let(:input) { { 'foo' => 'bar baz' } }
181
+
182
+ it 'is successful' do
183
+ expect(result).to be_successful
184
+ end
185
+ end
186
+
187
+ context 'with missing input' do
188
+ let(:input) { {} }
189
+
190
+ it 'is not successful' do
191
+ expect(result).to be_failing ['is missing', 'is in invalid format']
192
+ end
193
+ end
194
+
195
+ context 'with nil input' do
196
+ let(:input) { { 'foo' => nil } }
197
+
198
+ it 'is not successful' do
199
+ expect(result).to be_failing ['must be filled', 'is in invalid format']
200
+ end
201
+ end
202
+
203
+ context 'with blank input' do
204
+ let(:input) { { 'foo' => '' } }
205
+
206
+ it 'is not successful' do
207
+ expect(result).to be_failing ['must be filled', 'is in invalid format']
208
+ end
209
+ end
210
+
211
+ context 'with invalid type' do
212
+ let(:input) { { 'foo' => { 'a' => '1' } } }
213
+
214
+ it 'raises error' do
215
+ expect(result).to be_failing ["must be a string", "is in invalid format"]
216
+ end
217
+ end
218
+
219
+ context 'with invalid input' do
220
+ let(:input) { { 'foo' => 'wat' } }
221
+
222
+ it 'is not successful' do
223
+ expect(result).to be_failing ['is in invalid format']
224
+ end
225
+ end
226
+ end
227
+
228
+ context 'with maybe' do
229
+ subject(:schema) do
230
+ Dry::Validation.Form do
231
+ required(:foo).maybe(:str?, format?: /bar/)
232
+ end
233
+ end
234
+
235
+ context 'with valid input' do
236
+ let(:input) { { 'foo' => 'bar baz' } }
237
+
238
+ it 'is successful' do
239
+ expect(result).to be_successful
240
+ end
241
+ end
242
+
243
+ context 'with missing input' do
244
+ let(:input) { {} }
245
+
246
+ it 'is not successful' do
247
+ expect(result).to be_failing ['is missing', 'is in invalid format']
248
+ end
249
+ end
250
+
251
+ context 'with nil input' do
252
+ let(:input) { { 'foo' => nil } }
253
+
254
+ it 'is successful' do
255
+ expect(result).to be_successful
256
+ end
257
+ end
258
+
259
+ context 'with blank input' do
260
+ let(:input) { { 'foo' => '' } }
261
+ it 'is not successful' do
262
+ expect(result).to be_success
263
+ end
264
+ end
265
+
266
+ context 'with invalid type' do
267
+ let(:input) { { 'foo' => { 'a' => '1' } } }
268
+
269
+ it 'is not successful' do
270
+ expect(result).to be_failing ['must be a string', 'is in invalid format']
271
+ end
272
+ end
273
+
274
+ context 'with invalid input' do
275
+ let(:input) { { 'foo' => 'wat' } }
276
+
277
+ it 'is not successful' do
278
+ expect(result).to be_failing ['is in invalid format']
279
+ end
280
+ end
281
+ end
282
+ end
283
+
284
+ context 'with optional' do
285
+ context 'with value' do
286
+ subject(:schema) do
287
+ Dry::Validation.Form do
288
+ optional(:foo).value(:str?, format?: /bar/)
289
+ end
290
+ end
291
+
292
+ context 'with valid input' do
293
+ let(:input) { { 'foo' => 'bar baz' } }
294
+
295
+ it 'is successful' do
296
+ expect(result).to be_successful
297
+ end
298
+ end
299
+
300
+ context 'with missing input' do
301
+ let(:input) { {} }
302
+
303
+ it 'is successful' do
304
+ expect(result).to be_successful
305
+ end
306
+ end
307
+
308
+ context 'with nil input' do
309
+ let(:input) { { 'foo' => nil } }
310
+
311
+ it 'is not successful' do
312
+ expect(result).to be_failing ['must be a string', 'is in invalid format']
313
+ end
314
+ end
315
+
316
+ context 'with blank input' do
317
+ let(:input) { { 'foo' => '' } }
318
+
319
+ it 'is not successful' do
320
+ expect(result).to be_failing ['is in invalid format']
321
+ end
322
+ end
323
+
324
+ context 'with invalid type' do
325
+ let(:input) { { 'foo' => { 'a' => '1' } } }
326
+
327
+ it 'raises error' do
328
+ expect(result).to be_failing ['must be a string', 'is in invalid format']
329
+ end
330
+ end
331
+
332
+ context 'with invalid input' do
333
+ let(:input) { { 'foo' => 'wat' } }
334
+
335
+ it 'is not successful' do
336
+ expect(result).to be_failing ['is in invalid format']
337
+ end
338
+ end
339
+ end
340
+
341
+ context 'with filled' do
342
+ subject(:schema) do
343
+ Dry::Validation.Form do
344
+ optional(:foo).filled(:str?, format?: /bar/)
345
+ end
346
+ end
347
+
348
+ context 'with valid input' do
349
+ let(:input) { { 'foo' => 'bar baz' } }
350
+
351
+ it 'is successful' do
352
+ expect(result).to be_successful
353
+ end
354
+ end
355
+
356
+ context 'with missing input' do
357
+ let(:input) { {} }
358
+
359
+ it 'is successful' do
360
+ expect(result).to be_successful
361
+ end
362
+ end
363
+
364
+ context 'with nil input' do
365
+ let(:input) { { 'foo' => nil } }
366
+
367
+ it 'is not successful' do
368
+ expect(result).to be_failing ['must be filled', 'is in invalid format']
369
+ end
370
+ end
371
+
372
+ context 'with blank input' do
373
+ let(:input) { { 'foo' => '' } }
374
+
375
+ it 'is not successful' do
376
+ expect(result).to be_failing ['must be filled', 'is in invalid format']
377
+ end
378
+ end
379
+
380
+ context 'with invalid type' do
381
+ let(:input) { { 'foo' => { 'a' => '1' } } }
382
+
383
+ it 'raises error' do
384
+ expect(result).to be_failing ['must be a string', 'is in invalid format']
385
+ end
386
+ end
387
+
388
+ context 'with invalid input' do
389
+ let(:input) { { 'foo' => 'wat' } }
390
+
391
+ it 'is not successful' do
392
+ expect(result).to be_failing ['is in invalid format']
393
+ end
394
+ end
395
+ end
396
+
397
+ context 'with maybe' do
398
+ subject(:schema) do
399
+ Dry::Validation.Form do
400
+ optional(:foo).maybe(:str?, format?: /bar/)
401
+ end
402
+ end
403
+
404
+ context 'with valid input' do
405
+ let(:input) { { 'foo' => 'bar baz' } }
406
+
407
+ it 'is successful' do
408
+ expect(result).to be_successful
409
+ end
410
+ end
411
+
412
+ context 'with missing input' do
413
+ let(:input) { {} }
414
+
415
+ it 'is successful' do
416
+ expect(result).to be_successful
417
+ end
418
+ end
419
+
420
+ context 'with nil input' do
421
+ let(:input) { { 'foo' => nil } }
422
+
423
+ it 'is successful' do
424
+ expect(result).to be_successful
425
+ end
426
+ end
427
+
428
+ context 'with blank input' do
429
+ let(:input) { { 'foo' => '' } }
430
+
431
+ it 'is successful' do
432
+ expect(result).to be_successful
433
+ end
434
+ end
435
+
436
+ context 'with invalid type' do
437
+ let(:input) { { 'foo' => { 'a' => '1' } } }
438
+
439
+ it 'raises error' do
440
+ expect(result).to be_failing ['must be a string', 'is in invalid format']
441
+ end
442
+ end
443
+
444
+ context 'with invalid input' do
445
+ let(:input) { { 'foo' => 'wat' } }
446
+
447
+ it 'is not successful' do
448
+ expect(result).to be_failing ['is in invalid format']
449
+ end
450
+ end
451
+ end
452
+ end
453
+ end
454
+ end