diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 8c600a2cb4e..7ca3e49b4b5 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -174,7 +174,7 @@ function getSearchText(report, personalDetailList, isChatRoomOrPolicyExpenseChat if (!isChatRoomOrPolicyExpenseChat) { _.each(personalDetailList, (personalDetail) => { searchTerms.push(personalDetail.displayName); - searchTerms.push(personalDetail.login); + searchTerms.push(personalDetail.login.replace(/\./g, '')); }); } if (report) { @@ -333,6 +333,7 @@ function createOption(personalDetailList, report, { function isSearchStringMatch(searchValue, searchText, participantNames = new Set(), isChatRoom = false) { const searchWords = _.map( searchValue + .replace(/\./g, '') .replace(/,/g, ' ') .split(' '), word => word.trim(), @@ -586,9 +587,9 @@ function getOptions(reports, personalDetails, activeReportID, { } let userToInvite = null; - if (searchValue - && recentReportOptions.length === 0 - && personalDetailsOptions.length === 0 + const noOptions = (recentReportOptions.length + personalDetailsOptions.length) === 0; + const noOptionsMatchExactly = !_.find(personalDetailsOptions.concat(recentReportOptions), option => option.login === searchValue.toLowerCase()); + if (searchValue && (noOptions || noOptionsMatchExactly) && !isCurrentUser({login: searchValue}) && _.every(selectedOptions, option => option.login !== searchValue) && ((Str.isValidEmail(searchValue) && !Str.isDomainEmail(searchValue)) || Str.isValidPhone(searchValue)) diff --git a/tests/unit/OptionsListUtilsTest.js b/tests/unit/OptionsListUtilsTest.js index dd401341639..15a9a797830 100644 --- a/tests/unit/OptionsListUtilsTest.js +++ b/tests/unit/OptionsListUtilsTest.js @@ -238,6 +238,15 @@ describe('OptionsListUtils', () => { }, }; + const PERSONAL_DETAILS_WITH_PERIODS = { + ...PERSONAL_DETAILS, + + 'barry.allen@expensify.com': { + displayName: 'The Flash', + login: 'barry.allen@expensify.com', + }, + }; + // Set the currently logged in user, report data, and personal details beforeAll(() => { Onyx.init({ @@ -277,6 +286,13 @@ describe('OptionsListUtils', () => { // Then we get both values with the pinned value still on top expect(results.recentReports.length).toBe(2); expect(results.recentReports[0].text).toBe('Mister Fantastic'); + + // When we filter again but provide a searchValue that should match with periods + results = OptionsListUtils.getSearchOptions(REPORTS, PERSONAL_DETAILS_WITH_PERIODS, 'barryallen@expensify.com'); + + // Then we expect to have the personal detail with period filtered + expect(results.recentReports.length).toBe(1); + expect(results.recentReports[0].text).toBe('The Flash'); }); it('getNewChatOptions()', () => { @@ -457,6 +473,13 @@ describe('OptionsListUtils', () => { expect(results.personalDetails.length).toBe(0); expect(results.userToInvite).not.toBe(null); + // When we add a search term for which exist options for it excluding its period. + results = OptionsListUtils.getNewChatOptions(REPORTS, PERSONAL_DETAILS, [], 'peter.parker@expensify.com'); + + // Then we will have an options at all and there should be a userToInvite too. + expect(results.recentReports.length).toBe(1); + expect(results.userToInvite).not.toBe(null); + // When we add a search term for which no options exist and the searchValue itself // is a potential phone number without country code added results = OptionsListUtils.getNewChatOptions(REPORTS, PERSONAL_DETAILS, [], '5005550006');