Files
fn_registry/functions/infra/config_validate_test.go
egutierrez c3b007a4e7 feat(infra): tipos ConfigError y ConfigValidation + funciones puras Go (validate, merge, dump)
- ConfigError y ConfigValidation como tipos producto con sus .md en types/infra/
- config_validate: validacion con tags required/format/min/max/oneof via reflection
- config_merge: merge no-mutante de map[string]string con precedencia de override
- config_dump: serializacion de structs a map con mascara *** para campos secret
- 17 tests unitarios, todos PASS

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 02:01:43 +02:00

99 lines
2.5 KiB
Go

package infra
import (
"testing"
)
func TestConfigValidate(t *testing.T) {
t.Run("struct valido retorna IsValid true", func(t *testing.T) {
type Cfg struct {
Host string `required:"true"`
Port int `required:"true"`
}
got := ConfigValidate(Cfg{Host: "localhost", Port: 8080})
if !got.IsValid {
t.Errorf("expected IsValid=true, errors: %v", got.Errors)
}
if len(got.Errors) != 0 {
t.Errorf("expected no errors, got %v", got.Errors)
}
})
t.Run("campo required vacio acumula error", func(t *testing.T) {
type Cfg struct {
Host string `required:"true"`
Key string `required:"true"`
}
got := ConfigValidate(Cfg{})
if got.IsValid {
t.Error("expected IsValid=false")
}
if len(got.Errors) != 2 {
t.Errorf("expected 2 errors, got %d: %v", len(got.Errors), got.Errors)
}
for _, e := range got.Errors {
if e.Tag != "required" {
t.Errorf("expected tag 'required', got %q", e.Tag)
}
}
})
t.Run("format email invalido produce error", func(t *testing.T) {
type Cfg struct {
Email string `format:"email"`
}
got := ConfigValidate(Cfg{Email: "not-an-email"})
if got.IsValid {
t.Error("expected IsValid=false")
}
if len(got.Errors) == 0 || got.Errors[0].Tag != "format" {
t.Errorf("expected format error, got %v", got.Errors)
}
})
t.Run("format email valido pasa", func(t *testing.T) {
type Cfg struct {
Email string `format:"email"`
}
got := ConfigValidate(Cfg{Email: "user@example.com"})
if !got.IsValid {
t.Errorf("expected IsValid=true, errors: %v", got.Errors)
}
})
t.Run("format url invalido produce error", func(t *testing.T) {
type Cfg struct {
BaseURL string `format:"url"`
}
got := ConfigValidate(Cfg{BaseURL: "ftp://bad.url"})
if got.IsValid {
t.Error("expected IsValid=false")
}
if len(got.Errors) == 0 || got.Errors[0].Tag != "format" {
t.Errorf("expected format error, got %v", got.Errors)
}
})
t.Run("puntero a struct funciona igual", func(t *testing.T) {
type Cfg struct {
Name string `required:"true"`
}
got := ConfigValidate(&Cfg{Name: "test"})
if !got.IsValid {
t.Errorf("expected IsValid=true, errors: %v", got.Errors)
}
})
t.Run("todos los errores acumulados aunque falle el primero", func(t *testing.T) {
type Cfg struct {
A string `required:"true"`
B string `required:"true"`
C string `required:"true"`
}
got := ConfigValidate(Cfg{})
if len(got.Errors) != 3 {
t.Errorf("expected 3 errors, got %d", len(got.Errors))
}
})
}