From dc9ebb7355c3fcd4d0038bafbdba715b1329aa08 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Wed, 30 Nov 2022 11:04:35 +0100 Subject: [PATCH 1/7] Fixed: You can't search a room with names like 'x.y' --- src/libs/OptionsListUtils.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 50c60eeea5a92..90b5a0d96e8ac 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -146,7 +146,7 @@ function getParticipantNames(personalDetailList) { } /** - * A very optimized method to remove unique items from an array. + * A very optimized method to remove duplicates from an array. * Taken from https://stackoverflow.com/a/9229821/9114791 * * @param {Array} items @@ -186,7 +186,7 @@ function getSearchText(report, reportName, personalDetailList, isChatRoomOrPolic if (!isChatRoomOrPolicyExpenseChat) { for (let i = 0; i < personalDetailList.length; i++) { const personalDetail = personalDetailList[i]; - searchTerms = searchTerms.concat([personalDetail.displayName, personalDetail.login.replace(/\./g, '')]); + searchTerms = searchTerms.concat([personalDetail.displayName, personalDetail.login, personalDetail.login.replace(/\./g, '')]); } } if (report) { @@ -381,16 +381,13 @@ function createOption(logins, personalDetails, report, reportActions = {}, { * @returns {Boolean} */ function isSearchStringMatch(searchValue, searchText, participantNames = new Set(), isChatRoom = false) { - const searchWords = _.map( - searchValue - .replace(/\./g, '') - .replace(/,/g, ' ') - .split(' '), - word => word.trim(), - ); - return _.every(searchWords, (word) => { + const searchWords = _.compact(uniqFast([ + searchValue, + ..._.map(searchValue.replace(/,/g, ' ').split(' '), word => word.trim()), + ])); + const valueToSearch = searchText && searchText.replace(new RegExp(/ /g), ''); + return _.some(searchWords, (word) => { const matchRegex = new RegExp(Str.escapeForRegExp(word), 'i'); - const valueToSearch = searchText && searchText.replace(new RegExp(/ /g), ''); return matchRegex.test(valueToSearch) || (!isChatRoom && participantNames.has(word)); }); } From aa599993ddc31a93df08c1625df8c1672e1575e4 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Wed, 30 Nov 2022 12:00:41 +0100 Subject: [PATCH 2/7] Remove dots only from the local part of the email --- src/libs/OptionsListUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 90b5a0d96e8ac..bff780ef4e396 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -186,7 +186,7 @@ function getSearchText(report, reportName, personalDetailList, isChatRoomOrPolic if (!isChatRoomOrPolicyExpenseChat) { for (let i = 0; i < personalDetailList.length; i++) { const personalDetail = personalDetailList[i]; - searchTerms = searchTerms.concat([personalDetail.displayName, personalDetail.login, personalDetail.login.replace(/\./g, '')]); + searchTerms = searchTerms.concat([personalDetail.displayName, personalDetail.login, personalDetail.login.replace(/\.(?=[^\s@]*@)/g, '')]); } } if (report) { From 16493ff568f993395a9dcb480f7f7d2aa2df7180 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Thu, 1 Dec 2022 08:22:44 +0100 Subject: [PATCH 3/7] Updated a test --- tests/unit/OptionsListUtilsTest.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/OptionsListUtilsTest.js b/tests/unit/OptionsListUtilsTest.js index db6dffdc0f1ad..a807d6d165795 100644 --- a/tests/unit/OptionsListUtilsTest.js +++ b/tests/unit/OptionsListUtilsTest.js @@ -514,11 +514,11 @@ 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. + // 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); + // Then we should have no options at all but there should be a userToInvite + expect(results.recentReports.length).toBe(0); expect(results.userToInvite).not.toBe(null); // When we add a search term for which no options exist and the searchValue itself From 8057b09384f454a28d39ef277845e6637e7bd22c Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Thu, 1 Dec 2022 14:53:13 +0100 Subject: [PATCH 4/7] Added a comment about the dot remover email regex --- src/libs/OptionsListUtils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index bff780ef4e396..b84ae2311e379 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -186,6 +186,7 @@ function getSearchText(report, reportName, personalDetailList, isChatRoomOrPolic if (!isChatRoomOrPolicyExpenseChat) { for (let i = 0; i < personalDetailList.length; i++) { const personalDetail = personalDetailList[i]; + // The regex below is used to remove dots only from the local part of the user email (local-part@domain) searchTerms = searchTerms.concat([personalDetail.displayName, personalDetail.login, personalDetail.login.replace(/\.(?=[^\s@]*@)/g, '')]); } } From 988705c46136adc58deb1a28f56da99677eb80cf Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Thu, 1 Dec 2022 14:58:02 +0100 Subject: [PATCH 5/7] Added an empty line before comment (lint fix) --- src/libs/OptionsListUtils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index b84ae2311e379..e62e36848b71c 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -186,6 +186,7 @@ function getSearchText(report, reportName, personalDetailList, isChatRoomOrPolic if (!isChatRoomOrPolicyExpenseChat) { for (let i = 0; i < personalDetailList.length; i++) { const personalDetail = personalDetailList[i]; + // The regex below is used to remove dots only from the local part of the user email (local-part@domain) searchTerms = searchTerms.concat([personalDetail.displayName, personalDetail.login, personalDetail.login.replace(/\.(?=[^\s@]*@)/g, '')]); } From f337bcde57a75b883c90a94fbc49ab869a5f0ce5 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Fri, 2 Dec 2022 00:20:46 +0100 Subject: [PATCH 6/7] Update tests/unit/OptionsListUtilsTest.js Co-authored-by: Carlos Alvarez --- tests/unit/OptionsListUtilsTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/OptionsListUtilsTest.js b/tests/unit/OptionsListUtilsTest.js index a807d6d165795..9e63d1f076441 100644 --- a/tests/unit/OptionsListUtilsTest.js +++ b/tests/unit/OptionsListUtilsTest.js @@ -514,7 +514,7 @@ 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 + // When we add a search term with a period, with options for it that don't contain the period results = OptionsListUtils.getNewChatOptions(REPORTS, PERSONAL_DETAILS, [], 'peter.parker@expensify.com'); // Then we should have no options at all but there should be a userToInvite From 6c62e6004ee19198a95009e372f46c6aaaaf3c2e Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Fri, 2 Dec 2022 00:32:36 +0100 Subject: [PATCH 7/7] Update OptionsListUtils.js --- src/libs/OptionsListUtils.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index e62e36848b71c..6ae60712b19c0 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -188,6 +188,8 @@ function getSearchText(report, reportName, personalDetailList, isChatRoomOrPolic const personalDetail = personalDetailList[i]; // The regex below is used to remove dots only from the local part of the user email (local-part@domain) + // so that we can match emails that have dots without explicitly writing the dots (e.g: fistlast@domain will match first.last@domain) + // More info https://github.com/Expensify/App/issues/8007 searchTerms = searchTerms.concat([personalDetail.displayName, personalDetail.login, personalDetail.login.replace(/\.(?=[^\s@]*@)/g, '')]); } }