Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions required_if_defined_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package validate_test

import (
"testing"

"github.com/gookit/goutil/x/assert"
"github.com/gookit/validate/v2"
)

type conditionalStatus string
type conditionalCount int
type conditionalByte uint8
type conditionalEnabled bool
type conditionalRatio float32

func TestRequiredIfDefinedTypes(t *testing.T) {
member := conditionalStatus("member")
memberPtr := &member
var absentStatus *conditionalStatus
var absentName *string
emptyName := ""
presentName := "Ada"
for _, tt := range []struct {
name string
mode any
rule string
value any
want bool
}{
{"defined string", member, "required_if:mode,member", "", false},
{"defined string pointer", &member, "required_if:mode,member", "", false},
{"defined string double pointer", &memberPtr, "required_if:mode,member", "", false},
{"nil defined pointer", absentStatus, "required_if:mode,member", "", true},
{"nil source pointer", member, "required_if:mode,member", absentName, false},
{"empty source pointer", member, "required_if:mode,member", &emptyName, false},
{"present source pointer", member, "required_if:mode,member", &presentName, true},
{"defined integer", conditionalCount(2), "required_if:mode,2", "", false},
{"defined unsigned", conditionalByte(2), "required_if:mode,2", "", false},
{"defined boolean", conditionalEnabled(true), "required_if:mode,true", "", false},
{"defined false boolean", conditionalEnabled(false), "required_if:mode,false", "", false},
{"defined float", conditionalRatio(1.5), "required_if:mode,1.5", "", false},
{"nonmatching string", conditionalStatus("guest"), "required_if:mode,member", "", true},
{"matching with value", member, "required_if:mode,member", "Ada", true},
{"multiple literals", member, "required_if:mode,member,guest", "", false},
{"builtin string", "member", "required_if:mode,member", "", false},
{"invalid literal", conditionalCount(2), "required_if:mode,no-number", "", true},
} {
t.Run(tt.name, func(t *testing.T) {
v := validate.Map(map[string]any{"mode": tt.mode, "name": tt.value})
v.StringRule("name", tt.rule)
assert.Eq(t, tt.want, v.Validate())
})
}
}

func TestRequiredIfDefinedTypeStructField(t *testing.T) {
type account struct {
Mode conditionalStatus
Name string `validate:"required_if:Mode,member"`
}
v := validate.Struct(&account{Mode: "member"})
assert.False(t, v.Validate())
assert.NotEmpty(t, v.Errors.Field("Name"))
assert.True(t, validate.Struct(&account{Mode: "guest"}).Validate())
assert.True(t, validate.Struct(&account{Mode: "member", Name: "Ada"}).Validate())
}
2 changes: 1 addition & 1 deletion validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ func (v *Validation) RequiredIf(sourceField string, val any, kvs ...string) bool
// up: only one check value, direct compare value
if len(args) == 1 {
wantVal, err := reflectx.ConvTypeByBaseKind(args[0], rftDv.Kind())
if err == nil && dstVal == wantVal {
if err == nil && IsEqual(dstVal, wantVal) {
return requiredIfValIsPresent(val) || v.isIgnoreableZeroNumeric(sourceField)
}
} else if Enum(dstVal, args) {
Expand Down
Loading