mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2025-11-13 18:03:53 +00:00
364 lines
9.2 KiB
Go
364 lines
9.2 KiB
Go
package common
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// TestModel represents a sample model for testing
|
|
type TestModel struct {
|
|
ID int64 `json:"id" gorm:"primaryKey"`
|
|
Name string `json:"name" gorm:"column:name"`
|
|
Email string `json:"email" bun:"email"`
|
|
Age int `json:"age"`
|
|
IsActive bool `json:"is_active"`
|
|
CreatedAt string `json:"created_at"`
|
|
}
|
|
|
|
func TestNewColumnValidator(t *testing.T) {
|
|
model := TestModel{}
|
|
validator := NewColumnValidator(model)
|
|
|
|
if validator == nil {
|
|
t.Fatal("Expected validator to be created")
|
|
}
|
|
|
|
if len(validator.validColumns) == 0 {
|
|
t.Fatal("Expected validator to have valid columns")
|
|
}
|
|
|
|
// Check that expected columns are present
|
|
expectedColumns := []string{"id", "name", "email", "age", "is_active", "created_at"}
|
|
for _, col := range expectedColumns {
|
|
if !validator.validColumns[col] {
|
|
t.Errorf("Expected column '%s' to be valid", col)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestValidateColumn(t *testing.T) {
|
|
model := TestModel{}
|
|
validator := NewColumnValidator(model)
|
|
|
|
tests := []struct {
|
|
name string
|
|
column string
|
|
shouldError bool
|
|
}{
|
|
{"Valid column - id", "id", false},
|
|
{"Valid column - name", "name", false},
|
|
{"Valid column - email", "email", false},
|
|
{"Valid column - uppercase", "ID", false}, // Case insensitive
|
|
{"Invalid column", "invalid_column", true},
|
|
{"CQL prefixed - should be valid", "cqlComputedField", false},
|
|
{"CQL prefixed uppercase - should be valid", "CQLComputedField", false},
|
|
{"Empty column", "", false}, // Empty columns are allowed
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := validator.ValidateColumn(tt.column)
|
|
if tt.shouldError && err == nil {
|
|
t.Errorf("Expected error for column '%s', got nil", tt.column)
|
|
}
|
|
if !tt.shouldError && err != nil {
|
|
t.Errorf("Expected no error for column '%s', got: %v", tt.column, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidateColumns(t *testing.T) {
|
|
model := TestModel{}
|
|
validator := NewColumnValidator(model)
|
|
|
|
tests := []struct {
|
|
name string
|
|
columns []string
|
|
shouldError bool
|
|
}{
|
|
{"All valid columns", []string{"id", "name", "email"}, false},
|
|
{"One invalid column", []string{"id", "invalid_col", "name"}, true},
|
|
{"All invalid columns", []string{"bad1", "bad2"}, true},
|
|
{"With CQL prefix", []string{"id", "cqlComputed", "name"}, false},
|
|
{"Empty list", []string{}, false},
|
|
{"Nil list", nil, false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := validator.ValidateColumns(tt.columns)
|
|
if tt.shouldError && err == nil {
|
|
t.Errorf("Expected error for columns %v, got nil", tt.columns)
|
|
}
|
|
if !tt.shouldError && err != nil {
|
|
t.Errorf("Expected no error for columns %v, got: %v", tt.columns, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidateRequestOptions(t *testing.T) {
|
|
model := TestModel{}
|
|
validator := NewColumnValidator(model)
|
|
|
|
tests := []struct {
|
|
name string
|
|
options RequestOptions
|
|
shouldError bool
|
|
errorMsg string
|
|
}{
|
|
{
|
|
name: "Valid options with columns",
|
|
options: RequestOptions{
|
|
Columns: []string{"id", "name"},
|
|
Filters: []FilterOption{
|
|
{Column: "name", Operator: "eq", Value: "test"},
|
|
},
|
|
Sort: []SortOption{
|
|
{Column: "id", Direction: "ASC"},
|
|
},
|
|
},
|
|
shouldError: false,
|
|
},
|
|
{
|
|
name: "Invalid column in Columns",
|
|
options: RequestOptions{
|
|
Columns: []string{"id", "invalid_column"},
|
|
},
|
|
shouldError: true,
|
|
errorMsg: "select columns",
|
|
},
|
|
{
|
|
name: "Invalid column in Filters",
|
|
options: RequestOptions{
|
|
Filters: []FilterOption{
|
|
{Column: "invalid_col", Operator: "eq", Value: "test"},
|
|
},
|
|
},
|
|
shouldError: true,
|
|
errorMsg: "filter",
|
|
},
|
|
{
|
|
name: "Invalid column in Sort",
|
|
options: RequestOptions{
|
|
Sort: []SortOption{
|
|
{Column: "invalid_col", Direction: "ASC"},
|
|
},
|
|
},
|
|
shouldError: true,
|
|
errorMsg: "sort",
|
|
},
|
|
{
|
|
name: "Valid CQL prefixed columns",
|
|
options: RequestOptions{
|
|
Columns: []string{"id", "cqlComputedField"},
|
|
Filters: []FilterOption{
|
|
{Column: "cqlCustomFilter", Operator: "eq", Value: "test"},
|
|
},
|
|
},
|
|
shouldError: false,
|
|
},
|
|
{
|
|
name: "Invalid column in Preload",
|
|
options: RequestOptions{
|
|
Preload: []PreloadOption{
|
|
{
|
|
Relation: "SomeRelation",
|
|
Columns: []string{"id", "invalid_col"},
|
|
},
|
|
},
|
|
},
|
|
shouldError: true,
|
|
errorMsg: "preload",
|
|
},
|
|
{
|
|
name: "Valid preload with valid columns",
|
|
options: RequestOptions{
|
|
Preload: []PreloadOption{
|
|
{
|
|
Relation: "SomeRelation",
|
|
Columns: []string{"id", "name"},
|
|
},
|
|
},
|
|
},
|
|
shouldError: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := validator.ValidateRequestOptions(tt.options)
|
|
if tt.shouldError {
|
|
if err == nil {
|
|
t.Errorf("Expected error, got nil")
|
|
} else if tt.errorMsg != "" && !strings.Contains(err.Error(), tt.errorMsg) {
|
|
t.Errorf("Expected error to contain '%s', got: %v", tt.errorMsg, err)
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Errorf("Expected no error, got: %v", err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetValidColumns(t *testing.T) {
|
|
model := TestModel{}
|
|
validator := NewColumnValidator(model)
|
|
|
|
columns := validator.GetValidColumns()
|
|
if len(columns) == 0 {
|
|
t.Error("Expected to get valid columns, got empty list")
|
|
}
|
|
|
|
// Should have at least the columns from TestModel
|
|
if len(columns) < 6 {
|
|
t.Errorf("Expected at least 6 columns, got %d", len(columns))
|
|
}
|
|
}
|
|
|
|
// Test with Bun tags specifically
|
|
type BunModel struct {
|
|
ID int64 `bun:"id,pk"`
|
|
Name string `bun:"name"`
|
|
Email string `bun:"user_email"`
|
|
}
|
|
|
|
func TestBunTagSupport(t *testing.T) {
|
|
model := BunModel{}
|
|
validator := NewColumnValidator(model)
|
|
|
|
// Test that bun tags are properly recognized
|
|
tests := []struct {
|
|
column string
|
|
shouldError bool
|
|
}{
|
|
{"id", false},
|
|
{"name", false},
|
|
{"user_email", false}, // Bun tag specifies this name
|
|
{"email", true}, // JSON tag would be "email", but bun tag says "user_email"
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.column, func(t *testing.T) {
|
|
err := validator.ValidateColumn(tt.column)
|
|
if tt.shouldError && err == nil {
|
|
t.Errorf("Expected error for column '%s'", tt.column)
|
|
}
|
|
if !tt.shouldError && err != nil {
|
|
t.Errorf("Expected no error for column '%s', got: %v", tt.column, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFilterValidColumns(t *testing.T) {
|
|
model := TestModel{}
|
|
validator := NewColumnValidator(model)
|
|
|
|
tests := []struct {
|
|
name string
|
|
input []string
|
|
expectedOutput []string
|
|
}{
|
|
{
|
|
name: "All valid columns",
|
|
input: []string{"id", "name", "email"},
|
|
expectedOutput: []string{"id", "name", "email"},
|
|
},
|
|
{
|
|
name: "Mix of valid and invalid",
|
|
input: []string{"id", "invalid_col", "name", "bad_col", "email"},
|
|
expectedOutput: []string{"id", "name", "email"},
|
|
},
|
|
{
|
|
name: "All invalid columns",
|
|
input: []string{"bad1", "bad2"},
|
|
expectedOutput: []string{},
|
|
},
|
|
{
|
|
name: "With CQL prefix (should pass)",
|
|
input: []string{"id", "cqlComputed", "name"},
|
|
expectedOutput: []string{"id", "cqlComputed", "name"},
|
|
},
|
|
{
|
|
name: "Empty input",
|
|
input: []string{},
|
|
expectedOutput: []string{},
|
|
},
|
|
{
|
|
name: "Nil input",
|
|
input: nil,
|
|
expectedOutput: nil,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := validator.FilterValidColumns(tt.input)
|
|
if len(result) != len(tt.expectedOutput) {
|
|
t.Errorf("Expected %d columns, got %d", len(tt.expectedOutput), len(result))
|
|
}
|
|
for i, col := range result {
|
|
if col != tt.expectedOutput[i] {
|
|
t.Errorf("At index %d: expected %s, got %s", i, tt.expectedOutput[i], col)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFilterRequestOptions(t *testing.T) {
|
|
model := TestModel{}
|
|
validator := NewColumnValidator(model)
|
|
|
|
options := RequestOptions{
|
|
Columns: []string{"id", "name", "invalid_col"},
|
|
OmitColumns: []string{"email", "bad_col"},
|
|
Filters: []FilterOption{
|
|
{Column: "name", Operator: "eq", Value: "test"},
|
|
{Column: "invalid_col", Operator: "eq", Value: "test"},
|
|
},
|
|
Sort: []SortOption{
|
|
{Column: "id", Direction: "ASC"},
|
|
{Column: "bad_col", Direction: "DESC"},
|
|
},
|
|
}
|
|
|
|
filtered := validator.FilterRequestOptions(options)
|
|
|
|
// Check Columns
|
|
if len(filtered.Columns) != 2 {
|
|
t.Errorf("Expected 2 columns, got %d", len(filtered.Columns))
|
|
}
|
|
if filtered.Columns[0] != "id" || filtered.Columns[1] != "name" {
|
|
t.Errorf("Expected columns [id, name], got %v", filtered.Columns)
|
|
}
|
|
|
|
// Check OmitColumns
|
|
if len(filtered.OmitColumns) != 1 {
|
|
t.Errorf("Expected 1 omit column, got %d", len(filtered.OmitColumns))
|
|
}
|
|
if filtered.OmitColumns[0] != "email" {
|
|
t.Errorf("Expected omit column [email], got %v", filtered.OmitColumns)
|
|
}
|
|
|
|
// Check Filters
|
|
if len(filtered.Filters) != 1 {
|
|
t.Errorf("Expected 1 filter, got %d", len(filtered.Filters))
|
|
}
|
|
if filtered.Filters[0].Column != "name" {
|
|
t.Errorf("Expected filter column 'name', got %s", filtered.Filters[0].Column)
|
|
}
|
|
|
|
// Check Sort
|
|
if len(filtered.Sort) != 1 {
|
|
t.Errorf("Expected 1 sort, got %d", len(filtered.Sort))
|
|
}
|
|
if filtered.Sort[0].Column != "id" {
|
|
t.Errorf("Expected sort column 'id', got %s", filtered.Sort[0].Column)
|
|
}
|
|
}
|