diff --git a/utils/utils.go b/utils/utils.go index 19b1b77e37f57bc3c2ad16354bda87ec6401f355..40bf5be0176584e384ddefcffa08af245a60f84d 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -212,6 +212,30 @@ func FormatPhoneNumber(phoneNumber string) string { return phoneNumber } +func ValidatePhoneNumber(phoneNumber string) (string, error) { + phoneNumber = string_utils.RemoveAllWhiteSpaces(phoneNumber) + + for _, char := range string_utils.NonOfficialWhitespaceChars { + phoneNumber = strings.ReplaceAll(phoneNumber, char, "") + } + + if phoneNumber == "" { + return "", errors.Error("phone number is empty") + } + + if !isPhoneNumber(phoneNumber) { + return "", errors.Error("phone number is invalid") + } + + return phoneNumber, nil +} + +// isPhoneNumber checks if a string is a valid phone number. It only allows numbers and a leading "+". Remove whitespace before calling this function. Note: it does not validate the length of the phone number. +func isPhoneNumber(phoneNumber string) bool { + phoneRegex := regexp.MustCompile(`^\+?[0-9]+$`) + return phoneRegex.MatchString(phoneNumber) +} + func insertInto(s string, index int, characters string) string { return s[:index] + characters + s[index:] } diff --git a/utils/utils_test.go b/utils/utils_test.go index b1a07699ec800d5f43bea7aef7aef65d843a992d..5eafa56ac391ad979a93c0bb8045010028b61223 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -146,3 +146,73 @@ func TestValidateIPAddress(t *testing.T) { }) } } + +func TestValidatePhoneNumber(t *testing.T) { + tests := []struct { + name string + phoneNumber string + want string + wantErr error + }{ + { + name: "Valid phone number with country code", + phoneNumber: "+27123456789", + want: "+27123456789", + wantErr: nil, + }, + { + name: "Valid phone number with country code and spaces", + phoneNumber: " + 271 2345 6789", + want: "+27123456789", + wantErr: nil, + }, + { + name: "Valid phone number without country code", + phoneNumber: "0123456789", + want: "0123456789", + wantErr: nil, + }, + { + name: "Phone number with spaces", + phoneNumber: "012 345 6789", + want: "0123456789", + wantErr: nil, + }, + { + name: "Phone number with non-official whitespaces", + phoneNumber: "012\u00A0345\u00A06789", + want: "0123456789", + wantErr: nil, + }, + { + name: "Empty phone number", + phoneNumber: "", + want: "", + wantErr: errors.Error("phone number is empty"), + }, + { + name: "Invalid phone number with letters", + phoneNumber: "01234abcde", + want: "", + wantErr: errors.Error("phone number is invalid"), + }, + { + name: "Phone number with special characters", + phoneNumber: "01234!@#$%", + want: "", + wantErr: errors.Error("phone number is invalid"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ValidatePhoneNumber(tt.phoneNumber) + if got != tt.want { + t.Errorf("ValidatePhoneNumber() got = %v, want %v", got, tt.want) + } + if err != nil && err.Error() != tt.wantErr.Error() { + t.Errorf("ValidatePhoneNumber() err = %v, want %v", err, tt.wantErr) + } + }) + } +}