Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate phone numbers in different formats #672

Merged
merged 12 commits into from
Apr 2, 2024
27 changes: 25 additions & 2 deletions __tests__/Str-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Str from '../lib/str';

const buildTestURLForType = (type) => `https://chat.expensify.com/chat-attachments/5/w_eadf5d35cfce6a98e2dd3607cf8463b1e46219e4.${type}?authToken=12345`;
const buildTestURLForType = type => `https://chat.expensify.com/chat-attachments/5/w_eadf5d35cfce6a98e2dd3607cf8463b1e46219e4.${type}?authToken=12345`;

describe('Str.isImage', () => {
it('Correctly identifies all valid image types', () => {
Expand Down Expand Up @@ -114,7 +114,7 @@ describe('Str.isValidEmail', () => {
expect(Str.isValidEmail('test@gmail')).toBeFalsy();
expect(Str.isValidEmail('@gmail.com')).toBeFalsy();
expect(Str.isValidEmail('usernamelongerthan64charactersshouldnotworkaccordingtorfc822whichisusedbyphp@gmail.com')).toBeFalsy();

// Domain length (63 chars in each label)
expect(Str.isValidEmail('test@asjjssjdjdjdjdjdjjeiwiwiwowkdjdjdieikdjfidekjcjdkekejdcjdkeekcj.com')).toBeTruthy();
expect(Str.isValidEmail('abc@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.km')).toBeTruthy();
Expand Down Expand Up @@ -189,3 +189,26 @@ describe('Str.isValidEmail', () => {
expect(Str.isValidEmail('a@a.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkl')).toBeFalsy();
});
});

describe('Str.isValidPhoneFormat', () => {
it('Correctly identifies valid phone numbers', () => {
// Significant part of phone
expect(Str.isValidPhoneFormat('4404589784')).toBeTruthy();

// International standard
expect(Str.isValidPhoneFormat('+1 440-458-9784')).toBeTruthy();

// E.164 standard
expect(Str.isValidPhoneFormat('+14404589784')).toBeTruthy();

// US national standard
expect(Str.isValidPhoneFormat('(440) 458-9784')).toBeTruthy();
expect(Str.isValidPhoneFormat('123.456.7890')).toBeTruthy();
});
});

describe('Str.isValidE164Phone', () => {
it('Correctly identifies valid E.164 phone numbers', () => {
expect(Str.isValidE164Phone('+14404589784')).toBeTruthy();
});
});
4 changes: 4 additions & 0 deletions lib/CONST.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@ export declare const CONST: {
* Regex matching an text containing an email
*/
readonly EMAIL_PART: "([\\w\\-\\+\\'#]+(?:\\.[\\w\\-\\'\\+]+)*@(?:[\\w\\-]+\\.)+[a-z]{2,})";
/**
* Regex matching a text containing general phone number
*/
readonly GENERAL_PHONE_PART: RegExp,
/**
* Regex matching a text containing an E.164 format phone number
*/
Expand Down
14 changes: 11 additions & 3 deletions lib/CONST.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ export const CONST = {

/**
* Display this amount to users to encourage them to book a call
*
*
* @type Number
*/
MAX_TRIAL_BONUS_DAYS: 42,

COUNTRY: {
US: 'US',
AU: 'AU',
Expand Down Expand Up @@ -295,6 +295,13 @@ export const CONST = {
*/
EMAIL_PART: EMAIL_BASE_REGEX,

/**
* Regex matching a text containing general phone number
*
* @type RegExp
*/
GENERAL_PHONE_PART: /(\+\d{1,2}\s?)?(\(\d{3}\)|\d{3})[\s.-]?\d{3}[\s.-]?\d{4}/,

/**
* Regex matching a text containing an E.164 format phone number
*/
Expand Down Expand Up @@ -357,6 +364,7 @@ export const CONST = {
* @type RegExp
*/
EMOJIS: /[\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3/gu,

/**
* Regex matching an text containing an Emoji that can be a single emoji or made up by some different emojis
*
Expand Down Expand Up @@ -537,7 +545,7 @@ export const CONST = {
'notifications@expensify.com',
],

/**
/**
* Emails that the user shouldn't submit reports to nor share reports with
* Any changes here should be reflected in the PHP constant,
* which is located in _constant.php and also named INVALID_APPROVER_AND_SHAREE_EMAILS
Expand Down
18 changes: 17 additions & 1 deletion lib/str.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -478,8 +478,24 @@ declare const Str: {
/**
* Check for whether a phone number is valid.
* @param phone
* @deprecated use isValidE164Phone to validate E.164 phone numbers or isValidPhoneFormat to validate phone numbers in general
*/
isValidPhone(phone: string): boolean;
/**
* Check for whether a phone number is valid according to E.164 standard.
* @param phone
*/
isValidE164Phone(phone: string): boolean;
/**
* Check for whether a phone number is valid in different formats/standards. For example:
* significant: 4404589784
* international: +1 440-458-9784
* e164: +14404589784
* national: (440) 458-9784
* 123.456.7890
* @param phone
*/
isValidPhoneFormat(phone: string): boolean;
/**
* We validate mentions by checking if it's first character is an allowed character.
*
Expand All @@ -493,7 +509,7 @@ declare const Str: {
*/
removeSMSDomain(text: string): string;
/**
* Returns true if the text is a valid phone number with our SMS domain removed
* Returns true if the text is a valid E.164 phone number with our SMS domain removed
*
* @param text
*/
Expand Down
30 changes: 28 additions & 2 deletions lib/str.js
Original file line number Diff line number Diff line change
Expand Up @@ -930,11 +930,37 @@ const Str = {
* @param {String} phone
*
* @return {bool}
* @deprecated use isValidE164Phone to validate E.164 phone numbers or isValidPhoneFormat to validate phone numbers in general
*/
isValidPhone(phone) {
return CONST.SMS.E164_REGEX.test(phone);
},

/**
* Check for whether a phone number is valid according to E.164 standard.
* @param {String} phone
*
* @return {bool}
*/
isValidE164Phone(phone) {
return CONST.SMS.E164_REGEX.test(phone);
},

/**
* Check for whether a phone number is valid in different formats/standards. For example:
* significant: 4404589784
* international: +1 440-458-9784
* e164: +14404589784
* national: (440) 458-9784
* 123.456.7890
* @param {String} phone
*
* @return {bool}
*/
isValidPhoneFormat(phone) {
return CONST.REG_EXP.GENERAL_PHONE_PART.test(phone);
},

/**
* We validate mentions by checking if it's first character is an allowed character.
*
Expand Down Expand Up @@ -965,13 +991,13 @@ const Str = {
},

/**
* Returns true if the text is a valid phone number with our SMS domain removed
* Returns true if the text is a valid E.164 phone number with our SMS domain removed
*
* @param {String} text
* @return {String}
*/
isSMSLogin(text) {
return this.isValidPhone(this.removeSMSDomain(text));
return this.isValidE164Phone(this.removeSMSDomain(text));
},

/**
Expand Down
Loading