Passed
Push — main ( 2a46cd...12059c )
by Igor
01:41
created

test/constraints_test.go   B

Size/Duplication

Total Lines 230
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
cc 48
eloc 139
dl 0
loc 230
c 0
b 0
f 0
rs 8.5599
1
package test
2
3
import (
4
	"testing"
5
	"time"
6
7
	"github.com/muonsoft/validation"
8
	"github.com/muonsoft/validation/code"
9
	"github.com/muonsoft/validation/it"
10
	"github.com/muonsoft/validation/message"
11
	"github.com/muonsoft/validation/validator"
12
)
13
14
const (
15
	customMessage = "Custom message."
16
	customPath    = "properties[0].value"
17
18
	// Value types.
19
	boolType      = "bool"
20
	intType       = "int"
21
	floatType     = "float"
22
	stringType    = "string"
23
	iterableType  = "iterable"
24
	countableType = "countable"
25
	timeType      = "time"
26
)
27
28
type ConstraintValidationTestCase struct {
29
	name            string
30
	isApplicableFor func(valueType string) bool
31
	boolValue       *bool
32
	intValue        *int64
33
	floatValue      *float64
34
	stringValue     *string
35
	timeValue       *time.Time
36
	sliceValue      []string
37
	mapValue        map[string]string
38
	options         []validation.Option
39
	assert          func(t *testing.T, err error)
40
}
41
42
var validateTestCases = mergeTestCases(
43
	isNotBlankConstraintTestCases,
44
	isBlankConstraintTestCases,
45
	isNotNilConstraintTestCases,
46
	lengthConstraintTestCases,
47
	countConstraintTestCases,
48
)
49
50
func TestValidateBool(t *testing.T) {
51
	for _, test := range validateTestCases {
52
		if !test.isApplicableFor(boolType) {
53
			continue
54
		}
55
56
		t.Run(test.name, func(t *testing.T) {
57
			err := validator.ValidateBool(test.boolValue, test.options...)
58
59
			test.assert(t, err)
60
		})
61
	}
62
}
63
64
func TestValidateNumber_AsInt(t *testing.T) {
65
	for _, test := range validateTestCases {
66
		t.Run(test.name, func(t *testing.T) {
67
			err := validator.ValidateNumber(test.intValue, test.options...)
68
69
			if test.isApplicableFor(intType) {
70
				test.assert(t, err)
71
			} else {
72
				assertIsInapplicableConstraintError(t, err, "number")
73
			}
74
		})
75
	}
76
}
77
78
func TestValidateNumber_AsFloat(t *testing.T) {
79
	for _, test := range validateTestCases {
80
		t.Run(test.name, func(t *testing.T) {
81
			err := validator.ValidateNumber(test.floatValue, test.options...)
82
83
			if test.isApplicableFor(floatType) {
84
				test.assert(t, err)
85
			} else {
86
				assertIsInapplicableConstraintError(t, err, "number")
87
			}
88
		})
89
	}
90
}
91
92
func TestValidateString(t *testing.T) {
93
	for _, test := range validateTestCases {
94
		t.Run(test.name, func(t *testing.T) {
95
			err := validator.ValidateString(test.stringValue, test.options...)
96
97
			if test.isApplicableFor(stringType) {
98
				test.assert(t, err)
99
			} else {
100
				assertIsInapplicableConstraintError(t, err, stringType)
101
			}
102
		})
103
	}
104
}
105
106
func TestValidateIterable_AsSlice(t *testing.T) {
107
	for _, test := range validateTestCases {
108
		t.Run(test.name, func(t *testing.T) {
109
			err := validator.ValidateIterable(test.sliceValue, test.options...)
110
111
			if test.isApplicableFor(iterableType) {
112
				test.assert(t, err)
113
			} else {
114
				assertIsInapplicableConstraintError(t, err, iterableType)
115
			}
116
		})
117
	}
118
}
119
120
func TestValidateIterable_AsMap(t *testing.T) {
121
	for _, test := range validateTestCases {
122
		t.Run(test.name, func(t *testing.T) {
123
			err := validator.ValidateIterable(test.mapValue, test.options...)
124
125
			if test.isApplicableFor(iterableType) {
126
				test.assert(t, err)
127
			} else {
128
				assertIsInapplicableConstraintError(t, err, iterableType)
129
			}
130
		})
131
	}
132
}
133
134
func TestValidateCountable(t *testing.T) {
135
	for _, test := range validateTestCases {
136
		if !test.isApplicableFor(countableType) {
137
			continue
138
		}
139
140
		t.Run(test.name, func(t *testing.T) {
141
			err := validator.ValidateCountable(len(test.sliceValue), test.options...)
142
143
			if test.isApplicableFor(countableType) {
144
				test.assert(t, err)
145
			} else {
146
				assertIsInapplicableConstraintError(t, err, countableType)
147
			}
148
		})
149
	}
150
}
151
152
func TestValidateTime(t *testing.T) {
153
	for _, test := range validateTestCases {
154
		if !test.isApplicableFor(timeType) {
155
			continue
156
		}
157
158
		t.Run(test.name, func(t *testing.T) {
159
			err := validator.ValidateTime(test.timeValue, test.options...)
160
161
			if test.isApplicableFor(timeType) {
162
				test.assert(t, err)
163
			} else {
164
				assertIsInapplicableConstraintError(t, err, timeType)
165
			}
166
		})
167
	}
168
}
169
170
func TestValidateNil(t *testing.T) {
171
	tests := []struct {
172
		name          string
173
		nilConstraint validation.NilConstraint
174
		assert        func(t *testing.T, err error)
175
	}{
176
		{"not blank", it.IsNotBlank(), assertHasOneViolation(code.NotBlank, message.NotBlank, "")},
177
		{"not blank when true", it.IsNotBlank().When(true), assertHasOneViolation(code.NotBlank, message.NotBlank, "")},
178
		{"not blank when false", it.IsNotBlank().When(false), assertNoError},
179
		{"not blank when nil allowed", it.IsNotBlank().AllowNil(), assertNoError},
180
		{"blank", it.IsBlank(), assertNoError},
181
		{"blank when true", it.IsBlank().When(true), assertNoError},
182
		{"blank when false", it.IsBlank().When(false), assertNoError},
183
	}
184
	for _, test := range tests {
185
		t.Run(test.name, func(t *testing.T) {
186
			var v *bool
187
188
			err := validator.ValidateValue(v, test.nilConstraint)
189
190
			test.assert(t, err)
191
		})
192
	}
193
}
194
195
func anyValueType(valueType string) bool {
196
	return true
197
}
198
199
func specificValueTypes(types ...string) func(valueType string) bool {
200
	return func(valueType string) bool {
201
		for _, t := range types {
202
			if valueType == t {
203
				return true
204
			}
205
		}
206
207
		return false
208
	}
209
}
210
211
func exceptValueTypes(types ...string) func(valueType string) bool {
212
	return func(valueType string) bool {
213
		for _, t := range types {
214
			if valueType == t {
215
				return false
216
			}
217
		}
218
219
		return true
220
	}
221
}
222
223
func mergeTestCases(testCases ...[]ConstraintValidationTestCase) []ConstraintValidationTestCase {
224
	merged := make([]ConstraintValidationTestCase, 0)
225
226
	for _, testCase := range testCases {
227
		merged = append(merged, testCase...)
228
	}
229
230
	return merged
231
}
232