Skip to content

Commit

Permalink
Add oneofci validator (oneof case insensitive) (#1321)
Browse files Browse the repository at this point in the history
## Fixes Or Enhances

- Adds oneofci, a case insensitive version of oneof
- resolves #840

**Make sure that you've checked the boxes below before you submit PR:**
- [ X] Tests exist or have been written that cover this particular
change.

@go-playground/validator-maintainers
  • Loading branch information
connorcarnes authored Nov 16, 2024
1 parent 078d0c0 commit d7abf32
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 0 deletions.
18 changes: 18 additions & 0 deletions baked_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ var (
"fqdn": isFQDN,
"unique": isUnique,
"oneof": isOneOf,
"oneofci": isOneOfCI,
"html": isHTML,
"html_encoded": isHTMLEncoded,
"url_encoded": isURLEncoded,
Expand Down Expand Up @@ -299,6 +300,23 @@ func isOneOf(fl FieldLevel) bool {
return false
}

// isOneOfCI is the validation function for validating if the current field's value is one of the provided string values (case insensitive).
func isOneOfCI(fl FieldLevel) bool {
vals := parseOneOfParam2(fl.Param())
field := fl.Field()

if field.Kind() != reflect.String {
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
}
v := field.String()
for _, val := range vals {
if strings.EqualFold(val, v) {
return true
}
}
return false
}

// isUnique is the validation function for validating if each array|slice|map value is unique
func isUnique(fl FieldLevel) bool {
field := fl.Field()
Expand Down
7 changes: 7 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,13 @@ the target string between single quotes. Kind of like an 'enum'.
oneof='red green' 'blue yellow'
oneof=5 7 9
# One Of Case Insensitive
Works the same as oneof but is case insensitive and therefore only accepts strings.
Usage: oneofci=red green
oneofci='red green' 'blue yellow'
# Greater Than
For numbers, this will ensure that the value is greater than the
Expand Down
76 changes: 76 additions & 0 deletions validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5680,6 +5680,82 @@ func TestOneOfValidation(t *testing.T) {
}, "Bad field type float64")
}

func TestOneOfCIValidation(t *testing.T) {
validate := New()

passSpecs := []struct {
f interface{}
t string
}{
{f: "red", t: "oneofci=RED GREEN"},
{f: "RED", t: "oneofci=red green"},
{f: "red", t: "oneofci=red green"},
{f: "RED", t: "oneofci=RED GREEN"},
{f: "green", t: "oneofci=red green"},
{f: "red green", t: "oneofci='red green' blue"},
{f: "blue", t: "oneofci='red green' blue"},
{f: "GREEN", t: "oneofci=Red Green"},
{f: "ReD", t: "oneofci=RED GREEN"},
{f: "gReEn", t: "oneofci=rEd GrEeN"},
{f: "RED GREEN", t: "oneofci='red green' blue"},
{f: "red Green", t: "oneofci='RED GREEN' Blue"},
{f: "Red green", t: "oneofci='Red Green' BLUE"},
{f: "rEd GrEeN", t: "oneofci='ReD gReEn' BlUe"},
{f: "BLUE", t: "oneofci='Red Green' BLUE"},
{f: "BlUe", t: "oneofci='RED GREEN' Blue"},
{f: "bLuE", t: "oneofci='red green' BLUE"},
}

for _, spec := range passSpecs {
t.Logf("%#v", spec)
errs := validate.Var(spec.f, spec.t)
Equal(t, errs, nil)
}

failSpecs := []struct {
f interface{}
t string
}{
{f: "", t: "oneofci=red green"},
{f: "yellow", t: "oneofci=red green"},
{f: "green", t: "oneofci='red green' blue"},
}

for _, spec := range failSpecs {
t.Logf("%#v", spec)
errs := validate.Var(spec.f, spec.t)
AssertError(t, errs, "", "", "", "", "oneofci")
}

panicSpecs := []struct {
f interface{}
t string
}{
{f: 3.14, t: "oneofci=red green"},
{f: 5, t: "oneofci=red green"},
{f: uint(6), t: "oneofci=7"},
{f: int8(5), t: "oneofci=red green"},
{f: int16(5), t: "oneofci=red green"},
{f: int32(5), t: "oneofci=red green"},
{f: int64(5), t: "oneofci=red green"},
{f: uint(5), t: "oneofci=red green"},
{f: uint8(5), t: "oneofci=red green"},
{f: uint16(5), t: "oneofci=red green"},
{f: uint32(5), t: "oneofci=red green"},
{f: uint64(5), t: "oneofci=red green"},
}

panicCount := 0
for _, spec := range panicSpecs {
t.Logf("%#v", spec)
PanicMatches(t, func() {
_ = validate.Var(spec.f, spec.t)
}, fmt.Sprintf("Bad field type %T", spec.f))
panicCount++
}
Equal(t, panicCount, len(panicSpecs))
}

func TestBase32Validation(t *testing.T) {
validate := New()

Expand Down

0 comments on commit d7abf32

Please sign in to comment.