diff --git a/src/CONST.js b/src/CONST.js index 30f9e24ae3e7..9e5823138368 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -785,7 +785,7 @@ const CONST = { US_PHONE_WITH_OPTIONAL_COUNTRY_CODE: /^(\+1)?\d{10}$/, DIGITS_AND_PLUS: /^\+?[0-9]*$/, PHONE_E164_PLUS: /^\+?[1-9]\d{1,14}$/, - PHONE_WITH_SPECIAL_CHARS: /^[+]*[(]{0,1}[0-9]{1,3}[)]{0,1}[-\s\\./0-9]{0,12}$/, + PHONE_WITH_SPECIAL_CHARS: /^\s*(?:\+?(\d{1,3}))?[-. (]*(\d{3})[-. )]*(\d{3})[-. ]*(\d{4})(?: *x(\d+))?\s*$/, ALPHABETIC_CHARS: /[a-zA-Z]+/, POSITIVE_INTEGER: /^\d+$/, NON_ALPHA_NUMERIC: /[^A-Za-z0-9+]/g, @@ -808,6 +808,7 @@ const CONST = { EMOJIS: /[\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3/gu, TAX_ID: /^\d{9}$/, NON_NUMERIC: /\D/g, + NON_NUMERIC_WITH_PLUS: /[^0-9+]/g, EMOJI_NAME: /:[\w+-]+:/g, EMOJI_SUGGESTIONS: /:[a-zA-Z0-9_+-]{1,40}$/, AFTER_FIRST_LINE_BREAK: /\n.*/g, diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 0f8c3828a543..cc45e6dad8f0 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -442,7 +442,7 @@ function getOptions(reports, personalDetails, { // When sortByReportTypeInSearch flag is true, recentReports will include the personalDetails options as well. sortByReportTypeInSearch = false, - searchValue = '', + searchInputValue = '', showChatPreviewLine = false, sortPersonalDetailsByAlphaAsc = true, forcePolicyNamePreview = false, @@ -450,6 +450,8 @@ function getOptions(reports, personalDetails, { let recentReportOptions = []; let personalDetailsOptions = []; const reportMapForLogins = {}; + const isPhoneNumber = CONST.REGEX.PHONE_WITH_SPECIAL_CHARS.test(searchInputValue); + const searchValue = isPhoneNumber ? searchInputValue.replace(CONST.REGEX.NON_NUMERIC_WITH_PLUS, '') : searchInputValue; // Filter out all the reports that shouldn't be displayed const filteredReports = _.filter(reports, report => ReportUtils.shouldReportBeInOptionList( @@ -641,7 +643,7 @@ function getSearchOptions( ) { return getOptions(reports, personalDetails, { betas, - searchValue: searchValue.trim(), + searchInputValue: searchValue.trim(), includeRecentReports: true, includeMultipleParticipantReports: true, maxRecentReportsToShow: 0, // Unlimited @@ -705,7 +707,7 @@ function getNewChatOptions( ) { return getOptions(reports, personalDetails, { betas, - searchValue: searchValue.trim(), + searchInputValue: searchValue.trim(), selectedOptions, excludeChatRooms: true, includeRecentReports: true, @@ -732,7 +734,7 @@ function getMemberInviteOptions( ) { return getOptions([], personalDetails, { betas, - searchValue: searchValue.trim(), + searchInputValue: searchValue.trim(), excludeDefaultRooms: true, includePersonalDetails: true, excludeLogins, diff --git a/tests/unit/OptionsListUtilsTest.js b/tests/unit/OptionsListUtilsTest.js index c48dec63801f..8a71c44e8825 100644 --- a/tests/unit/OptionsListUtilsTest.js +++ b/tests/unit/OptionsListUtilsTest.js @@ -515,6 +515,17 @@ describe('OptionsListUtils', () => { expect(results.userToInvite).not.toBe(null); expect(results.userToInvite.login).toBe('+15005550006'); + // When we add a search term for which no options exist and the searchValue itself + // is a potential phone number with special characters added + results = OptionsListUtils.getNewChatOptions(REPORTS, PERSONAL_DETAILS, [], '+1 (800)324-3233'); + + // Then we should have no options or personal details at all but there should be a userToInvite and the login + // should have the country code included + expect(results.recentReports.length).toBe(0); + expect(results.personalDetails.length).toBe(0); + expect(results.userToInvite).not.toBe(null); + expect(results.userToInvite.login).toBe('+18003243233'); + // Test Concierge's existence in new group options results = OptionsListUtils.getNewChatOptions(REPORTS_WITH_CONCIERGE, PERSONAL_DETAILS_WITH_CONCIERGE);