package naming import ( "testing" ) func TestSingularize(t *testing.T) { tests := []struct { name string input string expected string }{ // Regular plurals {"simple s", "users", "user"}, {"simple s uppercase", "Users", "User"}, {"tables", "tables", "table"}, // ies -> y {"ies to y", "companies", "company"}, {"ies to y uppercase", "Companies", "Company"}, {"cities", "cities", "city"}, {"categories", "categories", "category"}, // ves -> f/fe {"ves to f", "halves", "half"}, {"ves to fe - knife", "knives", "knife"}, {"ves to fe - wife", "wives", "wife"}, {"ves to fe - life", "lives", "life"}, // es endings {"xes", "boxes", "box"}, {"shes", "dishes", "dish"}, {"ches", "watches", "watch"}, {"ses", "classes", "class"}, // oes -> o {"oes", "tomatoes", "tomato"}, {"heroes", "heroes", "hero"}, // Irregular plurals {"people", "people", "person"}, {"children", "children", "child"}, {"men", "men", "man"}, {"women", "women", "woman"}, {"teeth", "teeth", "tooth"}, {"feet", "feet", "foot"}, {"mice", "mice", "mouse"}, {"geese", "geese", "goose"}, // Unchanged {"sheep", "sheep", "sheep"}, {"fish", "fish", "fish"}, {"deer", "deer", "deer"}, {"series", "series", "series"}, {"species", "species", "species"}, // Special cases {"data", "data", "datum"}, {"analyses", "analyses", "analysis"}, {"crises", "crises", "crisis"}, // Edge cases {"empty", "", ""}, {"already singular", "user", "user"}, {"ss ending", "glass", "glass"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := Singularize(tt.input) if result != tt.expected { t.Errorf("Singularize(%q) = %q, want %q", tt.input, result, tt.expected) } }) } } func TestPluralize(t *testing.T) { tests := []struct { name string input string expected string }{ // Regular plurals {"simple", "user", "users"}, {"simple uppercase", "User", "Users"}, {"table", "table", "tables"}, // y -> ies {"y to ies", "company", "companies"}, {"y to ies uppercase", "Company", "Companies"}, {"city", "city", "cities"}, {"category", "category", "categories"}, // consonant + y stays {"ay ending", "day", "days"}, {"ey ending", "key", "keys"}, {"oy ending", "boy", "boys"}, // f/fe -> ves {"f to ves", "half", "halves"}, {"fe to ves - knife", "knife", "knives"}, {"fe to ves - wife", "wife", "wives"}, {"fe to ves - life", "life", "lives"}, // s, x, sh, ch -> es {"x to es", "box", "boxes"}, {"sh to es", "dish", "dishes"}, {"ch to es", "watch", "watches"}, {"s to es", "class", "classes"}, // o -> oes {"o to oes", "tomato", "tomatoes"}, {"hero", "hero", "heroes"}, // Irregular plurals {"person", "person", "people"}, {"child", "child", "children"}, {"man", "man", "men"}, {"woman", "woman", "women"}, {"tooth", "tooth", "teeth"}, {"foot", "foot", "feet"}, {"mouse", "mouse", "mice"}, {"goose", "goose", "geese"}, // Unchanged {"sheep", "sheep", "sheep"}, {"fish", "fish", "fish"}, {"deer", "deer", "deer"}, {"series", "series", "series"}, {"species", "species", "species"}, // Edge cases {"empty", "", ""}, {"already plural", "users", "users"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := Pluralize(tt.input) if result != tt.expected { t.Errorf("Pluralize(%q) = %q, want %q", tt.input, result, tt.expected) } }) } } func TestSingularizeTableName(t *testing.T) { tests := []struct { name string input string expected string }{ {"simple", "users", "user"}, {"compound", "user_accounts", "user_account"}, {"triple compound", "user_login_histories", "user_login_history"}, {"already singular", "user", "user"}, {"ies ending", "cashbag_conforms", "cashbag_conform"}, {"complex table", "auth_user_groups", "auth_user_group"}, {"empty", "", ""}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := SingularizeTableName(tt.input) if result != tt.expected { t.Errorf("SingularizeTableName(%q) = %q, want %q", tt.input, result, tt.expected) } }) } } func TestToPascalCase(t *testing.T) { tests := []struct { name string input string expected string }{ {"simple", "user", "User"}, {"snake_case", "user_account", "UserAccount"}, {"triple", "user_login_history", "UserLoginHistory"}, {"already pascal", "UserAccount", "UserAccount"}, {"single char", "a", "A"}, {"empty", "", ""}, {"with numbers", "user_2fa", "User2fa"}, {"multiple underscores", "user___account", "UserAccount"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := ToPascalCase(tt.input) if result != tt.expected { t.Errorf("ToPascalCase(%q) = %q, want %q", tt.input, result, tt.expected) } }) } } func TestToSnakeCase(t *testing.T) { tests := []struct { name string input string expected string }{ {"PascalCase", "UserAccount", "user_account"}, {"simple", "User", "user"}, {"multiple words", "UserLoginHistory", "user_login_history"}, {"already snake", "user_account", "user_account"}, {"empty", "", ""}, {"single char", "A", "a"}, {"with numbers", "User2FA", "user2_f_a"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := ToSnakeCase(tt.input) if result != tt.expected { t.Errorf("ToSnakeCase(%q) = %q, want %q", tt.input, result, tt.expected) } }) } } // Benchmark tests func BenchmarkSingularize(b *testing.B) { for i := 0; i < b.N; i++ { Singularize("companies") } } func BenchmarkPluralize(b *testing.B) { for i := 0; i < b.N; i++ { Pluralize("company") } } func BenchmarkToPascalCase(b *testing.B) { for i := 0; i < b.N; i++ { ToPascalCase("user_login_history") } } func BenchmarkToSnakeCase(b *testing.B) { for i := 0; i < b.N; i++ { ToSnakeCase("UserLoginHistory") } }