200 lines
5.3 KiB
Go
200 lines
5.3 KiB
Go
package generator
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/entity-maker/entity-maker/internal/database"
|
|
)
|
|
|
|
func TestSanitizePythonIdentifier(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected string
|
|
}{
|
|
{"starts with digit", "12_HOUR", "_12_HOUR"},
|
|
{"starts with letter", "HOUR_12", "HOUR_12"},
|
|
{"all digits", "24", "_24"},
|
|
{"underscore first", "_12_HOUR", "_12_HOUR"},
|
|
{"empty", "", ""},
|
|
{"single digit", "1", "_1"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := sanitizePythonIdentifier(tt.input)
|
|
if result != tt.expected {
|
|
t.Errorf("sanitizePythonIdentifier(%q) = %q, want %q", tt.input, result, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGenerateEnum(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
enumTypes map[string]database.EnumType
|
|
expectError bool
|
|
checkFunc func(t *testing.T, result string)
|
|
}{
|
|
{
|
|
name: "simple enum",
|
|
enumTypes: map[string]database.EnumType{
|
|
"status_enum": {
|
|
TypeName: "status_enum",
|
|
Values: []string{"OPEN", "CLOSED", "PENDING"},
|
|
},
|
|
},
|
|
expectError: false,
|
|
checkFunc: func(t *testing.T, result string) {
|
|
if !strings.Contains(result, "class StatusEnum") {
|
|
t.Error("Expected class StatusEnum")
|
|
}
|
|
if !strings.Contains(result, "OPEN = \"OPEN\"") {
|
|
t.Error("Expected OPEN = \"OPEN\"")
|
|
}
|
|
if !strings.Contains(result, "CLOSED = \"CLOSED\"") {
|
|
t.Error("Expected CLOSED = \"CLOSED\"")
|
|
}
|
|
if !strings.Contains(result, "PENDING = \"PENDING\"") {
|
|
t.Error("Expected PENDING = \"PENDING\"")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "enum with spaces and hyphens",
|
|
enumTypes: map[string]database.EnumType{
|
|
"time_format_enum": {
|
|
TypeName: "time_format_enum",
|
|
Values: []string{"12-hour", "24-hour"},
|
|
},
|
|
},
|
|
expectError: false,
|
|
checkFunc: func(t *testing.T, result string) {
|
|
if !strings.Contains(result, "class TimeFormatEnum") {
|
|
t.Error("Expected class TimeFormatEnum")
|
|
}
|
|
if !strings.Contains(result, "_12_HOUR = \"12-hour\"") {
|
|
t.Error("Expected _12_HOUR = \"12-hour\" (sanitized)")
|
|
}
|
|
if !strings.Contains(result, "_24_HOUR = \"24-hour\"") {
|
|
t.Error("Expected _24_HOUR = \"24-hour\" (sanitized)")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "enum with duplicates after normalization",
|
|
enumTypes: map[string]database.EnumType{
|
|
"measurement_enum": {
|
|
TypeName: "measurement_enum",
|
|
Values: []string{"international", "INTERNATIONAL", "imperial", "IMPERIAL"},
|
|
},
|
|
},
|
|
expectError: false,
|
|
checkFunc: func(t *testing.T, result string) {
|
|
if !strings.Contains(result, "class MeasurementEnum") {
|
|
t.Error("Expected class MeasurementEnum")
|
|
}
|
|
// Should only have one INTERNATIONAL and one IMPERIAL
|
|
internationalCount := strings.Count(result, "INTERNATIONAL = ")
|
|
if internationalCount != 1 {
|
|
t.Errorf("Expected 1 INTERNATIONAL, got %d", internationalCount)
|
|
}
|
|
imperialCount := strings.Count(result, "IMPERIAL = ")
|
|
if imperialCount != 1 {
|
|
t.Errorf("Expected 1 IMPERIAL, got %d", imperialCount)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "empty enum",
|
|
enumTypes: map[string]database.EnumType{
|
|
"empty_enum": {
|
|
TypeName: "empty_enum",
|
|
Values: []string{},
|
|
},
|
|
},
|
|
expectError: false,
|
|
checkFunc: func(t *testing.T, result string) {
|
|
if !strings.Contains(result, "class EmptyEnum") {
|
|
t.Error("Expected class EmptyEnum")
|
|
}
|
|
if !strings.Contains(result, "pass") {
|
|
t.Error("Expected 'pass' for empty enum")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "multiple enums",
|
|
enumTypes: map[string]database.EnumType{
|
|
"status_enum": {
|
|
TypeName: "status_enum",
|
|
Values: []string{"OPEN", "CLOSED"},
|
|
},
|
|
"priority_enum": {
|
|
TypeName: "priority_enum",
|
|
Values: []string{"HIGH", "LOW"},
|
|
},
|
|
},
|
|
expectError: false,
|
|
checkFunc: func(t *testing.T, result string) {
|
|
if !strings.Contains(result, "class StatusEnum") {
|
|
t.Error("Expected class StatusEnum")
|
|
}
|
|
if !strings.Contains(result, "class PriorityEnum") {
|
|
t.Error("Expected class PriorityEnum")
|
|
}
|
|
},
|
|
},
|
|
{
|
|
name: "enum with special characters",
|
|
enumTypes: map[string]database.EnumType{
|
|
"special_enum": {
|
|
TypeName: "special_enum",
|
|
Values: []string{"IN-PROGRESS", "ON HOLD", "DONE"},
|
|
},
|
|
},
|
|
expectError: false,
|
|
checkFunc: func(t *testing.T, result string) {
|
|
if !strings.Contains(result, "IN_PROGRESS = \"IN-PROGRESS\"") {
|
|
t.Error("Expected IN_PROGRESS = \"IN-PROGRESS\"")
|
|
}
|
|
if !strings.Contains(result, "ON_HOLD = \"ON HOLD\"") {
|
|
t.Error("Expected ON_HOLD = \"ON HOLD\"")
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ctx := &Context{
|
|
TableInfo: &database.TableInfo{
|
|
EnumTypes: tt.enumTypes,
|
|
},
|
|
EntityName: "TestEntity",
|
|
ModuleName: "test_entity",
|
|
}
|
|
|
|
result, err := GenerateEnum(ctx)
|
|
if (err != nil) != tt.expectError {
|
|
t.Errorf("GenerateEnum() error = %v, expectError %v", err, tt.expectError)
|
|
return
|
|
}
|
|
|
|
if tt.checkFunc != nil {
|
|
tt.checkFunc(t, result)
|
|
}
|
|
|
|
// Check common requirements
|
|
if !strings.Contains(result, "from enum import StrEnum") {
|
|
t.Error("Expected import of StrEnum")
|
|
}
|
|
if !strings.Contains(result, "from televend_core.databases.enum import EnumMixin") {
|
|
t.Error("Expected import of EnumMixin")
|
|
}
|
|
})
|
|
}
|
|
}
|