Test Failed
Pull Request — main (#71)
by Igor
02:01
created

it.ChoiceConstraint.ValidateString   B

Complexity

Conditions 6

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 12
nop 2
dl 0
loc 17
ccs 5
cts 5
cp 1
crap 6
rs 8.6666
c 0
b 0
f 0
1
package it
2
3
import (
4
	"fmt"
5
	"strings"
6
7
	"github.com/muonsoft/validation"
8
	"github.com/muonsoft/validation/code"
9
	"github.com/muonsoft/validation/message"
10
)
11
12
// ChoiceConstraint is used to ensure that the given value corresponds to one of the expected choices.
13
type ChoiceConstraint[T comparable] struct {
14
	blank             T
15
	choices           map[T]bool
16
	choicesValue      string
17
	groups            []string
18
	code              string
19
	messageTemplate   string
20
	messageParameters validation.TemplateParameterList
21
	isIgnored         bool
22
}
23
24 1
// IsOneOf creates a ChoiceConstraint for checking that values are in the expected list of values.
25 1
func IsOneOf[T comparable](values ...T) ChoiceConstraint[T] {
26 1
	choices := make(map[T]bool, len(values))
27
	for _, value := range values {
28
		choices[value] = true
29 1
	}
30
31
	s := strings.Builder{}
32
	for i, value := range values {
33
		if i > 0 {
34
			s.WriteString(", ")
35
		}
36
		s.WriteString(fmt.Sprint(value))
37
	}
38
39 1
	return ChoiceConstraint[T]{
40 1
		choices:         choices,
41
		choicesValue:    s.String(),
42
		code:            code.NoSuchChoice,
43 1
		messageTemplate: message.Templates[code.NoSuchChoice],
44
	}
45
}
46
47
// Code overrides default code for produced violation.
48 1
func (c ChoiceConstraint[T]) Code(code string) ChoiceConstraint[T] {
49
	c.code = code
50
	return c
51
}
52
53 1
// Message sets the violation message template. You can set custom template parameters
54 1
// for injecting its values into the final message. Also, you can use default parameters:
55
//
56
//	{{ choices }} - a comma-separated list of available choices;
57
//	{{ value }} - the current (invalid) value.
58
func (c ChoiceConstraint[T]) Message(template string, parameters ...validation.TemplateParameter) ChoiceConstraint[T] {
59
	c.messageTemplate = template
60
	c.messageParameters = parameters
61
	return c
62
}
63 1
64 1
// When enables conditional validation of this constraint. If the expression evaluates to false,
65 1
// then the constraint will be ignored.
66
func (c ChoiceConstraint[T]) When(condition bool) ChoiceConstraint[T] {
67
	c.isIgnored = !condition
68
	return c
69
}
70
71 1
// WhenGroups enables conditional validation of the constraint by using the validation groups.
72 1
func (c ChoiceConstraint[T]) WhenGroups(groups ...string) ChoiceConstraint[T] {
73
	c.groups = groups
74
	return c
75
}
76
77 1
func (c ChoiceConstraint[T]) ValidateComparable(value *T, scope validation.Scope) error {
78 1
	if len(c.choices) == 0 {
79
		return scope.NewConstraintError("ChoiceConstraint", "empty list of choices")
80
	}
81
	if c.isIgnored || scope.IsIgnored(c.groups...) || value == nil || *value == c.blank {
82 1
		return nil
83 1
	}
84
	if c.choices[*value] {
85 1
		return nil
86 1
	}
87
88
	return scope.
89 1
		BuildViolation(c.code, c.messageTemplate).
90
		SetParameters(
91
			c.messageParameters.Prepend(
92
				validation.TemplateParameter{Key: "{{ value }}", Value: fmt.Sprint(*value)},
93
				validation.TemplateParameter{Key: "{{ choices }}", Value: c.choicesValue},
94
			)...,
95
		).
96
		CreateViolation()
97
}
98