113 lines
3.0 KiB
Go
113 lines
3.0 KiB
Go
package validate
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
ut "github.com/go-playground/universal-translator"
|
|
"github.com/go-playground/validator/v10"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"testing"
|
|
)
|
|
|
|
// Test struct for validation scenarios
|
|
type User struct {
|
|
Username string `json:"username" validate:"required,min=4"`
|
|
Email string `json:"email" validate:"required,email"`
|
|
Bio string `json:"bio" validate:"is-awesome"`
|
|
}
|
|
|
|
// Custom validation function: must be "awesome"
|
|
func IsAwesomeValidator(fl validator.FieldLevel) bool {
|
|
return fl.Field().String() == "awesome"
|
|
}
|
|
|
|
func TestValidateAll_Success(t *testing.T) {
|
|
// A custom option for the "is-awesome" tag
|
|
awesomeOption := Option{
|
|
ValidatorName: "is-awesome",
|
|
ValidatorFunc: IsAwesomeValidator,
|
|
}
|
|
|
|
v, err := NewWithDefaultEN(awesomeOption)
|
|
require.NoError(t, err)
|
|
|
|
user := User{
|
|
Username: "tester",
|
|
Email: "test@example.com",
|
|
Bio: "awesome",
|
|
}
|
|
|
|
err = v.ValidateAll(user)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestValidateAll_DefaultTranslationFailure(t *testing.T) {
|
|
v, err := NewWithDefaultEN()
|
|
require.NoError(t, err)
|
|
|
|
user := struct {
|
|
Name string `json:"name" validate:"required"`
|
|
Email string `json:"email_address" validate:"email"`
|
|
}{
|
|
Name: "",
|
|
Email: "not-an-email",
|
|
}
|
|
|
|
err = v.ValidateAll(user)
|
|
require.Error(t, err)
|
|
|
|
var validationErrs ValidationErrors
|
|
require.True(t, errors.As(err, &validationErrs), "Error should be of type ValidationErrors")
|
|
require.Len(t, validationErrs, 2)
|
|
|
|
// Check errors (order might vary)
|
|
errMap := make(map[string]string)
|
|
for _, ve := range validationErrs {
|
|
errMap[ve.Field] = ve.Message
|
|
}
|
|
|
|
assert.Equal(t, "name is a required field", errMap["name"])
|
|
assert.Equal(t, "email_address must be a valid email address", errMap["email_address"])
|
|
}
|
|
|
|
func TestValidateAll_CustomValidationWithTranslation(t *testing.T) {
|
|
// A custom option for a "status" validator with translation
|
|
statusOption := Option{
|
|
ValidatorName: "status",
|
|
ValidatorFunc: func(fl validator.FieldLevel) bool {
|
|
status := fl.Field().String()
|
|
return status == "active" || status == "inactive"
|
|
},
|
|
// Function to register the translation
|
|
RegisterTranslationFunc: func(ut ut.Translator) error {
|
|
return ut.Add("status", "{0} must be 'active' or 'inactive'", true)
|
|
},
|
|
// Function that defines how the translation message is generated
|
|
TranslationFunc: func(ut ut.Translator, fe validator.FieldError) string {
|
|
t, _ := ut.T("status", fe.Field())
|
|
return t
|
|
},
|
|
}
|
|
|
|
v, err := NewWithDefaultEN(statusOption)
|
|
require.NoError(t, err)
|
|
|
|
payload := struct {
|
|
Status string `json:"user_status" validate:"status"`
|
|
}{
|
|
Status: "pending",
|
|
}
|
|
|
|
err = v.ValidateAll(payload)
|
|
require.Error(t, err)
|
|
|
|
var validationErrs ValidationErrors
|
|
require.True(t, errors.As(err, &validationErrs))
|
|
require.Len(t, validationErrs, 1)
|
|
|
|
assert.Equal(t, "user_status", validationErrs[0].Field)
|
|
assert.Equal(t, "user_status must be 'active' or 'inactive'", validationErrs[0].Message)
|
|
fmt.Println(validationErrs.Error()) // For visual confirmation
|
|
}
|