Files
rogee dc5ace9003
Build and publish Docker images / Build and publish images (push) Failing after 25s
fix: localize validation errors and polish delivery
2026-09-15 16:28:02 +08:00

225 lines
4.8 KiB
Go

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)
}