Skip to content

Commit

Permalink
Add method Skip.When() (#123)
Browse files Browse the repository at this point in the history
Skip.When() determines if all rules following it should be skipped
  • Loading branch information
maratori authored Aug 13, 2020
1 parent 6a5d431 commit b589ba5
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 27 deletions.
18 changes: 10 additions & 8 deletions struct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,17 @@ func TestValidateStruct(t *testing.T) {
// validatable field
{"t6.1", &m2, []*FieldRules{Field(&m2.E)}, "E: error 123."},
{"t6.2", &m2, []*FieldRules{Field(&m2.E, Skip)}, ""},
{"t6.3", &m2, []*FieldRules{Field(&m2.E, Skip.When(true))}, ""},
{"t6.4", &m2, []*FieldRules{Field(&m2.E, Skip.When(false))}, "E: error 123."},
// Required, NotNil
{"t7.1", &m2, []*FieldRules{Field(&m2.F, Required)}, "F: cannot be blank."},
{"t7.2", &m2, []*FieldRules{Field(&m2.F, NotNil)}, "F: is required."},
{"t7.3", &m2, []*FieldRules{Field(&m2.E, Required, Skip)}, ""},
{"t7.4", &m2, []*FieldRules{Field(&m2.E, NotNil, Skip)}, ""},
{"t7.3", &m2, []*FieldRules{Field(&m2.F, Skip, Required)}, ""},
{"t7.4", &m2, []*FieldRules{Field(&m2.F, Skip, NotNil)}, ""},
{"t7.5", &m2, []*FieldRules{Field(&m2.F, Skip.When(true), Required)}, ""},
{"t7.6", &m2, []*FieldRules{Field(&m2.F, Skip.When(true), NotNil)}, ""},
{"t7.7", &m2, []*FieldRules{Field(&m2.F, Skip.When(false), Required)}, "F: cannot be blank."},
{"t7.8", &m2, []*FieldRules{Field(&m2.F, Skip.When(false), NotNil)}, "F: is required."},
// embedded structs
{"t8.1", &m3, []*FieldRules{Field(&m3.M3, Skip)}, ""},
{"t8.2", &m3, []*FieldRules{Field(&m3.M3)}, "M3: (A: error abc.)."},
Expand All @@ -126,9 +132,7 @@ func TestValidateStruct(t *testing.T) {

// embedded struct
err := Validate(&m3)
if assert.NotNil(t, err) {
assert.Equal(t, "A: error abc.", err.Error())
}
assert.EqualError(t, err, "A: error abc.")

a := struct {
Name string
Expand All @@ -138,9 +142,7 @@ func TestValidateStruct(t *testing.T) {
Field(&a.Name, Required),
Field(&a.Value, Required, Length(5, 10)),
)
if assert.NotNil(t, err) {
assert.Equal(t, "Value: the length must be between 5 and 10.", err.Error())
}
assert.EqualError(t, err, "Value: the length must be between 5 and 10.")
}

func TestValidateStructWithContext(t *testing.T) {
Expand Down
18 changes: 13 additions & 5 deletions validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ var (
ErrorTag = "json"

// Skip is a special validation rule that indicates all rules following it should be skipped.
Skip = &skipRule{}
Skip = skipRule{skip: true}

validatableType = reflect.TypeOf((*Validatable)(nil)).Elem()
validatableWithContextType = reflect.TypeOf((*ValidatableWithContext)(nil)).Elem()
Expand All @@ -67,7 +67,7 @@ var (
// for each element call the element value's `Validate()`. Return with the validation result.
func Validate(value interface{}, rules ...Rule) error {
for _, rule := range rules {
if _, ok := rule.(*skipRule); ok {
if s, ok := rule.(skipRule); ok && s.skip {
return nil
}
if err := rule.Validate(value); err != nil {
Expand Down Expand Up @@ -115,7 +115,7 @@ func Validate(value interface{}, rules ...Rule) error {
// for each element call the element value's `Validate()`. Return with the validation result.
func ValidateWithContext(ctx context.Context, value interface{}, rules ...Rule) error {
for _, rule := range rules {
if _, ok := rule.(*skipRule); ok {
if s, ok := rule.(skipRule); ok && s.skip {
return nil
}
if rc, ok := rule.(RuleWithContext); ok {
Expand Down Expand Up @@ -228,12 +228,20 @@ func validateSliceWithContext(ctx context.Context, rv reflect.Value) error {
return nil
}

type skipRule struct{}
type skipRule struct {
skip bool
}

func (r *skipRule) Validate(interface{}) error {
func (r skipRule) Validate(interface{}) error {
return nil
}

// When determines if all rules following it should be skipped.
func (r skipRule) When(condition bool) skipRule {
r.skip = condition
return r
}

type inlineRule struct {
f RuleFunc
fc RuleWithContextFunc
Expand Down
32 changes: 18 additions & 14 deletions validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,26 @@ func TestValidate(t *testing.T) {

// with rules
err := Validate("123", &validateAbc{}, &validateXyz{})
if assert.NotNil(t, err) {
assert.Equal(t, "error abc", err.Error())
}
assert.EqualError(t, err, "error abc")
err = Validate("abc", &validateAbc{}, &validateXyz{})
if assert.NotNil(t, err) {
assert.Equal(t, "error xyz", err.Error())
}
assert.EqualError(t, err, "error xyz")
err = Validate("abcxyz", &validateAbc{}, &validateXyz{})
assert.Nil(t, err)
assert.NoError(t, err)

err = Validate("123", &validateAbc{}, Skip, &validateXyz{})
if assert.NotNil(t, err) {
assert.Equal(t, "error abc", err.Error())
}
assert.EqualError(t, err, "error abc")
err = Validate("abc", &validateAbc{}, Skip, &validateXyz{})
assert.Nil(t, err)
assert.NoError(t, err)

err = Validate("123", &validateAbc{}, Skip.When(true), &validateXyz{})
assert.EqualError(t, err, "error abc")
err = Validate("abc", &validateAbc{}, Skip.When(true), &validateXyz{})
assert.NoError(t, err)

err = Validate("123", &validateAbc{}, Skip.When(false), &validateXyz{})
assert.EqualError(t, err, "error abc")
err = Validate("abc", &validateAbc{}, Skip.When(false), &validateXyz{})
assert.EqualError(t, err, "error xyz")
}

func stringEqual(str string) RuleFunc {
Expand Down Expand Up @@ -131,9 +135,9 @@ func Test_skipRule_Validate(t *testing.T) {

func assertError(t *testing.T, expected string, err error, tag string) {
if expected == "" {
assert.Nil(t, err, tag)
} else if assert.NotNil(t, err, tag) {
assert.Equal(t, expected, err.Error(), tag)
assert.NoError(t, err, tag)
} else {
assert.EqualError(t, err, expected, tag)
}
}

Expand Down

0 comments on commit b589ba5

Please sign in to comment.