hash_validator 2.0.0 → 2.0.1
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/.github/workflows/ruby.yml +6 -1
- data/.rubocop.yml +340 -0
- data/Gemfile +3 -1
- data/README.md +2 -1
- data/Rakefile +6 -4
- data/hash_validator.gemspec +11 -5
- data/lib/hash_validator/base.rb +2 -0
- data/lib/hash_validator/configuration.rb +5 -3
- data/lib/hash_validator/validations/many.rb +2 -0
- data/lib/hash_validator/validations/multiple.rb +2 -0
- data/lib/hash_validator/validations/optional.rb +2 -0
- data/lib/hash_validator/validations.rb +5 -3
- data/lib/hash_validator/validators/alpha_validator.rb +5 -3
- data/lib/hash_validator/validators/alphanumeric_validator.rb +5 -3
- data/lib/hash_validator/validators/array_validator.rb +44 -48
- data/lib/hash_validator/validators/base.rb +6 -4
- data/lib/hash_validator/validators/boolean_validator.rb +3 -1
- data/lib/hash_validator/validators/class_validator.rb +3 -1
- data/lib/hash_validator/validators/digits_validator.rb +5 -3
- data/lib/hash_validator/validators/dynamic_func_validator.rb +8 -8
- data/lib/hash_validator/validators/dynamic_pattern_validator.rb +5 -3
- data/lib/hash_validator/validators/email_validator.rb +4 -2
- data/lib/hash_validator/validators/enumerable_validator.rb +4 -2
- data/lib/hash_validator/validators/hash_validator.rb +5 -3
- data/lib/hash_validator/validators/hex_color_validator.rb +5 -3
- data/lib/hash_validator/validators/ip_validator.rb +6 -4
- data/lib/hash_validator/validators/ipv4_validator.rb +5 -3
- data/lib/hash_validator/validators/ipv6_validator.rb +6 -4
- data/lib/hash_validator/validators/json_validator.rb +6 -4
- data/lib/hash_validator/validators/lambda_validator.rb +4 -2
- data/lib/hash_validator/validators/many_validator.rb +3 -1
- data/lib/hash_validator/validators/multiple_validator.rb +4 -2
- data/lib/hash_validator/validators/optional_validator.rb +3 -1
- data/lib/hash_validator/validators/presence_validator.rb +4 -2
- data/lib/hash_validator/validators/regex_validator.rb +4 -2
- data/lib/hash_validator/validators/simple_type_validators.rb +3 -1
- data/lib/hash_validator/validators/simple_validator.rb +2 -0
- data/lib/hash_validator/validators/url_validator.rb +6 -4
- data/lib/hash_validator/validators.rb +35 -33
- data/lib/hash_validator/version.rb +3 -1
- data/lib/hash_validator.rb +7 -5
- data/spec/configuration_spec.rb +76 -74
- data/spec/hash_validator_spec.rb +132 -113
- data/spec/hash_validator_spec_helper.rb +2 -0
- data/spec/spec_helper.rb +14 -4
- data/spec/validators/alpha_validator_spec.rb +43 -41
- data/spec/validators/alphanumeric_validator_spec.rb +44 -42
- data/spec/validators/array_spec.rb +102 -47
- data/spec/validators/base_spec.rb +25 -10
- data/spec/validators/boolean_spec.rb +15 -13
- data/spec/validators/class_spec.rb +20 -18
- data/spec/validators/digits_validator_spec.rb +46 -44
- data/spec/validators/dynamic_func_validator_spec.rb +90 -88
- data/spec/validators/dynamic_pattern_validator_spec.rb +65 -63
- data/spec/validators/email_spec.rb +15 -13
- data/spec/validators/hash_validator_spec.rb +39 -37
- data/spec/validators/hex_color_validator_spec.rb +49 -47
- data/spec/validators/in_enumerable_spec.rb +32 -30
- data/spec/validators/ip_validator_spec.rb +46 -44
- data/spec/validators/ipv4_validator_spec.rb +45 -43
- data/spec/validators/ipv6_validator_spec.rb +44 -42
- data/spec/validators/json_validator_spec.rb +38 -36
- data/spec/validators/lambda_spec.rb +20 -18
- data/spec/validators/many_spec.rb +25 -23
- data/spec/validators/multiple_spec.rb +13 -11
- data/spec/validators/optional_spec.rb +22 -20
- data/spec/validators/presence_spec.rb +16 -14
- data/spec/validators/regexp_spec.rb +14 -12
- data/spec/validators/simple_spec.rb +17 -15
- data/spec/validators/simple_types_spec.rb +21 -19
- data/spec/validators/url_validator_spec.rb +34 -32
- data/spec/validators/user_defined_spec.rb +29 -27
- metadata +59 -2
@@ -1,99 +1,101 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
describe HashValidator::Validator::DigitsValidator do
|
4
6
|
let(:validator) { HashValidator::Validator::DigitsValidator.new }
|
5
7
|
|
6
|
-
context
|
7
|
-
it
|
8
|
+
context "valid digit strings" do
|
9
|
+
it "validates single digit" do
|
8
10
|
errors = {}
|
9
|
-
validator.validate(
|
11
|
+
validator.validate("key", "1", {}, errors)
|
10
12
|
expect(errors).to be_empty
|
11
13
|
end
|
12
14
|
|
13
|
-
it
|
15
|
+
it "validates multiple digits" do
|
14
16
|
errors = {}
|
15
|
-
validator.validate(
|
17
|
+
validator.validate("key", "123", {}, errors)
|
16
18
|
expect(errors).to be_empty
|
17
19
|
end
|
18
20
|
|
19
|
-
it
|
21
|
+
it "validates zero" do
|
20
22
|
errors = {}
|
21
|
-
validator.validate(
|
23
|
+
validator.validate("key", "0", {}, errors)
|
22
24
|
expect(errors).to be_empty
|
23
25
|
end
|
24
26
|
|
25
|
-
it
|
27
|
+
it "validates long number strings" do
|
26
28
|
errors = {}
|
27
|
-
validator.validate(
|
29
|
+
validator.validate("key", "1234567890", {}, errors)
|
28
30
|
expect(errors).to be_empty
|
29
31
|
end
|
30
32
|
|
31
|
-
it
|
33
|
+
it "validates leading zeros" do
|
32
34
|
errors = {}
|
33
|
-
validator.validate(
|
35
|
+
validator.validate("key", "0123", {}, errors)
|
34
36
|
expect(errors).to be_empty
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
38
|
-
context
|
39
|
-
it
|
40
|
+
context "invalid digit strings" do
|
41
|
+
it "rejects non-string values" do
|
40
42
|
errors = {}
|
41
|
-
validator.validate(
|
42
|
-
expect(errors[
|
43
|
+
validator.validate("key", 123, {}, errors)
|
44
|
+
expect(errors["key"]).to eq("must contain only digits")
|
43
45
|
end
|
44
46
|
|
45
|
-
it
|
47
|
+
it "rejects nil values" do
|
46
48
|
errors = {}
|
47
|
-
validator.validate(
|
48
|
-
expect(errors[
|
49
|
+
validator.validate("key", nil, {}, errors)
|
50
|
+
expect(errors["key"]).to eq("must contain only digits")
|
49
51
|
end
|
50
52
|
|
51
|
-
it
|
53
|
+
it "rejects strings with letters" do
|
52
54
|
errors = {}
|
53
|
-
validator.validate(
|
54
|
-
expect(errors[
|
55
|
+
validator.validate("key", "123abc", {}, errors)
|
56
|
+
expect(errors["key"]).to eq("must contain only digits")
|
55
57
|
end
|
56
58
|
|
57
|
-
it
|
59
|
+
it "rejects strings with spaces" do
|
58
60
|
errors = {}
|
59
|
-
validator.validate(
|
60
|
-
expect(errors[
|
61
|
+
validator.validate("key", "123 456", {}, errors)
|
62
|
+
expect(errors["key"]).to eq("must contain only digits")
|
61
63
|
end
|
62
64
|
|
63
|
-
it
|
65
|
+
it "rejects strings with special characters" do
|
64
66
|
errors = {}
|
65
|
-
validator.validate(
|
66
|
-
expect(errors[
|
67
|
+
validator.validate("key", "123!", {}, errors)
|
68
|
+
expect(errors["key"]).to eq("must contain only digits")
|
67
69
|
end
|
68
70
|
|
69
|
-
it
|
71
|
+
it "rejects strings with hyphens" do
|
70
72
|
errors = {}
|
71
|
-
validator.validate(
|
72
|
-
expect(errors[
|
73
|
+
validator.validate("key", "123-456", {}, errors)
|
74
|
+
expect(errors["key"]).to eq("must contain only digits")
|
73
75
|
end
|
74
76
|
|
75
|
-
it
|
77
|
+
it "rejects strings with periods" do
|
76
78
|
errors = {}
|
77
|
-
validator.validate(
|
78
|
-
expect(errors[
|
79
|
+
validator.validate("key", "123.456", {}, errors)
|
80
|
+
expect(errors["key"]).to eq("must contain only digits")
|
79
81
|
end
|
80
82
|
|
81
|
-
it
|
83
|
+
it "rejects empty strings" do
|
82
84
|
errors = {}
|
83
|
-
validator.validate(
|
84
|
-
expect(errors[
|
85
|
+
validator.validate("key", "", {}, errors)
|
86
|
+
expect(errors["key"]).to eq("must contain only digits")
|
85
87
|
end
|
86
88
|
|
87
|
-
it
|
89
|
+
it "rejects negative signs" do
|
88
90
|
errors = {}
|
89
|
-
validator.validate(
|
90
|
-
expect(errors[
|
91
|
+
validator.validate("key", "-123", {}, errors)
|
92
|
+
expect(errors["key"]).to eq("must contain only digits")
|
91
93
|
end
|
92
94
|
|
93
|
-
it
|
95
|
+
it "rejects positive signs" do
|
94
96
|
errors = {}
|
95
|
-
validator.validate(
|
96
|
-
expect(errors[
|
97
|
+
validator.validate("key", "+123", {}, errors)
|
98
|
+
expect(errors["key"]).to eq("must contain only digits")
|
97
99
|
end
|
98
100
|
end
|
99
|
-
end
|
101
|
+
end
|
@@ -1,88 +1,90 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
describe HashValidator::Validator::DynamicFuncValidator do
|
4
|
-
describe
|
6
|
+
describe "Function-based validator" do
|
5
7
|
let(:odd_func_validator) do
|
6
8
|
HashValidator::Validator::DynamicFuncValidator.new(
|
7
|
-
|
9
|
+
"odd_func",
|
8
10
|
->(n) { n.is_a?(Integer) && n.odd? },
|
9
|
-
|
11
|
+
"is not an odd integer"
|
10
12
|
)
|
11
13
|
end
|
12
14
|
|
13
15
|
let(:range_validator) do
|
14
16
|
HashValidator::Validator::DynamicFuncValidator.new(
|
15
|
-
|
17
|
+
"in_range",
|
16
18
|
->(n) { n.is_a?(Numeric) && n >= 18 && n <= 65 },
|
17
|
-
|
19
|
+
"must be between 18 and 65"
|
18
20
|
)
|
19
21
|
end
|
20
22
|
|
21
23
|
let(:custom_validator) do
|
22
24
|
HashValidator::Validator::DynamicFuncValidator.new(
|
23
|
-
|
25
|
+
"custom",
|
24
26
|
proc { |v| v.to_s.length > 5 },
|
25
|
-
|
27
|
+
"must be longer than 5 characters"
|
26
28
|
)
|
27
29
|
end
|
28
30
|
|
29
31
|
let(:errors) { Hash.new }
|
30
32
|
|
31
|
-
describe
|
32
|
-
it
|
33
|
+
describe "#initialize" do
|
34
|
+
it "requires a callable object" do
|
33
35
|
expect {
|
34
|
-
HashValidator::Validator::DynamicFuncValidator.new(
|
35
|
-
}.to raise_error(ArgumentError,
|
36
|
+
HashValidator::Validator::DynamicFuncValidator.new("test", "not_callable")
|
37
|
+
}.to raise_error(ArgumentError, "Function must be callable (proc or lambda)")
|
36
38
|
end
|
37
39
|
|
38
|
-
it
|
40
|
+
it "accepts a lambda" do
|
39
41
|
validator = HashValidator::Validator::DynamicFuncValidator.new(
|
40
|
-
|
42
|
+
"test",
|
41
43
|
->(v) { true }
|
42
44
|
)
|
43
45
|
expect(validator.func).to respond_to(:call)
|
44
46
|
end
|
45
47
|
|
46
|
-
it
|
48
|
+
it "accepts a proc" do
|
47
49
|
validator = HashValidator::Validator::DynamicFuncValidator.new(
|
48
|
-
|
50
|
+
"test",
|
49
51
|
proc { |v| true }
|
50
52
|
)
|
51
53
|
expect(validator.func).to respond_to(:call)
|
52
54
|
end
|
53
55
|
|
54
|
-
it
|
56
|
+
it "accepts a custom error message" do
|
55
57
|
validator = HashValidator::Validator::DynamicFuncValidator.new(
|
56
|
-
|
58
|
+
"test",
|
57
59
|
->(v) { true },
|
58
|
-
|
60
|
+
"custom error"
|
59
61
|
)
|
60
|
-
expect(validator.error_message).to eq(
|
62
|
+
expect(validator.error_message).to eq("custom error")
|
61
63
|
end
|
62
64
|
|
63
|
-
it
|
65
|
+
it "uses default error message when none provided" do
|
64
66
|
validator = HashValidator::Validator::DynamicFuncValidator.new(
|
65
|
-
|
67
|
+
"test",
|
66
68
|
->(v) { true }
|
67
69
|
)
|
68
|
-
expect(validator.error_message).to eq(
|
70
|
+
expect(validator.error_message).to eq("test required")
|
69
71
|
end
|
70
72
|
end
|
71
73
|
|
72
|
-
describe
|
73
|
-
it
|
74
|
-
expect(odd_func_validator.should_validate?(
|
74
|
+
describe "#should_validate?" do
|
75
|
+
it "validates the correct name" do
|
76
|
+
expect(odd_func_validator.should_validate?("odd_func")).to eq true
|
75
77
|
end
|
76
78
|
|
77
|
-
it
|
78
|
-
expect(odd_func_validator.should_validate?(
|
79
|
-
expect(odd_func_validator.should_validate?(
|
79
|
+
it "does not validate other names" do
|
80
|
+
expect(odd_func_validator.should_validate?("even_func")).to eq false
|
81
|
+
expect(odd_func_validator.should_validate?("string")).to eq false
|
80
82
|
end
|
81
83
|
end
|
82
84
|
|
83
|
-
describe
|
84
|
-
context
|
85
|
-
it
|
85
|
+
describe "#validate" do
|
86
|
+
context "with odd number function" do
|
87
|
+
it "validates odd integers correctly" do
|
86
88
|
odd_func_validator.validate(:key, 1, {}, errors)
|
87
89
|
expect(errors).to be_empty
|
88
90
|
|
@@ -95,27 +97,27 @@ describe HashValidator::Validator::DynamicFuncValidator do
|
|
95
97
|
expect(errors).to be_empty
|
96
98
|
end
|
97
99
|
|
98
|
-
it
|
100
|
+
it "rejects even integers" do
|
99
101
|
odd_func_validator.validate(:key, 2, {}, errors)
|
100
|
-
expect(errors).to eq({ key:
|
102
|
+
expect(errors).to eq({ key: "is not an odd integer" })
|
101
103
|
|
102
104
|
errors.clear
|
103
105
|
odd_func_validator.validate(:key, 100, {}, errors)
|
104
|
-
expect(errors).to eq({ key:
|
106
|
+
expect(errors).to eq({ key: "is not an odd integer" })
|
105
107
|
end
|
106
108
|
|
107
|
-
it
|
109
|
+
it "rejects non-integers" do
|
108
110
|
odd_func_validator.validate(:key, 1.5, {}, errors)
|
109
|
-
expect(errors).to eq({ key:
|
111
|
+
expect(errors).to eq({ key: "is not an odd integer" })
|
110
112
|
|
111
113
|
errors.clear
|
112
|
-
odd_func_validator.validate(:key,
|
113
|
-
expect(errors).to eq({ key:
|
114
|
+
odd_func_validator.validate(:key, "1", {}, errors)
|
115
|
+
expect(errors).to eq({ key: "is not an odd integer" })
|
114
116
|
end
|
115
117
|
end
|
116
118
|
|
117
|
-
context
|
118
|
-
it
|
119
|
+
context "with range validator" do
|
120
|
+
it "validates numbers in range" do
|
119
121
|
range_validator.validate(:key, 18, {}, errors)
|
120
122
|
expect(errors).to be_empty
|
121
123
|
|
@@ -132,121 +134,121 @@ describe HashValidator::Validator::DynamicFuncValidator do
|
|
132
134
|
expect(errors).to be_empty
|
133
135
|
end
|
134
136
|
|
135
|
-
it
|
137
|
+
it "rejects numbers outside range" do
|
136
138
|
range_validator.validate(:key, 17, {}, errors)
|
137
|
-
expect(errors).to eq({ key:
|
139
|
+
expect(errors).to eq({ key: "must be between 18 and 65" })
|
138
140
|
|
139
141
|
errors.clear
|
140
142
|
range_validator.validate(:key, 66, {}, errors)
|
141
|
-
expect(errors).to eq({ key:
|
143
|
+
expect(errors).to eq({ key: "must be between 18 and 65" })
|
142
144
|
|
143
145
|
errors.clear
|
144
146
|
range_validator.validate(:key, -5, {}, errors)
|
145
|
-
expect(errors).to eq({ key:
|
147
|
+
expect(errors).to eq({ key: "must be between 18 and 65" })
|
146
148
|
end
|
147
149
|
|
148
|
-
it
|
149
|
-
range_validator.validate(:key,
|
150
|
-
expect(errors).to eq({ key:
|
150
|
+
it "rejects non-numeric values" do
|
151
|
+
range_validator.validate(:key, "twenty", {}, errors)
|
152
|
+
expect(errors).to eq({ key: "must be between 18 and 65" })
|
151
153
|
end
|
152
154
|
end
|
153
155
|
|
154
|
-
context
|
155
|
-
it
|
156
|
-
custom_validator.validate(:key,
|
156
|
+
context "with custom validator using proc" do
|
157
|
+
it "validates strings longer than 5 chars" do
|
158
|
+
custom_validator.validate(:key, "hello world", {}, errors)
|
157
159
|
expect(errors).to be_empty
|
158
160
|
|
159
161
|
errors.clear
|
160
|
-
custom_validator.validate(:key,
|
162
|
+
custom_validator.validate(:key, "testing", {}, errors)
|
161
163
|
expect(errors).to be_empty
|
162
164
|
end
|
163
165
|
|
164
|
-
it
|
165
|
-
custom_validator.validate(:key,
|
166
|
-
expect(errors).to eq({ key:
|
166
|
+
it "rejects strings 5 chars or shorter" do
|
167
|
+
custom_validator.validate(:key, "hello", {}, errors)
|
168
|
+
expect(errors).to eq({ key: "must be longer than 5 characters" })
|
167
169
|
|
168
170
|
errors.clear
|
169
|
-
custom_validator.validate(:key,
|
170
|
-
expect(errors).to eq({ key:
|
171
|
+
custom_validator.validate(:key, "hi", {}, errors)
|
172
|
+
expect(errors).to eq({ key: "must be longer than 5 characters" })
|
171
173
|
end
|
172
174
|
|
173
|
-
it
|
175
|
+
it "converts values to strings" do
|
174
176
|
custom_validator.validate(:key, 123456, {}, errors)
|
175
177
|
expect(errors).to be_empty
|
176
178
|
|
177
179
|
errors.clear
|
178
180
|
custom_validator.validate(:key, 12345, {}, errors)
|
179
|
-
expect(errors).to eq({ key:
|
181
|
+
expect(errors).to eq({ key: "must be longer than 5 characters" })
|
180
182
|
end
|
181
183
|
end
|
182
184
|
|
183
|
-
context
|
185
|
+
context "with function that raises errors" do
|
184
186
|
let(:error_func_validator) do
|
185
187
|
HashValidator::Validator::DynamicFuncValidator.new(
|
186
|
-
|
187
|
-
->(v) { raise
|
188
|
-
|
188
|
+
"error_func",
|
189
|
+
->(v) { raise "intentional error" },
|
190
|
+
"validation failed"
|
189
191
|
)
|
190
192
|
end
|
191
193
|
|
192
|
-
it
|
193
|
-
error_func_validator.validate(:key,
|
194
|
-
expect(errors).to eq({ key:
|
194
|
+
it "treats exceptions as validation failures" do
|
195
|
+
error_func_validator.validate(:key, "any value", {}, errors)
|
196
|
+
expect(errors).to eq({ key: "validation failed" })
|
195
197
|
end
|
196
198
|
end
|
197
199
|
end
|
198
200
|
|
199
|
-
describe
|
201
|
+
describe "Integration with HashValidator.add_validator" do
|
200
202
|
before do
|
201
|
-
HashValidator.add_validator(
|
202
|
-
func: ->(age) { age.is_a?(Integer) && age >= 18 },
|
203
|
-
error_message:
|
204
|
-
|
205
|
-
HashValidator.add_validator(
|
203
|
+
HashValidator.add_validator("adult_age",
|
204
|
+
func: ->(age) { age.is_a?(Integer) && age >= 18 },
|
205
|
+
error_message: "must be 18 or older")
|
206
|
+
|
207
|
+
HashValidator.add_validator("palindrome",
|
206
208
|
func: proc { |s| s.to_s == s.to_s.reverse },
|
207
|
-
error_message:
|
209
|
+
error_message: "must be a palindrome")
|
208
210
|
end
|
209
211
|
|
210
212
|
after do
|
211
|
-
HashValidator.remove_validator(
|
212
|
-
HashValidator.remove_validator(
|
213
|
+
HashValidator.remove_validator("adult_age")
|
214
|
+
HashValidator.remove_validator("palindrome")
|
213
215
|
end
|
214
216
|
|
215
|
-
it
|
217
|
+
it "can register lambda-based validators" do
|
216
218
|
validator = HashValidator.validate(
|
217
219
|
{ age: 25 },
|
218
|
-
{ age:
|
220
|
+
{ age: "adult_age" }
|
219
221
|
)
|
220
222
|
expect(validator.valid?).to eq true
|
221
223
|
expect(validator.errors).to be_empty
|
222
224
|
end
|
223
225
|
|
224
|
-
it
|
226
|
+
it "returns errors for invalid lambda validations" do
|
225
227
|
validator = HashValidator.validate(
|
226
228
|
{ age: 16 },
|
227
|
-
{ age:
|
229
|
+
{ age: "adult_age" }
|
228
230
|
)
|
229
231
|
expect(validator.valid?).to eq false
|
230
|
-
expect(validator.errors).to eq({ age:
|
232
|
+
expect(validator.errors).to eq({ age: "must be 18 or older" })
|
231
233
|
end
|
232
234
|
|
233
|
-
it
|
235
|
+
it "can register proc-based validators" do
|
234
236
|
validator = HashValidator.validate(
|
235
|
-
{ word:
|
236
|
-
{ word:
|
237
|
+
{ word: "racecar" },
|
238
|
+
{ word: "palindrome" }
|
237
239
|
)
|
238
240
|
expect(validator.valid?).to eq true
|
239
241
|
expect(validator.errors).to be_empty
|
240
242
|
end
|
241
243
|
|
242
|
-
it
|
244
|
+
it "returns errors for invalid proc validations" do
|
243
245
|
validator = HashValidator.validate(
|
244
|
-
{ word:
|
245
|
-
{ word:
|
246
|
+
{ word: "hello" },
|
247
|
+
{ word: "palindrome" }
|
246
248
|
)
|
247
249
|
expect(validator.valid?).to eq false
|
248
|
-
expect(validator.errors).to eq({ word:
|
250
|
+
expect(validator.errors).to eq({ word: "must be a palindrome" })
|
249
251
|
end
|
250
252
|
end
|
251
253
|
end
|
252
|
-
end
|
254
|
+
end
|