fx build fix
This commit is contained in:
311
api/server/internal/server/accountapiimp/signup_test.go
Normal file
311
api/server/internal/server/accountapiimp/signup_test.go
Normal file
@@ -0,0 +1,311 @@
|
||||
package accountapiimp
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/tech/sendico/pkg/model"
|
||||
"github.com/tech/sendico/server/interface/api/srequest"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// Helper function to create string pointers
|
||||
func stringPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
// TestTimezoneValidation tests timezone validation logic separately
|
||||
func TestTimezoneValidation(t *testing.T) {
|
||||
t.Run("ValidTimezones", func(t *testing.T) {
|
||||
validTimezones := []string{
|
||||
"UTC",
|
||||
"America/New_York",
|
||||
"Europe/London",
|
||||
"Asia/Tokyo",
|
||||
"Australia/Sydney",
|
||||
}
|
||||
|
||||
for _, tz := range validTimezones {
|
||||
t.Run(tz, func(t *testing.T) {
|
||||
_, err := time.LoadLocation(tz)
|
||||
assert.NoError(t, err, "Timezone %s should be valid", tz)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("InvalidTimezones", func(t *testing.T) {
|
||||
invalidTimezones := []string{
|
||||
"Invalid/Timezone",
|
||||
"Not/A/Timezone",
|
||||
"BadTimezone",
|
||||
"America/NotACity",
|
||||
}
|
||||
|
||||
for _, tz := range invalidTimezones {
|
||||
t.Run(tz, func(t *testing.T) {
|
||||
_, err := time.LoadLocation(tz)
|
||||
assert.Error(t, err, "Timezone %s should be invalid", tz)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestCreateValidSignupRequest tests the helper function for creating valid requests
|
||||
func TestCreateValidSignupRequest(t *testing.T) {
|
||||
request := srequest.Signup{
|
||||
Account: model.AccountData{
|
||||
LoginData: model.LoginData{
|
||||
UserDataBase: model.UserDataBase{
|
||||
Login: "test@example.com",
|
||||
},
|
||||
Password: "TestPassword123!",
|
||||
},
|
||||
Name: "Test User",
|
||||
},
|
||||
OrganizationName: "Test Organization",
|
||||
OrganizationTimeZone: "UTC",
|
||||
DefaultPriorityGroup: srequest.CreatePriorityGroup{
|
||||
Description: model.Describable{
|
||||
Name: "Default Priority Group",
|
||||
},
|
||||
Priorities: []model.Colorable{
|
||||
{
|
||||
Describable: model.Describable{Name: "High"},
|
||||
Color: stringPtr("#FF0000"),
|
||||
},
|
||||
{
|
||||
Describable: model.Describable{Name: "Medium"},
|
||||
Color: stringPtr("#FFFF00"),
|
||||
},
|
||||
{
|
||||
Describable: model.Describable{Name: "Low"},
|
||||
Color: stringPtr("#00FF00"),
|
||||
},
|
||||
},
|
||||
},
|
||||
AnonymousUser: model.Describable{
|
||||
Name: "Anonymous User",
|
||||
},
|
||||
OwnerRole: model.Describable{
|
||||
Name: "Owner",
|
||||
},
|
||||
AnonymousRole: model.Describable{
|
||||
Name: "Anonymous",
|
||||
},
|
||||
}
|
||||
|
||||
// Validate the request structure
|
||||
assert.Equal(t, "test@example.com", request.Account.Login)
|
||||
assert.Equal(t, "TestPassword123!", request.Account.Password)
|
||||
assert.Equal(t, "Test User", request.Account.Name)
|
||||
assert.Equal(t, "Test Organization", request.OrganizationName)
|
||||
assert.Equal(t, "UTC", request.OrganizationTimeZone)
|
||||
assert.Equal(t, "Default Priority Group", request.DefaultPriorityGroup.Description.Name)
|
||||
assert.Len(t, request.DefaultPriorityGroup.Priorities, 3)
|
||||
assert.Equal(t, "High", request.DefaultPriorityGroup.Priorities[0].Name)
|
||||
assert.Equal(t, "#FF0000", *request.DefaultPriorityGroup.Priorities[0].Color)
|
||||
}
|
||||
|
||||
// TestSignupRequestValidation tests various signup request validation scenarios
|
||||
func TestSignupRequestValidation(t *testing.T) {
|
||||
t.Run("ValidRequest", func(t *testing.T) {
|
||||
request := srequest.Signup{
|
||||
Account: model.AccountData{
|
||||
LoginData: model.LoginData{
|
||||
UserDataBase: model.UserDataBase{
|
||||
Login: "test@example.com",
|
||||
},
|
||||
Password: "TestPassword123!",
|
||||
},
|
||||
Name: "Test User",
|
||||
},
|
||||
OrganizationName: "Test Organization",
|
||||
OrganizationTimeZone: "UTC",
|
||||
}
|
||||
|
||||
// Basic validation - all required fields present
|
||||
assert.NotEmpty(t, request.Account.Login)
|
||||
assert.NotEmpty(t, request.Account.Password)
|
||||
assert.NotEmpty(t, request.Account.Name)
|
||||
assert.NotEmpty(t, request.OrganizationName)
|
||||
assert.NotEmpty(t, request.OrganizationTimeZone)
|
||||
})
|
||||
|
||||
t.Run("EmailFormats", func(t *testing.T) {
|
||||
validEmails := []string{
|
||||
"test@example.com",
|
||||
"user.name@example.com",
|
||||
"user+tag@example.org",
|
||||
"test123@domain.co.uk",
|
||||
}
|
||||
|
||||
for _, email := range validEmails {
|
||||
t.Run(email, func(t *testing.T) {
|
||||
request := srequest.Signup{
|
||||
Account: model.AccountData{
|
||||
LoginData: model.LoginData{
|
||||
UserDataBase: model.UserDataBase{
|
||||
Login: email,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.Equal(t, email, request.Account.Login)
|
||||
assert.Contains(t, email, "@")
|
||||
assert.Contains(t, email, ".")
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("PasswordComplexity", func(t *testing.T) {
|
||||
passwordTests := []struct {
|
||||
name string
|
||||
password string
|
||||
valid bool
|
||||
}{
|
||||
{"Strong", "TestPassword123!", true},
|
||||
{"WithNumbers", "MyPass123!", true},
|
||||
{"WithSymbols", "Complex@Pass1", true},
|
||||
{"TooShort", "Test1!", false},
|
||||
{"NoNumbers", "TestPassword!", false},
|
||||
{"NoSymbols", "TestPassword123", false},
|
||||
{"NoUppercase", "testpassword123!", false},
|
||||
{"NoLowercase", "TESTPASSWORD123!", false},
|
||||
}
|
||||
|
||||
for _, tt := range passwordTests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
request := srequest.Signup{
|
||||
Account: model.AccountData{
|
||||
LoginData: model.LoginData{
|
||||
Password: tt.password,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Basic structure validation
|
||||
assert.Equal(t, tt.password, request.Account.Password)
|
||||
|
||||
if tt.valid {
|
||||
assert.True(t, len(tt.password) >= 8, "Password should be at least 8 characters")
|
||||
} else {
|
||||
// For invalid passwords, at least one condition should fail
|
||||
hasDigit := false
|
||||
hasUpper := false
|
||||
hasLower := false
|
||||
hasSpecial := false
|
||||
|
||||
for _, char := range tt.password {
|
||||
switch {
|
||||
case char >= '0' && char <= '9':
|
||||
hasDigit = true
|
||||
case char >= 'A' && char <= 'Z':
|
||||
hasUpper = true
|
||||
case char >= 'a' && char <= 'z':
|
||||
hasLower = true
|
||||
case char >= '!' && char <= '/' || char >= ':' && char <= '@':
|
||||
hasSpecial = true
|
||||
}
|
||||
}
|
||||
|
||||
// At least one requirement should fail for invalid passwords
|
||||
if len(tt.password) >= 8 {
|
||||
assert.False(t, hasDigit && hasUpper && hasLower && hasSpecial,
|
||||
"Password %s should fail at least one requirement", tt.password)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestPriorityGroupCreation tests the priority group structure
|
||||
func TestPriorityGroupCreation(t *testing.T) {
|
||||
priorityGroup := srequest.CreatePriorityGroup{
|
||||
Description: model.Describable{
|
||||
Name: "Test Priority Group",
|
||||
},
|
||||
Priorities: []model.Colorable{
|
||||
{
|
||||
Describable: model.Describable{Name: "Critical"},
|
||||
Color: stringPtr("#FF0000"),
|
||||
},
|
||||
{
|
||||
Describable: model.Describable{Name: "High"},
|
||||
Color: stringPtr("#FF8000"),
|
||||
},
|
||||
{
|
||||
Describable: model.Describable{Name: "Medium"},
|
||||
Color: stringPtr("#FFFF00"),
|
||||
},
|
||||
{
|
||||
Describable: model.Describable{Name: "Low"},
|
||||
Color: stringPtr("#00FF00"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, "Test Priority Group", priorityGroup.Description.Name)
|
||||
assert.Len(t, priorityGroup.Priorities, 4)
|
||||
|
||||
// Test each priority
|
||||
expectedPriorities := []struct {
|
||||
name string
|
||||
color string
|
||||
}{
|
||||
{"Critical", "#FF0000"},
|
||||
{"High", "#FF8000"},
|
||||
{"Medium", "#FFFF00"},
|
||||
{"Low", "#00FF00"},
|
||||
}
|
||||
|
||||
for i, expected := range expectedPriorities {
|
||||
assert.Equal(t, expected.name, priorityGroup.Priorities[i].Name)
|
||||
assert.Equal(t, expected.color, *priorityGroup.Priorities[i].Color)
|
||||
}
|
||||
}
|
||||
|
||||
// TestAccountDataToAccount tests the ToAccount method
|
||||
func TestAccountDataToAccount(t *testing.T) {
|
||||
accountData := model.AccountData{
|
||||
LoginData: model.LoginData{
|
||||
UserDataBase: model.UserDataBase{
|
||||
Login: "test@example.com",
|
||||
},
|
||||
Password: "TestPassword123!",
|
||||
},
|
||||
Name: "Test User",
|
||||
}
|
||||
|
||||
account := accountData.ToAccount()
|
||||
|
||||
assert.Equal(t, accountData.Login, account.Login)
|
||||
assert.Equal(t, accountData.Password, account.Password)
|
||||
assert.Equal(t, accountData.Name, account.Name)
|
||||
|
||||
// Verify the account has proper structure
|
||||
assert.NotNil(t, account)
|
||||
assert.IsType(t, &model.Account{}, account)
|
||||
}
|
||||
|
||||
// TestColorValidation tests that colors are properly formatted
|
||||
func TestColorValidation(t *testing.T) {
|
||||
validColors := []string{
|
||||
"#FF0000", // Red
|
||||
"#00FF00", // Green
|
||||
"#0000FF", // Blue
|
||||
"#FFFFFF", // White
|
||||
"#000000", // Black
|
||||
"#FF8000", // Orange
|
||||
}
|
||||
|
||||
for _, color := range validColors {
|
||||
t.Run(color, func(t *testing.T) {
|
||||
colorPtr := stringPtr(color)
|
||||
assert.NotNil(t, colorPtr)
|
||||
assert.Equal(t, color, *colorPtr)
|
||||
assert.True(t, len(color) == 7, "Color should be 7 characters long")
|
||||
assert.True(t, color[0] == '#', "Color should start with #")
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user