From 1f8b20bb6b69fe3ba5bac4f4e8df679e05847779 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 9 Apr 2026 11:57:01 +0700 Subject: [PATCH 1/5] refactor getValidOptions to use conciergeReportID from useOnyx --- .../Search/SearchFiltersChatsSelector.tsx | 3 +- src/hooks/useSearchSelector.base.ts | 10 +++--- src/libs/OptionsListUtils/index.ts | 14 ++++++-- src/pages/NewChatPage.tsx | 2 ++ .../MoneyRequestAccountantSelector.tsx | 3 ++ tests/unit/OptionsListUtilsTest.tsx | 36 ++++++++++++++----- 6 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/components/Search/SearchFiltersChatsSelector.tsx b/src/components/Search/SearchFiltersChatsSelector.tsx index 3f8fc264fbd9..2d11924c8199 100644 --- a/src/components/Search/SearchFiltersChatsSelector.tsx +++ b/src/components/Search/SearchFiltersChatsSelector.tsx @@ -54,6 +54,7 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen const [countryCode = CONST.DEFAULT_COUNTRY_CODE] = useOnyx(ONYXKEYS.COUNTRY_CODE); const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY); + const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const currentUserAccountID = currentUserPersonalDetails.accountID; const currentUserEmail = currentUserPersonalDetails.email ?? ''; @@ -75,7 +76,7 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen const report = getSelectedOptionData(createOptionFromReport({...reportData, reportID: id}, personalDetails, privateIsArchived, reportPolicy, reportAttributesDerived)); const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${reportData?.policyID}`]; const reportPolicyTags = policyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${getNonEmptyStringOnyxID(report?.policyID)}`]; - const alternateText = getAlternateText(report, {}, {isReportArchived: privateIsArchived, policy, reportAttributesDerived, policyTags: reportPolicyTags}); + const alternateText = getAlternateText(report, {}, {isReportArchived: privateIsArchived, policy, reportAttributesDerived, policyTags: reportPolicyTags, conciergeReportID}); return {...report, alternateText}; }); diff --git a/src/hooks/useSearchSelector.base.ts b/src/hooks/useSearchSelector.base.ts index 33901dc93cfb..137cdd777df2 100644 --- a/src/hooks/useSearchSelector.base.ts +++ b/src/hooks/useSearchSelector.base.ts @@ -201,6 +201,7 @@ function useSearchSelectorBase({ const currentUserEmail = currentUserPersonalDetails.email ?? ''; const personalDetails = usePersonalDetails(); const [allPolicyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {selector: passthroughPolicyTagListSelector}); + const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const onListEndReached = useDebounce( useCallback(() => { @@ -240,7 +241,7 @@ function useSearchSelectorBase({ personalDetails, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_MEMBER_INVITE: - return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, loginList, currentUserAccountID, currentUserEmail, { + return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, loginList, currentUserAccountID, currentUserEmail, conciergeReportID, { betas: betas ?? [], includeP2P: true, includeSelectedOptions: false, @@ -261,7 +262,7 @@ function useSearchSelectorBase({ sortedActions, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_GENERAL: - return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, loginList, currentUserAccountID, currentUserEmail, { + return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, loginList, currentUserAccountID, currentUserEmail, conciergeReportID, { betas: betas ?? [], searchString: computedSearchTerm, searchInputValue: trimmedSearchInput, @@ -284,7 +285,7 @@ function useSearchSelectorBase({ ...getValidOptionsConfig, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_SHARE_DESTINATION: - return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, loginList, currentUserAccountID, currentUserEmail, { + return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, loginList, currentUserAccountID, currentUserEmail, conciergeReportID, { betas, selectedOptions, includeMultipleParticipantReports: true, @@ -308,7 +309,7 @@ function useSearchSelectorBase({ sortedActions, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_ATTENDEES: - return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, loginList, currentUserAccountID, currentUserEmail, { + return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, loginList, currentUserAccountID, currentUserEmail, conciergeReportID, { betas: betas ?? [], includeP2P: true, includeSelectedOptions: false, @@ -348,6 +349,7 @@ function useSearchSelectorBase({ loginList, currentUserAccountID, currentUserEmail, + conciergeReportID, personalDetails, excludeLogins, excludeFromSuggestionsOnly, diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index a73d04680fb2..a3ce88ea4ac6 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -438,6 +438,7 @@ type GetAlternateTextConfig = { translate?: LocalizedTranslate; reportAttributesDerived?: ReportAttributesDerivedValue['reports']; policyTags?: OnyxEntry; + conciergeReportID: string | undefined; }; /** @@ -446,7 +447,7 @@ type GetAlternateTextConfig = { function getAlternateText( option: OptionData, {showChatPreviewLine = false, forcePolicyNamePreview = false}: PreviewConfig, - {isReportArchived, policy, lastActorDetails = {}, visibleReportActionsData = {}, translate, reportAttributesDerived, policyTags}: GetAlternateTextConfig, + {isReportArchived, policy, lastActorDetails = {}, visibleReportActionsData = {}, translate, reportAttributesDerived, policyTags, conciergeReportID}: GetAlternateTextConfig, ) { const report = getReportOrDraftReport(option.reportID); const isAdminRoom = reportUtilsIsAdminRoom(report); @@ -466,6 +467,7 @@ function getAlternateText( visibleReportActionsDataParam: visibleReportActionsData, reportAttributesDerived, policyTags, + conciergeReportID, }); const reportPrefix = getReportSubtitlePrefix(report); const formattedLastMessageTextWithPrefix = reportPrefix + formattedLastMessageText; @@ -1106,6 +1108,7 @@ function createOption({ translate: translateFn, reportAttributesDerived, policyTags, + conciergeReportID, }, ); @@ -2270,6 +2273,7 @@ function prepareReportOptionsForDisplay( currentUserAccountID: number, config: GetValidReportsConfig, visibleReportActionsData: VisibleReportActionsDerivedValue = {}, + conciergeReportID: string | undefined, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], // eslint-disable-next-line @typescript-eslint/no-deprecated sortedActions: Record = deprecatedAllSortedReportActions, @@ -2316,6 +2320,7 @@ function prepareReportOptionsForDisplay( visibleReportActionsData, reportAttributesDerived, policyTags: reportPolicyTags, + conciergeReportID, }, ); const isSelected = isReportSelected(option, selectedOptions); @@ -2438,6 +2443,7 @@ function getValidOptions( loginList: OnyxEntry, currentUserAccountID: number, currentUserEmail: string, + conciergeReportID: string | undefined, { excludeLogins = {}, excludeFromSuggestionsOnly = {}, @@ -2565,6 +2571,7 @@ function getValidOptions( personalDetails, }, visibleReportActionsData, + conciergeReportID, reportAttributesDerived, sortedActions, allPolicyTags, @@ -2588,6 +2595,7 @@ function getValidOptions( personalDetails, }, visibleReportActionsData, + conciergeReportID, reportAttributesDerived, sortedActions, allPolicyTags, @@ -2607,6 +2615,7 @@ function getValidOptions( personalDetails, }, visibleReportActionsData, + conciergeReportID, reportAttributesDerived, sortedActions, allPolicyTags, @@ -2765,7 +2774,8 @@ function getSearchOptions({ personalDetails, allPolicyTags, }: SearchOptionsConfig): Options { - const optionList = getValidOptions(options, policyCollection, draftComments, nvpDismissedProductTraining, loginList, currentUserAccountID, currentUserEmail, { + // TODO: We'll pass the conciergeReportID eventually. Refactor issue: https://github.com/Expensify/App/issues/66411 + const optionList = getValidOptions(options, policyCollection, draftComments, nvpDismissedProductTraining, loginList, currentUserAccountID, currentUserEmail, undefined, { betas, includeRecentReports, includeMultipleParticipantReports: true, diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index d80ab7d7d46b..f70cf97df231 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -78,6 +78,7 @@ function useOptions(reportAttributesDerived: ReportAttributesDerivedValue['repor const isScreenFocusedRef = useIsFocusedRef(); const [sortedActions] = useOnyx(ONYXKEYS.DERIVED.RAM_ONLY_SORTED_REPORT_ACTIONS, {selector: sortedActionsSelector}); const [allPolicyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {selector: passthroughPolicyTagListSelector}); + const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const { options: listOptions, @@ -111,6 +112,7 @@ function useOptions(reportAttributesDerived: ReportAttributesDerivedValue['repor loginList, currentUserAccountID, currentUserEmail, + conciergeReportID, { betas: betas ?? [], includeSelfDM: true, diff --git a/src/pages/iou/request/MoneyRequestAccountantSelector.tsx b/src/pages/iou/request/MoneyRequestAccountantSelector.tsx index 3b427160995f..17e95ed4270f 100644 --- a/src/pages/iou/request/MoneyRequestAccountantSelector.tsx +++ b/src/pages/iou/request/MoneyRequestAccountantSelector.tsx @@ -72,6 +72,7 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType const currentUserEmail = currentUserPersonalDetails.email ?? ''; const currentUserAccountID = currentUserPersonalDetails.accountID; const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY); + const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const privateIsArchivedMap = usePrivateIsArchivedMap(); useEffect(() => { @@ -94,6 +95,7 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType loginList, currentUserAccountID, currentUserEmail, + conciergeReportID, { betas, excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, @@ -123,6 +125,7 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType countryCode, currentUserAccountID, currentUserEmail, + conciergeReportID, personalDetails, ]); diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index e9d066817d96..503ac2805ac8 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -1052,7 +1052,16 @@ describe('OptionsListUtils', () => { it('should return empty options when no reports or personal details are provided', () => { // Given empty arrays of reports and personalDetails // When we call getValidOptions() - const results = getValidOptions({reports: [], personalDetails: []}, allPolicies, {}, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL); + const results = getValidOptions( + {reports: [], personalDetails: []}, + allPolicies, + {}, + nvpDismissedProductTraining, + loginList, + CURRENT_USER_ACCOUNT_ID, + CURRENT_USER_EMAIL, + undefined, + ); // Then the result should be empty expect(results.personalDetails).toEqual([]); @@ -1497,7 +1506,7 @@ describe('OptionsListUtils', () => { it('should include all reports by default', () => { // Given a set of reports and personalDetails that includes workspace rooms // When we call getValidOptions() - const results = getValidOptions(OPTIONS_WITH_WORKSPACE_ROOM, allPolicies, {}, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, { + const results = getValidOptions(OPTIONS_WITH_WORKSPACE_ROOM, allPolicies, {}, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined, { includeRecentReports: true, includeMultipleParticipantReports: true, includeP2P: true, @@ -1529,7 +1538,7 @@ describe('OptionsListUtils', () => { }; // When we call getValidOptions with shouldSeparateWorkspaceChat and personalDetails config - const results = getValidOptions(OPTIONS_WITH_WORKSPACE_ROOM, allPolicies, {}, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, { + const results = getValidOptions(OPTIONS_WITH_WORKSPACE_ROOM, allPolicies, {}, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined, { includeRecentReports: true, includeMultipleParticipantReports: true, includeP2P: true, @@ -1547,7 +1556,7 @@ describe('OptionsListUtils', () => { it('should handle undefined personalDetails config in workspace chat lookups', () => { // Given a set of reports with workspace rooms // When we call getValidOptions with shouldSeparateWorkspaceChat but no personalDetails config - const results = getValidOptions(OPTIONS_WITH_WORKSPACE_ROOM, allPolicies, {}, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, { + const results = getValidOptions(OPTIONS_WITH_WORKSPACE_ROOM, allPolicies, {}, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined, { includeRecentReports: true, includeMultipleParticipantReports: true, includeP2P: true, @@ -1564,7 +1573,7 @@ describe('OptionsListUtils', () => { it('should handle empty personalDetails config in workspace chat lookups', () => { // Given a set of reports with workspace rooms // When we call getValidOptions with shouldSeparateWorkspaceChat and empty personalDetails - const results = getValidOptions(OPTIONS_WITH_WORKSPACE_ROOM, allPolicies, {}, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, { + const results = getValidOptions(OPTIONS_WITH_WORKSPACE_ROOM, allPolicies, {}, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined, { includeRecentReports: true, includeMultipleParticipantReports: true, includeP2P: true, @@ -1581,7 +1590,7 @@ describe('OptionsListUtils', () => { it('should handle null personalDetails config in workspace chat lookups', () => { // Given a set of reports with workspace rooms // When we call getValidOptions with shouldSeparateWorkspaceChat and null personalDetails - const results = getValidOptions(OPTIONS_WITH_WORKSPACE_ROOM, allPolicies, {}, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, { + const results = getValidOptions(OPTIONS_WITH_WORKSPACE_ROOM, allPolicies, {}, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined, { includeRecentReports: true, includeMultipleParticipantReports: true, includeP2P: true, @@ -5214,7 +5223,16 @@ describe('OptionsListUtils', () => { const policies = {[`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`]: policy}; // Test that getValidOptions accepts policies collection as second parameter - const results = getValidOptions({reports: [], personalDetails: []}, policies, undefined, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL); + const results = getValidOptions( + {reports: [], personalDetails: []}, + policies, + undefined, + nvpDismissedProductTraining, + loginList, + CURRENT_USER_ACCOUNT_ID, + CURRENT_USER_EMAIL, + undefined, + ); expect(results).toBeDefined(); expect(results.recentReports).toBeDefined(); @@ -5223,7 +5241,7 @@ describe('OptionsListUtils', () => { it('should work with undefined policies', () => { const options = {reports: [], personalDetails: []}; - const results = getValidOptions(options, undefined, undefined, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL); + const results = getValidOptions(options, undefined, undefined, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined); expect(results).toBeDefined(); expect(results.recentReports).toBeDefined(); @@ -5232,7 +5250,7 @@ describe('OptionsListUtils', () => { it('should work with empty policies collection', () => { const options = {reports: [], personalDetails: []}; - const results = getValidOptions(options, {}, undefined, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL); + const results = getValidOptions(options, {}, undefined, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined); expect(results).toBeDefined(); expect(results.recentReports).toBeDefined(); From 83473a28509b4672a4d070304f96b777cb72cfb8 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 9 Apr 2026 12:45:08 +0700 Subject: [PATCH 2/5] lint fix --- src/libs/OptionsListUtils/index.ts | 8 +-- tests/perf-test/OptionsListUtils.perf-test.ts | 3 + tests/unit/OptionsListUtilsTest.tsx | 57 +++++++++++++++++++ 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index a3ce88ea4ac6..1d3aab7128d5 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -2272,8 +2272,8 @@ function prepareReportOptionsForDisplay( policiesCollection: OnyxCollection, currentUserAccountID: number, config: GetValidReportsConfig, - visibleReportActionsData: VisibleReportActionsDerivedValue = {}, conciergeReportID: string | undefined, + visibleReportActionsData: VisibleReportActionsDerivedValue = {}, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], // eslint-disable-next-line @typescript-eslint/no-deprecated sortedActions: Record = deprecatedAllSortedReportActions, @@ -2570,8 +2570,8 @@ function getValidOptions( shouldShowGBR, personalDetails, }, - visibleReportActionsData, conciergeReportID, + visibleReportActionsData, reportAttributesDerived, sortedActions, allPolicyTags, @@ -2594,8 +2594,8 @@ function getValidOptions( shouldShowGBR, personalDetails, }, - visibleReportActionsData, conciergeReportID, + visibleReportActionsData, reportAttributesDerived, sortedActions, allPolicyTags, @@ -2614,8 +2614,8 @@ function getValidOptions( shouldShowGBR, personalDetails, }, - visibleReportActionsData, conciergeReportID, + visibleReportActionsData, reportAttributesDerived, sortedActions, allPolicyTags, diff --git a/tests/perf-test/OptionsListUtils.perf-test.ts b/tests/perf-test/OptionsListUtils.perf-test.ts index 07e9c0cb3f96..a64cb4db02a9 100644 --- a/tests/perf-test/OptionsListUtils.perf-test.ts +++ b/tests/perf-test/OptionsListUtils.perf-test.ts @@ -156,6 +156,7 @@ describe('OptionsListUtils', () => { loginList, MOCK_CURRENT_USER_ACCOUNT_ID, MOCK_CURRENT_USER_EMAIL, + undefined, ValidOptionsConfig, ); await measureFunction(() => { @@ -172,6 +173,7 @@ describe('OptionsListUtils', () => { loginList, MOCK_CURRENT_USER_ACCOUNT_ID, MOCK_CURRENT_USER_EMAIL, + undefined, ValidOptionsConfig, ); await measureFunction(() => { @@ -191,6 +193,7 @@ describe('OptionsListUtils', () => { loginList, MOCK_CURRENT_USER_ACCOUNT_ID, MOCK_CURRENT_USER_EMAIL, + undefined, { betas: mockedBetas, includeMultipleParticipantReports: true, diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index 503ac2805ac8..f322168a789e 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -986,6 +986,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call orderOptions() results = orderOptions(results); @@ -1025,6 +1026,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call orderOptions() results = orderOptions(results); @@ -1083,6 +1085,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // Then the result should include all personalDetails except the currently logged in user @@ -1105,6 +1108,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { excludeLogins: {[CONST.EMAIL.CONCIERGE]: true}, }, @@ -1127,6 +1131,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { excludeLogins: {[CONST.EMAIL.CHRONOS]: true}, }, @@ -1152,6 +1157,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { excludeLogins: {[CONST.EMAIL.RECEIPTS]: true}, }, @@ -1179,6 +1185,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeP2P: true, canShowManagerMcTest: true, @@ -1203,6 +1210,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeP2P: true, canShowManagerMcTest: false, @@ -1236,6 +1244,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeP2P: true, canShowManagerMcTest: true, @@ -1293,6 +1302,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeMultipleParticipantReports: true, }, @@ -1347,6 +1357,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeMultipleParticipantReports: true, showRBR: true, @@ -1399,6 +1410,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeMultipleParticipantReports: true, showRBR: false, @@ -1455,6 +1467,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeRecentReports: true, shouldUnreadBeBold: true, @@ -1490,6 +1503,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { personalDetails: customPersonalDetails, }, @@ -1617,6 +1631,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); const reportLogins = new Set(results.recentReports.map((reportOption) => reportOption.login)); const personalDetailsOverlapWithReports = results.personalDetails.every((personalDetailOption) => reportLogins.has(personalDetailOption.login)); @@ -1638,6 +1653,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { excludeLogins: {'peterparker@expensify.com': true}, }, @@ -1659,6 +1675,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // Then the result should include all personalDetails except the currently logged in user @@ -1681,6 +1698,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { excludeLogins: {[CONST.EMAIL.CONCIERGE]: true}, }, @@ -1704,6 +1722,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { excludeLogins: {[CONST.EMAIL.CHRONOS]: true}, }, @@ -1730,6 +1749,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { excludeLogins: {[CONST.EMAIL.RECEIPTS]: true}, }, @@ -1754,6 +1774,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { maxRecentReportElements: maxRecentReports, }, @@ -1774,6 +1795,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); const resultsWithLimit = getValidOptions( {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, @@ -1783,6 +1805,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { maxRecentReportElements: 2, }, @@ -1803,6 +1826,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); const resultsWithLimit = getValidOptions( {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, @@ -1812,6 +1836,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { maxRecentReportElements: 2, }, @@ -1834,6 +1859,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { maxElements: maxTotalElements, maxRecentReportElements: maxRecentReports, @@ -1868,6 +1894,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { betas: [], includeMultipleParticipantReports: true, @@ -1909,6 +1936,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { betas: [], includeMultipleParticipantReports: true, @@ -2379,6 +2407,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, }, @@ -2489,6 +2518,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { betas: [], includeMultipleParticipantReports: true, @@ -2531,6 +2561,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { betas: [], includeMultipleParticipantReports: true, @@ -2573,6 +2604,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { betas: [], includeMultipleParticipantReports: true, @@ -2605,6 +2637,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call filterAndOrderOptions with a search value that matches a personal detail with no existing report const filteredOptions = filterAndOrderOptions(options, 'hulk', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, PERSONAL_DETAILS); @@ -2830,6 +2863,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call filterAndOrderOptions with a search value that does not match any personal details or reports const filteredOptions = filterAndOrderOptions(options, 'marc@expensify', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, PERSONAL_DETAILS); @@ -2851,6 +2885,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call filterAndOrderOptions with a search value that does not match any personal details or reports const filteredOptions = filterAndOrderOptions(options, 'marc@expensify.com', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, PERSONAL_DETAILS); @@ -2872,6 +2907,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call filterAndOrderOptions with a search value that does not match any personal details or reports but matches user to invite const filteredOptions = filterAndOrderOptions(options, 'peter.parker@expensify.com', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, PERSONAL_DETAILS); @@ -2892,6 +2928,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call filterAndOrderOptions with a search value without accent mark const filteredOptions = filterAndOrderOptions(options, 'Timothee', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, PERSONAL_DETAILS); @@ -2910,6 +2947,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call filterAndOrderOptions with a search value that does not match any personal details or reports but matches user to invite const filteredOptions = filterAndOrderOptions(options, '5005550006', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, PERSONAL_DETAILS); @@ -2933,6 +2971,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call filterAndOrderOptions with a search value that does not match any personal details or reports but matches user to invite const filteredOptions = filterAndOrderOptions(options, '+15005550006', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, PERSONAL_DETAILS); @@ -2956,6 +2995,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call filterAndOrderOptions with a search value that does not match any personal details or reports but matches user to invite const filteredOptions = filterAndOrderOptions(options, '+1 (800)324-3233', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, PERSONAL_DETAILS); @@ -2979,6 +3019,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call filterAndOrderOptions with a search value that does not match any personal details or reports const filteredOptions = filterAndOrderOptions(options, '998243aaaa', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, PERSONAL_DETAILS); @@ -3000,6 +3041,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeUserToInvite: true, }, @@ -3024,6 +3066,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeUserToInvite: true, }, @@ -3048,6 +3091,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call filterAndOrderOptions with a search value that does not match any personal details const filteredOptions = filterAndOrderOptions(options, 'magneto', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, PERSONAL_DETAILS); @@ -3066,6 +3110,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call filterAndOrderOptions with a search value that matches an email const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, PERSONAL_DETAILS, { @@ -3090,6 +3135,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call filterAndOrderOptions with a search value that matches both reports and personal details and maxRecentReportsToShow param const filteredOptions = filterAndOrderOptions(options, '.com', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, PERSONAL_DETAILS, { @@ -5282,6 +5328,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { betas: [], includeRecentReports: true, @@ -6662,6 +6709,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // Then the function should complete without errors and return valid results @@ -6680,6 +6728,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // When we call filterAndOrderOptions with the reports parameter @@ -6734,6 +6783,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // Then the function should still work correctly @@ -6752,6 +6802,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, ); // Then the function should still work correctly @@ -7385,6 +7436,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeRecentReports: true, includeMultipleParticipantReports: true, @@ -7448,6 +7500,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeRecentReports: true, action: CONST.IOU.ACTION.CREATE, @@ -7507,6 +7560,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeRecentReports: true, action: CONST.IOU.ACTION.CREATE, @@ -7592,6 +7646,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeRecentReports: true, includeMultipleParticipantReports: true, @@ -7671,6 +7726,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeRecentReports: true, sortedActions, @@ -7738,6 +7794,7 @@ describe('OptionsListUtils', () => { loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, + undefined, { includeRecentReports: true, action: CONST.IOU.ACTION.CREATE, From b0f8671240ed99529d004f9cf6477d89cf17f506 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 9 Apr 2026 23:35:01 +0700 Subject: [PATCH 3/5] fix test --- tests/unit/useSearchSelectorTest.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/unit/useSearchSelectorTest.tsx b/tests/unit/useSearchSelectorTest.tsx index e58167a8645d..d81776b33322 100644 --- a/tests/unit/useSearchSelectorTest.tsx +++ b/tests/unit/useSearchSelectorTest.tsx @@ -106,7 +106,7 @@ describe('useSearchSelector sortedActions integration', () => { expect(mockGetValidOptions).toHaveBeenCalled(); const lastCall = mockGetValidOptions.mock.calls.at(-1); - const config = lastCall?.[7]; + const config = lastCall?.[8]; expect(config?.sortedActions).toBeUndefined(); }); @@ -128,7 +128,7 @@ describe('useSearchSelector sortedActions integration', () => { expect(mockGetValidOptions).toHaveBeenCalled(); const lastCall = mockGetValidOptions.mock.calls.at(-1); - const config = lastCall?.[7]; + const config = lastCall?.[8]; expect(config?.sortedActions).toEqual(mockData.sortedActions); }); @@ -150,7 +150,7 @@ describe('useSearchSelector sortedActions integration', () => { expect(mockGetValidOptions).toHaveBeenCalled(); const lastCall = mockGetValidOptions.mock.calls.at(-1); - const config = lastCall?.[7]; + const config = lastCall?.[8]; expect(config?.sortedActions).toEqual(mockData.sortedActions); }); @@ -172,7 +172,7 @@ describe('useSearchSelector sortedActions integration', () => { expect(mockGetValidOptions).toHaveBeenCalled(); const lastCall = mockGetValidOptions.mock.calls.at(-1); - const config = lastCall?.[7]; + const config = lastCall?.[8]; expect(config?.sortedActions).toEqual(mockData.sortedActions); }); @@ -194,7 +194,7 @@ describe('useSearchSelector sortedActions integration', () => { expect(mockGetValidOptions).toHaveBeenCalled(); const lastCall = mockGetValidOptions.mock.calls.at(-1); - const config = lastCall?.[7]; + const config = lastCall?.[8]; expect(config?.sortedActions).toEqual(mockData.sortedActions); }); @@ -214,7 +214,7 @@ describe('useSearchSelector sortedActions integration', () => { ); await waitForBatchedUpdatesWithAct(); - const firstCallConfig = mockGetValidOptions.mock.calls.at(-1)?.[7]; + const firstCallConfig = mockGetValidOptions.mock.calls.at(-1)?.[8]; expect(firstCallConfig?.sortedActions).toEqual(initialData.sortedActions); const updatedData = buildMockSortedActions(['1', '2', '3']); @@ -223,7 +223,7 @@ describe('useSearchSelector sortedActions integration', () => { }); await waitForBatchedUpdatesWithAct(); - const latestCallConfig = mockGetValidOptions.mock.calls.at(-1)?.[7]; + const latestCallConfig = mockGetValidOptions.mock.calls.at(-1)?.[8]; expect(latestCallConfig?.sortedActions).toEqual(updatedData.sortedActions); }); From d3614ef6742752bf1d9ce71e61dadf0c11e70d55 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Fri, 10 Apr 2026 00:03:36 +0700 Subject: [PATCH 4/5] add conciergeReportID --- src/components/Search/FilterDropdowns/InSelectPopup.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/Search/FilterDropdowns/InSelectPopup.tsx b/src/components/Search/FilterDropdowns/InSelectPopup.tsx index ae29a78d9e8c..c0374fd18df5 100644 --- a/src/components/Search/FilterDropdowns/InSelectPopup.tsx +++ b/src/components/Search/FilterDropdowns/InSelectPopup.tsx @@ -71,6 +71,7 @@ function InSelectPopup({closeOverlay, updateFilterForm}: InSelectPopupProps) { const privateIsArchivedMap = usePrivateIsArchivedMap(); const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING); const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {selector: passthroughPolicyTagListSelector}); + const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const selectedOptions: OptionData[] = selectedReportIDs.map((id) => { const privateIsArchived = privateIsArchivedMap[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${id}`]; @@ -80,7 +81,7 @@ function InSelectPopup({closeOverlay, updateFilterForm}: InSelectPopupProps) { const isReportArchived = !!privateIsArchived; const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${reportData?.policyID}`]; const reportPolicyTags = policyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${getNonEmptyStringOnyxID(report?.policyID)}`]; - const alternateText = getAlternateText(report, {}, {isReportArchived, policy, reportAttributesDerived, policyTags: reportPolicyTags}); + const alternateText = getAlternateText(report, {}, {isReportArchived, policy, reportAttributesDerived, policyTags: reportPolicyTags, conciergeReportID}); return {...report, alternateText}; }); From a356d17275045f8180f8035ff5f5a49e87713ae4 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Fri, 10 Apr 2026 22:00:17 +0700 Subject: [PATCH 5/5] add tests --- tests/unit/OptionsListUtilsTest.tsx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index f322168a789e..d49e0253616c 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -1120,6 +1120,28 @@ describe('OptionsListUtils', () => { expect(results.personalDetails).not.toEqual(expect.arrayContaining([expect.objectContaining({login: 'concierge@expensify.com'})])); }); + it('should pass conciergeReportID through to options when provided', () => { + // Given a set of reports that includes Concierge and a valid conciergeReportID + const conciergeReportID = '11'; + // When we call getValidOptions() with a conciergeReportID + const results = getValidOptions( + {reports: OPTIONS_WITH_CONCIERGE.reports, personalDetails: OPTIONS_WITH_CONCIERGE.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + loginList, + CURRENT_USER_ACCOUNT_ID, + CURRENT_USER_EMAIL, + conciergeReportID, + ); + + // Then the result should still include Concierge in the results + expect(results.recentReports).toEqual(expect.arrayContaining([expect.objectContaining({login: 'concierge@expensify.com'})])); + // And the concierge report should have a valid reportID + const conciergeOption = results.recentReports.find((option) => option.login === 'concierge@expensify.com'); + expect(conciergeOption?.reportID).toBe(conciergeReportID); + }); + it('should exclude Chronos when excludedLogins is specified', () => { // Given a set of reports and personalDetails that includes Chronos and a config object that excludes Chronos // When we call getValidOptions()