package validator import ( "fmt" "testing" "github.com/gin-gonic/gin/binding" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // testStruct is a sample struct with validation tags for testing. type testStruct struct { Name string `validate:"required"` Email string `validate:"required,email"` Age int `validate:"gte=0,lte=130"` } func TestInit(t *testing.T) { // Should not panic Init() // validate should be set assert.NotNil(t, validate) } func TestValidateStruct_Valid(t *testing.T) { // Ensure initialized Init() s := testStruct{ Name: "Alice", Email: "alice@example.com", Age: 30, } err := ValidateStruct(s) assert.NoError(t, err) } func TestValidateStruct_Invalid_MissingRequired(t *testing.T) { Init() s := testStruct{ Name: "", Email: "alice@example.com", Age: 30, } err := ValidateStruct(s) assert.Error(t, err) } func TestValidateStruct_Invalid_BadEmail(t *testing.T) { Init() s := testStruct{ Name: "Alice", Email: "not-an-email", Age: 30, } err := ValidateStruct(s) assert.Error(t, err) } func TestValidateStruct_Invalid_AgeOutOfRange(t *testing.T) { Init() s := testStruct{ Name: "Alice", Email: "alice@example.com", Age: 200, } err := ValidateStruct(s) assert.Error(t, err) } func TestValidateStruct_Invalid_NegativeAge(t *testing.T) { Init() s := testStruct{ Name: "Alice", Email: "alice@example.com", Age: -1, } err := ValidateStruct(s) assert.Error(t, err) } func TestValidateStruct_AutoInit(t *testing.T) { // Reset validate to nil to test auto-initialization validate = nil s := testStruct{ Name: "Bob", Email: "bob@example.com", Age: 25, } err := ValidateStruct(s) assert.NoError(t, err) // validate should have been auto-initialized assert.NotNil(t, validate) } func TestVar_Valid(t *testing.T) { Init() err := Var("test@example.com", "required,email") assert.NoError(t, err) } func TestVar_Invalid(t *testing.T) { Init() err := Var("not-an-email", "email") assert.Error(t, err) } func TestVar_Required_Empty(t *testing.T) { Init() err := Var("", "required") assert.Error(t, err) } func TestVar_MinLength(t *testing.T) { Init() err := Var("ab", "min=3") assert.Error(t, err) err = Var("abc", "min=3") assert.NoError(t, err) } func TestVar_AutoInit(t *testing.T) { // Reset validate to nil to test auto-initialization validate = nil err := Var("test@example.com", "email") assert.NoError(t, err) assert.NotNil(t, validate) } func TestValidateStruct_ReturnsLocalizedWrappedError(t *testing.T) { type request struct { Password string `json:"password" validate:"min=6"` } err := ValidateStruct(request{Password: "123"}) require.Error(t, err) wrapped := fmt.Errorf("validation error: %w", err) assert.True(t, IsValidationError(wrapped)) assert.Equal(t, "密码长度不能少于 6 个字符", ValidationMessage(wrapped)) } func TestValidationMessage_LoginPasswordMin(t *testing.T) { type loginRequest struct { Password string `json:"password" binding:"required,min=6"` } err := binding.Validator.ValidateStruct(loginRequest{Password: "123"}) require.Error(t, err) assert.True(t, IsValidationError(err)) assert.Equal(t, "密码长度不能少于 6 个字符", ValidationMessage(err)) assert.NotContains(t, err.Error(), "Field validation") } func TestValidationMessage_MultipleFields(t *testing.T) { type request struct { Email string `json:"email" binding:"required,email"` Password string `json:"password" binding:"required,min=6"` } err := binding.Validator.ValidateStruct(request{}) require.Error(t, err) message := ValidationMessage(err) assert.Contains(t, message, "请填写邮箱") assert.Contains(t, message, "请填写密码") assert.NotContains(t, message, "Key:") } func TestValidationMessageText_RemovesRawValidatorDetails(t *testing.T) { raw := "Key: 'LoginRequest.Password' Error:Field validation for 'Password' failed on the 'min' tag" assert.Equal(t, "请求参数不符合要求", ValidationMessageText(raw)) assert.Equal(t, "密码长度不能少于 6 个字符", ValidationMessageText("validation: 密码长度不能少于 6 个字符")) } func TestValidateStruct_Pointer(t *testing.T) { Init() s := &testStruct{ Name: "Alice", Email: "alice@example.com", Age: 30, } err := ValidateStruct(s) assert.NoError(t, err) } func TestValidateStruct_InvalidPointer(t *testing.T) { Init() s := &testStruct{ Name: "", Email: "bad", Age: 500, } err := ValidateStruct(s) assert.Error(t, err) } func TestValidateStruct_NonStruct(t *testing.T) { Init() // Validating a non-struct with Struct() should return an error err := ValidateStruct("just a string") require.Error(t, err) } func TestValidateStruct_Nil(t *testing.T) { Init() // validate.Struct(nil) returns an error err := ValidateStruct(nil) assert.Error(t, err) }