// this is in a validation test
type Report struct {
SysrptID json.Number `json:"SysrptID" validate:"required"`
Name string `json:"Name" validate:"required"`
Description string `json:"Description"`
FileName string `json:"FileName"`
RptType string `json:"RptType" validate:"oneof=AIS MDR CTE MCM GEN RAL DOC"`
Category []string
}
// this is my validation code:
import (
"fmt"
"github.com/go-playground/validator"
"regexp"
)
// ValidationError wraps the validators FieldError so we do not
// expose this to out code
type ValidationError struct {
validator.FieldError
}
func (v ValidationError) Error() string {
return fmt.Sprintf(
"Key: '%s' Error: Field validation for '%s' failed on the '%s' tag",
v.Namespace(),
v.Field(),
v.Tag(),
)
}
// ValidationErrors is a collection of ValidationError
type ValidationErrors []ValidationError
// Errors converts the slice into a string slice
func (v ValidationErrors) Errors() []string {
errs := []string{}
for _, err := range v {
errs = append(errs, err.Error())
}
return errs
}
// Validation contains
type Validation struct {
validate *validator.Validate
}
// NewValidation creates a new Validation type
func NewValidation() *Validation {
validate := validator.New()
//validate.RegisterValidation("sku", validateSKU)
return &Validation{validate}
}
// Validate the item
// for more detail the returned error can be cast into a
// validator.ValidationErrors collection
//
// if ve, ok := err.(validator.ValidationErrors); ok {
// fmt.Println(ve.Namespace())
// fmt.Println(ve.Field())
// fmt.Println(ve.StructNamespace())
// fmt.Println(ve.StructField())
// fmt.Println(ve.Tag())
// fmt.Println(ve.ActualTag())
// fmt.Println(ve.Kind())
// fmt.Println(ve.Type())
// fmt.Println(ve.Value())
// fmt.Println(ve.Param())
// fmt.Println()
// }
func (v *Validation) Validate(i interface{}) ValidationErrors {
errs := v.validate.Struct(i).(validator.ValidationErrors)
// I think the issue is here :frowning:
if len(errs) == 0 {
return nil
}
var returnErrs []ValidationError
for _, err := range errs {
// cast the FieldError into our ValidationError and append to the slice
ve := ValidationError{err.(validator.FieldError)}
returnErrs = append(returnErrs, ve)
}
return returnErrs
}
// validateSKU not used only example
func validateSKU(fl validator.FieldLevel) bool {
// SKU must be in the format abc-abc-abc
re := regexp.MustCompile(`[a-z]+-[a-z]+-[a-z]+`)
sku := re.FindAllString(fl.Field().String(), -1)
if len(sku) == 1 {
return true
}
return false
}
// end of validator
// when i run this test i get a panic on what [i think] should be a valid // report it never hits the if statement, not sure what I am doing wrong
// the structs that fail validation work great.
// the panic is:
// 2021/02/17 08:13:36 panic occurred: interface conversion: error is // nil, not validator.ValidationErrors
func TestReportsValidator(t *testing.T) {
tests := map[string]struct {
input Report
want int
}{
//"just id": {input: Report{SysrptID: "1"}, want: 2},
//"just name": {input: Report{Name: "test report"}, want: 2},
//"none": {input: Report{}, want: 3},
"valid": {input: Report{SysrptID: "1", Name: "test", RptType: "RAL"}, want: 0},
//"trailing sep": {input: Report{}, want: 1},
}
for name, tc := range tests {
fmt.Println(name, tc.input, tc.want)
t.Run(name, func(t *testing.T) {
v := NewValidation()
defer func() {
if err := recover(); err != nil {
log.Println("panic occurred:", err)
}
}()
fe := v.Validate(tc.input)
if fe != nil {
assert.Len(t, fe, tc.want)
}
//diff := cmp.Diff(tc.want, got)
//if diff != "" {
// t.Fatalf(diff)
//}
})
}
}