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 }