646 lines
16 KiB
Go
646 lines
16 KiB
Go
package validation
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestExistKey(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
key string
|
|
mapItem map[string]interface{}
|
|
message string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "key exists",
|
|
key: "name",
|
|
mapItem: map[string]interface{}{"name": "John"},
|
|
message: "Name is required",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "key does not exist",
|
|
key: "age",
|
|
mapItem: map[string]interface{}{"name": "John"},
|
|
message: "Age is required",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "empty map",
|
|
key: "name",
|
|
mapItem: map[string]interface{}{},
|
|
message: "Name is required",
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := ExistKey(tt.key, tt.mapItem, tt.message)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("ExistKey() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if err != nil && err.Error() != tt.message {
|
|
t.Errorf("ExistKey() error message = %v, want %v", err.Error(), tt.message)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNotBlank(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
key string
|
|
mapItem map[string]interface{}
|
|
message string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "valid string",
|
|
key: "name",
|
|
mapItem: map[string]interface{}{"name": "John"},
|
|
message: "Name cannot be blank",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "nil value",
|
|
key: "name",
|
|
mapItem: map[string]interface{}{"name": nil},
|
|
message: "Name cannot be blank",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "empty string",
|
|
key: "name",
|
|
mapItem: map[string]interface{}{"name": ""},
|
|
message: "Name cannot be blank",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "empty slice",
|
|
key: "tags",
|
|
mapItem: map[string]interface{}{"tags": []interface{}{}},
|
|
message: "Tags cannot be blank",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "non-empty slice",
|
|
key: "tags",
|
|
mapItem: map[string]interface{}{"tags": []interface{}{"tag1"}},
|
|
message: "Tags cannot be blank",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "key does not exist",
|
|
key: "name",
|
|
mapItem: map[string]interface{}{"age": 25},
|
|
message: "Name cannot be blank",
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := NotBlank(tt.key, tt.mapItem, tt.message)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("NotBlank() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if err != nil && err.Error() != tt.message {
|
|
t.Errorf("NotBlank() error message = %v, want %v", err.Error(), tt.message)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsString(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
key string
|
|
mapItem map[string]interface{}
|
|
message string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "valid string",
|
|
key: "name",
|
|
mapItem: map[string]interface{}{"name": "John"},
|
|
message: "Name must be a string",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "integer value",
|
|
key: "name",
|
|
mapItem: map[string]interface{}{"name": 123},
|
|
message: "Name must be a string",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "boolean value",
|
|
key: "name",
|
|
mapItem: map[string]interface{}{"name": true},
|
|
message: "Name must be a string",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "key does not exist",
|
|
key: "name",
|
|
mapItem: map[string]interface{}{"age": 25},
|
|
message: "Name must be a string",
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := IsString(tt.key, tt.mapItem, tt.message)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("IsString() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if err != nil && err.Error() != tt.message {
|
|
t.Errorf("IsString() error message = %v, want %v", err.Error(), tt.message)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsInt(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
key string
|
|
mapItem map[string]interface{}
|
|
message string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "valid integer",
|
|
key: "age",
|
|
mapItem: map[string]interface{}{"age": 25.0},
|
|
message: "Age must be an integer",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "float value",
|
|
key: "age",
|
|
mapItem: map[string]interface{}{"age": 25.5},
|
|
message: "Age must be an integer",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "string value",
|
|
key: "age",
|
|
mapItem: map[string]interface{}{"age": "25"},
|
|
message: "Age must be an integer",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "too large value",
|
|
key: "age",
|
|
mapItem: map[string]interface{}{"age": float64(1<<32 + 1)},
|
|
message: "Age must be an integer",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "key does not exist",
|
|
key: "age",
|
|
mapItem: map[string]interface{}{"name": "John"},
|
|
message: "Age must be an integer",
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := IsInt(tt.key, tt.mapItem, tt.message)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("IsInt() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if err != nil && err.Error() != tt.message {
|
|
t.Errorf("IsInt() error message = %v, want %v", err.Error(), tt.message)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsFloat64(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
key string
|
|
mapItem map[string]interface{}
|
|
message string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "valid float",
|
|
key: "price",
|
|
mapItem: map[string]interface{}{"price": 25.5},
|
|
message: "Price must be a number",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "integer value",
|
|
key: "price",
|
|
mapItem: map[string]interface{}{"price": 25.0},
|
|
message: "Price must be a number",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "string value",
|
|
key: "price",
|
|
mapItem: map[string]interface{}{"price": "25.5"},
|
|
message: "Price must be a number",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "key does not exist",
|
|
key: "price",
|
|
mapItem: map[string]interface{}{"name": "John"},
|
|
message: "Price must be a number",
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := IsFloat64(tt.key, tt.mapItem, tt.message)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("IsFloat64() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if err != nil && err.Error() != tt.message {
|
|
t.Errorf("IsFloat64() error message = %v, want %v", err.Error(), tt.message)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsBool(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
key string
|
|
mapItem map[string]interface{}
|
|
message string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "valid boolean true",
|
|
key: "active",
|
|
mapItem: map[string]interface{}{"active": true},
|
|
message: "Active must be a boolean",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid boolean false",
|
|
key: "active",
|
|
mapItem: map[string]interface{}{"active": false},
|
|
message: "Active must be a boolean",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "string value",
|
|
key: "active",
|
|
mapItem: map[string]interface{}{"active": "true"},
|
|
message: "Active must be a boolean",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "integer value",
|
|
key: "active",
|
|
mapItem: map[string]interface{}{"active": 1},
|
|
message: "Active must be a boolean",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "key does not exist",
|
|
key: "active",
|
|
mapItem: map[string]interface{}{"name": "John"},
|
|
message: "Active must be a boolean",
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := IsBool(tt.key, tt.mapItem, tt.message)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("IsBool() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if err != nil && err.Error() != tt.message {
|
|
t.Errorf("IsBool() error message = %v, want %v", err.Error(), tt.message)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAtLeastOneFieldMustBePresent(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
keys string
|
|
mapItem map[string]interface{}
|
|
message string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "one field present",
|
|
keys: "name,email,phone",
|
|
mapItem: map[string]interface{}{"name": "John", "age": 25},
|
|
message: "At least one field must be present",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "multiple fields present",
|
|
keys: "name,email,phone",
|
|
mapItem: map[string]interface{}{"name": "John", "email": "john@example.com"},
|
|
message: "At least one field must be present",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "no fields present",
|
|
keys: "name,email,phone",
|
|
mapItem: map[string]interface{}{"age": 25, "city": "NYC"},
|
|
message: "At least one field must be present",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "empty map",
|
|
keys: "name,email,phone",
|
|
mapItem: map[string]interface{}{},
|
|
message: "At least one field must be present",
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := AtLeastOneFieldMustBePresent(tt.keys, tt.mapItem, tt.message)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("AtLeastOneFieldMustBePresent() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if err != nil && err.Error() != tt.message {
|
|
t.Errorf("AtLeastOneFieldMustBePresent() error message = %v, want %v", err.Error(), tt.message)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUnexpectedField(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
keys string
|
|
mapItem map[string]interface{}
|
|
message string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "all fields expected",
|
|
keys: "name,age,email",
|
|
mapItem: map[string]interface{}{"name": "John", "age": 25, "email": "john@example.com"},
|
|
message: "Unexpected field found",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "subset of expected fields",
|
|
keys: "name,age,email",
|
|
mapItem: map[string]interface{}{"name": "John", "age": 25},
|
|
message: "Unexpected field found",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "unexpected field present",
|
|
keys: "name,age",
|
|
mapItem: map[string]interface{}{"name": "John", "age": 25, "unexpected": "value"},
|
|
message: "Unexpected field found",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "empty map",
|
|
keys: "name,age",
|
|
mapItem: map[string]interface{}{},
|
|
message: "Unexpected field found",
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := UnexpectedField(tt.keys, tt.mapItem, tt.message)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("UnexpectedField() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if err != nil && err.Error() != tt.message {
|
|
t.Errorf("UnexpectedField() error message = %v, want %v", err.Error(), tt.message)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMaxRange(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
key string
|
|
max int
|
|
mapItem map[string]interface{}
|
|
message string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "value within range",
|
|
key: "age",
|
|
max: 100,
|
|
mapItem: map[string]interface{}{"age": 25.0},
|
|
message: "Age must be less than 100",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "value at maximum",
|
|
key: "age",
|
|
max: 100,
|
|
mapItem: map[string]interface{}{"age": 100.0},
|
|
message: "Age must be less than 100",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "value exceeds maximum",
|
|
key: "age",
|
|
max: 100,
|
|
mapItem: map[string]interface{}{"age": 150.0},
|
|
message: "Age must be less than 100",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "key does not exist",
|
|
key: "age",
|
|
max: 100,
|
|
mapItem: map[string]interface{}{"name": "John"},
|
|
message: "Age must be less than 100",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "non-numeric value",
|
|
key: "age",
|
|
max: 100,
|
|
mapItem: map[string]interface{}{"age": "25"},
|
|
message: "Age must be less than 100",
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := MaxRange(tt.key, tt.max, tt.mapItem, tt.message)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("MaxRange() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if err != nil && err.Error() != tt.message {
|
|
t.Errorf("MaxRange() error message = %v, want %v", err.Error(), tt.message)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMinRange(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
key string
|
|
min int
|
|
mapItem map[string]interface{}
|
|
message string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "value within range",
|
|
key: "age",
|
|
min: 18,
|
|
mapItem: map[string]interface{}{"age": 25.0},
|
|
message: "Age must be at least 18",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "value at minimum",
|
|
key: "age",
|
|
min: 18,
|
|
mapItem: map[string]interface{}{"age": 18.0},
|
|
message: "Age must be at least 18",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "value below minimum",
|
|
key: "age",
|
|
min: 18,
|
|
mapItem: map[string]interface{}{"age": 15.0},
|
|
message: "Age must be at least 18",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "key does not exist",
|
|
key: "age",
|
|
min: 18,
|
|
mapItem: map[string]interface{}{"name": "John"},
|
|
message: "Age must be at least 18",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "non-numeric value",
|
|
key: "age",
|
|
min: 18,
|
|
mapItem: map[string]interface{}{"age": "25"},
|
|
message: "Age must be at least 18",
|
|
wantErr: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := MinRange(tt.key, tt.min, tt.mapItem, tt.message)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("MinRange() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if err != nil && err.Error() != tt.message {
|
|
t.Errorf("MinRange() error message = %v, want %v", err.Error(), tt.message)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestContains(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
limitedSoftwareTypes []int
|
|
currentSoftwareType int
|
|
expected bool
|
|
}{
|
|
{
|
|
name: "value found",
|
|
limitedSoftwareTypes: []int{1, 2, 3, 4, 5},
|
|
currentSoftwareType: 3,
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "value not found",
|
|
limitedSoftwareTypes: []int{1, 2, 3, 4, 5},
|
|
currentSoftwareType: 6,
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "empty slice",
|
|
limitedSoftwareTypes: []int{},
|
|
currentSoftwareType: 1,
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "single value found",
|
|
limitedSoftwareTypes: []int{42},
|
|
currentSoftwareType: 42,
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "single value not found",
|
|
limitedSoftwareTypes: []int{42},
|
|
currentSoftwareType: 43,
|
|
expected: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := Contains(tt.limitedSoftwareTypes, tt.currentSoftwareType)
|
|
if result != tt.expected {
|
|
t.Errorf("Contains() = %v, want %v", result, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidationError(t *testing.T) {
|
|
// Test Error() method
|
|
err := Error{Message: "Test error"}
|
|
if err.Error() != "Test error" {
|
|
t.Errorf("ValidationError.Error() = %v, want %v", err.Error(), "Test error")
|
|
}
|
|
|
|
// Test SetMessage() method
|
|
newErr := err.SetMessage("New error message")
|
|
if newErr.Message != "New error message" {
|
|
t.Errorf("SetMessage() = %v, want %v", newErr.Message, "New error message")
|
|
}
|
|
// Original error should not be modified
|
|
if err.Message != "Test error" {
|
|
t.Errorf("Original error was modified, got %v, want %v", err.Message, "Test error")
|
|
}
|
|
}
|
|
|
|
func TestErrBadRequest(t *testing.T) {
|
|
if ErrBadRequest.Message != "Bad Request" {
|
|
t.Errorf("ErrBadRequest.Message = %v, want %v", ErrBadRequest.Message, "Bad Request")
|
|
}
|
|
|
|
// Test that ErrBadRequest can be used with SetMessage
|
|
customErr := ErrBadRequest.SetMessage("Custom error")
|
|
if customErr.Message != "Custom error" {
|
|
t.Errorf("SetMessage() = %v, want %v", customErr.Message, "Custom error")
|
|
}
|
|
// Original ErrBadRequest should not be modified
|
|
if ErrBadRequest.Message != "Bad Request" {
|
|
t.Errorf("ErrBadRequest was modified, got %v, want %v", ErrBadRequest.Message, "Bad Request")
|
|
}
|
|
}
|