Files
probo/pkg/validator/validator_common_test.go
Émile Ré 9156d6a16a Add wsl linter and fix
Signed-off-by: Émile Ré <emile@probo.com>
2026-05-20 09:27:28 +04:00

359 lines
8.2 KiB
Go

// Copyright (c) 2025-2026 Probo Inc <hello@getprobo.com>.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
package validator
import (
"testing"
)
func TestOptionalByDefault(t *testing.T) {
t.Run("nil value skips validation by default", func(t *testing.T) {
v := New()
v.Check(nil, "field", MinLen(5))
if v.Error() != nil {
t.Errorf("expected no errors for nil (optional by default), got: %v", v.Error())
}
})
t.Run("nil pointer skips validation by default", func(t *testing.T) {
v := New()
var str *string
v.Check(str, "field", MinLen(5))
if v.Error() != nil {
t.Errorf("expected no errors for nil pointer (optional by default), got: %v", v.Error())
}
})
t.Run("valid value passes validation", func(t *testing.T) {
v := New()
str := "hello world"
v.Check(&str, "field", MinLen(5))
if v.Error() != nil {
t.Errorf("expected no errors, got: %v", v.Error())
}
})
t.Run("invalid value fails validation", func(t *testing.T) {
v := New()
str := "hi"
v.Check(&str, "field", MinLen(5))
if v.Error() == nil {
t.Error("expected validation error")
}
})
t.Run("multiple validators", func(t *testing.T) {
v := New()
str := "hello"
v.Check(&str, "field", MinLen(3), MaxLen(10))
if v.Error() != nil {
t.Errorf("expected no errors, got: %v", v.Error())
}
})
t.Run("empty string is not nil and gets validated", func(t *testing.T) {
v := New()
str := ""
v.Check(&str, "field", MinLen(5))
if v.Error() == nil {
t.Error("expected validation error for empty string")
}
})
t.Run("Required() validates nil values", func(t *testing.T) {
v := New()
var str *string
v.Check(str, "field", Required())
if v.Error() == nil {
t.Error("expected validation error for nil with Required()")
}
})
}
func TestRequired(t *testing.T) {
t.Run("valid string", func(t *testing.T) {
str := "hello"
err := Required()(&str)
if err != nil {
t.Errorf("expected no error, got: %v", err)
}
})
t.Run("empty string", func(t *testing.T) {
str := ""
err := Required()(&str)
if err == nil {
t.Fatal("expected validation error")
} else if err.Code != ErrorCodeRequired {
t.Errorf("expected error code %s, got %s", ErrorCodeRequired, err.Code)
}
})
t.Run("whitespace string", func(t *testing.T) {
str := " "
err := Required()(&str)
if err == nil {
t.Error("expected validation error for whitespace")
}
})
t.Run("nil string pointer", func(t *testing.T) {
var str *string
err := Required()(str)
if err == nil {
t.Error("expected validation error for nil pointer")
}
})
t.Run("valid string pointer", func(t *testing.T) {
str := "hello"
err := Required()(&str)
if err != nil {
t.Errorf("expected no error, got: %v", err)
}
})
t.Run("nil interface", func(t *testing.T) {
err := Required()(nil)
if err == nil {
t.Error("expected validation error for nil")
}
})
t.Run("zero int", func(t *testing.T) {
num := 0
err := Required()(&num)
if err != nil {
t.Errorf("expected no error for zero int, got: %v", err)
}
})
t.Run("positive int", func(t *testing.T) {
num := 42
err := Required()(&num)
if err != nil {
t.Errorf("expected no error, got: %v", err)
}
})
t.Run("nil int pointer", func(t *testing.T) {
var num *int
err := Required()(num)
if err == nil {
t.Error("expected validation error for nil int pointer")
}
})
t.Run("valid int pointer", func(t *testing.T) {
num := 42
err := Required()(&num)
if err != nil {
t.Errorf("expected no error, got: %v", err)
}
})
t.Run("empty slice", func(t *testing.T) {
slice := []any{}
err := Required()(slice)
if err == nil {
t.Error("expected validation error for empty slice")
}
})
t.Run("non-empty slice", func(t *testing.T) {
slice := []any{1, 2, 3}
err := Required()(slice)
if err != nil {
t.Errorf("expected no error, got: %v", err)
}
})
t.Run("empty string slice", func(t *testing.T) {
slice := []string{}
err := Required()(slice)
if err == nil {
t.Fatal("expected validation error for empty []string slice")
} else if err.Code != ErrorCodeRequired {
t.Errorf("expected error code %s, got %s", ErrorCodeRequired, err.Code)
}
})
t.Run("non-empty string slice", func(t *testing.T) {
slice := []string{"a", "b", "c"}
err := Required()(slice)
if err != nil {
t.Errorf("expected no error for non-empty []string, got: %v", err)
}
})
t.Run("empty int slice", func(t *testing.T) {
slice := []int{}
err := Required()(slice)
if err == nil {
t.Fatal("expected validation error for empty []int slice")
} else if err.Code != ErrorCodeRequired {
t.Errorf("expected error code %s, got %s", ErrorCodeRequired, err.Code)
}
})
t.Run("non-empty int slice", func(t *testing.T) {
slice := []int{1, 2, 3}
err := Required()(slice)
if err != nil {
t.Errorf("expected no error for non-empty []int, got: %v", err)
}
})
t.Run("empty custom type slice", func(t *testing.T) {
type CustomType struct {
ID int
}
slice := []CustomType{}
err := Required()(slice)
if err == nil {
t.Fatal("expected validation error for empty custom type slice")
} else if err.Code != ErrorCodeRequired {
t.Errorf("expected error code %s, got %s", ErrorCodeRequired, err.Code)
}
})
t.Run("non-empty custom type slice", func(t *testing.T) {
type CustomType struct {
ID int
}
slice := []CustomType{{ID: 1}, {ID: 2}}
err := Required()(slice)
if err != nil {
t.Errorf("expected no error for non-empty custom type slice, got: %v", err)
}
})
t.Run("empty pointer slice", func(t *testing.T) {
slice := []*string{}
err := Required()(slice)
if err == nil {
t.Error("expected validation error for empty []*string slice")
}
})
t.Run("non-empty pointer slice", func(t *testing.T) {
str1, str2 := "a", "b"
slice := []*string{&str1, &str2}
err := Required()(slice)
if err != nil {
t.Errorf("expected no error for non-empty []*string, got: %v", err)
}
})
}
func TestNoDuplicates(t *testing.T) {
t.Run("nil slice", func(t *testing.T) {
var slice []string
err := NoDuplicates()(slice)
if err != nil {
t.Errorf("expected no error for nil slice, got: %v", err)
}
})
t.Run("empty slice", func(t *testing.T) {
slice := []string{}
err := NoDuplicates()(slice)
if err != nil {
t.Errorf("expected no error for empty slice, got: %v", err)
}
})
t.Run("unique strings", func(t *testing.T) {
slice := []string{"a", "b", "c"}
err := NoDuplicates()(slice)
if err != nil {
t.Errorf("expected no error, got: %v", err)
}
})
t.Run("duplicate strings", func(t *testing.T) {
slice := []string{"a", "b", "a"}
err := NoDuplicates()(slice)
if err == nil {
t.Fatal("expected validation error for duplicates")
} else if err.Code != ErrorCodeInvalidFormat {
t.Errorf("expected error code %s, got %s", ErrorCodeInvalidFormat, err.Code)
}
})
t.Run("unique ints", func(t *testing.T) {
slice := []int{1, 2, 3}
err := NoDuplicates()(slice)
if err != nil {
t.Errorf("expected no error, got: %v", err)
}
})
t.Run("duplicate ints", func(t *testing.T) {
slice := []int{1, 2, 1}
err := NoDuplicates()(slice)
if err == nil {
t.Fatal("expected validation error for duplicates")
}
})
t.Run("non-comparable elements", func(t *testing.T) {
slice := []map[string]string{{"a": "b"}}
err := NoDuplicates()(slice)
if err == nil {
t.Fatal("expected validation error for non-comparable elements")
} else if err.Code != ErrorCodeInvalidFormat {
t.Errorf("expected error code %s, got %s", ErrorCodeInvalidFormat, err.Code)
}
})
}