Test Failed
Push — main ( 7dfe2c...03ceef )
by Igor
01:04 queued 12s
created

it.CountConstraint.WithExactError   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
dl 0
loc 3
ccs 1
cts 1
cp 1
crap 1
rs 10
c 0
b 0
f 0
nop 1
1
package it
2
3
import (
4
	"context"
5
	"strconv"
6
7
	"github.com/muonsoft/validation"
8
)
9
10
// CountConstraint checks that a given collection's (array, slice or a map) length is between some minimum and
11
// maximum value.
12
type CountConstraint struct {
13
	isIgnored              bool
14
	checkMin               bool
15
	checkMax               bool
16
	min                    int
17
	max                    int
18
	groups                 []string
19
	minErr                 error
20
	maxErr                 error
21
	exactErr               error
22
	minMessageTemplate     string
23
	minMessageParameters   validation.TemplateParameterList
24
	maxMessageTemplate     string
25
	maxMessageParameters   validation.TemplateParameterList
26
	exactMessageTemplate   string
27
	exactMessageParameters validation.TemplateParameterList
28
}
29
30
func newCountConstraint(min int, max int, checkMin bool, checkMax bool) CountConstraint {
31
	return CountConstraint{
32
		min:                  min,
33 1
		max:                  max,
34
		checkMin:             checkMin,
35
		checkMax:             checkMax,
36
		minErr:               validation.ErrTooFewElements,
37
		maxErr:               validation.ErrTooManyElements,
38
		exactErr:             validation.ErrNotExactCount,
39
		minMessageTemplate:   validation.ErrTooFewElements.Message(),
40
		maxMessageTemplate:   validation.ErrTooManyElements.Message(),
41
		exactMessageTemplate: validation.ErrNotExactCount.Message(),
42
	}
43
}
44
45
// HasMinCount creates a CountConstraint that checks the length of the iterable (slice, array, or map)
46
// is greater than the minimum value.
47
func HasMinCount(min int) CountConstraint {
48
	return newCountConstraint(min, 0, true, false)
49
}
50 1
51
// HasMaxCount creates a CountConstraint that checks the length of the iterable (slice, array, or map)
52
// is less than the maximum value.
53
func HasMaxCount(max int) CountConstraint {
54
	return newCountConstraint(0, max, false, true)
55
}
56 1
57
// HasCountBetween creates a CountConstraint that checks the length of the iterable (slice, array, or map)
58
// is between some minimum and maximum value.
59
func HasCountBetween(min int, max int) CountConstraint {
60
	return newCountConstraint(min, max, true, true)
61
}
62 1
63
// HasExactCount creates a CountConstraint that checks the length of the iterable (slice, array, or map)
64
// has exact value.
65
func HasExactCount(count int) CountConstraint {
66
	return newCountConstraint(count, count, true, true)
67
}
68 1
69
// When enables conditional validation of this constraint. If the expression evaluates to false,
70
// then the constraint will be ignored.
71
func (c CountConstraint) When(condition bool) CountConstraint {
72
	c.isIgnored = !condition
73 1
	return c
74
}
75
76
// WhenGroups enables conditional validation of the constraint by using the validation groups.
77
func (c CountConstraint) WhenGroups(groups ...string) CountConstraint {
78
	c.groups = groups
79
	return c
80
}
81
82
// WithMinError overrides default underlying error for violation that will be shown if the
83
// collection length is less than the minimum value.
84 1
func (c CountConstraint) WithMinError(err error) CountConstraint {
85 1
	c.minErr = err
86
	return c
87
}
88
89
// WithMaxError overrides default underlying error for violation that will be shown if the
90 1
// collection length is greater than the maximum value.
91 1
func (c CountConstraint) WithMaxError(err error) CountConstraint {
92
	c.maxErr = err
93
	return c
94
}
95
96
// WithExactError overrides default underlying error for violation that will be shown if minimum and
97 1
// maximum values are equal and the length of the collection is not exactly this value.
98 1
func (c CountConstraint) WithExactError(err error) CountConstraint {
99
	c.exactErr = err
100
	return c
101
}
102
103
// WithMinMessage sets the violation message that will be shown if the collection length is less than
104 1
// the minimum value. You can set custom template parameters for injecting its values
105 1
// into the final message. Also, you can use default parameters:
106
//
107
//	{{ count }} - the current collection size;
108
//	{{ limit }} - the lower limit.
109
func (c CountConstraint) WithMinMessage(template string, parameters ...validation.TemplateParameter) CountConstraint {
110
	c.minMessageTemplate = template
111 1
	c.minMessageParameters = parameters
112 1
	return c
113
}
114
115
// WithMaxMessage sets the violation message that will be shown if the collection length is greater than
116
// the maximum value. You can set custom template parameters for injecting its values
117
// into the final message. Also, you can use default parameters:
118
//
119
//	{{ count }} - the current collection size;
120
//	{{ limit }} - the upper limit.
121
func (c CountConstraint) WithMaxMessage(template string, parameters ...validation.TemplateParameter) CountConstraint {
122 1
	c.maxMessageTemplate = template
123 1
	c.maxMessageParameters = parameters
124 1
	return c
125
}
126
127
// WithExactMessage sets the violation message that will be shown if minimum and maximum values are equal and
128
// the length of the collection is not exactly this value. You can set custom template parameters
129
// for injecting its values into the final message. Also, you can use default parameters:
130
//
131
//	{{ count }} - the current collection size;
132
//	{{ limit }} - the exact expected collection size.
133
func (c CountConstraint) WithExactMessage(template string, parameters ...validation.TemplateParameter) CountConstraint {
134 1
	c.exactMessageTemplate = template
135 1
	c.exactMessageParameters = parameters
136 1
	return c
137
}
138
139
func (c CountConstraint) ValidateCountable(ctx context.Context, validator *validation.Validator, count int) error {
140
	if c.isIgnored || validator.IsIgnoredForGroups(c.groups...) {
141
		return nil
142
	}
143
	if c.checkMax && count > c.max {
144
		return c.newViolation(ctx, validator, count, c.max, c.maxErr, c.maxMessageTemplate, c.maxMessageParameters)
145
	}
146 1
	if c.checkMin && count < c.min {
147 1
		return c.newViolation(ctx, validator, count, c.min, c.minErr, c.minMessageTemplate, c.minMessageParameters)
148 1
	}
149
150
	return nil
151
}
152 1
153
func (c CountConstraint) newViolation(
154
	ctx context.Context,
155
	validator *validation.Validator,
156 1
	count, limit int,
157 1
	err error,
158
	template string,
159 1
	parameters validation.TemplateParameterList,
160 1
) validation.Violation {
161
	if c.checkMin && c.checkMax && c.min == c.max {
162 1
		template = c.exactMessageTemplate
163 1
		parameters = c.exactMessageParameters
164
		err = c.exactErr
165
	}
166 1
167
	return validator.BuildViolation(ctx, err, template).
168
		WithPluralCount(limit).
169
		WithParameters(
170
			parameters.Prepend(
171
				validation.TemplateParameter{Key: "{{ count }}", Value: strconv.Itoa(count)},
172
				validation.TemplateParameter{Key: "{{ limit }}", Value: strconv.Itoa(limit)},
173
			)...,
174
		).
175 1
		Create()
176
}
177