From 103437306f6fbc4ea7081b9e323b87576525a87d Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Wed, 19 Nov 2025 17:08:17 +0100 Subject: [PATCH 01/39] migrate options list utils to use temporary getForReportAction --- .../LHNOptionsList/LHNOptionsList.tsx | 7 +- .../LHNOptionsList/OptionRowLHNData.tsx | 9 + src/components/OptionListContextProvider.tsx | 12 +- .../FilterDropdowns/UserSelectPopup.tsx | 3 +- .../Search/SearchAutocompleteList.tsx | 3 + .../Search/SearchFiltersChatsSelector.tsx | 16 +- .../SearchFiltersParticipantsSelector.tsx | 4 +- .../Search/SearchRouter/SearchRouter.tsx | 5 +- src/hooks/useSearchSelector.base.ts | 8 +- src/libs/ContactUtils.ts | 1 + src/libs/OptionsListUtils/index.ts | 151 +++++++--- src/libs/OptionsListUtils/types.ts | 3 +- src/libs/SidebarUtils.ts | 16 +- src/pages/NewChatPage.tsx | 6 +- src/pages/RoomInvitePage.tsx | 4 +- src/pages/Share/ShareDetailsPage.tsx | 6 +- src/pages/Share/ShareTab.tsx | 1 + src/pages/Share/SubmitDetailsPage.tsx | 2 +- src/pages/iou/SplitBillDetailsPage.tsx | 3 +- .../MoneyRequestAccountantSelector.tsx | 6 +- .../request/MoneyRequestAttendeeSelector.tsx | 6 +- .../MoneyRequestParticipantsSelector.tsx | 3 +- .../iou/request/step/IOURequestStepAmount.tsx | 3 +- .../step/IOURequestStepConfirmation.tsx | 13 +- .../request/step/IOURequestStepDistance.tsx | 4 +- .../step/IOURequestStepDistanceManual.tsx | 4 +- .../step/IOURequestStepDistanceMap.tsx | 4 +- .../step/IOURequestStepScan/index.native.tsx | 6 +- .../request/step/IOURequestStepScan/index.tsx | 6 +- tests/perf-test/OptionsListUtils.perf-test.ts | 19 +- tests/perf-test/SearchRouter.perf-test.tsx | 2 +- tests/perf-test/SidebarUtils.perf-test.ts | 1 + tests/unit/OptionsListUtilsTest.tsx | 268 ++++++++++-------- tests/unit/SidebarUtilsTest.ts | 16 ++ 34 files changed, 391 insertions(+), 230 deletions(-) diff --git a/src/components/LHNOptionsList/LHNOptionsList.tsx b/src/components/LHNOptionsList/LHNOptionsList.tsx index 91995ac2b304b..9a153f765d3af 100644 --- a/src/components/LHNOptionsList/LHNOptionsList.tsx +++ b/src/components/LHNOptionsList/LHNOptionsList.tsx @@ -16,7 +16,6 @@ import TextBlock from '@components/TextBlock'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; -import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; import usePrevious from '@hooks/usePrevious'; import useRootNavigationState from '@hooks/useRootNavigationState'; import useScrollEventEmitter from '@hooks/useScrollEventEmitter'; @@ -67,7 +66,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const [isFullscreenVisible] = useOnyx(ONYXKEYS.FULLSCREEN_VISIBILITY, {canBeMissing: true}); - const {policyForMovingExpensesID} = usePolicyForMovingExpenses(); + const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); const theme = useTheme(); const styles = useThemeStyles(); @@ -174,6 +173,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio const itemParentReportActions = reportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${item?.parentReportID}`]; const itemParentReportAction = item?.parentReportActionID ? itemParentReportActions?.[item?.parentReportActionID] : undefined; const itemReportAttributes = reportAttributes?.[reportID]; + const itemPolicyTags = policyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${item?.policyID}`]; let invoiceReceiverPolicyID = '-1'; if (item?.invoiceReceiver && 'policyID' in item.invoiceReceiver) { @@ -227,7 +227,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio movedToReport, policy: itemPolicy, isReportArchived: !!itemReportNameValuePairs?.private_isArchived, - policyForMovingExpensesID, + policyTags: itemPolicyTags, }); const shouldShowRBRorGBRTooltip = firstReportIDWithGBRorRBR === reportID; @@ -298,7 +298,6 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio transactions, draftComments, personalDetails, - policyForMovingExpensesID, firstReportIDWithGBRorRBR, optionMode, shouldDisableFocusOptions, diff --git a/src/components/LHNOptionsList/OptionRowLHNData.tsx b/src/components/LHNOptionsList/OptionRowLHNData.tsx index 5f60fd84ad5a5..9c99850eee703 100644 --- a/src/components/LHNOptionsList/OptionRowLHNData.tsx +++ b/src/components/LHNOptionsList/OptionRowLHNData.tsx @@ -3,6 +3,7 @@ import React, {useMemo, useRef} from 'react'; import useCurrentReportID from '@hooks/useCurrentReportID'; import useGetExpensifyCardFromReportAction from '@hooks/useGetExpensifyCardFromReportAction'; import useOnyx from '@hooks/useOnyx'; +import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; import usePrevious from '@hooks/usePrevious'; import SidebarUtils from '@libs/SidebarUtils'; import CONST from '@src/CONST'; @@ -46,9 +47,14 @@ function OptionRowLHNData({ const currentReportIDValue = useCurrentReportID(); const isReportFocused = isOptionFocused && currentReportIDValue?.currentReportID === reportID; const optionItemRef = useRef(undefined); + const {policyForMovingExpensesID} = usePolicyForMovingExpenses(); const [movedFromReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(lastAction, CONST.REPORT.MOVE_TYPE.FROM)}`, {canBeMissing: true}); const [movedToReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(lastAction, CONST.REPORT.MOVE_TYPE.TO)}`, {canBeMissing: true}); + + // Determine the correct policy ID for fetching policy tags + const policyIDForTags = fullReport?.policyID === CONST.POLICY.OWNER_EMAIL_FAKE && policyForMovingExpensesID ? policyForMovingExpensesID : fullReport?.policyID; + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyIDForTags}`, {canBeMissing: true}); // Check the report errors equality to avoid re-rendering when there are no changes const prevReportErrors = usePrevious(reportAttributes?.reportErrors); const areReportErrorsEqual = useMemo(() => deepEqual(prevReportErrors, reportAttributes?.reportErrors), [prevReportErrors, reportAttributes?.reportErrors]); @@ -74,6 +80,7 @@ function OptionRowLHNData({ lastActionReport, movedFromReport, movedToReport, + policyTags, }); // eslint-disable-next-line react-compiler/react-compiler if (deepEqual(item, optionItemRef.current)) { @@ -111,6 +118,8 @@ function OptionRowLHNData({ isReportArchived, movedFromReport, movedToReport, + policyTags, + policyForMovingExpensesID, ]); return ( diff --git a/src/components/OptionListContextProvider.tsx b/src/components/OptionListContextProvider.tsx index 0b42aabfffc05..51acc4ff7c74b 100644 --- a/src/components/OptionListContextProvider.tsx +++ b/src/components/OptionListContextProvider.tsx @@ -55,14 +55,15 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { const personalDetails = usePersonalDetails(); const prevPersonalDetails = usePrevious(personalDetails); const hasInitialData = useMemo(() => Object.keys(personalDetails ?? {}).length > 0, [personalDetails]); + const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); const loadOptions = useCallback(() => { - const optionLists = createOptionList(personalDetails, reports, reportAttributes?.reports); + const optionLists = createOptionList(personalDetails, policyTags, reports, reportAttributes?.reports); setOptions({ reports: optionLists.reports, personalDetails: optionLists.personalDetails, }); - }, [personalDetails, reports, reportAttributes?.reports]); + }, [personalDetails, reports, reportAttributes?.reports, policyTags]); /** * This effect is responsible for generating the options list when their data is not yet initialized @@ -182,7 +183,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { // Handle initial personal details load. This initialization is required here specifically to prevent // UI freezing that occurs when resetting the app from the troubleshooting page. if (!prevPersonalDetails) { - const {personalDetails: newPersonalDetailsOptions, reports: newReports} = createOptionList(personalDetails, reports, reportAttributes?.reports); + const {personalDetails: newPersonalDetailsOptions, reports: newReports} = createOptionList(personalDetails, policyTags, reports, reportAttributes?.reports); setOptions((prevOptions) => ({ ...prevOptions, personalDetails: newPersonalDetailsOptions, @@ -210,7 +211,8 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { if (!report) { return; } - const newReportOption = createOptionFromReport(report, personalDetails, reportAttributes?.reports); + const reportPolicyTags = policyTags?.[report.policyID ?? '']; + const newReportOption = createOptionFromReport(report, personalDetails, reportPolicyTags, reportAttributes?.reports); const replaceIndex = options.reports.findIndex((option) => option.reportID === report.reportID); newReportOptions.push({ newReportOption, @@ -220,7 +222,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { }); // since personal details are not a collection, we need to recreate the whole list from scratch - const newPersonalDetailsOptions = createOptionList(personalDetails, reports, reportAttributes?.reports).personalDetails; + const newPersonalDetailsOptions = createOptionList(personalDetails, policyTags, reports, reportAttributes?.reports).personalDetails; setOptions((prevOptions) => { const newOptions = {...prevOptions}; diff --git a/src/components/Search/FilterDropdowns/UserSelectPopup.tsx b/src/components/Search/FilterDropdowns/UserSelectPopup.tsx index 81596ebf2d892..d0504e3646b15 100644 --- a/src/components/Search/FilterDropdowns/UserSelectPopup.tsx +++ b/src/components/Search/FilterDropdowns/UserSelectPopup.tsx @@ -91,6 +91,7 @@ function UserSelectPopup({value, closeOverlay, onChange}: UserSelectPopupProps) }, draftComments, nvpDismissedProductTraining, + undefined, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, includeCurrentUser: true, @@ -100,7 +101,7 @@ function UserSelectPopup({value, closeOverlay, onChange}: UserSelectPopupProps) }, [options.reports, options.personalDetails, draftComments, nvpDismissedProductTraining, countryCode]); const filteredOptions = useMemo(() => { - return filterAndOrderOptions(optionsList, cleanSearchTerm, countryCode, { + return filterAndOrderOptions(optionsList, cleanSearchTerm, countryCode, undefined, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, canInviteUser: false, diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx index 3cda7e435e24e..fd08536edcaac 100644 --- a/src/components/Search/SearchAutocompleteList.tsx +++ b/src/components/Search/SearchAutocompleteList.tsx @@ -205,6 +205,7 @@ function SearchAutocompleteList({ includeCurrentUser: true, countryCode, shouldShowGBR: false, + policyTags: undefined, }); }, [areOptionsInitialized, options, draftComments, nvpDismissedProductTraining, betas, autocompleteQueryValue, countryCode]); @@ -416,6 +417,7 @@ function SearchAutocompleteList({ includeCurrentUser: true, countryCode, shouldShowGBR: true, + policyTags: undefined, }).personalDetails.filter((participant) => participant.text && !alreadyAutocompletedKeys.has(participant.text.toLowerCase())); return participants.map((participant) => ({ @@ -440,6 +442,7 @@ function SearchAutocompleteList({ includeCurrentUser: false, countryCode, shouldShowGBR: true, + policyTags: undefined, }).recentReports; return filteredReports.map((chat) => ({ diff --git a/src/components/Search/SearchFiltersChatsSelector.tsx b/src/components/Search/SearchFiltersChatsSelector.tsx index da088e59ba007..28ced7c51ae3b 100644 --- a/src/components/Search/SearchFiltersChatsSelector.tsx +++ b/src/components/Search/SearchFiltersChatsSelector.tsx @@ -57,25 +57,28 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, {canBeMissing: true}); const archivedReportsIdSet = useArchivedReportsIdSet(); const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); - + const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); const selectedOptions = useMemo(() => { return selectedReportIDs.map((id) => { - const report = getSelectedOptionData(createOptionFromReport({...reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`], reportID: id}, personalDetails, reportAttributesDerived)); + const reportObj = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`]; + const report = getSelectedOptionData( + createOptionFromReport({...reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`], reportID: id}, personalDetails, policyTags?.[reportObj?.policyID ?? ''], reportAttributesDerived), + ); const isReportArchived = archivedReportsIdSet.has(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`); - const alternateText = getAlternateText(report, {}, isReportArchived, {}); + const alternateText = getAlternateText(report, {}, policyTags?.[report.policyID ?? ''], isReportArchived, {}); return {...report, alternateText}; }); - }, [archivedReportsIdSet, personalDetails, reportAttributesDerived, reports, selectedReportIDs]); + }, [archivedReportsIdSet, personalDetails, reportAttributesDerived, reports, selectedReportIDs, policyTags]); const defaultOptions = useMemo(() => { if (!areOptionsInitialized || !isScreenTransitionEnd) { return defaultListOptions; } - return getSearchOptions({options, draftComments, nvpDismissedProductTraining, betas: undefined, isUsedInChatFinder: false, countryCode}); + return getSearchOptions({options, draftComments, nvpDismissedProductTraining, betas: undefined, policyTags: undefined, isUsedInChatFinder: false, countryCode}); }, [areOptionsInitialized, draftComments, nvpDismissedProductTraining, isScreenTransitionEnd, options, countryCode]); const chatOptions = useMemo(() => { - return filterAndOrderOptions(defaultOptions, cleanSearchTerm, countryCode, { + return filterAndOrderOptions(defaultOptions, cleanSearchTerm, countryCode, undefined, { selectedOptions, excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, }); @@ -92,6 +95,7 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen selectedOptions, chatOptions.recentReports, chatOptions.personalDetails, + undefined, personalDetails, false, undefined, diff --git a/src/components/Search/SearchFiltersParticipantsSelector.tsx b/src/components/Search/SearchFiltersParticipantsSelector.tsx index 5d3242545ad01..4e1b63e6086b7 100644 --- a/src/components/Search/SearchFiltersParticipantsSelector.tsx +++ b/src/components/Search/SearchFiltersParticipantsSelector.tsx @@ -66,6 +66,7 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: }, draftComments, nvpDismissedProductTraining, + undefined, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, includeCurrentUser: true, @@ -79,7 +80,7 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: }, [defaultOptions, selectedOptions]); const chatOptions = useMemo(() => { - const filteredOptions = filterAndOrderOptions(unselectedOptions, cleanSearchTerm, countryCode, { + const filteredOptions = filterAndOrderOptions(unselectedOptions, cleanSearchTerm, countryCode, undefined, { selectedOptions, excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, @@ -107,6 +108,7 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: selectedOptions, chatOptions.recentReports, chatOptions.personalDetails, + undefined, personalDetails, true, undefined, diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index ff2d80b0ddbeb..ec75d32c161f5 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -108,6 +108,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla const [allFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER, {canBeMissing: true}); const {shouldUseNarrowLayout} = useResponsiveLayout(); const listRef = useRef(null); + const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: true}); // The actual input text that the user sees const [textInputValue, , setTextInputValue] = useDebouncedState('', 500); @@ -151,8 +152,8 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla if (!report) { return undefined; } - - const option = createOptionFromReport(report, personalDetails); + const reportPolicyTags = policyTags?.[report.policyID ?? '']; + const option = createOptionFromReport(report, personalDetails, reportPolicyTags); reportForContextualSearch = option; } diff --git a/src/hooks/useSearchSelector.base.ts b/src/hooks/useSearchSelector.base.ts index e6897611ca73c..88aaec8838610 100644 --- a/src/hooks/useSearchSelector.base.ts +++ b/src/hooks/useSearchSelector.base.ts @@ -185,9 +185,10 @@ function useSearchSelectorBase({ maxResults, includeUserToInvite, countryCode, + policyTags: undefined, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_MEMBER_INVITE: - return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, { + return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, undefined, { betas: betas ?? [], includeP2P: true, includeSelectedOptions: false, @@ -199,7 +200,7 @@ function useSearchSelectorBase({ includeUserToInvite, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_GENERAL: - return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, { + return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, undefined, { ...getValidOptionsConfig, betas: betas ?? [], searchString: computedSearchTerm, @@ -213,6 +214,7 @@ function useSearchSelectorBase({ optionsWithContacts, draftComments, nvpDismissedProductTraining, + undefined, { betas, includeMultipleParticipantReports: true, @@ -229,7 +231,7 @@ function useSearchSelectorBase({ countryCode, ); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_SHARE_DESTINATION: - return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, { + return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, undefined, { betas, selectedOptions, includeMultipleParticipantReports: true, diff --git a/src/libs/ContactUtils.ts b/src/libs/ContactUtils.ts index f5945491a4ce4..8c834f0e305c6 100644 --- a/src/libs/ContactUtils.ts +++ b/src/libs/ContactUtils.ts @@ -48,6 +48,7 @@ const getContacts = (deviceContacts: DeviceContact[] | [], localeCompare: Locale phone: phoneNumber, avatar: avatarSource, countryCode, + policyTags: undefined, }); }) .filter((contact): contact is SearchOption => contact !== null); diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index 1a6c796a76c7b..faa003ac39770 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -18,7 +18,7 @@ import {translateLocal} from '@libs/Localize'; import {appendCountryCode, getPhoneNumberWithoutSpecialChars} from '@libs/LoginUtils'; import {MaxHeap} from '@libs/MaxHeap'; import {MinHeap} from '@libs/MinHeap'; -import {getForReportAction} from '@libs/ModifiedExpenseMessage'; +import {getForReportActionTemp} from '@libs/ModifiedExpenseMessage'; import Navigation from '@libs/Navigation/Navigation'; import Parser from '@libs/Parser'; import Performance from '@libs/Performance'; @@ -465,6 +465,7 @@ function shouldShowLastActorDisplayName(report: OnyxEntry, lastActorDeta function getAlternateText( option: OptionData, {showChatPreviewLine = false, forcePolicyNamePreview = false}: PreviewConfig, + policyTags: OnyxEntry, isReportArchived: boolean | undefined, lastActorDetails: Partial | null = {}, ) { @@ -474,7 +475,7 @@ function getAlternateText( const isGroupChat = reportUtilsIsGroupChat(report); const isExpenseThread = isMoneyRequest(report); const formattedLastMessageText = - formatReportLastMessageText(Parser.htmlToText(option.lastMessageText ?? '')) || getLastMessageTextForReport({report, lastActorDetails, isReportArchived}); + formatReportLastMessageText(Parser.htmlToText(option.lastMessageText ?? '')) || getLastMessageTextForReport({report, lastActorDetails, isReportArchived, policyTags}); const reportPrefix = getReportSubtitlePrefix(report); const formattedLastMessageTextWithPrefix = reportPrefix + formattedLastMessageText; @@ -601,7 +602,7 @@ function getLastMessageTextForReport({ movedToReport, policy, isReportArchived = false, - policyForMovingExpensesID, + policyTags, }: { report: OnyxEntry; lastActorDetails: Partial | null; @@ -609,7 +610,7 @@ function getLastMessageTextForReport({ movedToReport?: OnyxEntry; policy?: OnyxEntry; isReportArchived?: boolean; - policyForMovingExpensesID?: string; + policyTags: OnyxEntry; }): string { const reportID = report?.reportID; const lastReportAction = reportID ? lastVisibleReportActions[reportID] : undefined; @@ -688,12 +689,11 @@ function getLastMessageTextForReport({ // eslint-disable-next-line @typescript-eslint/no-deprecated lastMessageTextFromReport = `[${translateLocal('common.attachment')}]`; } else if (isModifiedExpenseAction(lastReportAction)) { - const properSchemaForModifiedExpenseMessage = getForReportAction({ + const properSchemaForModifiedExpenseMessage = getForReportActionTemp({ reportAction: lastReportAction, - policyID: report?.policyID, movedFromReport, movedToReport, - policyForMovingExpensesID, + policyTags, }); lastMessageTextFromReport = formatReportLastMessageText(properSchemaForModifiedExpenseMessage, true); } else if (isMovedTransactionAction(lastReportAction)) { @@ -832,6 +832,7 @@ function createOption( accountIDs: number[], personalDetails: OnyxInputOrEntry, report: OnyxInputOrEntry, + policyTags: OnyxEntry = CONST.POLICY.DEFAULT_TAG_LIST, config?: PreviewConfig, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], ): SearchOptionData { @@ -908,11 +909,11 @@ function createOption( // If displaying chat preview line is needed, let's overwrite the default alternate text const lastActorDetails = personalDetails?.[report?.lastActorAccountID ?? String(CONST.DEFAULT_NUMBER_ID)] ?? {}; - result.lastMessageText = getLastMessageTextForReport({report, lastActorDetails, isReportArchived: !!result.private_isArchived}); + result.lastMessageText = getLastMessageTextForReport({report, lastActorDetails, isReportArchived: !!result.private_isArchived, policyTags}); result.alternateText = showPersonalDetails && personalDetail?.login ? personalDetail.login - : getAlternateText(result, {showChatPreviewLine, forcePolicyNamePreview}, !!result.private_isArchived, lastActorDetails); + : getAlternateText(result, {showChatPreviewLine, forcePolicyNamePreview}, policyTags, !!result.private_isArchived, lastActorDetails); reportName = showPersonalDetails ? getDisplayNameForParticipant({accountID: accountIDs.at(0)}) || formatPhoneNumber(personalDetail?.login ?? '') : getReportName(report); } else { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing @@ -939,7 +940,12 @@ function createOption( /** * Get the option for a given report. */ -function getReportOption(participant: Participant, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], reportDrafts?: OnyxCollection): OptionData { +function getReportOption( + participant: Participant, + policyTags: OnyxEntry, + reportAttributesDerived?: ReportAttributesDerivedValue['reports'], + reportDrafts?: OnyxCollection, +): OptionData { const report = getReportOrDraftReport(participant.reportID, undefined, undefined, reportDrafts); const visibleParticipantAccountIDs = getParticipantsAccountIDsForDisplay(report, true); @@ -947,6 +953,7 @@ function getReportOption(participant: Participant, reportAttributesDerived?: Rep visibleParticipantAccountIDs, allPersonalDetails ?? {}, !isEmptyObject(report) ? report : undefined, + policyTags, { showChatPreviewLine: false, forcePolicyNamePreview: false, @@ -989,13 +996,19 @@ function getReportOption(participant: Participant, reportAttributesDerived?: Rep /** * Get the display option for a given report. */ -function getReportDisplayOption(report: OnyxEntry, unknownUserDetails: OnyxEntry, reportAttributesDerived?: ReportAttributesDerivedValue['reports']): OptionData { +function getReportDisplayOption( + report: OnyxEntry, + unknownUserDetails: OnyxEntry, + policyTags: OnyxEntry, + reportAttributesDerived?: ReportAttributesDerivedValue['reports'], +): OptionData { const visibleParticipantAccountIDs = getParticipantsAccountIDsForDisplay(report, true); const option = createOption( visibleParticipantAccountIDs, allPersonalDetails ?? {}, !isEmptyObject(report) ? report : undefined, + policyTags, { showChatPreviewLine: false, forcePolicyNamePreview: false, @@ -1029,7 +1042,11 @@ function getReportDisplayOption(report: OnyxEntry, unknownUserDetails: O /** * Get the option for a policy expense report. */ -function getPolicyExpenseReportOption(participant: Participant | SearchOptionData, reportAttributesDerived?: ReportAttributesDerivedValue['reports']): SearchOptionData { +function getPolicyExpenseReportOption( + participant: Participant | SearchOptionData, + policyTags: OnyxEntry, + reportAttributesDerived?: ReportAttributesDerivedValue['reports'], +): SearchOptionData { const expenseReport = reportUtilsIsPolicyExpenseChat(participant) ? getReportOrDraftReport(participant.reportID) : null; const visibleParticipantAccountIDs = Object.entries(expenseReport?.participants ?? {}) @@ -1040,6 +1057,7 @@ function getPolicyExpenseReportOption(participant: Participant | SearchOptionDat visibleParticipantAccountIDs, allPersonalDetails ?? {}, !isEmptyObject(expenseReport) ? expenseReport : null, + policyTags, { showChatPreviewLine: false, forcePolicyNamePreview: false, @@ -1182,7 +1200,12 @@ function processReport( }; } -function createOptionList(personalDetails: OnyxEntry, reports?: OnyxCollection, reportAttributesDerived?: ReportAttributesDerivedValue['reports']) { +function createOptionList( + personalDetails: OnyxEntry, + policyTags: OnyxCollection, + reports?: OnyxCollection, + reportAttributesDerived?: ReportAttributesDerivedValue['reports'], +) { const span = Sentry.startInactiveSpan({name: 'createOptionList'}); const reportMapForAccountIDs: Record = {}; @@ -1209,6 +1232,7 @@ function createOptionList(personalDetails: OnyxEntry, repor [personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID], personalDetails, reportMapForAccountIDs[personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID], + policyTags?.[reportMapForAccountIDs[personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID]?.policyID ?? ''] ?? CONST.POLICY.DEFAULT_TAG_LIST, { showPersonalDetails: true, }, @@ -1228,7 +1252,12 @@ function createOptionList(personalDetails: OnyxEntry, repor }; } -function createOptionFromReport(report: Report, personalDetails: OnyxEntry, reportAttributesDerived?: ReportAttributesDerivedValue['reports']) { +function createOptionFromReport( + report: Report, + personalDetails: OnyxEntry, + policyTags: OnyxEntry, + reportAttributesDerived?: ReportAttributesDerivedValue['reports'], +) { const accountIDs = getParticipantsAccountIDsForDisplay(report); return { @@ -1237,6 +1266,7 @@ function createOptionFromReport(report: Report, personalDetails: OnyxEntry, config: IsValidReportsConfi * @param config - Configuration object specifying display preferences and filtering criteria * @returns Array of enriched and filtered report options ready for UI display */ -function prepareReportOptionsForDisplay(options: Array>, config: GetValidReportsConfig): Array> { +function prepareReportOptionsForDisplay(options: Array>, config: GetValidReportsConfig, policyTags: OnyxEntry): Array> { const { showChatPreviewLine = false, forcePolicyNamePreview = false, @@ -1839,7 +1871,8 @@ function prepareReportOptionsForDisplay(options: Array>, co * By default, generated options does not have the chat preview line enabled. * If showChatPreviewLine or forcePolicyNamePreview are true, let's generate and overwrite the alternate text. */ - const alternateText = getAlternateText(option, {showChatPreviewLine, forcePolicyNamePreview}, !!option.private_isArchived); + console.log({showChatPreviewLine, forcePolicyNamePreview}); + const alternateText = getAlternateText(option, {showChatPreviewLine, forcePolicyNamePreview}, policyTags, !!option.private_isArchived); const isSelected = isReportSelected(option, selectedOptions); const isBold = shouldBoldTitleByDefault || shouldUseBoldText(option); @@ -1941,6 +1974,7 @@ function getValidOptions( options: OptionList, draftComments: OnyxCollection | undefined, nvpDismissedProductTraining: OnyxEntry, + policyTags: OnyxEntry, { excludeLogins = {}, includeSelectedOptions = false, @@ -2028,36 +2062,48 @@ function getValidOptions( [selfDMChats, workspaceChats, recentReportOptions] = optionsOrderAndGroupBy([isSelfDMChat, isWorkspaceChat], options.reports, recentReportComparator, maxElements, filteringFunction); if (selfDMChats.length > 0) { - selfDMChat = prepareReportOptionsForDisplay(selfDMChats, { + selfDMChat = prepareReportOptionsForDisplay( + selfDMChats, + { + ...getValidReportsConfig, + selectedOptions, + shouldBoldTitleByDefault, + shouldSeparateSelfDMChat, + shouldSeparateWorkspaceChat, + shouldShowGBR, + }, + policyTags, + ).at(0); + } + + if (maxRecentReportElements) { + recentReportOptions = recentReportOptions.splice(0, maxRecentReportElements); + } + recentReportOptions = prepareReportOptionsForDisplay( + recentReportOptions, + { ...getValidReportsConfig, selectedOptions, shouldBoldTitleByDefault, shouldSeparateSelfDMChat, shouldSeparateWorkspaceChat, shouldShowGBR, - }).at(0); - } - - if (maxRecentReportElements) { - recentReportOptions = recentReportOptions.splice(0, maxRecentReportElements); - } - recentReportOptions = prepareReportOptionsForDisplay(recentReportOptions, { - ...getValidReportsConfig, - selectedOptions, - shouldBoldTitleByDefault, - shouldSeparateSelfDMChat, - shouldSeparateWorkspaceChat, - shouldShowGBR, - }); + }, + policyTags, + ); - workspaceChats = prepareReportOptionsForDisplay(workspaceChats, { - ...getValidReportsConfig, - selectedOptions, - shouldBoldTitleByDefault, - shouldSeparateSelfDMChat, - shouldSeparateWorkspaceChat, - shouldShowGBR, - }); + workspaceChats = prepareReportOptionsForDisplay( + workspaceChats, + { + ...getValidReportsConfig, + selectedOptions, + shouldBoldTitleByDefault, + shouldSeparateSelfDMChat, + shouldSeparateWorkspaceChat, + shouldShowGBR, + }, + policyTags, + ); } else if (recentAttendees && recentAttendees?.length > 0) { recentAttendees.filter((attendee) => { const login = attendee.login ?? attendee.displayName; @@ -2134,6 +2180,7 @@ function getValidOptions( userToInvite = filterUserToInvite( {currentUserOption: currentUserRef.current, recentReports: recentReportOptions, personalDetails: personalDetailsOptions}, searchString ?? '', + policyTags, countryCode, { excludeLogins: loginsToExclude, @@ -2165,6 +2212,7 @@ type SearchOptionsConfig = { includeCurrentUser?: boolean; countryCode?: number; shouldShowGBR?: boolean; + policyTags: OnyxEntry; }; /** @@ -2175,6 +2223,7 @@ function getSearchOptions({ draftComments, nvpDismissedProductTraining, betas, + policyTags, isUsedInChatFinder = true, includeReadOnly = true, searchQuery = '', @@ -2192,6 +2241,7 @@ function getSearchOptions({ options, draftComments, nvpDismissedProductTraining, + policyTags, { betas, includeRecentReports, @@ -2258,6 +2308,7 @@ type GetAttendeeOptionsParams = { includeInvoiceRooms: boolean; action: IOUAction | undefined; countryCode: number; + policyTags: OnyxEntry; }; function getAttendeeOptions({ @@ -2268,6 +2319,7 @@ function getAttendeeOptions({ recentAttendees, draftComments, nvpDismissedProductTraining, + policyTags, includeOwnedWorkspaceChats = false, includeP2P = true, includeInvoiceRooms = false, @@ -2306,6 +2358,7 @@ function getAttendeeOptions({ {reports, personalDetails}, draftComments, nvpDismissedProductTraining, + policyTags, { betas, selectedOptions: attendees.map((attendee) => ({...attendee, login: attendee.email})), @@ -2356,6 +2409,7 @@ function formatMemberForList(member: SearchOptionData): MemberForList { function getMemberInviteOptions( personalDetails: Array>, nvpDismissedProductTraining: OnyxEntry, + policyTags: OnyxEntry, betas: Beta[] = [], excludeLogins: Record = {}, includeSelectedOptions = false, @@ -2365,6 +2419,7 @@ function getMemberInviteOptions( {personalDetails, reports: []}, undefined, nvpDismissedProductTraining, + policyTags, { betas, includeP2P: true, @@ -2438,6 +2493,7 @@ function formatSectionsFromSearchTerm( selectedOptions: SearchOptionData[], filteredRecentReports: SearchOptionData[], filteredPersonalDetails: SearchOptionData[], + policyTags: OnyxEntry, personalDetails: OnyxEntry = {}, shouldGetOptionDetails = false, filteredWorkspaceChats: SearchOptionData[] = [], @@ -2453,7 +2509,9 @@ function formatSectionsFromSearchTerm( data: shouldGetOptionDetails ? selectedOptions.map((participant) => { const isReportPolicyExpenseChat = participant.isPolicyExpenseChat ?? false; - return isReportPolicyExpenseChat ? getPolicyExpenseReportOption(participant, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); + return isReportPolicyExpenseChat + ? getPolicyExpenseReportOption(participant, policyTags, reportAttributesDerived) + : getParticipantsOption(participant, personalDetails); }) : selectedOptions, shouldShow: selectedOptions.length > 0, @@ -2479,7 +2537,7 @@ function formatSectionsFromSearchTerm( data: shouldGetOptionDetails ? selectedParticipantsWithoutDetails.map((participant) => { const isReportPolicyExpenseChat = participant.isPolicyExpenseChat ?? false; - return isReportPolicyExpenseChat ? getPolicyExpenseReportOption(participant, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); + return isReportPolicyExpenseChat ? getPolicyExpenseReportOption(participant, policyTags, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }) : selectedParticipantsWithoutDetails, shouldShow: selectedParticipantsWithoutDetails.length > 0, @@ -2603,6 +2661,7 @@ function filterCurrentUserOption(currentUserOption: SearchOptionData | null | un function filterUserToInvite( options: Omit, searchValue: string, + policyTags: OnyxEntry, countryCode: number = CONST.DEFAULT_COUNTRY_CODE, config?: FilterUserToInviteConfig, ): SearchOptionData | null { @@ -2628,6 +2687,7 @@ function filterUserToInvite( }; return getUserToInviteOption({ searchValue, + policyTags, loginsToExclude, countryCode, ...config, @@ -2664,7 +2724,7 @@ function filterSelfDMChat(report: SearchOptionData, searchTerms: string[]): Sear return isMatch ? report : undefined; } -function filterOptions(options: Options, searchInputValue: string, countryCode: number, config?: FilterUserToInviteConfig): Options { +function filterOptions(options: Options, searchInputValue: string, countryCode: number, policyTags: OnyxEntry, config?: FilterUserToInviteConfig): Options { const trimmedSearchInput = searchInputValue.trim(); // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing @@ -2682,6 +2742,7 @@ function filterOptions(options: Options, searchInputValue: string, countryCode: currentUserOption, }, searchValue, + policyTags, countryCode, config, ); @@ -2737,10 +2798,10 @@ function combineOrderingOfReportsAndPersonalDetails( * Filters and orders the options based on the search input value. * Note that personal details that are part of the recent reports will always be shown as part of the recent reports (ie. DMs). */ -function filterAndOrderOptions(options: Options, searchInputValue: string, countryCode: number, config: FilterAndOrderConfig = {}): Options { +function filterAndOrderOptions(options: Options, searchInputValue: string, countryCode: number, policyTags: OnyxEntry, config: FilterAndOrderConfig = {}): Options { let filterResult = options; if (searchInputValue.trim().length > 0) { - filterResult = filterOptions(options, searchInputValue, countryCode, config); + filterResult = filterOptions(options, searchInputValue, countryCode, policyTags, config); } const orderedOptions = combineOrderingOfReportsAndPersonalDetails(filterResult, searchInputValue, config); diff --git a/src/libs/OptionsListUtils/types.ts b/src/libs/OptionsListUtils/types.ts index 99172acc9beee..9235b74c9f7fc 100644 --- a/src/libs/OptionsListUtils/types.ts +++ b/src/libs/OptionsListUtils/types.ts @@ -2,7 +2,7 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import type {OptionData} from '@libs/ReportUtils'; import type {AvatarSource} from '@libs/UserAvatarUtils'; import type {IOUAction} from '@src/CONST'; -import type {Beta, PersonalDetails, Report, ReportActions, TransactionViolation} from '@src/types/onyx'; +import type {Beta, PersonalDetails, PolicyTagLists, Report, ReportActions, TransactionViolation} from '@src/types/onyx'; import type {Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; /** @@ -193,6 +193,7 @@ type GetOptionsConfig = { type GetUserToInviteConfig = { searchValue: string | undefined; + policyTags: OnyxEntry; loginsToExclude?: Record; reportActions?: ReportActions; firstName?: string; diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts index e0b80f4a64f43..09032b05cc5d7 100644 --- a/src/libs/SidebarUtils.ts +++ b/src/libs/SidebarUtils.ts @@ -5,7 +5,17 @@ import type {LocaleContextProps} from '@components/LocaleContextProvider'; import type {PartialPolicyForSidebar, ReportsToDisplayInLHN} from '@hooks/useSidebarOrderedReports'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Card, PersonalDetails, PersonalDetailsList, ReportActions, ReportAttributesDerivedValue, ReportNameValuePairs, Transaction, TransactionViolation} from '@src/types/onyx'; +import type { + Card, + PersonalDetails, + PersonalDetailsList, + PolicyTagLists, + ReportActions, + ReportAttributesDerivedValue, + ReportNameValuePairs, + Transaction, + TransactionViolation, +} from '@src/types/onyx'; import type Beta from '@src/types/onyx/Beta'; import type {ReportAttributes} from '@src/types/onyx/DerivedValues'; import type {Errors} from '@src/types/onyx/OnyxCommon'; @@ -634,6 +644,7 @@ function getOptionData({ lastActionReport, movedFromReport, movedToReport, + policyTags, }: { report: OnyxEntry; oneTransactionThreadReport: OnyxEntry; @@ -644,6 +655,7 @@ function getOptionData({ lastMessageTextFromReport?: string; invoiceReceiverPolicy?: OnyxEntry; reportAttributes: OnyxEntry; + policyTags: OnyxEntry; card: Card | undefined; lastAction: ReportAction | undefined; localeCompare: LocaleContextProps['localeCompare']; @@ -774,7 +786,7 @@ function getOptionData({ const lastActorDisplayName = getLastActorDisplayName(lastActorDetails); let lastMessageTextFromReport = lastMessageTextFromReportProp; if (!lastMessageTextFromReport) { - lastMessageTextFromReport = getLastMessageTextForReport({report, lastActorDetails, movedFromReport, movedToReport, policy, isReportArchived}); + lastMessageTextFromReport = getLastMessageTextForReport({report, lastActorDetails, movedFromReport, movedToReport, policy, isReportArchived, policyTags}); } // We need to remove sms domain in case the last message text has a phone number mention with sms domain. diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index 4383140cb692f..8f28e65d1fffc 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -80,6 +80,7 @@ function useOptions() { }, draftComments, nvpDismissedProductTraining, + undefined, { betas: betas ?? [], includeSelfDM: true, @@ -90,9 +91,8 @@ function useOptions() { }, [listOptions.reports, listOptions.personalDetails, contacts, draftComments, betas, nvpDismissedProductTraining, countryCode]); const unselectedOptions = useMemo(() => filterSelectedOptions(defaultOptions, new Set(selectedOptions.map(({accountID}) => accountID))), [defaultOptions, selectedOptions]); - const options = useMemo(() => { - const filteredOptions = filterAndOrderOptions(unselectedOptions, debouncedSearchTerm, countryCode, { + const filteredOptions = filterAndOrderOptions(unselectedOptions, debouncedSearchTerm, countryCode, undefined, { selectedOptions, maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, }); @@ -141,6 +141,7 @@ function useOptions() { if (!participantOption) { participantOption = getUserToInviteOption({ searchValue: participant?.login, + policyTags: undefined, }); } if (!participantOption) { @@ -207,6 +208,7 @@ function NewChatPage({ref}: NewChatPageProps) { undefined, undefined, undefined, + undefined, reportAttributesDerived, ); sectionsList.push(formatResults.section); diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx index 3740053d382e8..d086e42dd6585 100644 --- a/src/pages/RoomInvitePage.tsx +++ b/src/pages/RoomInvitePage.tsx @@ -87,7 +87,7 @@ function RoomInvitePage({ return {recentReports: [], personalDetails: [], userToInvite: null, currentUserOption: null}; } - const inviteOptions = getMemberInviteOptions(options.personalDetails, nvpDismissedProductTraining, betas ?? [], excludedUsers); + const inviteOptions = getMemberInviteOptions(options.personalDetails, nvpDismissedProductTraining, undefined, betas ?? [], excludedUsers); // Update selectedOptions with the latest personalDetails information const detailsMap: Record = {}; for (const detail of inviteOptions.personalDetails) { @@ -114,7 +114,7 @@ function RoomInvitePage({ if (debouncedSearchTerm.trim() === '') { return defaultOptions; } - const filteredOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, countryCode, {excludeLogins: excludedUsers}); + const filteredOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, countryCode, undefined, {excludeLogins: excludedUsers}); return filteredOptions; }, [debouncedSearchTerm, defaultOptions, excludedUsers, countryCode]); diff --git a/src/pages/Share/ShareDetailsPage.tsx b/src/pages/Share/ShareDetailsPage.tsx index 1ea715172b177..665a2d633d832 100644 --- a/src/pages/Share/ShareDetailsPage.tsx +++ b/src/pages/Share/ShareDetailsPage.tsx @@ -59,7 +59,11 @@ function ShareDetailsPage({route}: ShareDetailsPageProps) { const [errorMessage, setErrorMessage] = useState(undefined); const report: OnyxEntry = getReportOrDraftReport(reportOrAccountID); - const displayReport = useMemo(() => getReportDisplayOption(report, unknownUserDetails, reportAttributesDerived), [report, unknownUserDetails, reportAttributesDerived]); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID ?? ''}`, {canBeMissing: false}); + const displayReport = useMemo( + () => getReportDisplayOption(report, unknownUserDetails, policyTags, reportAttributesDerived), + [report, unknownUserDetails, policyTags, reportAttributesDerived], + ); const fileSource = shouldUsePreValidatedFile ? (validatedFile?.uri ?? '') : (currentAttachment?.content ?? ''); const validateFileName = shouldUsePreValidatedFile ? getFileName(validatedFile?.uri ?? CONST.ATTACHMENT_IMAGE_DEFAULT_NAME) : getFileName(currentAttachment?.content ?? ''); diff --git a/src/pages/Share/ShareTab.tsx b/src/pages/Share/ShareTab.tsx index c767fc7a433de..3d9a380c0f2b2 100644 --- a/src/pages/Share/ShareTab.tsx +++ b/src/pages/Share/ShareTab.tsx @@ -74,6 +74,7 @@ function ShareTab({ref}: ShareTabProps) { maxResults: 20, includeUserToInvite: true, countryCode, + policyTags: undefined, }); }, [areOptionsInitialized, betas, draftComments, nvpDismissedProductTraining, options, textInputValue, countryCode]); diff --git a/src/pages/Share/SubmitDetailsPage.tsx b/src/pages/Share/SubmitDetailsPage.tsx index 9fcdefccf67d9..315ba5df3f2de 100644 --- a/src/pages/Share/SubmitDetailsPage.tsx +++ b/src/pages/Share/SubmitDetailsPage.tsx @@ -96,7 +96,7 @@ function SubmitDetailsPage({ const selectedParticipants = unknownUserDetails ? [unknownUserDetails] : getMoneyRequestParticipantsFromReport(report); const participants = selectedParticipants.map((participant) => - participant?.accountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, reportAttributesDerived), + participant?.accountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived), ); const trimmedComment = transaction?.comment?.comment?.trim() ?? ''; const transactionAmount = transaction?.amount ?? 0; diff --git a/src/pages/iou/SplitBillDetailsPage.tsx b/src/pages/iou/SplitBillDetailsPage.tsx index 5ebb70978157d..774121162b939 100644 --- a/src/pages/iou/SplitBillDetailsPage.tsx +++ b/src/pages/iou/SplitBillDetailsPage.tsx @@ -53,6 +53,7 @@ function SplitBillDetailsPage({route, report, reportAction}: SplitBillDetailsPag const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: true}); const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false}); const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector}); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: false}); // In case this is workspace split expense, we manually add the workspace as the second participant of the split expense // because we don't save any accountID in the report action's originalMessage other than the payee's accountID @@ -60,7 +61,7 @@ function SplitBillDetailsPage({route, report, reportAction}: SplitBillDetailsPag if (isPolicyExpenseChat(report)) { participants = [ getParticipantsOption({accountID: participantAccountIDs.at(0), selected: true, reportID: ''}, personalDetails), - getPolicyExpenseReportOption({...report, selected: true, reportID}, reportAttributesDerived), + getPolicyExpenseReportOption({...report, selected: true, reportID}, policyTags, reportAttributesDerived), ]; } else { participants = participantAccountIDs.map((accountID) => getParticipantsOption({accountID, selected: true, reportID: ''}, personalDetails)); diff --git a/src/pages/iou/request/MoneyRequestAccountantSelector.tsx b/src/pages/iou/request/MoneyRequestAccountantSelector.tsx index 6d90d34e01db9..0997052323f3c 100644 --- a/src/pages/iou/request/MoneyRequestAccountantSelector.tsx +++ b/src/pages/iou/request/MoneyRequestAccountantSelector.tsx @@ -81,6 +81,7 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType }, draftComments, nvpDismissedProductTraining, + undefined, { betas, excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, @@ -107,7 +108,7 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType headerMessage: '', }; } - const newOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, countryCode, { + const newOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, countryCode, undefined, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, }); @@ -131,6 +132,7 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType [], chatOptions.recentReports, chatOptions.personalDetails, + undefined, personalDetails, true, undefined, @@ -158,7 +160,7 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType title: undefined, data: [chatOptions.userToInvite].map((participant) => { const isPolicyExpenseChat = participant?.isPolicyExpenseChat ?? false; - return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); + return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant, undefined, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }), shouldShow: true, }); diff --git a/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx b/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx index f02eac741caba..889fd2b84a6af 100644 --- a/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx +++ b/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx @@ -103,6 +103,7 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde includeInvoiceRooms: false, action, countryCode, + policyTags: undefined, }); if (isPaidGroupPolicy) { const orderedOptions = orderOptions(optionList, searchTerm, { @@ -141,7 +142,7 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde headerMessage: '', }; } - const newOptions = filterAndOrderOptions(defaultOptions, cleanSearchTerm, countryCode, { + const newOptions = filterAndOrderOptions(defaultOptions, cleanSearchTerm, countryCode, undefined, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, preferPolicyExpenseChat: isPaidGroupPolicy, shouldAcceptName: true, @@ -180,6 +181,7 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde })), chatOptions.recentReports, chatOptions.personalDetails, + undefined, personalDetails, true, undefined, @@ -207,7 +209,7 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde title: undefined, data: [chatOptions.userToInvite].map((participant) => { const isPolicyExpenseChat = participant?.isPolicyExpenseChat ?? false; - return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); + return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant, undefined, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }), shouldShow: true, }); diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index 058c1d3717a61..1bb94bba1248f 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -285,6 +285,7 @@ function MoneyRequestParticipantsSelector({ participants.map((participant) => ({...participant, reportID: participant.reportID})) as OptionData[], [], [], + undefined, personalDetails, true, undefined, @@ -333,7 +334,7 @@ function MoneyRequestParticipantsSelector({ title: undefined, data: [availableOptions.userToInvite].map((participant) => { const isPolicyExpenseChat = participant?.isPolicyExpenseChat ?? false; - return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); + return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant, undefined, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }), shouldShow: true, }); diff --git a/src/pages/iou/request/step/IOURequestStepAmount.tsx b/src/pages/iou/request/step/IOURequestStepAmount.tsx index e96640d0fa61f..cd80ecd040f8a 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.tsx +++ b/src/pages/iou/request/step/IOURequestStepAmount.tsx @@ -83,6 +83,7 @@ function IOURequestStepAmount({ const isReportArchived = useReportIsArchived(report?.reportID); const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {canBeMissing: true}); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, {canBeMissing: false}); const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, {canBeMissing: true}); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); const [draftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {canBeMissing: true}); @@ -193,7 +194,7 @@ function IOURequestStepAmount({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, reportAttributesDerived); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived); }); const backendAmount = convertToBackendAmount(Number.parseFloat(amount)); diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 5d4a7ee869e89..8e7fa79b616bb 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -264,9 +264,9 @@ function IOURequestStepConfirmation({ if (participant.isSender && iouType === CONST.IOU.TYPE.INVOICE) { return participant; } - return participant.accountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, reportAttributesDerived, reportDrafts); + return participant.accountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived, reportDrafts); }) ?? [], - [transaction?.participants, iouType, personalDetails, reportAttributesDerived, reportDrafts], + [transaction?.participants, iouType, personalDetails, policyTags, reportAttributesDerived, reportDrafts], ); const isPolicyExpenseChat = useMemo(() => participants?.some((participant) => participant.isPolicyExpenseChat), [participants]); const shouldGenerateTransactionThreadReport = !isBetaEnabled(CONST.BETAS.NO_OPTIMISTIC_TRANSACTION_THREADS); @@ -605,24 +605,21 @@ function IOURequestStepConfirmation({ }, [ transactions, + getMoneyRequestContextForParticipant, + report, receiptFiles, archivedReportsIdSet, - report, currentUserPersonalDetails.login, currentUserPersonalDetails.accountID, - policy, - policyTags, - policyCategories, - policyRecentlyUsedCategories, action, transactionTaxCode, transactionTaxAmount, customUnitRateID, shouldGenerateTransactionThreadReport, backToReport, + isASAPSubmitBetaEnabled, viewTourTaskReport, viewTourTaskParentReport, - isASAPSubmitBetaEnabled, isViewTourTaskParentReportArchived, ], ); diff --git a/src/pages/iou/request/step/IOURequestStepDistance.tsx b/src/pages/iou/request/step/IOURequestStepDistance.tsx index 434f47620f9b1..da2f9c09b84f2 100644 --- a/src/pages/iou/request/step/IOURequestStepDistance.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistance.tsx @@ -94,6 +94,7 @@ function IOURequestStepDistance({ const [skipConfirmation] = useOnyx(`${ONYXKEYS.COLLECTION.SKIP_CONFIRMATION}${transactionID}`, {canBeMissing: false}); const [lastSelectedDistanceRates] = useOnyx(ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES, {canBeMissing: true}); const [optimisticWaypoints, setOptimisticWaypoints] = useState(null); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: false}); const waypoints = useMemo( () => optimisticWaypoints ?? @@ -316,7 +317,7 @@ function IOURequestStepDistance({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, reportAttributesDerived); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived); }); setDistanceRequestData(participants); if (shouldSkipConfirmation) { @@ -428,6 +429,7 @@ function IOURequestStepDistance({ shouldSkipConfirmation, transactionID, personalDetails, + policyTags, reportAttributesDerived, translate, currentUserPersonalDetails.login, diff --git a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx index b7a807133c7f7..becf295e6787e 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx @@ -86,6 +86,7 @@ function IOURequestStepDistanceManual({ const [skipConfirmation] = useOnyx(`${ONYXKEYS.COLLECTION.SKIP_CONFIRMATION}${transactionID}`, {canBeMissing: true}); const [lastSelectedDistanceRates] = useOnyx(ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES, {canBeMissing: true}); const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector}); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: false}); const isEditing = action === CONST.IOU.ACTION.EDIT; const isCreatingNewRequest = !(backTo || isEditing); @@ -175,7 +176,7 @@ function IOURequestStepDistanceManual({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, reportAttributesDerived); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived); }); if (shouldSkipConfirmation) { setMoneyRequestPendingFields(transactionID, {waypoints: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD}); @@ -289,6 +290,7 @@ function IOURequestStepDistanceManual({ policy, shouldSkipConfirmation, personalDetails, + policyTags, reportAttributesDerived, translate, currentUserPersonalDetails.login, diff --git a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx index 2093fdd4e79b5..21e69eeb3ea88 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx @@ -95,6 +95,7 @@ function IOURequestStepDistanceMap({ const [skipConfirmation] = useOnyx(`${ONYXKEYS.COLLECTION.SKIP_CONFIRMATION}${transactionID}`, {canBeMissing: false}); const [lastSelectedDistanceRates] = useOnyx(ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES, {canBeMissing: true}); const [optimisticWaypoints, setOptimisticWaypoints] = useState(null); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: false}); const waypoints = useMemo( () => optimisticWaypoints ?? @@ -317,7 +318,7 @@ function IOURequestStepDistanceMap({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, reportAttributesDerived); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived); }); setDistanceRequestData(participants); if (shouldSkipConfirmation) { @@ -429,6 +430,7 @@ function IOURequestStepDistanceMap({ shouldSkipConfirmation, transactionID, personalDetails, + policyTags, reportAttributesDerived, translate, currentUserPersonalDetails.login, diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index 4360ea9c56f64..b5f663a6af594 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -119,6 +119,7 @@ function IOURequestStepScan({ const [startLocationPermissionFlow, setStartLocationPermissionFlow] = useState(false); const [receiptFiles, setReceiptFiles] = useState([]); const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`, {canBeMissing: true}); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: false}); const policy = usePolicy(report?.policyID); const personalPolicy = usePersonalPolicy(); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); @@ -404,7 +405,7 @@ function IOURequestStepScan({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, reportAttributesDerived); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived); }); if (shouldSkipConfirmation) { @@ -517,13 +518,13 @@ function IOURequestStepScan({ initialTransaction?.reportID, reportNameValuePairs, iouType, - personalPolicy, defaultExpensePolicy, report, initialTransactionID, navigateToConfirmationPage, shouldSkipConfirmation, personalDetails, + policyTags, reportAttributesDerived, createTransaction, currentUserPersonalDetails?.login, @@ -532,6 +533,7 @@ function IOURequestStepScan({ transactionTaxCode, transactionTaxAmount, policy, + personalPolicy?.autoReporting, selfDMReportID, ], ); diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index 1090eafa1f444..dfd68d054d845 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -129,6 +129,7 @@ function IOURequestStepScan({ const defaultExpensePolicy = useDefaultExpensePolicy(); const [dismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector}); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: false}); const isEditing = action === CONST.IOU.ACTION.EDIT; const canUseMultiScan = isStartingScan && iouType !== CONST.IOU.TYPE.SPLIT; const isReplacingReceipt = (isEditing && hasReceipt(initialTransaction)) || (!!initialTransaction?.receipt && !!backTo); @@ -466,7 +467,7 @@ function IOURequestStepScan({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, reportAttributesDerived); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived); }); if (shouldSkipConfirmation) { @@ -578,13 +579,13 @@ function IOURequestStepScan({ initialTransaction?.reportID, reportNameValuePairs, iouType, - personalPolicy?.autoReporting, defaultExpensePolicy, report, initialTransactionID, navigateToConfirmationPage, shouldSkipConfirmation, personalDetails, + policyTags, reportAttributesDerived, createTransaction, currentUserPersonalDetails?.login, @@ -593,6 +594,7 @@ function IOURequestStepScan({ transactionTaxCode, transactionTaxAmount, policy, + personalPolicy?.autoReporting, selfDMReportID, ], ); diff --git a/tests/perf-test/OptionsListUtils.perf-test.ts b/tests/perf-test/OptionsListUtils.perf-test.ts index e9ff5807ca1db..8d39ec5f1db2b 100644 --- a/tests/perf-test/OptionsListUtils.perf-test.ts +++ b/tests/perf-test/OptionsListUtils.perf-test.ts @@ -77,7 +77,7 @@ jest.mock('@react-navigation/native', () => { }; }); -const options = createOptionList(personalDetails, reports); +const options = createOptionList(personalDetails, undefined, reports); const ValidOptionsConfig = { betas: mockedBetas, @@ -110,22 +110,22 @@ describe('OptionsListUtils', () => { /* Testing getSearchOptions */ test('[OptionsListUtils] getSearchOptions', async () => { await waitForBatchedUpdates(); - await measureFunction(() => getSearchOptions({options, betas: mockedBetas, draftComments: {}, nvpDismissedProductTraining})); + await measureFunction(() => getSearchOptions({options, betas: mockedBetas, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined})); }); /* Testing getFilteredOptions */ test('[OptionsListUtils] getFilteredOptions with search value', async () => { await waitForBatchedUpdates(); - const formattedOptions = getValidOptions({reports: options.reports, personalDetails: options.personalDetails}, {}, nvpDismissedProductTraining, ValidOptionsConfig); + const formattedOptions = getValidOptions({reports: options.reports, personalDetails: options.personalDetails}, {}, nvpDismissedProductTraining, undefined, ValidOptionsConfig); await measureFunction(() => { - filterAndOrderOptions(formattedOptions, SEARCH_VALUE, COUNTRY_CODE); + filterAndOrderOptions(formattedOptions, SEARCH_VALUE, COUNTRY_CODE, undefined); }); }); test('[OptionsListUtils] getFilteredOptions with empty search value', async () => { await waitForBatchedUpdates(); - const formattedOptions = getValidOptions({reports: options.reports, personalDetails: options.personalDetails}, {}, nvpDismissedProductTraining, ValidOptionsConfig); + const formattedOptions = getValidOptions({reports: options.reports, personalDetails: options.personalDetails}, {}, nvpDismissedProductTraining, undefined, ValidOptionsConfig); await measureFunction(() => { - filterAndOrderOptions(formattedOptions, '', COUNTRY_CODE); + filterAndOrderOptions(formattedOptions, '', COUNTRY_CODE, undefined); }); }); @@ -133,7 +133,7 @@ describe('OptionsListUtils', () => { test('[OptionsListUtils] getShareDestinationOptions', async () => { await waitForBatchedUpdates(); await measureFunction(() => - getValidOptions({reports: options.reports, personalDetails: options.personalDetails}, {}, nvpDismissedProductTraining, { + getValidOptions({reports: options.reports, personalDetails: options.personalDetails}, {}, nvpDismissedProductTraining, undefined, { betas: mockedBetas, includeMultipleParticipantReports: true, showChatPreviewLine: true, @@ -153,7 +153,7 @@ describe('OptionsListUtils', () => { /* Testing getMemberInviteOptions */ test('[OptionsListUtils] getMemberInviteOptions', async () => { await waitForBatchedUpdates(); - await measureFunction(() => getMemberInviteOptions(options.personalDetails, nvpDismissedProductTraining, mockedBetas)); + await measureFunction(() => getMemberInviteOptions(options.personalDetails, nvpDismissedProductTraining, undefined, mockedBetas)); }); test('[OptionsListUtils] worst case scenario with a search term that matches a subset of selectedOptions, filteredRecentReports, and filteredPersonalDetails', async () => { @@ -198,6 +198,7 @@ describe('OptionsListUtils', () => { Object.values(selectedOptions), Object.values(filteredRecentReports), Object.values(filteredPersonalDetails), + undefined, mockedPersonalDetails, true, ), @@ -210,6 +211,6 @@ describe('OptionsListUtils', () => { const mockedPersonalDetails = getMockedPersonalDetails(PERSONAL_DETAILS_COUNT); await waitForBatchedUpdates(); - await measureFunction(() => formatSectionsFromSearchTerm('', Object.values(selectedOptions), [], [], mockedPersonalDetails, true)); + await measureFunction(() => formatSectionsFromSearchTerm('', Object.values(selectedOptions), [], [], undefined, mockedPersonalDetails, true)); }); }); diff --git a/tests/perf-test/SearchRouter.perf-test.tsx b/tests/perf-test/SearchRouter.perf-test.tsx index 10f4f21c435f9..5ea9e4ae02b35 100644 --- a/tests/perf-test/SearchRouter.perf-test.tsx +++ b/tests/perf-test/SearchRouter.perf-test.tsx @@ -89,7 +89,7 @@ const getMockedPersonalDetails = (length = 100) => const mockedReports = getMockedReports(600); const mockedBetas = Object.values(CONST.BETAS); const mockedPersonalDetails = getMockedPersonalDetails(100); -const mockedOptions = createOptionList(mockedPersonalDetails, mockedReports); +const mockedOptions = createOptionList(mockedPersonalDetails, undefined, mockedReports); beforeAll(() => Onyx.init({ diff --git a/tests/perf-test/SidebarUtils.perf-test.ts b/tests/perf-test/SidebarUtils.perf-test.ts index 85724688fa363..ca2680adb3594 100644 --- a/tests/perf-test/SidebarUtils.perf-test.ts +++ b/tests/perf-test/SidebarUtils.perf-test.ts @@ -89,6 +89,7 @@ describe('SidebarUtils', () => { localeCompare, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }), ); }); diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index 6ac5a3cf58b28..8decf37e4584b 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -627,19 +627,19 @@ describe('OptionsListUtils', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}10`, reportNameValuePairs); await waitForBatchedUpdates(); - OPTIONS = createOptionList(PERSONAL_DETAILS, REPORTS); - OPTIONS_WITH_CONCIERGE = createOptionList(PERSONAL_DETAILS_WITH_CONCIERGE, REPORTS_WITH_CONCIERGE); - OPTIONS_WITH_CHRONOS = createOptionList(PERSONAL_DETAILS_WITH_CHRONOS, REPORTS_WITH_CHRONOS); - OPTIONS_WITH_RECEIPTS = createOptionList(PERSONAL_DETAILS_WITH_RECEIPTS, REPORTS_WITH_RECEIPTS); - OPTIONS_WITH_WORKSPACE_ROOM = createOptionList(PERSONAL_DETAILS, REPORTS_WITH_WORKSPACE_ROOMS); - OPTIONS_WITH_MANAGER_MCTEST = createOptionList(PERSONAL_DETAILS_WITH_MANAGER_MCTEST); + OPTIONS = createOptionList(PERSONAL_DETAILS, undefined, REPORTS); + OPTIONS_WITH_CONCIERGE = createOptionList(PERSONAL_DETAILS_WITH_CONCIERGE, undefined, REPORTS_WITH_CONCIERGE); + OPTIONS_WITH_CHRONOS = createOptionList(PERSONAL_DETAILS_WITH_CHRONOS, undefined, REPORTS_WITH_CHRONOS); + OPTIONS_WITH_RECEIPTS = createOptionList(PERSONAL_DETAILS_WITH_RECEIPTS, undefined, REPORTS_WITH_RECEIPTS); + OPTIONS_WITH_WORKSPACE_ROOM = createOptionList(PERSONAL_DETAILS, undefined, REPORTS_WITH_WORKSPACE_ROOMS); + OPTIONS_WITH_MANAGER_MCTEST = createOptionList(PERSONAL_DETAILS_WITH_MANAGER_MCTEST, undefined); }); describe('getSearchOptions()', () => { it('should return all options when no search value is provided', () => { // Given a set of options // When we call getSearchOptions with all betas - const results = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL]}); + const results = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); // Then all personal details (including those that have reports) should be returned expect(results.personalDetails.length).toBe(10); @@ -663,6 +663,7 @@ describe('OptionsListUtils', () => { includeUserToInvite: false, includeRecentReports: true, includeCurrentUser: true, + policyTags: {}, }); // Then the current user should be included in personalDetails @@ -689,6 +690,7 @@ describe('OptionsListUtils', () => { maxResults: undefined, includeUserToInvite: false, includeRecentReports: true, + policyTags: undefined, }); // Then the current user should not be included in personalDetails @@ -711,6 +713,7 @@ describe('OptionsListUtils', () => { }, {}, nvpDismissedProductTraining, + undefined, ); // When we call orderOptions() results = orderOptions(results); @@ -742,7 +745,12 @@ describe('OptionsListUtils', () => { it('should sort personal details options alphabetically when only personal details are provided', () => { // Given a set of personalDetails and an empty reports array - let results: Pick = getValidOptions({personalDetails: OPTIONS.personalDetails, reports: []}, {}, nvpDismissedProductTraining); + let results: Pick = getValidOptions( + {personalDetails: OPTIONS.personalDetails, reports: []}, + {}, + nvpDismissedProductTraining, + undefined, + ); // When we call orderOptions() results = orderOptions(results); @@ -769,7 +777,7 @@ 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: []}, {}, nvpDismissedProductTraining); + const results = getValidOptions({reports: [], personalDetails: []}, {}, nvpDismissedProductTraining, undefined); // Then the result should be empty expect(results.personalDetails).toEqual([]); @@ -783,7 +791,7 @@ describe('OptionsListUtils', () => { it('should include Concierge by default in results', () => { // Given a set of reports and personalDetails that includes Concierge // When we call getValidOptions() - const results = getValidOptions({reports: OPTIONS_WITH_CONCIERGE.reports, personalDetails: OPTIONS_WITH_CONCIERGE.personalDetails}, {}, nvpDismissedProductTraining); + const results = getValidOptions({reports: OPTIONS_WITH_CONCIERGE.reports, personalDetails: OPTIONS_WITH_CONCIERGE.personalDetails}, {}, nvpDismissedProductTraining, undefined); // Then the result should include all personalDetails except the currently logged in user expect(results.personalDetails.length).toBe(Object.values(OPTIONS_WITH_CONCIERGE.personalDetails).length - 1); @@ -801,6 +809,7 @@ describe('OptionsListUtils', () => { }, {}, nvpDismissedProductTraining, + undefined, { excludeLogins: {[CONST.EMAIL.CONCIERGE]: true}, }, @@ -815,7 +824,7 @@ describe('OptionsListUtils', () => { 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() - const results = getValidOptions({reports: OPTIONS_WITH_CHRONOS.reports, personalDetails: OPTIONS_WITH_CHRONOS.personalDetails}, {}, nvpDismissedProductTraining, { + const results = getValidOptions({reports: OPTIONS_WITH_CHRONOS.reports, personalDetails: OPTIONS_WITH_CHRONOS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { excludeLogins: {[CONST.EMAIL.CHRONOS]: true}, }); @@ -835,6 +844,7 @@ describe('OptionsListUtils', () => { }, {}, nvpDismissedProductTraining, + undefined, { excludeLogins: {[CONST.EMAIL.RECEIPTS]: true}, }, @@ -858,6 +868,7 @@ describe('OptionsListUtils', () => { timestamp: DateUtils.getDBTime(new Date().valueOf()), }, }, + undefined, { includeP2P: true, canShowManagerMcTest: true, @@ -874,11 +885,17 @@ describe('OptionsListUtils', () => { it('should exclude Manager McTest from results if flag is set to false', () => { // Given a set of reports and personalDetails that includes Manager McTest and a config object that excludes Manager McTest // When we call getValidOptions() - const result = getValidOptions({reports: OPTIONS_WITH_MANAGER_MCTEST.reports, personalDetails: OPTIONS_WITH_MANAGER_MCTEST.personalDetails}, {}, nvpDismissedProductTraining, { - includeP2P: true, - canShowManagerMcTest: false, - betas: [CONST.BETAS.NEWDOT_MANAGER_MCTEST], - }); + const result = getValidOptions( + {reports: OPTIONS_WITH_MANAGER_MCTEST.reports, personalDetails: OPTIONS_WITH_MANAGER_MCTEST.personalDetails}, + {}, + nvpDismissedProductTraining, + undefined, + { + includeP2P: true, + canShowManagerMcTest: false, + betas: [CONST.BETAS.NEWDOT_MANAGER_MCTEST], + }, + ); // Then the result should include all personalDetails except the currently logged in user and Manager McTest expect(result.personalDetails.length).toBe(Object.values(OPTIONS_WITH_MANAGER_MCTEST.personalDetails).length - 2); @@ -902,6 +919,7 @@ describe('OptionsListUtils', () => { {reports: OPTIONS_WITH_MANAGER_MCTEST.reports, personalDetails: OPTIONS_WITH_MANAGER_MCTEST.personalDetails}, {}, nvpDismissedProductTraining, + undefined, {includeP2P: true, canShowManagerMcTest: true, betas: [CONST.BETAS.NEWDOT_MANAGER_MCTEST]}, ); @@ -947,7 +965,7 @@ describe('OptionsListUtils', () => { notificationPreference: 'hidden', }; // When we call getValidOptions with includeMultipleParticipantReports set to true - const results = getValidOptions({reports: [adminRoom], personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, { + const results = getValidOptions({reports: [adminRoom], personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { includeMultipleParticipantReports: true, }); const adminRoomOption = results.recentReports.find((report) => report.reportID === '1455140530846319'); @@ -992,7 +1010,7 @@ describe('OptionsListUtils', () => { notificationPreference: 'hidden', brickRoadIndicator: CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR, }; - const results = getValidOptions({reports: [workspaceChat], personalDetails: []}, {}, nvpDismissedProductTraining, { + const results = getValidOptions({reports: [workspaceChat], personalDetails: []}, {}, nvpDismissedProductTraining, undefined, { includeMultipleParticipantReports: true, showRBR: true, }); @@ -1035,7 +1053,7 @@ describe('OptionsListUtils', () => { notificationPreference: 'hidden', brickRoadIndicator: CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR, }; - const results = getValidOptions({reports: [workspaceChat], personalDetails: []}, {}, nvpDismissedProductTraining, { + const results = getValidOptions({reports: [workspaceChat], personalDetails: []}, {}, nvpDismissedProductTraining, undefined, { includeMultipleParticipantReports: true, showRBR: false, }); @@ -1047,7 +1065,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, {}, nvpDismissedProductTraining, { + const results = getValidOptions(OPTIONS_WITH_WORKSPACE_ROOM, {}, nvpDismissedProductTraining, undefined, { includeRecentReports: true, includeMultipleParticipantReports: true, includeP2P: true, @@ -1064,7 +1082,7 @@ describe('OptionsListUtils', () => { it('should exclude users with recent reports from personalDetails', () => { // Given a set of reports and personalDetails // When we call getValidOptions with no search value - const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); + const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); const reportLogins = new Set(results.recentReports.map((reportOption) => reportOption.login)); const personalDetailsOverlapWithReports = results.personalDetails.every((personalDetailOption) => reportLogins.has(personalDetailOption.login)); @@ -1077,7 +1095,7 @@ describe('OptionsListUtils', () => { it('should exclude selected options', () => { // Given a set of reports and personalDetails // When we call getValidOptions with excludeLogins param - const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, { + const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { excludeLogins: {'peterparker@expensify.com': true}, }); @@ -1089,7 +1107,7 @@ describe('OptionsListUtils', () => { it('should include Concierge in the results by default', () => { // Given a set of report and personalDetails that include Concierge // When we call getValidOptions() - const results = getValidOptions({reports: OPTIONS_WITH_CONCIERGE.reports, personalDetails: OPTIONS_WITH_CONCIERGE.personalDetails}, {}, nvpDismissedProductTraining); + const results = getValidOptions({reports: OPTIONS_WITH_CONCIERGE.reports, personalDetails: OPTIONS_WITH_CONCIERGE.personalDetails}, {}, nvpDismissedProductTraining, undefined); // Then the result should include all personalDetails except the currently logged in user expect(results.personalDetails.length).toBe(Object.values(OPTIONS_WITH_CONCIERGE.personalDetails).length - 1); @@ -1107,6 +1125,7 @@ describe('OptionsListUtils', () => { }, {}, nvpDismissedProductTraining, + undefined, { excludeLogins: {[CONST.EMAIL.CONCIERGE]: true}, }, @@ -1122,7 +1141,7 @@ describe('OptionsListUtils', () => { it('should exclude Chronos from the results when it is specified in excludedLogins', () => { // given a set of reports and personalDetails that includes Chronos // When we call getValidOptions() with excludeLogins param - const results = getValidOptions({reports: OPTIONS_WITH_CHRONOS.reports, personalDetails: OPTIONS_WITH_CHRONOS.personalDetails}, {}, nvpDismissedProductTraining, { + const results = getValidOptions({reports: OPTIONS_WITH_CHRONOS.reports, personalDetails: OPTIONS_WITH_CHRONOS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { excludeLogins: {[CONST.EMAIL.CHRONOS]: true}, }); @@ -1143,6 +1162,7 @@ describe('OptionsListUtils', () => { }, {}, nvpDismissedProductTraining, + undefined, { excludeLogins: {[CONST.EMAIL.RECEIPTS]: true}, }, @@ -1159,7 +1179,7 @@ describe('OptionsListUtils', () => { // Given a set of reports and personalDetails with multiple reports // When we call getValidOptions with maxRecentReportElements set to 2 const maxRecentReports = 2; - const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, { + const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { maxRecentReportElements: maxRecentReports, }); @@ -1170,8 +1190,10 @@ describe('OptionsListUtils', () => { it('should show all reports when maxRecentReportElements is not specified', () => { // Given a set of reports and personalDetails // When we call getValidOptions without maxRecentReportElements - const resultsWithoutLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); - const resultsWithLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, {maxRecentReportElements: 2}); + const resultsWithoutLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const resultsWithLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + maxRecentReportElements: 2, + }); // Then the results without limit should have more or equal reports expect(resultsWithoutLimit.recentReports.length).toBeGreaterThanOrEqual(resultsWithLimit.recentReports.length); @@ -1180,8 +1202,10 @@ describe('OptionsListUtils', () => { it('should not affect personalDetails count when maxRecentReportElements is specified', () => { // Given a set of reports and personalDetails // When we call getValidOptions with and without maxRecentReportElements - const resultsWithoutLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); - const resultsWithLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, {maxRecentReportElements: 2}); + const resultsWithoutLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const resultsWithLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + maxRecentReportElements: 2, + }); // Then personalDetails should remain the same regardless of maxRecentReportElements expect(resultsWithLimit.personalDetails.length).toBe(resultsWithoutLimit.personalDetails.length); @@ -1192,7 +1216,7 @@ describe('OptionsListUtils', () => { // When we call getValidOptions with both maxElements and maxRecentReportElements const maxRecentReports = 3; const maxTotalElements = 10; - const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, { + const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { maxElements: maxTotalElements, maxRecentReportElements: maxRecentReports, }); @@ -1217,7 +1241,7 @@ describe('OptionsListUtils', () => { }, []); // When we call getValidOptions for share destination with an empty search value - const results = getValidOptions({reports: filteredReports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, { + const results = getValidOptions({reports: filteredReports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { betas: [], includeMultipleParticipantReports: true, showChatPreviewLine: true, @@ -1249,7 +1273,7 @@ describe('OptionsListUtils', () => { }, []); // When we call getValidOptions for share destination with an empty search value - const results = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, { + const results = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { betas: [], includeMultipleParticipantReports: true, showChatPreviewLine: true, @@ -1273,7 +1297,7 @@ describe('OptionsListUtils', () => { it('should sort personal details alphabetically', () => { // Given a set of personalDetails // When we call getMemberInviteOptions - const results = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, []); + const results = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, undefined, []); // Then personal details should be sorted alphabetically expect(results.personalDetails.at(0)?.text).toBe('Black Panther'); @@ -1321,9 +1345,9 @@ describe('OptionsListUtils', () => { it('should return all options when search is empty', () => { // Given a set of options // When we call getSearchOptions with all betas - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL]}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); // When we pass the returned options to filterAndOrderOptions with an empty search value - const filteredOptions = filterAndOrderOptions(options, '', COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, '', COUNTRY_CODE, undefined); // Then all options should be returned expect(filteredOptions.recentReports.length + filteredOptions.personalDetails.length).toBe(14); @@ -1333,9 +1357,9 @@ describe('OptionsListUtils', () => { const searchText = 'man'; // Given a set of options // When we call getSearchOptions with all betas - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL]}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); // When we pass the returned options to filterAndOrderOptions with a search value and sortByReportTypeInSearch param - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, {sortByReportTypeInSearch: true}); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined, {sortByReportTypeInSearch: true}); // Then we expect all options to be part of the recentReports list and reports should be first: expect(filteredOptions.personalDetails.length).toBe(0); @@ -1352,9 +1376,9 @@ describe('OptionsListUtils', () => { const searchText = 'mistersinister@marauders.com'; // Given a set of options // When we call getSearchOptions with all betas - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL]}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1366,9 +1390,9 @@ describe('OptionsListUtils', () => { const searchText = 'Archived'; // Given a set of options // When we call getSearchOptions with all betas - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL]}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1380,11 +1404,11 @@ describe('OptionsListUtils', () => { // cspell:disable-next-line const searchText = 'barryallen'; // Given a set of options created from PERSONAL_DETAILS_WITH_PERIODS - const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, REPORTS); + const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, {}, REPORTS); // When we call getSearchOptions with all betas - const options = getSearchOptions({options: OPTIONS_WITH_PERIODS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL]}); + const options = getSearchOptions({options: OPTIONS_WITH_PERIODS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); // When we pass the returned options to filterAndOrderOptions with a search value and sortByReportTypeInSearch param - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, {sortByReportTypeInSearch: true}); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined, {sortByReportTypeInSearch: true}); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1396,9 +1420,9 @@ describe('OptionsListUtils', () => { const searchText = 'avengers'; // Given a set of options with workspace rooms // When we call getSearchOptions with all betas - const options = getSearchOptions({options: OPTIONS_WITH_WORKSPACE_ROOM, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL]}); + const options = getSearchOptions({options: OPTIONS_WITH_WORKSPACE_ROOM, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1409,9 +1433,9 @@ describe('OptionsListUtils', () => { it('should put exact match by login on the top of the list', () => { const searchText = 'reedrichards@expensify.com'; // Given a set of options with all betas - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL]}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1422,11 +1446,11 @@ describe('OptionsListUtils', () => { it('should prioritize options with matching display name over chat rooms', () => { const searchText = 'spider'; // Given a set of options with chat rooms - const OPTIONS_WITH_CHAT_ROOMS = createOptionList(PERSONAL_DETAILS, REPORTS_WITH_CHAT_ROOM); + const OPTIONS_WITH_CHAT_ROOMS = createOptionList(PERSONAL_DETAILS, {}, REPORTS_WITH_CHAT_ROOM); // When we call getSearchOptions with all betas - const options = getSearchOptions({options: OPTIONS_WITH_CHAT_ROOMS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL]}); + const options = getSearchOptions({options: OPTIONS_WITH_CHAT_ROOMS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); // When we pass the returned options to filterAndOrderOptions with a search value - const filterOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE); + const filterOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); // Then only two reports should be returned expect(filterOptions.recentReports.length).toBe(2); @@ -1438,9 +1462,9 @@ describe('OptionsListUtils', () => { renderLocaleContextProvider(); const searchText = 'fantastic'; // Given a set of options - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined}); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); // Then only three reports should be returned expect(filteredOptions.recentReports.length).toBe(3); @@ -1453,9 +1477,9 @@ describe('OptionsListUtils', () => { it('should return the user to invite when the search value is a valid, non-existent email', () => { const searchText = 'test@email.com'; // Given a set of options - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined}); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); // Then the user to invite should be returned expect(filteredOptions.userToInvite?.login).toBe(searchText); @@ -1464,11 +1488,11 @@ describe('OptionsListUtils', () => { it('should not return any results if the search value is on an excluded logins list', () => { const searchText = 'admin@expensify.com'; // Given a set of options with excluded logins list - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, { + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, }); // When we call filterAndOrderOptions with a search value and excluded logins list - const filterOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, {excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT}); + const filterOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined, {excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT}); // Then no personal details should be returned expect(filterOptions.recentReports.length).toBe(0); @@ -1477,9 +1501,9 @@ describe('OptionsListUtils', () => { it('should return the user to invite when the search value is a valid, non-existent email and the user is not excluded', () => { const searchText = 'test@email.com'; // Given a set of options - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined}); // When we call filterAndOrderOptions with a search value and excludeLogins - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, {excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT}); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined, {excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT}); // Then the user to invite should be returned expect(filteredOptions.userToInvite?.login).toBe(searchText); @@ -1488,16 +1512,16 @@ describe('OptionsListUtils', () => { it('should return limited amount of recent reports if the limit is set', () => { const searchText = ''; // Given a set of options - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined}); // When we call filterAndOrderOptions with a search value and maxRecentReportsToShow set to 2 - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, {maxRecentReportsToShow: 2}); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined, {maxRecentReportsToShow: 2}); // Then only two reports should be returned expect(filteredOptions.recentReports.length).toBe(2); // Note: in the past maxRecentReportsToShow: 0 would return all recent reports, this has changed, and is expected to return none now // When we call filterAndOrderOptions with a search value and maxRecentReportsToShow set to 0 - const limitToZeroOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, {maxRecentReportsToShow: 0}); + const limitToZeroOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined, {maxRecentReportsToShow: 0}); // Then no reports should be returned expect(limitToZeroOptions.recentReports.length).toBe(0); @@ -1506,9 +1530,9 @@ describe('OptionsListUtils', () => { it('should not return any user to invite if email exists on the personal details list', () => { const searchText = 'natasharomanoff@expensify.com'; // Given a set of options with all betas - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL]}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); // Then there should be one matching result expect(filteredOptions.personalDetails.length).toBe(1); @@ -1518,9 +1542,9 @@ describe('OptionsListUtils', () => { it('should not return any options if search value does not match any personal details (getMemberInviteOptions)', () => { // Given a set of options - const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, []); + const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, undefined, []); // When we call filterAndOrderOptions with a search value that does not match any personal details - const filteredOptions = filterAndOrderOptions(options, 'magneto', COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, 'magneto', COUNTRY_CODE, undefined); // Then no personal details should be returned expect(filteredOptions.personalDetails.length).toBe(0); @@ -1528,9 +1552,9 @@ describe('OptionsListUtils', () => { it('should return one personal detail if search value matches an email (getMemberInviteOptions)', () => { // Given a set of options - const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, []); + const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, undefined, []); // When we call filterAndOrderOptions with a search value that matches an email - const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', COUNTRY_CODE, undefined); // Then one personal detail should be returned expect(filteredOptions.personalDetails.length).toBe(1); @@ -1548,7 +1572,7 @@ describe('OptionsListUtils', () => { return filtered; }, []); // When we call getValidOptions for share destination with the filteredReports - const options = getValidOptions({reports: filteredReports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, { + const options = getValidOptions({reports: filteredReports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { betas: [], includeMultipleParticipantReports: true, showChatPreviewLine: true, @@ -1563,7 +1587,7 @@ describe('OptionsListUtils', () => { includeUserToInvite: false, }); // When we pass the returned options to filterAndOrderOptions with a search value that does not match the group chat name - const filteredOptions = filterAndOrderOptions(options, 'mutants', COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, 'mutants', COUNTRY_CODE, undefined); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1581,7 +1605,7 @@ describe('OptionsListUtils', () => { }, []); // When we call getValidOptions for share destination with the filteredReports - const options = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, { + const options = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { betas: [], includeMultipleParticipantReports: true, showChatPreviewLine: true, @@ -1596,7 +1620,7 @@ describe('OptionsListUtils', () => { includeUserToInvite: false, }); // When we pass the returned options to filterAndOrderOptions with a search value that matches the group chat name - const filteredOptions = filterAndOrderOptions(options, 'Avengers Room', COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, 'Avengers Room', COUNTRY_CODE, undefined); // Then one recent report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1614,7 +1638,7 @@ describe('OptionsListUtils', () => { }, []); // When we call getValidOptions for share destination with the filteredReports - const options = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, { + const options = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { betas: [], includeMultipleParticipantReports: true, showChatPreviewLine: true, @@ -1629,7 +1653,7 @@ describe('OptionsListUtils', () => { includeUserToInvite: false, }); // When we pass the returned options to filterAndOrderOptions with a search value that does not match the group chat name - const filteredOptions = filterAndOrderOptions(options, 'Mutants Lair', COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, 'Mutants Lair', COUNTRY_CODE, undefined); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1637,9 +1661,9 @@ describe('OptionsListUtils', () => { it('should show the option from personal details when searching for personal detail with no existing report', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, 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); + const filteredOptions = filterAndOrderOptions(options, 'hulk', COUNTRY_CODE, undefined); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1651,9 +1675,9 @@ describe('OptionsListUtils', () => { it('should not return any options or user to invite if there are no search results and the string does not match a potential email or phone', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, 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); + const filteredOptions = filterAndOrderOptions(options, 'marc@expensify', COUNTRY_CODE, undefined); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1664,9 +1688,9 @@ describe('OptionsListUtils', () => { it('should not return any options but should return an user to invite if no matching options exist and the search value is a potential email', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, 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); + const filteredOptions = filterAndOrderOptions(options, 'marc@expensify.com', COUNTRY_CODE, undefined); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1677,9 +1701,9 @@ describe('OptionsListUtils', () => { it('should return user to invite when search term has a period with options for it that do not contain the period', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, 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); + const filteredOptions = filterAndOrderOptions(options, 'peter.parker@expensify.com', COUNTRY_CODE, undefined); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1689,9 +1713,9 @@ describe('OptionsListUtils', () => { it('should return user which has displayName with accent mark when search value without accent mark', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); // When we call filterAndOrderOptions with a search value without accent mark - const filteredOptions = filterAndOrderOptions(options, 'Timothee', COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, 'Timothee', COUNTRY_CODE, undefined); // Then one personalDetails with accent mark should be returned expect(filteredOptions.personalDetails.length).toBe(1); @@ -1699,9 +1723,9 @@ describe('OptionsListUtils', () => { it('should not return options but should return an user to invite if no matching options exist and the search value is a potential phone number', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, 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); + const filteredOptions = filterAndOrderOptions(options, '5005550006', COUNTRY_CODE, undefined); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1714,9 +1738,9 @@ describe('OptionsListUtils', () => { it('should not return options but should return an user to invite if no matching options exist and the search value is a potential phone number with country code added', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, 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); + const filteredOptions = filterAndOrderOptions(options, '+15005550006', COUNTRY_CODE, undefined); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1729,9 +1753,9 @@ describe('OptionsListUtils', () => { it('should not return options but should return an user to invite if no matching options exist and the search value is a potential phone number with special characters added', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, 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); + const filteredOptions = filterAndOrderOptions(options, '+1 (800)324-3233', COUNTRY_CODE, undefined); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1744,9 +1768,9 @@ describe('OptionsListUtils', () => { it('should not return any options or user to invite if contact number contains alphabet characters', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, 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); + const filteredOptions = filterAndOrderOptions(options, '998243aaaa', COUNTRY_CODE, undefined); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1757,9 +1781,9 @@ describe('OptionsListUtils', () => { it('should not return any options if search value does not match any personal details', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); // When we call filterAndOrderOptions with a search value that does not match any personal details - const filteredOptions = filterAndOrderOptions(options, 'magneto', COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, 'magneto', COUNTRY_CODE, undefined); // Then no personal details should be returned expect(filteredOptions.personalDetails.length).toBe(0); @@ -1767,9 +1791,9 @@ describe('OptionsListUtils', () => { it('should return one recent report and no personal details if a search value provides an email', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); // When we call filterAndOrderOptions with a search value that matches an email - const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', COUNTRY_CODE, {sortByReportTypeInSearch: true}); + const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', COUNTRY_CODE, undefined, {sortByReportTypeInSearch: true}); // Then one recent report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1781,9 +1805,9 @@ describe('OptionsListUtils', () => { it('should return all matching reports and personal details', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, 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, {maxRecentReportsToShow: 5}); + const filteredOptions = filterAndOrderOptions(options, '.com', COUNTRY_CODE, undefined, {maxRecentReportsToShow: 5}); // Then there should be 4 matching personal details expect(filteredOptions.personalDetails.length).toBe(5); @@ -1798,9 +1822,9 @@ describe('OptionsListUtils', () => { it('should return matching option when searching (getSearchOptions)', () => { // Given a set of options - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined}); // When we call filterAndOrderOptions with a search value that matches a personal detail - const filteredOptions = filterAndOrderOptions(options, 'spider', COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, 'spider', COUNTRY_CODE, undefined); // Then one personal detail should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1810,9 +1834,9 @@ describe('OptionsListUtils', () => { it('should return latest lastVisibleActionCreated item on top when search value matches multiple items (getSearchOptions)', () => { // Given a set of options - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined}); // When we call filterAndOrderOptions with a search value that matches multiple items - const filteredOptions = filterAndOrderOptions(options, 'fantastic', COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, 'fantastic', COUNTRY_CODE, undefined); // Then only three reports should be returned expect(filteredOptions.recentReports.length).toBe(3); @@ -1825,11 +1849,11 @@ describe('OptionsListUtils', () => { .then(() => Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, PERSONAL_DETAILS_WITH_PERIODS)) .then(() => { // Given a set of options with periods - const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, REPORTS); + const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, undefined, REPORTS) as OptionList; // When we call getSearchOptions - const results = getSearchOptions({options: OPTIONS_WITH_PERIODS, draftComments: {}, nvpDismissedProductTraining}); + const results = getSearchOptions({options: OPTIONS_WITH_PERIODS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined}); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredResults = filterAndOrderOptions(results, 'barry.allen@expensify.com', COUNTRY_CODE, {sortByReportTypeInSearch: true}); + const filteredResults = filterAndOrderOptions(results, 'barry.allen@expensify.com', COUNTRY_CODE, undefined, {sortByReportTypeInSearch: true}); // Then only one report should be returned expect(filteredResults.recentReports.length).toBe(1); @@ -1845,9 +1869,9 @@ describe('OptionsListUtils', () => { OPTIONS.personalDetails = OPTIONS.personalDetails.flatMap((obj) => [obj, {...obj}]); // Given a set of options - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL]}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); // When we call filterAndOrderOptions with a an empty search value - const filteredOptions = filterAndOrderOptions(options, '', COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, '', COUNTRY_CODE, undefined); const matchingEntries = filteredOptions.personalDetails.filter((detail) => detail.login === login); // Then there should be 2 unique login entries @@ -1858,12 +1882,12 @@ describe('OptionsListUtils', () => { it('should order self dm always on top if the search matches with the self dm login', () => { const searchTerm = 'tonystark@expensify.com'; - const OPTIONS_WITH_SELF_DM = createOptionList(PERSONAL_DETAILS, REPORTS_WITH_SELF_DM); + const OPTIONS_WITH_SELF_DM = createOptionList(PERSONAL_DETAILS, undefined, REPORTS_WITH_SELF_DM); // Given a set of options with self dm and all betas - const options = getSearchOptions({options: OPTIONS_WITH_SELF_DM, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL]}); + const options = getSearchOptions({options: OPTIONS_WITH_SELF_DM, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchTerm, COUNTRY_CODE); + const filteredOptions = filterAndOrderOptions(options, searchTerm, COUNTRY_CODE, undefined); // Then the self dm should be on top. expect(filteredOptions.recentReports.at(0)?.isSelfDM).toBe(true); @@ -1910,7 +1934,7 @@ describe('OptionsListUtils', () => { renderLocaleContextProvider(); // Given a set of reports and personal details // When we call createOptionList and extract the reports - const reports = createOptionList(PERSONAL_DETAILS, REPORTS).reports; + const reports = createOptionList(PERSONAL_DETAILS, undefined, REPORTS).reports; // Then the returned reports should match the expected values expect(reports.at(10)?.subtitle).toBe(`Submits to Mister Fantastic`); @@ -1921,7 +1945,7 @@ describe('OptionsListUtils', () => { .then(() => Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, CONST.LOCALES.ES)) .then(() => { // When we call createOptionList again - const newReports = createOptionList(PERSONAL_DETAILS, REPORTS).reports; + const newReports = createOptionList(PERSONAL_DETAILS, undefined, REPORTS).reports; // Then the returned reports should change to Spanish // cspell:disable-next-line expect(newReports.at(10)?.subtitle).toBe('Se envía a Mister Fantastic'); @@ -2001,7 +2025,7 @@ describe('OptionsListUtils', () => { }, }); // When we call createOptionList - const reports = createOptionList(PERSONAL_DETAILS, REPORTS).reports; + const reports = createOptionList(PERSONAL_DETAILS, undefined, REPORTS).reports; const archivedReport = reports.find((report) => report.reportID === '10'); // Then the returned report should contain default archived reason @@ -2398,7 +2422,7 @@ describe('OptionsListUtils', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, transaction); await waitForBatchedUpdates(); - const result = createOption([1, 2], PERSONAL_DETAILS, report, {showChatPreviewLine: true}); + const result = createOption([1, 2], PERSONAL_DETAILS, report, CONST.POLICY.DEFAULT_TAG_LIST, {showChatPreviewLine: true}); expect(result.alternateText).toBe('Iron Man owes ₫34'); }); @@ -2455,7 +2479,7 @@ describe('OptionsListUtils', () => { [iouAction.reportActionID]: iouAction, }); await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, transaction); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); const reportPreviewMessage = getReportPreviewMessage(iouReport, iouAction, true, false, null, true, reportPreviewAction); const expected = formatReportLastMessageText(Parser.htmlToText(reportPreviewMessage)); expect(lastMessage).toBe(expected); @@ -2481,7 +2505,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [movedTransactionAction.reportActionID]: movedTransactionAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); expect(lastMessage).toBe(Parser.htmlToText(getMovedTransactionMessage(report2))); }); describe('SUBMITTED action', () => { @@ -2499,7 +2523,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [submittedAction.reportActionID]: submittedAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); expect(lastMessage).toBe(Parser.htmlToText(translate(CONST.LOCALES.EN, 'iou.automaticallySubmitted'))); }); }); @@ -2518,7 +2542,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [approvedAction.reportActionID]: approvedAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); expect(lastMessage).toBe(Parser.htmlToText(translate(CONST.LOCALES.EN, 'iou.automaticallyApproved'))); }); }); @@ -2537,7 +2561,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [forwardedAction.reportActionID]: forwardedAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); expect(lastMessage).toBe(Parser.htmlToText(translate(CONST.LOCALES.EN, 'iou.automaticallyForwarded'))); }); }); @@ -2552,7 +2576,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [takeControlAction.reportActionID]: takeControlAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); expect(lastMessage).toBe(Parser.htmlToText(getChangedApproverActionMessage(takeControlAction))); }); it('REROUTE action', async () => { @@ -2566,7 +2590,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [rerouteAction.reportActionID]: rerouteAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); expect(lastMessage).toBe(Parser.htmlToText(getChangedApproverActionMessage(rerouteAction))); }); it('MOVED action', async () => { @@ -2580,7 +2604,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [movedAction.reportActionID]: movedAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); expect(lastMessage).toBe(Parser.htmlToText(getMovedActionMessage(movedAction, report))); }); }); diff --git a/tests/unit/SidebarUtilsTest.ts b/tests/unit/SidebarUtilsTest.ts index ba613d10d9330..d63928c422807 100644 --- a/tests/unit/SidebarUtilsTest.ts +++ b/tests/unit/SidebarUtilsTest.ts @@ -353,6 +353,7 @@ describe('SidebarUtils', () => { lastAction: undefined, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); const optionDataUnpinned = SidebarUtils.getOptionData({ report: MOCK_REPORT_UNPINNED, @@ -367,6 +368,7 @@ describe('SidebarUtils', () => { lastAction: undefined, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); expect(optionDataPinned?.isPinned).toBe(true); @@ -899,6 +901,7 @@ describe('SidebarUtils', () => { lastAction, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); // Then the alternate text should be equal to the message of the last action prepended with the last actor display name. @@ -962,6 +965,7 @@ describe('SidebarUtils', () => { lastAction, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); // Then the alternate text should show @Hidden. @@ -1010,6 +1014,7 @@ describe('SidebarUtils', () => { localeCompare, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); expect(optionData?.alternateText).toBe(`test message`); @@ -1049,6 +1054,7 @@ describe('SidebarUtils', () => { localeCompare, isReportArchived: true, lastActionReport: undefined, + policyTags: undefined, }); expect(optionData?.alternateText).toBe(`test message`); @@ -1085,6 +1091,7 @@ describe('SidebarUtils', () => { localeCompare, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); expect(optionData?.alternateText).toBe(`test message`); @@ -1210,6 +1217,7 @@ describe('SidebarUtils', () => { localeCompare, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); expect(optionData?.alternateText).toBe(formatReportLastMessageText(iouReport.reportName)); @@ -1251,6 +1259,7 @@ describe('SidebarUtils', () => { localeCompare, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); expect(optionData?.alternateText).toBe(`${policy.name} ${CONST.DOT_SEPARATOR} test message`); @@ -1321,6 +1330,7 @@ describe('SidebarUtils', () => { lastAction, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); // Then the alternate text should be equal to the message of the last action prepended with the last actor display name. @@ -1380,6 +1390,7 @@ describe('SidebarUtils', () => { lastAction, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); expect(result?.alternateText).toBe(`You: moved this report to the Three's Workspace workspace`); @@ -1451,6 +1462,7 @@ describe('SidebarUtils', () => { lastAction, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); expect(result?.alternateText).toBe(`You: ${getReportActionMessageText(lastAction)}`); @@ -1568,6 +1580,7 @@ describe('SidebarUtils', () => { lastAction, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); expect(result?.alternateText).toContain(`${getReportActionMessageText(lastAction)}`); @@ -1651,6 +1664,7 @@ describe('SidebarUtils', () => { lastAction, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); expect(result?.alternateText).toBe(`One: submitted`); @@ -1747,6 +1761,7 @@ describe('SidebarUtils', () => { localeCompare, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); const reportPreviewMessage = getReportPreviewMessage(iouReport, iouAction, true, true, null, true, lastReportPreviewAction); @@ -1844,6 +1859,7 @@ describe('SidebarUtils', () => { localeCompare, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); const reportPreviewMessage = getReportPreviewMessage(iouReport, iouAction, true, true, null, true, lastReportPreviewAction); From 6bd00105409229911f9e6723fd6937581ef5708a Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Wed, 19 Nov 2025 17:13:39 +0100 Subject: [PATCH 02/39] remove log --- src/libs/OptionsListUtils/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index faa003ac39770..e3c7af83de4aa 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -1871,7 +1871,6 @@ function prepareReportOptionsForDisplay(options: Array>, co * By default, generated options does not have the chat preview line enabled. * If showChatPreviewLine or forcePolicyNamePreview are true, let's generate and overwrite the alternate text. */ - console.log({showChatPreviewLine, forcePolicyNamePreview}); const alternateText = getAlternateText(option, {showChatPreviewLine, forcePolicyNamePreview}, policyTags, !!option.private_isArchived); const isSelected = isReportSelected(option, selectedOptions); const isBold = shouldBoldTitleByDefault || shouldUseBoldText(option); From 1a8c72d42aa48a4b618165d2e4a6b1a31bd8faec Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Wed, 19 Nov 2025 17:21:40 +0100 Subject: [PATCH 03/39] remove unnecessary changes --- src/components/LHNOptionsList/OptionRowLHNData.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/components/LHNOptionsList/OptionRowLHNData.tsx b/src/components/LHNOptionsList/OptionRowLHNData.tsx index 9c99850eee703..83cb780ea9f16 100644 --- a/src/components/LHNOptionsList/OptionRowLHNData.tsx +++ b/src/components/LHNOptionsList/OptionRowLHNData.tsx @@ -3,7 +3,6 @@ import React, {useMemo, useRef} from 'react'; import useCurrentReportID from '@hooks/useCurrentReportID'; import useGetExpensifyCardFromReportAction from '@hooks/useGetExpensifyCardFromReportAction'; import useOnyx from '@hooks/useOnyx'; -import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; import usePrevious from '@hooks/usePrevious'; import SidebarUtils from '@libs/SidebarUtils'; import CONST from '@src/CONST'; @@ -47,14 +46,11 @@ function OptionRowLHNData({ const currentReportIDValue = useCurrentReportID(); const isReportFocused = isOptionFocused && currentReportIDValue?.currentReportID === reportID; const optionItemRef = useRef(undefined); - const {policyForMovingExpensesID} = usePolicyForMovingExpenses(); const [movedFromReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(lastAction, CONST.REPORT.MOVE_TYPE.FROM)}`, {canBeMissing: true}); const [movedToReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(lastAction, CONST.REPORT.MOVE_TYPE.TO)}`, {canBeMissing: true}); - // Determine the correct policy ID for fetching policy tags - const policyIDForTags = fullReport?.policyID === CONST.POLICY.OWNER_EMAIL_FAKE && policyForMovingExpensesID ? policyForMovingExpensesID : fullReport?.policyID; - const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyIDForTags}`, {canBeMissing: true}); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fullReport?.policyID}`, {canBeMissing: true}); // Check the report errors equality to avoid re-rendering when there are no changes const prevReportErrors = usePrevious(reportAttributes?.reportErrors); const areReportErrorsEqual = useMemo(() => deepEqual(prevReportErrors, reportAttributes?.reportErrors), [prevReportErrors, reportAttributes?.reportErrors]); @@ -119,7 +115,6 @@ function OptionRowLHNData({ movedFromReport, movedToReport, policyTags, - policyForMovingExpensesID, ]); return ( From 1665f04a992696db85a4e517bbb3a5e334f54c05 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Wed, 19 Nov 2025 18:46:44 +0100 Subject: [PATCH 04/39] lint --- .../step/IOURequestStepConfirmation.tsx | 39 ++++++++----------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 0b1adb69d0a6a..88608e93e6c59 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -515,20 +515,23 @@ function IOURequestStepConfirmation({ }); }, [requestType, iouType, initialTransactionID, reportID, action, report, transactions, participants]); - function getMoneyRequestContextForParticipant(participant: Participant | undefined, reportParam: Report | undefined) { - const isWorkspaceTarget = !!participant?.isPolicyExpenseChat; - return { - parentChatReport: isWorkspaceTarget ? reportParam : undefined, - policyParams: isWorkspaceTarget - ? { - policy, - policyTagList: policyTags, - policyCategories, - policyRecentlyUsedCategories, - } - : {}, - }; - } + const getMoneyRequestContextForParticipant = useCallback( + (participant: Participant | undefined, reportParam: Report | undefined) => { + const isWorkspaceTarget = !!participant?.isPolicyExpenseChat; + return { + parentChatReport: isWorkspaceTarget ? reportParam : undefined, + policyParams: isWorkspaceTarget + ? { + policy, + policyTagList: policyTags, + policyCategories, + policyRecentlyUsedCategories, + } + : {}, + }; + }, + [policy, policyTags, policyCategories, policyRecentlyUsedCategories], + ); const requestMoney = useCallback( (selectedParticipants: Participant[], gpsPoint?: GpsPoint) => { @@ -624,7 +627,6 @@ function IOURequestStepConfirmation({ viewTourTaskReport, viewTourTaskParentReport, isViewTourTaskParentReportArchived, - getMoneyRequestContextForParticipant, ], ); @@ -744,9 +746,6 @@ function IOURequestStepConfirmation({ currentUserPersonalDetails.accountID, transactionTaxCode, transactionTaxAmount, - policy, - policyTags, - policyCategories, action, customUnitRateID, isDraftPolicy, @@ -807,10 +806,6 @@ function IOURequestStepConfirmation({ currentUserPersonalDetails.login, currentUserPersonalDetails.accountID, iouType, - policy, - policyCategories, - policyTags, - policyRecentlyUsedCategories, isManualDistanceRequest, transactionTaxCode, transactionTaxAmount, From 5cc821c6264236373c75c074bef9a0c89a29b14f Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 1 Dec 2025 10:56:34 +0100 Subject: [PATCH 05/39] fix lint --- src/components/LHNOptionsList/LHNOptionsList.tsx | 8 +++++--- src/components/OptionListContextProvider.tsx | 3 ++- src/components/Search/SearchFiltersChatsSelector.tsx | 5 +++-- src/components/Search/SearchRouter/SearchRouter.tsx | 11 ++++++----- src/pages/Share/ShareDetailsPage.tsx | 2 +- .../iou/request/MoneyRequestAttendeeSelector.tsx | 2 ++ 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/components/LHNOptionsList/LHNOptionsList.tsx b/src/components/LHNOptionsList/LHNOptionsList.tsx index 1047b2ebfcd12..bff2a5e20c4ba 100644 --- a/src/components/LHNOptionsList/LHNOptionsList.tsx +++ b/src/components/LHNOptionsList/LHNOptionsList.tsx @@ -9,10 +9,10 @@ import {StyleSheet, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import BlockingView from '@components/BlockingViews/BlockingView'; import Icon from '@components/Icon'; -import * as Expensicons from '@components/Icon/Expensicons'; import LottieAnimations from '@components/LottieAnimations'; import {ScrollOffsetContext} from '@components/ScrollOffsetContextProvider'; import TextBlock from '@components/TextBlock'; +import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; @@ -53,6 +53,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio const flashListRef = useRef>(null); const route = useRoute(); const isScreenFocused = useIsFocused(); + const icons = useMemoizedLazyExpensifyIcons(['MagnifyingGlass', 'Plus']); const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: false}); const [reportAttributes] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {selector: reportsSelector, canBeMissing: true}); @@ -118,7 +119,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio text={translate('common.emptyLHN.subtitleText1')} /> option.reportID === report.reportID); newReportOptions.push({ diff --git a/src/components/Search/SearchFiltersChatsSelector.tsx b/src/components/Search/SearchFiltersChatsSelector.tsx index 28ced7c51ae3b..d3f90ab8d2ff7 100644 --- a/src/components/Search/SearchFiltersChatsSelector.tsx +++ b/src/components/Search/SearchFiltersChatsSelector.tsx @@ -61,11 +61,12 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen const selectedOptions = useMemo(() => { return selectedReportIDs.map((id) => { const reportObj = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`]; + const reportPolicyTags = reportObj?.policyID ? policyTags?.[reportObj.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; const report = getSelectedOptionData( - createOptionFromReport({...reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`], reportID: id}, personalDetails, policyTags?.[reportObj?.policyID ?? ''], reportAttributesDerived), + createOptionFromReport({...reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`], reportID: id}, personalDetails, reportPolicyTags, reportAttributesDerived), ); const isReportArchived = archivedReportsIdSet.has(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`); - const alternateText = getAlternateText(report, {}, policyTags?.[report.policyID ?? ''], isReportArchived, {}); + const alternateText = getAlternateText(report, {}, reportPolicyTags, isReportArchived, {}); return {...report, alternateText}; }); }, [archivedReportsIdSet, personalDetails, reportAttributesDerived, reports, selectedReportIDs, policyTags]); diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index 68bff9d37e3e5..f26dbf8e3c478 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -5,7 +5,6 @@ import type {TextInputProps} from 'react-native'; import {InteractionManager, View} from 'react-native'; import type {ValueOf} from 'type-fest'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import * as Expensicons from '@components/Icon/Expensicons'; import {usePersonalDetails} from '@components/OnyxListItemProvider'; import {useOptionsList} from '@components/OptionListContextProvider'; import OptionsListSkeletonView from '@components/OptionsListSkeletonView'; @@ -20,6 +19,7 @@ import {isSearchQueryItem} from '@components/SelectionListWithSections/Search/Se import type {SelectionListHandle} from '@components/SelectionListWithSections/types'; import useDebouncedState from '@hooks/useDebouncedState'; import useKeyboardShortcut from '@hooks/useKeyboardShortcut'; +import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; @@ -109,6 +109,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla const {shouldUseNarrowLayout} = useResponsiveLayout(); const listRef = useRef(null); const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: true}); + const icons = useMemoizedLazyExpensifyIcons(['MagnifyingGlass']); // The actual input text that the user sees const [textInputValue, , setTextInputValue] = useDebouncedState('', 500); @@ -152,7 +153,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla if (!report) { return undefined; } - const reportPolicyTags = policyTags?.[report.policyID ?? '']; + const reportPolicyTags = report.policyID ? policyTags?.[report.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; const option = createOptionFromReport(report, personalDetails, reportPolicyTags, undefined, {showPersonalDetails: true}); reportForContextualSearch = option; } @@ -185,7 +186,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla data: [ { text: StringUtils.lineBreaksToSpaces(`${translate('search.searchIn')} ${reportForContextualSearch.text ?? reportForContextualSearch.alternateText}`), - singleIcon: Expensicons.MagnifyingGlass, + singleIcon: icons.MagnifyingGlass, searchQuery: reportQueryValue, autocompleteID, itemStyle: styles.activeComponentBG, @@ -198,13 +199,13 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla }, ]; }, - [contextualReportID, styles.activeComponentBG, textInputValue, translate, isSearchRouterDisplayed, reports, personalDetails], + [contextualReportID, styles.activeComponentBG, textInputValue, translate, isSearchRouterDisplayed, reports, personalDetails, policyTags], ); const searchQueryItem = textInputValue ? { text: textInputValue, - singleIcon: Expensicons.MagnifyingGlass, + singleIcon: icons.MagnifyingGlass, searchQuery: textInputValue, itemStyle: styles.activeComponentBG, keyForList: 'findItem', diff --git a/src/pages/Share/ShareDetailsPage.tsx b/src/pages/Share/ShareDetailsPage.tsx index 4a01af0a13026..cff13e54123c4 100644 --- a/src/pages/Share/ShareDetailsPage.tsx +++ b/src/pages/Share/ShareDetailsPage.tsx @@ -61,7 +61,7 @@ function ShareDetailsPage({route}: ShareDetailsPageProps) { const [errorMessage, setErrorMessage] = useState(undefined); const report: OnyxEntry = getReportOrDraftReport(reportOrAccountID); - const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID ?? ''}`, {canBeMissing: false}); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: false}); const displayReport = useMemo( () => getReportDisplayOption(report, unknownUserDetails, policyTags, reportAttributesDerived), [report, unknownUserDetails, policyTags, reportAttributesDerived], diff --git a/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx b/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx index 973e3f680506d..ebba86cd23ffa 100644 --- a/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx +++ b/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx @@ -276,6 +276,8 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde personalDetails, translate, reportAttributesDerived, + countryCode, + policyTags, ]); const optionLength = useMemo(() => { From 0de37fde81cb6c2b884f648a4006844614ea6d5d Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 1 Dec 2025 11:28:19 +0100 Subject: [PATCH 06/39] fix tests --- src/hooks/useSearchSelector.base.ts | 2 +- tests/unit/OptionsListUtilsTest.tsx | 2 +- tests/unit/SidebarUtilsTest.ts | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hooks/useSearchSelector.base.ts b/src/hooks/useSearchSelector.base.ts index 98e07db4e3bd4..951e62c7f1885 100644 --- a/src/hooks/useSearchSelector.base.ts +++ b/src/hooks/useSearchSelector.base.ts @@ -253,7 +253,7 @@ function useSearchSelectorBase({ includeUserToInvite, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_ATTENDEES: - return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, { + return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, CONST.POLICY.DEFAULT_TAG_LIST, { ...getValidOptionsConfig, betas: betas ?? [], includeP2P: true, diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index 8d298c8659e24..e95f933e7960b 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -2714,7 +2714,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [corporateForceUpgradeAction.reportActionID]: corporateForceUpgradeAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); expect(lastMessage).toBe(Parser.htmlToText(translate(CONST.LOCALES.EN, 'workspaceActions.forcedCorporateUpgrade'))); }); }); diff --git a/tests/unit/SidebarUtilsTest.ts b/tests/unit/SidebarUtilsTest.ts index 4c097ef998c79..235a724a7ef77 100644 --- a/tests/unit/SidebarUtilsTest.ts +++ b/tests/unit/SidebarUtilsTest.ts @@ -1065,6 +1065,7 @@ describe('SidebarUtils', () => { lastAction, lastActionReport: undefined, isReportArchived: undefined, + policyTags: undefined, }); // Then the alternate text should be equal to the message of the last action prepended with the last actor display name. From 1683eb02e949dabe90d3078bd48ae1560eda0799 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 1 Dec 2025 11:43:25 +0100 Subject: [PATCH 07/39] lint --- src/components/LHNOptionsList/LHNOptionsList.tsx | 2 ++ src/components/Search/SearchRouter/SearchRouter.tsx | 2 +- src/pages/iou/request/step/IOURequestStepDistance.tsx | 1 + src/pages/iou/request/step/IOURequestStepDistanceManual.tsx | 1 + src/pages/iou/request/step/IOURequestStepDistanceMap.tsx | 4 ++++ .../iou/request/step/IOURequestStepScan/index.native.tsx | 1 - 6 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/LHNOptionsList/LHNOptionsList.tsx b/src/components/LHNOptionsList/LHNOptionsList.tsx index bff2a5e20c4ba..8ee4cabed438a 100644 --- a/src/components/LHNOptionsList/LHNOptionsList.tsx +++ b/src/components/LHNOptionsList/LHNOptionsList.tsx @@ -157,6 +157,8 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio theme.textSupporting, styles.textNormal, translate, + icons.MagnifyingGlass, + icons.Plus, ], ); diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index f26dbf8e3c478..97df638c1086a 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -199,7 +199,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla }, ]; }, - [contextualReportID, styles.activeComponentBG, textInputValue, translate, isSearchRouterDisplayed, reports, personalDetails, policyTags], + [contextualReportID, styles.activeComponentBG, textInputValue, translate, isSearchRouterDisplayed, reports, personalDetails, policyTags, icons.MagnifyingGlass], ); const searchQueryItem = textInputValue diff --git a/src/pages/iou/request/step/IOURequestStepDistance.tsx b/src/pages/iou/request/step/IOURequestStepDistance.tsx index 3db83fcbe8e44..446a0d89a13c9 100644 --- a/src/pages/iou/request/step/IOURequestStepDistance.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistance.tsx @@ -447,6 +447,7 @@ function IOURequestStepDistance({ personalPolicy?.autoReporting, reportID, transactionViolations, + currentUserPersonalDetails.accountID, ]); const getError = () => { diff --git a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx index f3d88cb5b0dee..4ef1b73a65b6d 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx @@ -309,6 +309,7 @@ function IOURequestStepDistanceManual({ navigateToConfirmationPage, personalPolicy?.autoReporting, transactionViolations, + currentUserPersonalDetails.accountID, ], ); diff --git a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx index 62465fcb943ae..900d186d144e6 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx @@ -449,6 +449,7 @@ function IOURequestStepDistanceMap({ personalPolicy?.autoReporting, reportID, transactionViolations, + currentUserPersonalDetails.accountID, ]); const getError = () => { @@ -551,6 +552,9 @@ function IOURequestStepDistanceMap({ transaction?.routes, report?.reportID, policy, + currentUserAccountIDParam, + currentUserEmailParam, + isASAPSubmitBetaEnabled, ]); const renderItem = useCallback( diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index 46a539d9c8063..73bbdd9d422c1 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -548,7 +548,6 @@ function IOURequestStepScan({ transactionTaxCode, transactionTaxAmount, policy, - personalPolicy?.autoReporting, selfDMReportID, ], ); From 00e4c7aabf1df893103ed4aa9d0e4ece98296a32 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 1 Dec 2025 12:09:35 +0100 Subject: [PATCH 08/39] . --- src/hooks/useSearchSelector.base.ts | 1 + src/libs/OptionsListUtils/index.ts | 30 +++++++++++-------- src/pages/iou/SplitBillDetailsPage.tsx | 5 ++-- .../step/IOURequestStepConfirmation.tsx | 24 +++++++++------ 4 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/hooks/useSearchSelector.base.ts b/src/hooks/useSearchSelector.base.ts index 951e62c7f1885..9dcca0db3bbd0 100644 --- a/src/hooks/useSearchSelector.base.ts +++ b/src/hooks/useSearchSelector.base.ts @@ -286,6 +286,7 @@ function useSearchSelectorBase({ maxRecentReportsToShow, getValidOptionsConfig, selectedOptions, + includeCurrentUser, ]); const isOptionSelected = useMemo(() => { diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index 85615430fd268..203c67c00b812 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -1228,19 +1228,23 @@ function createOptionList( } } - const allPersonalDetailsOptions = Object.values(personalDetails ?? {}).map((personalDetail) => ({ - item: personalDetail, - ...createOption( - [personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID], - personalDetails, - reportMapForAccountIDs[personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID], - policyTags?.[reportMapForAccountIDs[personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID]?.policyID ?? ''] ?? CONST.POLICY.DEFAULT_TAG_LIST, - { - showPersonalDetails: true, - }, - reportAttributesDerived, - ), - })); + const allPersonalDetailsOptions = Object.values(personalDetails ?? {}).map((personalDetail) => { + const reportID = reportMapForAccountIDs[personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID]?.policyID; + const policyTagList = reportID ? policyTags?.[reportID] : CONST.POLICY.DEFAULT_TAG_LIST; + return { + item: personalDetail, + ...createOption( + [personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID], + personalDetails, + reportMapForAccountIDs[personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID], + policyTagList, + { + showPersonalDetails: true, + }, + reportAttributesDerived, + ), + }; + }); span.setAttributes({ personalDetails: allPersonalDetailsOptions.length, diff --git a/src/pages/iou/SplitBillDetailsPage.tsx b/src/pages/iou/SplitBillDetailsPage.tsx index e6f3781d6fb91..3b3c5bd449d38 100644 --- a/src/pages/iou/SplitBillDetailsPage.tsx +++ b/src/pages/iou/SplitBillDetailsPage.tsx @@ -4,11 +4,11 @@ import {View} from 'react-native'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Icon from '@components/Icon'; -import * as Expensicons from '@components/Icon/Expensicons'; import {ImageBehaviorContextProvider} from '@components/Image/ImageBehaviorContextProvider'; import MoneyRequestConfirmationList from '@components/MoneyRequestConfirmationList'; import MoneyRequestHeaderStatusBar from '@components/MoneyRequestHeaderStatusBar'; import ScreenWrapper from '@components/ScreenWrapper'; +import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; @@ -42,6 +42,7 @@ function SplitBillDetailsPage({route, report, reportAction}: SplitBillDetailsPag const {translate} = useLocalize(); const theme = useTheme(); const {isBetaEnabled} = usePermissions(); + const icons = useMemoizedLazyExpensifyIcons(['ReceiptScan']); const reportID = report?.reportID; const originalMessage = reportAction && isMoneyRequestAction(reportAction) ? getOriginalMessage(reportAction) : undefined; @@ -107,7 +108,7 @@ function SplitBillDetailsPage({route, report, reportAction}: SplitBillDetailsPag Date: Mon, 1 Dec 2025 12:43:15 +0100 Subject: [PATCH 09/39] lint --- .../step/IOURequestStepConfirmation.tsx | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index f41214e6a6636..bd98d4fe38333 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -611,19 +611,21 @@ function IOURequestStepConfirmation({ }, [ transactions, - getMoneyRequestContextForParticipant, - getReportToUseAndBackToReport, - report, - backToReport, receiptFiles, archivedReportsIdSet, + report, currentUserPersonalDetails.login, currentUserPersonalDetails.accountID, + policy, + policyTags, + policyCategories, + policyRecentlyUsedCategories, action, transactionTaxCode, transactionTaxAmount, customUnitRateID, shouldGenerateTransactionThreadReport, + backToReport, isASAPSubmitBetaEnabled, transactionViolations, viewTourTaskReport, @@ -749,15 +751,15 @@ function IOURequestStepConfirmation({ }, [ transactions, - getMoneyRequestContextForParticipant, - getReportToUseAndBackToReport, - report, - backToReport, archivedReportsIdSet, + report, isDraftPolicy, action, currentUserPersonalDetails.login, currentUserPersonalDetails.accountID, + policy, + policyCategories, + policyTags, isManualDistanceRequest, receiptFiles, transactionTaxCode, @@ -811,18 +813,20 @@ function IOURequestStepConfirmation({ }, [ transaction, - getMoneyRequestContextForParticipant, - getReportToUseAndBackToReport, report, - backToReport, currentUserPersonalDetails.login, currentUserPersonalDetails.accountID, iouType, + policy, + policyCategories, + policyTags, + policyRecentlyUsedCategories, isManualDistanceRequest, transactionTaxCode, transactionTaxAmount, customUnitRateID, receiptFiles, + backToReport, isASAPSubmitBetaEnabled, transactionViolations, ], From 2d8dbac63d6301c9e3dc502b250e9c6feebffb40 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 8 Dec 2025 09:59:48 +0100 Subject: [PATCH 10/39] lint fixes --- src/libs/SidebarUtils.ts | 4 ++-- src/pages/RoomInvitePage.tsx | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts index 12995ec61adf3..6a5297d1e2d3e 100644 --- a/src/libs/SidebarUtils.ts +++ b/src/libs/SidebarUtils.ts @@ -96,6 +96,7 @@ import { isTaskAction, isTransactionThread, } from './ReportActionsUtils'; +import {getReportName} from './ReportNameUtils'; import type {OptionData} from './ReportUtils'; import { canUserPerformWriteAction as canUserPerformWriteActionUtil, @@ -113,7 +114,6 @@ import { getReportActionActorAccountID, getReportDescription, getReportMetadata, - getReportName, getReportNotificationPreference, getReportParticipantsTitle, getReportSubtitlePrefix, @@ -1006,7 +1006,7 @@ function getOptionData({ result.phoneNumber = personalDetail?.phoneNumber ?? ''; } - const reportName = getReportName(report, policy, undefined, undefined, invoiceReceiverPolicy, undefined, undefined, isReportArchived); + const reportName = getReportName(report); result.text = reportName; result.subtitle = subtitle; diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx index f2e86df307491..73fd98929e11a 100644 --- a/src/pages/RoomInvitePage.tsx +++ b/src/pages/RoomInvitePage.tsx @@ -32,8 +32,9 @@ import {getLoginsByAccountIDs} from '@libs/PersonalDetailsUtils'; import {addSMSDomainIfPhoneNumber, parsePhoneNumber} from '@libs/PhoneNumber'; import type {MemberEmailsToAccountIDs} from '@libs/PolicyUtils'; import {isPolicyEmployee as isPolicyEmployeeUtil} from '@libs/PolicyUtils'; +import {getReportName} from '@libs/ReportNameUtils'; import type {OptionData} from '@libs/ReportUtils'; -import {getReportName, isHiddenForCurrentUser} from '@libs/ReportUtils'; +import {isHiddenForCurrentUser} from '@libs/ReportUtils'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; From 4c5baa1da892e294df3e4c9eabadee33e4cf49fb Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 8 Dec 2025 16:29:52 +0100 Subject: [PATCH 11/39] fix lint --- src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 48a08665d284d..fc3a97f3fd10d 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -619,7 +619,6 @@ function IOURequestStepConfirmation({ shouldGenerateTransactionThreadReport, backToReport, isASAPSubmitBetaEnabled, - transactionViolations, viewTourTaskReport, viewTourTaskParentReport, isViewTourTaskParentReportArchived, From fb834d623389e4cd4956380b6e002b33e9f2f7e8 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Tue, 9 Dec 2025 15:40:06 +0100 Subject: [PATCH 12/39] . --- src/libs/SidebarUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts index 6a5297d1e2d3e..81a3bff3521ab 100644 --- a/src/libs/SidebarUtils.ts +++ b/src/libs/SidebarUtils.ts @@ -96,7 +96,6 @@ import { isTaskAction, isTransactionThread, } from './ReportActionsUtils'; -import {getReportName} from './ReportNameUtils'; import type {OptionData} from './ReportUtils'; import { canUserPerformWriteAction as canUserPerformWriteActionUtil, @@ -114,6 +113,7 @@ import { getReportActionActorAccountID, getReportDescription, getReportMetadata, + getReportName, getReportNotificationPreference, getReportParticipantsTitle, getReportSubtitlePrefix, From 0adeef9fe9d2525f126b896235f67d7ac08322b1 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 15 Dec 2025 16:26:58 +0100 Subject: [PATCH 13/39] resolve comments --- src/components/LHNOptionsList/LHNOptionsList.tsx | 5 ++++- src/libs/OptionsListUtils/index.ts | 13 ++++--------- src/libs/OptionsListUtils/types.ts | 1 - src/pages/NewChatPage.tsx | 1 - src/pages/RoomInvitePage.tsx | 3 +-- 5 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/components/LHNOptionsList/LHNOptionsList.tsx b/src/components/LHNOptionsList/LHNOptionsList.tsx index 71525f2a732b4..b0206662515e4 100644 --- a/src/components/LHNOptionsList/LHNOptionsList.tsx +++ b/src/components/LHNOptionsList/LHNOptionsList.tsx @@ -16,6 +16,7 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; +import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; import usePrevious from '@hooks/usePrevious'; import useRootNavigationState from '@hooks/useRootNavigationState'; import useScrollEventEmitter from '@hooks/useScrollEventEmitter'; @@ -54,6 +55,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio const route = useRoute(); const isScreenFocused = useIsFocused(); const expensifyIcons = useMemoizedLazyExpensifyIcons(['MagnifyingGlass', 'Plus'] as const); + const {policyForMovingExpensesID} = usePolicyForMovingExpenses(); const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: false}); const [reportAttributes] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {selector: reportsSelector, canBeMissing: true}); @@ -176,7 +178,8 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio const itemParentReportActions = reportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${item?.parentReportID}`]; const itemParentReportAction = item?.parentReportActionID ? itemParentReportActions?.[item?.parentReportActionID] : undefined; const itemReportAttributes = reportAttributes?.[reportID]; - const itemPolicyTags = policyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${item?.policyID}`]; + const itemPolicyID = item?.policyID === CONST.POLICY.OWNER_EMAIL_FAKE && policyForMovingExpensesID ? policyForMovingExpensesID : item?.policyID; + const itemPolicyTags = policyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${itemPolicyID}`]; let invoiceReceiverPolicyID = '-1'; if (item?.invoiceReceiver && 'policyID' in item.invoiceReceiver) { diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index 670005e5ac814..ed9dc5f2d178b 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -1234,14 +1234,14 @@ function createOptionList( } const allPersonalDetailsOptions = Object.values(personalDetails ?? {}).map((personalDetail) => { - const reportID = reportMapForAccountIDs[personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID]?.policyID; - const policyTagList = reportID ? policyTags?.[reportID] : CONST.POLICY.DEFAULT_TAG_LIST; + const report = reportMapForAccountIDs[personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID]; + const policyTagList = report.policyID ? policyTags?.[report.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; return { item: personalDetail, ...createOption( [personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID], personalDetails, - reportMapForAccountIDs[personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID], + report, policyTagList, { showPersonalDetails: true, @@ -1553,7 +1553,6 @@ function canCreateOptimisticPersonalDetailOption({ */ function getUserToInviteOption({ searchValue, - policyTags, loginsToExclude = {}, selectedOptions = [], showChatPreviewLine = false, @@ -1585,7 +1584,7 @@ function getUserToInviteOption({ }, }; - const userToInvite = createOption([optimisticAccountID], personalDetailsExtended, null, policyTags, { + const userToInvite = createOption([optimisticAccountID], personalDetailsExtended, null, undefined, { showChatPreviewLine, }); userToInvite.isOptimisticAccount = true; @@ -2207,7 +2206,6 @@ function getValidOptions( userToInvite = filterUserToInvite( {currentUserOption: currentUserRef.current, recentReports: recentReportOptions, personalDetails: personalDetailsOptions}, searchString ?? '', - policyTags, countryCode, { excludeLogins: loginsToExclude, @@ -2645,7 +2643,6 @@ function filterCurrentUserOption(currentUserOption: SearchOptionData | null | un function filterUserToInvite( options: Omit, searchValue: string, - policyTags: OnyxEntry, countryCode: number = CONST.DEFAULT_COUNTRY_CODE, config?: FilterUserToInviteConfig, ): SearchOptionData | null { @@ -2671,7 +2668,6 @@ function filterUserToInvite( }; return getUserToInviteOption({ searchValue, - policyTags, loginsToExclude, countryCode, ...config, @@ -2726,7 +2722,6 @@ function filterOptions(options: Options, searchInputValue: string, countryCode: currentUserOption, }, searchValue, - policyTags, countryCode, config, ); diff --git a/src/libs/OptionsListUtils/types.ts b/src/libs/OptionsListUtils/types.ts index 2b7225d5e9ecb..54e424250f088 100644 --- a/src/libs/OptionsListUtils/types.ts +++ b/src/libs/OptionsListUtils/types.ts @@ -194,7 +194,6 @@ type GetOptionsConfig = { type GetUserToInviteConfig = { searchValue: string | undefined; - policyTags: OnyxEntry; loginsToExclude?: Record; reportActions?: ReportActions; firstName?: string; diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index 8f28e65d1fffc..c0d51079c69f3 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -141,7 +141,6 @@ function useOptions() { if (!participantOption) { participantOption = getUserToInviteOption({ searchValue: participant?.login, - policyTags: undefined, }); } if (!participantOption) { diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx index fa0fb88b0691e..24800f2684350 100644 --- a/src/pages/RoomInvitePage.tsx +++ b/src/pages/RoomInvitePage.tsx @@ -34,9 +34,8 @@ import {getLoginsByAccountIDs} from '@libs/PersonalDetailsUtils'; import {addSMSDomainIfPhoneNumber, parsePhoneNumber} from '@libs/PhoneNumber'; import type {MemberEmailsToAccountIDs} from '@libs/PolicyUtils'; import {isPolicyEmployee as isPolicyEmployeeUtil} from '@libs/PolicyUtils'; -import {getReportName} from '@libs/ReportNameUtils'; import type {OptionData} from '@libs/ReportUtils'; -import {isHiddenForCurrentUser} from '@libs/ReportUtils'; +import {getReportName, isHiddenForCurrentUser} from '@libs/ReportUtils'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; From 4cd30331b3dcd2801cd91d46560dc44d6f1f140d Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Wed, 17 Dec 2025 16:52:15 +0100 Subject: [PATCH 14/39] fixes --- src/components/LHNOptionsList/LHNOptionsList.tsx | 3 ++- src/components/Search/SearchAutocompleteList.tsx | 10 ++++++---- src/components/Search/SearchFiltersChatsSelector.tsx | 4 ++-- src/hooks/useSearchSelector.base.ts | 7 ++++--- src/libs/ContactUtils.ts | 1 - src/libs/OptionsListUtils/index.ts | 12 ++++++------ src/libs/OptionsListUtils/types.ts | 2 +- src/pages/RoomInvitePage.tsx | 2 +- src/pages/Share/ShareTab.tsx | 6 +++--- tests/perf-test/OptionsListUtils.perf-test.ts | 2 +- tests/unit/OptionsListUtilsTest.tsx | 8 ++++---- 11 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/components/LHNOptionsList/LHNOptionsList.tsx b/src/components/LHNOptionsList/LHNOptionsList.tsx index b0206662515e4..132430066662f 100644 --- a/src/components/LHNOptionsList/LHNOptionsList.tsx +++ b/src/components/LHNOptionsList/LHNOptionsList.tsx @@ -300,6 +300,8 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio reportActions, isOffline, reportAttributes, + policyForMovingExpensesID, + policyTags, policy, transactions, draftComments, @@ -317,7 +319,6 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio isReportsSplitNavigatorLast, isScreenFocused, localeCompare, - policyTags, ], ); diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx index 92fb1bfde4108..cc28bfc37848e 100644 --- a/src/components/Search/SearchAutocompleteList.tsx +++ b/src/components/Search/SearchAutocompleteList.tsx @@ -190,6 +190,7 @@ function SearchAutocompleteList({ const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); const [recentSearches] = useOnyx(ONYXKEYS.RECENT_SEARCHES, {canBeMissing: true}); const [countryCode] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); + const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: true}); const expensifyIcons = useMemoizedLazyExpensifyIcons(['History', 'MagnifyingGlass'] as const); const {options, areOptionsInitialized} = useOptionsList(); @@ -211,10 +212,10 @@ function SearchAutocompleteList({ includeCurrentUser: true, countryCode, shouldShowGBR: false, - policyTags: undefined, + policyTags, shouldUnreadBeBold: true, }); - }, [areOptionsInitialized, options, draftComments, nvpDismissedProductTraining, betas, autocompleteQueryValue, countryCode]); + }, [areOptionsInitialized, options, draftComments, nvpDismissedProductTraining, betas, autocompleteQueryValue, countryCode, policyTags]); const [isInitialRender, setIsInitialRender] = useState(true); const parsedQuery = useMemo(() => parseForAutocomplete(autocompleteQueryValue), [autocompleteQueryValue]); @@ -422,7 +423,7 @@ function SearchAutocompleteList({ includeCurrentUser: true, countryCode, shouldShowGBR: true, - policyTags: undefined, + policyTags, }).personalDetails.filter((participant) => participant.text && !alreadyAutocompletedKeys.has(participant.text.toLowerCase())); return participants.map((participant) => ({ @@ -447,7 +448,7 @@ function SearchAutocompleteList({ includeCurrentUser: false, countryCode, shouldShowGBR: true, - policyTags: undefined, + policyTags, }).recentReports; return filteredReports.map((chat) => ({ @@ -611,6 +612,7 @@ function SearchAutocompleteList({ nvpDismissedProductTraining, betas, countryCode, + policyTags, currentUserLogin, groupByAutocompleteList, statusAutocompleteList, diff --git a/src/components/Search/SearchFiltersChatsSelector.tsx b/src/components/Search/SearchFiltersChatsSelector.tsx index d3f90ab8d2ff7..dbf01dac4d202 100644 --- a/src/components/Search/SearchFiltersChatsSelector.tsx +++ b/src/components/Search/SearchFiltersChatsSelector.tsx @@ -75,8 +75,8 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen if (!areOptionsInitialized || !isScreenTransitionEnd) { return defaultListOptions; } - return getSearchOptions({options, draftComments, nvpDismissedProductTraining, betas: undefined, policyTags: undefined, isUsedInChatFinder: false, countryCode}); - }, [areOptionsInitialized, draftComments, nvpDismissedProductTraining, isScreenTransitionEnd, options, countryCode]); + return getSearchOptions({options, draftComments, nvpDismissedProductTraining, betas: undefined, policyTags, isUsedInChatFinder: false, countryCode}); + }, [areOptionsInitialized, isScreenTransitionEnd, options, draftComments, nvpDismissedProductTraining, policyTags, countryCode]); const chatOptions = useMemo(() => { return filterAndOrderOptions(defaultOptions, cleanSearchTerm, countryCode, undefined, { diff --git a/src/hooks/useSearchSelector.base.ts b/src/hooks/useSearchSelector.base.ts index 77b8c857e8ee4..733c8963d42ed 100644 --- a/src/hooks/useSearchSelector.base.ts +++ b/src/hooks/useSearchSelector.base.ts @@ -163,7 +163,7 @@ function useSearchSelectorBase({ const [countryCode = CONST.DEFAULT_COUNTRY_CODE] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, {canBeMissing: true}); const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); - + const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); const onListEndReached = useDebounce( useCallback(() => { setMaxResults((previous) => previous + maxResultsPerPage); @@ -193,7 +193,7 @@ function useSearchSelectorBase({ maxResults, includeUserToInvite, countryCode, - policyTags: undefined, + policyTags, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_MEMBER_INVITE: return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, undefined, { @@ -257,7 +257,7 @@ function useSearchSelectorBase({ includeUserToInvite, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_ATTENDEES: - return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, CONST.POLICY.DEFAULT_TAG_LIST, { + return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, undefined, { ...getValidOptionsConfig, betas: betas ?? [], includeP2P: true, @@ -285,6 +285,7 @@ function useSearchSelectorBase({ maxResults, includeUserToInvite, countryCode, + policyTags, excludeLogins, includeRecentReports, maxRecentReportsToShow, diff --git a/src/libs/ContactUtils.ts b/src/libs/ContactUtils.ts index 8c834f0e305c6..f5945491a4ce4 100644 --- a/src/libs/ContactUtils.ts +++ b/src/libs/ContactUtils.ts @@ -48,7 +48,6 @@ const getContacts = (deviceContacts: DeviceContact[] | [], localeCompare: Locale phone: phoneNumber, avatar: avatarSource, countryCode, - policyTags: undefined, }); }) .filter((contact): contact is SearchOption => contact !== null); diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index ed9dc5f2d178b..0a0adedb8dbb2 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -1849,7 +1849,7 @@ function isValidReport(option: SearchOption, config: IsValidReportsConfi * @param config - Configuration object specifying display preferences and filtering criteria * @returns Array of enriched and filtered report options ready for UI display */ -function prepareReportOptionsForDisplay(options: Array>, config: GetValidReportsConfig, policyTags: OnyxEntry): Array> { +function prepareReportOptionsForDisplay(options: Array>, config: GetValidReportsConfig, policyTags: OnyxCollection): Array> { const { showChatPreviewLine = false, forcePolicyNamePreview = false, @@ -1873,12 +1873,13 @@ function prepareReportOptionsForDisplay(options: Array>, co continue; } const report = option.item; + const reportPolicyTags = policyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report.policyID}`]; /** * By default, generated options does not have the chat preview line enabled. * If showChatPreviewLine or forcePolicyNamePreview are true, let's generate and overwrite the alternate text. */ - const alternateText = getAlternateText(option, {showChatPreviewLine, forcePolicyNamePreview}, policyTags, !!option.private_isArchived); + const alternateText = getAlternateText(option, {showChatPreviewLine, forcePolicyNamePreview}, reportPolicyTags, !!option.private_isArchived); const isSelected = isReportSelected(option, selectedOptions); let isOptionUnread = option.isUnread; @@ -1993,7 +1994,7 @@ function getValidOptions( options: OptionList, draftComments: OnyxCollection | undefined, nvpDismissedProductTraining: OnyxEntry, - policyTags: OnyxEntry, + policyTags: OnyxCollection, { excludeLogins = {}, includeSelectedOptions = false, @@ -2237,7 +2238,7 @@ type SearchOptionsConfig = { includeCurrentUser?: boolean; countryCode?: number; shouldShowGBR?: boolean; - policyTags: OnyxEntry; + policyTags: OnyxCollection; shouldUnreadBeBold?: boolean; }; @@ -2383,7 +2384,6 @@ function formatMemberForList(member: SearchOptionData): MemberForList { function getMemberInviteOptions( personalDetails: Array>, nvpDismissedProductTraining: OnyxEntry, - policyTags: OnyxEntry, betas: Beta[] = [], excludeLogins: Record = {}, includeSelectedOptions = false, @@ -2393,7 +2393,7 @@ function getMemberInviteOptions( {personalDetails, reports: []}, undefined, nvpDismissedProductTraining, - policyTags, + {}, { betas, includeP2P: true, diff --git a/src/libs/OptionsListUtils/types.ts b/src/libs/OptionsListUtils/types.ts index 54e424250f088..c13b856af8bfb 100644 --- a/src/libs/OptionsListUtils/types.ts +++ b/src/libs/OptionsListUtils/types.ts @@ -2,7 +2,7 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import type {OptionData} from '@libs/ReportUtils'; import type {AvatarSource} from '@libs/UserAvatarUtils'; import type {IOUAction} from '@src/CONST'; -import type {Beta, PersonalDetails, PolicyTagLists, Report, ReportActions, TransactionViolation} from '@src/types/onyx'; +import type {Beta, PersonalDetails, Report, ReportActions, TransactionViolation} from '@src/types/onyx'; import type {Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; /** diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx index 24800f2684350..1dd1fb7c2b373 100644 --- a/src/pages/RoomInvitePage.tsx +++ b/src/pages/RoomInvitePage.tsx @@ -90,7 +90,7 @@ function RoomInvitePage({ return {recentReports: [], personalDetails: [], userToInvite: null, currentUserOption: null}; } - const inviteOptions = getMemberInviteOptions(options.personalDetails, nvpDismissedProductTraining, undefined, betas ?? [], excludedUsers); + const inviteOptions = getMemberInviteOptions(options.personalDetails, nvpDismissedProductTraining, betas ?? [], excludedUsers); // Update selectedOptions with the latest personalDetails information const detailsMap: Record = {}; for (const detail of inviteOptions.personalDetails) { diff --git a/src/pages/Share/ShareTab.tsx b/src/pages/Share/ShareTab.tsx index 2ced0c70e78ac..a59a6ae106514 100644 --- a/src/pages/Share/ShareTab.tsx +++ b/src/pages/Share/ShareTab.tsx @@ -49,7 +49,7 @@ function ShareTab({ref}: ShareTabProps) { const [countryCode = CONST.DEFAULT_COUNTRY_CODE] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, {canBeMissing: true}); const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); - + const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); useImperativeHandle(ref, () => ({ focus: selectionListRef.current?.focusTextInput, })); @@ -76,9 +76,9 @@ function ShareTab({ref}: ShareTabProps) { maxResults: 20, includeUserToInvite: true, countryCode, - policyTags: undefined, + policyTags, }); - }, [areOptionsInitialized, betas, draftComments, nvpDismissedProductTraining, options, textInputValue, countryCode]); + }, [areOptionsInitialized, options, draftComments, nvpDismissedProductTraining, betas, textInputValue, countryCode, policyTags]); const recentReportsOptions = useMemo(() => { if (textInputValue.trim() === '') { diff --git a/tests/perf-test/OptionsListUtils.perf-test.ts b/tests/perf-test/OptionsListUtils.perf-test.ts index 8d39ec5f1db2b..75569bed5edec 100644 --- a/tests/perf-test/OptionsListUtils.perf-test.ts +++ b/tests/perf-test/OptionsListUtils.perf-test.ts @@ -153,7 +153,7 @@ describe('OptionsListUtils', () => { /* Testing getMemberInviteOptions */ test('[OptionsListUtils] getMemberInviteOptions', async () => { await waitForBatchedUpdates(); - await measureFunction(() => getMemberInviteOptions(options.personalDetails, nvpDismissedProductTraining, undefined, mockedBetas)); + await measureFunction(() => getMemberInviteOptions(options.personalDetails, nvpDismissedProductTraining, mockedBetas)); }); test('[OptionsListUtils] worst case scenario with a search term that matches a subset of selectedOptions, filteredRecentReports, and filteredPersonalDetails', async () => { diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index 0928d9ef18111..a79bef8099a25 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -1228,7 +1228,7 @@ describe('OptionsListUtils', () => { const selectedPerson = PERSONAL_DETAILS['3']; const selectedReport = REPORTS['3'] as unknown as OptionData; - const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, { + const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, selectedOptions: [selectedPerson, selectedReport], }); @@ -1364,7 +1364,7 @@ describe('OptionsListUtils', () => { it('should sort personal details alphabetically', () => { // Given a set of personalDetails // When we call getMemberInviteOptions - const results = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, undefined, []); + const results = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, []); // Then personal details should be sorted alphabetically expect(results.personalDetails.at(0)?.text).toBe('Black Panther'); @@ -1745,7 +1745,7 @@ describe('OptionsListUtils', () => { it('should not return any options if search value does not match any personal details (getMemberInviteOptions)', () => { // Given a set of options - const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, undefined, []); + const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, []); // When we call filterAndOrderOptions with a search value that does not match any personal details const filteredOptions = filterAndOrderOptions(options, 'magneto', COUNTRY_CODE, undefined); @@ -1755,7 +1755,7 @@ describe('OptionsListUtils', () => { it('should return one personal detail if search value matches an email (getMemberInviteOptions)', () => { // Given a set of options - const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, undefined, []); + const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, []); // When we call filterAndOrderOptions with a search value that matches an email const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', COUNTRY_CODE, undefined); From bc3803eaf39329e3d391dbaae27d7e9939ff8465 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Thu, 18 Dec 2025 09:00:51 +0100 Subject: [PATCH 15/39] resolve conflicts --- src/hooks/useFilteredOptions.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hooks/useFilteredOptions.ts b/src/hooks/useFilteredOptions.ts index da77f8ba42cec..4643602059b8f 100644 --- a/src/hooks/useFilteredOptions.ts +++ b/src/hooks/useFilteredOptions.ts @@ -76,12 +76,13 @@ function useFilteredOptions(config: UseFilteredOptionsConfig = {}): UseFilteredO canBeMissing: true, selector: reportsSelector, }); + const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); const totalReports = allReports ? Object.keys(allReports).length : 0; const options: OptionList | null = enabled && allReports && allPersonalDetails - ? createFilteredOptionList(allPersonalDetails, allReports, reportAttributesDerived, { + ? createFilteredOptionList(allPersonalDetails, allReports, policyTags, reportAttributesDerived, { maxRecentReports: reportsLimit, includeP2P, searchTerm, From e8b16decad58b2de852e8a4f003de4de7612d1c2 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Fri, 19 Dec 2025 11:58:01 +0100 Subject: [PATCH 16/39] fix typecheck --- .../LHNOptionsList/LHNOptionsList.tsx | 1 + .../LHNOptionsList/OptionRowLHNData.tsx | 3 + src/components/OptionListContextProvider.tsx | 23 +- .../FilterDropdowns/UserSelectPopup.tsx | 10 +- .../Search/SearchAutocompleteList.tsx | 6 +- .../Search/SearchFiltersChatsSelector.tsx | 15 +- .../SearchFiltersParticipantsSelector.tsx | 11 +- .../Search/SearchRouter/SearchRouter.tsx | 2 +- src/hooks/useContactImport.ts | 6 +- src/hooks/useFilteredOptions.ts | 4 +- src/hooks/useSearchSelector.base.ts | 16 +- src/libs/ContactUtils.ts | 10 +- src/libs/OptionsListUtils/index.ts | 87 +++-- src/libs/OptionsListUtils/types.ts | 2 + src/libs/SidebarUtils.ts | 6 +- src/pages/NewChatPage.tsx | 6 +- src/pages/RoomInvitePage.tsx | 8 +- src/pages/Share/ShareDetailsPage.tsx | 4 +- src/pages/Share/ShareTab.tsx | 3 +- src/pages/Share/SubmitDetailsPage.tsx | 2 +- src/pages/iou/SplitBillDetailsPage.tsx | 4 +- .../MoneyRequestAccountantSelector.tsx | 32 +- .../request/MoneyRequestAttendeeSelector.tsx | 7 +- .../MoneyRequestParticipantsSelector.tsx | 12 +- .../iou/request/step/IOURequestStepAmount.tsx | 2 +- .../step/IOURequestStepConfirmation.tsx | 6 +- .../request/step/IOURequestStepDistance.tsx | 2 +- .../step/IOURequestStepDistanceManual.tsx | 17 +- .../step/IOURequestStepDistanceMap.tsx | 2 +- .../step/IOURequestStepScan/index.native.tsx | 4 +- .../request/step/IOURequestStepScan/index.tsx | 4 +- tests/perf-test/OptionsListUtils.perf-test.ts | 33 +- tests/perf-test/SearchRouter.perf-test.tsx | 2 +- tests/perf-test/SidebarUtils.perf-test.ts | 1 + tests/unit/OptionsListUtilsTest.tsx | 311 +++++++++++------- tests/unit/SidebarUtilsTest.ts | 19 +- 36 files changed, 448 insertions(+), 235 deletions(-) diff --git a/src/components/LHNOptionsList/LHNOptionsList.tsx b/src/components/LHNOptionsList/LHNOptionsList.tsx index 8ff6212e347a0..04469669f458b 100644 --- a/src/components/LHNOptionsList/LHNOptionsList.tsx +++ b/src/components/LHNOptionsList/LHNOptionsList.tsx @@ -229,6 +229,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio const movedFromReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(lastReportAction, CONST.REPORT.MOVE_TYPE.FROM)}`]; const movedToReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(lastReportAction, CONST.REPORT.MOVE_TYPE.TO)}`]; const lastMessageTextFromReport = getLastMessageTextForReport({ + translate, report: item, lastActorDetails, movedFromReport, diff --git a/src/components/LHNOptionsList/OptionRowLHNData.tsx b/src/components/LHNOptionsList/OptionRowLHNData.tsx index c3d365350eab0..2a3ce9107e948 100644 --- a/src/components/LHNOptionsList/OptionRowLHNData.tsx +++ b/src/components/LHNOptionsList/OptionRowLHNData.tsx @@ -2,6 +2,7 @@ import {deepEqual} from 'fast-equals'; import React, {useMemo, useRef} from 'react'; import useCurrentReportID from '@hooks/useCurrentReportID'; import useGetExpensifyCardFromReportAction from '@hooks/useGetExpensifyCardFromReportAction'; +import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import usePrevious from '@hooks/usePrevious'; import SidebarUtils from '@libs/SidebarUtils'; @@ -56,10 +57,12 @@ function OptionRowLHNData({ const areReportErrorsEqual = useMemo(() => deepEqual(prevReportErrors, reportAttributes?.reportErrors), [prevReportErrors, reportAttributes?.reportErrors]); const card = useGetExpensifyCardFromReportAction({reportAction: lastAction, policyID: fullReport?.policyID}); + const {translate} = useLocalize(); const optionItem = useMemo(() => { // Note: ideally we'd have this as a dependent selector in onyx! const item = SidebarUtils.getOptionData({ + translate, report: fullReport, reportAttributes, oneTransactionThreadReport, diff --git a/src/components/OptionListContextProvider.tsx b/src/components/OptionListContextProvider.tsx index 3344751720744..d6e08aefd9e41 100644 --- a/src/components/OptionListContextProvider.tsx +++ b/src/components/OptionListContextProvider.tsx @@ -1,5 +1,6 @@ import React, {createContext, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; +import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import usePrevious from '@hooks/usePrevious'; import {createOptionFromReport, createOptionList, processReport, shallowOptionsListCompare} from '@libs/OptionsListUtils'; @@ -57,14 +58,15 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { const prevPersonalDetails = usePrevious(personalDetails); const hasInitialData = useMemo(() => Object.keys(personalDetails ?? {}).length > 0, [personalDetails]); const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); + const {translate} = useLocalize(); const loadOptions = useCallback(() => { - const optionLists = createOptionList(personalDetails, policyTags, reports, reportAttributes?.reports); + const optionLists = createOptionList(personalDetails, policyTags, translate, reports, reportAttributes?.reports); setOptions({ reports: optionLists.reports, personalDetails: optionLists.personalDetails, }); - }, [personalDetails, reports, reportAttributes?.reports, policyTags]); + }, [personalDetails, reports, reportAttributes?.reports, policyTags, translate]); /** * This effect is responsible for generating the options list when their data is not yet initialized @@ -120,7 +122,8 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { for (const reportKey of changedReportKeys) { const report = changedReportsEntries[reportKey]; const reportID = reportKey.replace(ONYXKEYS.COLLECTION.REPORT, ''); - const {reportOption} = processReport(report, personalDetails, reportAttributes?.reports); + const reportPolicyTags = report?.policyID ? policyTags?.[report?.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; + const {reportOption} = processReport(report, personalDetails, translate, reportPolicyTags, reportAttributes?.reports); if (reportOption) { updatedReportsMap.set(reportID, reportOption); @@ -134,7 +137,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { reports: Array.from(updatedReportsMap.values()), }; }); - }, [changedReportsEntries, personalDetails, reportAttributes?.reports]); + }, [changedReportsEntries, personalDetails, reportAttributes?.reports, translate, policyTags]); useEffect(() => { if (!changedReportActions || !areOptionsInitialized.current) { @@ -154,7 +157,9 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { } const reportID = key.replace(ONYXKEYS.COLLECTION.REPORT_ACTIONS, ''); - const {reportOption} = processReport(updatedReportsMap.get(reportID)?.item, personalDetails, reportAttributes?.reports); + const report = updatedReportsMap.get(reportID)?.item; + const reportPolicyTags = report?.policyID ? policyTags?.[report?.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; + const {reportOption} = processReport(updatedReportsMap.get(reportID)?.item, personalDetails, translate, reportPolicyTags, reportAttributes?.reports); if (reportOption) { updatedReportsMap.set(reportID, reportOption); @@ -166,7 +171,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { reports: Array.from(updatedReportsMap.values()), }; }); - }, [changedReportActions, personalDetails, reportAttributes?.reports]); + }, [changedReportActions, personalDetails, policyTags, reportAttributes?.reports, translate]); /** * This effect is used to update the options list when personal details change. @@ -184,7 +189,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { // Handle initial personal details load. This initialization is required here specifically to prevent // UI freezing that occurs when resetting the app from the troubleshooting page. if (!prevPersonalDetails) { - const {personalDetails: newPersonalDetailsOptions, reports: newReports} = createOptionList(personalDetails, policyTags, reports, reportAttributes?.reports); + const {personalDetails: newPersonalDetailsOptions, reports: newReports} = createOptionList(personalDetails, policyTags, translate, reports, reportAttributes?.reports); setOptions((prevOptions) => ({ ...prevOptions, personalDetails: newPersonalDetailsOptions, @@ -218,7 +223,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { } const reportPolicyTags = report.policyID ? policyTags?.[report.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; - const newReportOption = createOptionFromReport(report, personalDetails, reportPolicyTags, reportAttributes?.reports, {showPersonalDetails: true}); + const newReportOption = createOptionFromReport(report, personalDetails, reportPolicyTags, translate, reportAttributes?.reports, {showPersonalDetails: true}); const replaceIndex = options.reports.findIndex((option) => option.reportID === report.reportID); newReportOptions.push({ newReportOption, @@ -228,7 +233,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { } // since personal details are not a collection, we need to recreate the whole list from scratch - const newPersonalDetailsOptions = createOptionList(personalDetails, policyTags, reports, reportAttributes?.reports).personalDetails; + const newPersonalDetailsOptions = createOptionList(personalDetails, policyTags, translate, reports, reportAttributes?.reports).personalDetails; setOptions((prevOptions) => { const newOptions = {...prevOptions}; diff --git a/src/components/Search/FilterDropdowns/UserSelectPopup.tsx b/src/components/Search/FilterDropdowns/UserSelectPopup.tsx index 27d69a5e1bf98..a15f3eb58943e 100644 --- a/src/components/Search/FilterDropdowns/UserSelectPopup.tsx +++ b/src/components/Search/FilterDropdowns/UserSelectPopup.tsx @@ -66,6 +66,7 @@ function UserSelectPopup({value, closeOverlay, onChange, isSearchable}: UserSele const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false, canBeMissing: true}); const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, {canBeMissing: true}); const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); + const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); const initialSelectedOptions = useMemo(() => { return value.reduce((acc, id) => { const participant = personalDetails?.[id]; @@ -98,22 +99,23 @@ function UserSelectPopup({value, closeOverlay, onChange, isSearchable}: UserSele }, draftComments, nvpDismissedProductTraining, - undefined, + policyTags, + translate, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, includeCurrentUser: true, }, countryCode, ); - }, [options.reports, options.personalDetails, draftComments, nvpDismissedProductTraining, countryCode]); + }, [options.reports, options.personalDetails, draftComments, nvpDismissedProductTraining, policyTags, translate, countryCode]); const filteredOptions = useMemo(() => { - return filterAndOrderOptions(optionsList, cleanSearchTerm, countryCode, undefined, { + return filterAndOrderOptions(optionsList, cleanSearchTerm, translate, countryCode, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, canInviteUser: false, }); - }, [optionsList, cleanSearchTerm, countryCode]); + }, [optionsList, cleanSearchTerm, translate, countryCode]); const listData = useMemo(() => { const personalDetailList = filteredOptions.personalDetails.map((participant) => ({ diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx index 1db28175c8db3..f457f3750b779 100644 --- a/src/components/Search/SearchAutocompleteList.tsx +++ b/src/components/Search/SearchAutocompleteList.tsx @@ -199,6 +199,7 @@ function SearchAutocompleteList({ return defaultListOptions; } return getSearchOptions({ + translate, options, draftComments, nvpDismissedProductTraining, @@ -215,7 +216,7 @@ function SearchAutocompleteList({ policyTags, shouldUnreadBeBold: true, }); - }, [areOptionsInitialized, options, draftComments, nvpDismissedProductTraining, betas, autocompleteQueryValue, countryCode, policyTags]); + }, [areOptionsInitialized, translate, options, draftComments, nvpDismissedProductTraining, betas, autocompleteQueryValue, countryCode, policyTags]); const [isInitialRender, setIsInitialRender] = useState(true); const parsedQuery = useMemo(() => parseForAutocomplete(autocompleteQueryValue), [autocompleteQueryValue]); @@ -410,6 +411,7 @@ function SearchAutocompleteList({ case CONST.SEARCH.SYNTAX_FILTER_KEYS.ATTENDEE: case CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTER: { const participants = getSearchOptions({ + translate, options, draftComments, nvpDismissedProductTraining, @@ -435,6 +437,7 @@ function SearchAutocompleteList({ } case CONST.SEARCH.SYNTAX_FILTER_KEYS.IN: { const filteredReports = getSearchOptions({ + translate, options, draftComments, nvpDismissedProductTraining, @@ -607,6 +610,7 @@ function SearchAutocompleteList({ currencyAutocompleteList, recentCurrencyAutocompleteList, taxAutocompleteList, + translate, options, draftComments, nvpDismissedProductTraining, diff --git a/src/components/Search/SearchFiltersChatsSelector.tsx b/src/components/Search/SearchFiltersChatsSelector.tsx index 66b1deb324341..d87d27a4104ac 100644 --- a/src/components/Search/SearchFiltersChatsSelector.tsx +++ b/src/components/Search/SearchFiltersChatsSelector.tsx @@ -63,27 +63,27 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen const reportObj = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`]; const reportPolicyTags = reportObj?.policyID ? policyTags?.[reportObj.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; const report = getSelectedOptionData( - createOptionFromReport({...reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`], reportID: id}, personalDetails, reportPolicyTags, reportAttributesDerived), + createOptionFromReport({...reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`], reportID: id}, personalDetails, reportPolicyTags, translate, reportAttributesDerived), ); const isReportArchived = archivedReportsIdSet.has(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`); - const alternateText = getAlternateText(report, {}, reportPolicyTags, isReportArchived, {}); + const alternateText = getAlternateText(report, {}, reportPolicyTags, translate, isReportArchived, {}); return {...report, alternateText}; }); - }, [archivedReportsIdSet, personalDetails, reportAttributesDerived, reports, selectedReportIDs, policyTags]); + }, [selectedReportIDs, reports, policyTags, personalDetails, reportAttributesDerived, archivedReportsIdSet, translate]); const defaultOptions = useMemo(() => { if (!areOptionsInitialized || !isScreenTransitionEnd) { return defaultListOptions; } - return getSearchOptions({options, draftComments, nvpDismissedProductTraining, betas: undefined, policyTags, isUsedInChatFinder: false, countryCode}); - }, [areOptionsInitialized, isScreenTransitionEnd, options, draftComments, nvpDismissedProductTraining, policyTags, countryCode]); + return getSearchOptions({options, draftComments, nvpDismissedProductTraining, betas: undefined, policyTags, isUsedInChatFinder: false, countryCode, translate}); + }, [areOptionsInitialized, isScreenTransitionEnd, options, draftComments, nvpDismissedProductTraining, policyTags, countryCode, translate]); const chatOptions = useMemo(() => { - return filterAndOrderOptions(defaultOptions, cleanSearchTerm, countryCode, undefined, { + return filterAndOrderOptions(defaultOptions, cleanSearchTerm, translate, countryCode, { selectedOptions, excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, }); - }, [defaultOptions, cleanSearchTerm, selectedOptions, countryCode]); + }, [defaultOptions, cleanSearchTerm, translate, countryCode, selectedOptions]); const {sections, headerMessage} = useMemo(() => { const newSections: Section[] = []; @@ -97,6 +97,7 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen chatOptions.recentReports, chatOptions.personalDetails, undefined, + translate, personalDetails, false, undefined, diff --git a/src/components/Search/SearchFiltersParticipantsSelector.tsx b/src/components/Search/SearchFiltersParticipantsSelector.tsx index 6217384635b23..2060d87dd0542 100644 --- a/src/components/Search/SearchFiltersParticipantsSelector.tsx +++ b/src/components/Search/SearchFiltersParticipantsSelector.tsx @@ -54,6 +54,7 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: const cleanSearchTerm = useMemo(() => searchTerm.trim().toLowerCase(), [searchTerm]); const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, {canBeMissing: true}); const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); + const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); const defaultOptions = useMemo(() => { if (!areOptionsInitialized) { return defaultListOptions; @@ -66,21 +67,22 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: }, draftComments, nvpDismissedProductTraining, - undefined, + policyTags, + translate, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, includeCurrentUser: true, }, countryCode, ); - }, [areOptionsInitialized, draftComments, options.personalDetails, options.reports, nvpDismissedProductTraining, countryCode]); + }, [areOptionsInitialized, options.reports, options.personalDetails, draftComments, nvpDismissedProductTraining, policyTags, translate, countryCode]); const unselectedOptions = useMemo(() => { return filterSelectedOptions(defaultOptions, new Set(selectedOptions.map((option) => option.accountID))); }, [defaultOptions, selectedOptions]); const chatOptions = useMemo(() => { - const filteredOptions = filterAndOrderOptions(unselectedOptions, cleanSearchTerm, countryCode, undefined, { + const filteredOptions = filterAndOrderOptions(unselectedOptions, cleanSearchTerm, translate, countryCode, { selectedOptions, excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, @@ -95,7 +97,7 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: } return filteredOptions; - }, [unselectedOptions, cleanSearchTerm, selectedOptions, countryCode]); + }, [unselectedOptions, cleanSearchTerm, translate, countryCode, selectedOptions]); const {sections, headerMessage} = useMemo(() => { const newSections: Section[] = []; @@ -109,6 +111,7 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: chatOptions.recentReports, chatOptions.personalDetails, undefined, + translate, personalDetails, true, undefined, diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index 4d509f22bfc02..005761b95342e 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -156,7 +156,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla return undefined; } const reportPolicyTags = report.policyID ? policyTags?.[report.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; - const option = createOptionFromReport(report, personalDetails, reportPolicyTags, undefined, {showPersonalDetails: true}); + const option = createOptionFromReport(report, personalDetails, reportPolicyTags, translate, undefined, {showPersonalDetails: true}); reportForContextualSearch = option; } diff --git a/src/hooks/useContactImport.ts b/src/hooks/useContactImport.ts index 67f1d5ed9456b..d63c346236069 100644 --- a/src/hooks/useContactImport.ts +++ b/src/hooks/useContactImport.ts @@ -30,16 +30,16 @@ type UseContactImportResult = { function useContactImport(): UseContactImportResult { const [contactPermissionState, setContactPermissionState] = useState(RESULTS.UNAVAILABLE); const [contacts, setContacts] = useState>>([]); - const {localeCompare} = useLocalize(); + const {localeCompare, translate} = useLocalize(); const [countryCode = CONST.DEFAULT_COUNTRY_CODE] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const importAndSaveContacts = useCallback(() => { contactImport().then(({contactList, permissionStatus}: ContactImportResult) => { setContactPermissionState(permissionStatus); - const usersFromContact = getContacts(contactList, localeCompare, countryCode); + const usersFromContact = getContacts(contactList, localeCompare, countryCode, translate); setContacts(usersFromContact); }); - }, [localeCompare, countryCode]); + }, [localeCompare, translate, countryCode]); useContactPermissions({ importAndSaveContacts, diff --git a/src/hooks/useFilteredOptions.ts b/src/hooks/useFilteredOptions.ts index 4643602059b8f..07339c52a2154 100644 --- a/src/hooks/useFilteredOptions.ts +++ b/src/hooks/useFilteredOptions.ts @@ -5,6 +5,7 @@ import {createFilteredOptionList} from '@libs/OptionsListUtils'; import type {OptionList} from '@libs/OptionsListUtils/types'; import ONYXKEYS from '@src/ONYXKEYS'; import type Beta from '@src/types/onyx/Beta'; +import useLocalize from './useLocalize'; import useOnyx from './useOnyx'; type UseFilteredOptionsConfig = { @@ -77,12 +78,13 @@ function useFilteredOptions(config: UseFilteredOptionsConfig = {}): UseFilteredO selector: reportsSelector, }); const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); + const {translate} = useLocalize(); const totalReports = allReports ? Object.keys(allReports).length : 0; const options: OptionList | null = enabled && allReports && allPersonalDetails - ? createFilteredOptionList(allPersonalDetails, allReports, policyTags, reportAttributesDerived, { + ? createFilteredOptionList(allPersonalDetails, allReports, policyTags, translate, reportAttributesDerived, { maxRecentReports: reportsLimit, includeP2P, searchTerm, diff --git a/src/hooks/useSearchSelector.base.ts b/src/hooks/useSearchSelector.base.ts index 733c8963d42ed..03fccd49f6667 100644 --- a/src/hooks/useSearchSelector.base.ts +++ b/src/hooks/useSearchSelector.base.ts @@ -9,6 +9,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {PersonalDetails} from '@src/types/onyx'; import useDebounce from './useDebounce'; import useDebouncedState from './useDebouncedState'; +import useLocalize from './useLocalize'; import useOnyx from './useOnyx'; type SearchSelectorContext = (typeof CONST.SEARCH_SELECTOR)[keyof Pick< @@ -164,6 +165,8 @@ function useSearchSelectorBase({ const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, {canBeMissing: true}); const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); + const {translate} = useLocalize(); + const onListEndReached = useDebounce( useCallback(() => { setMaxResults((previous) => previous + maxResultsPerPage); @@ -183,6 +186,7 @@ function useSearchSelectorBase({ switch (searchContext) { case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_SEARCH: return getSearchOptions({ + translate, options: optionsWithContacts, draftComments, nvpDismissedProductTraining, @@ -196,7 +200,7 @@ function useSearchSelectorBase({ policyTags, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_MEMBER_INVITE: - return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, undefined, { + return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, policyTags, translate, { betas: betas ?? [], includeP2P: true, includeSelectedOptions: false, @@ -208,7 +212,7 @@ function useSearchSelectorBase({ includeUserToInvite, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_GENERAL: - return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, undefined, { + return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, policyTags, translate, { ...getValidOptionsConfig, betas: betas ?? [], searchString: computedSearchTerm, @@ -222,7 +226,8 @@ function useSearchSelectorBase({ optionsWithContacts, draftComments, nvpDismissedProductTraining, - undefined, + policyTags, + translate, { betas, includeMultipleParticipantReports: true, @@ -239,7 +244,7 @@ function useSearchSelectorBase({ countryCode, ); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_SHARE_DESTINATION: - return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, undefined, { + return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, policyTags, translate, { betas, selectedOptions, includeMultipleParticipantReports: true, @@ -257,7 +262,7 @@ function useSearchSelectorBase({ includeUserToInvite, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_ATTENDEES: - return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, undefined, { + return getValidOptions(optionsWithContacts, draftComments, nvpDismissedProductTraining, policyTags, translate, { ...getValidOptionsConfig, betas: betas ?? [], includeP2P: true, @@ -277,6 +282,7 @@ function useSearchSelectorBase({ }, [ areOptionsInitialized, searchContext, + translate, optionsWithContacts, draftComments, nvpDismissedProductTraining, diff --git a/src/libs/ContactUtils.ts b/src/libs/ContactUtils.ts index f5945491a4ce4..9845892dc2d94 100644 --- a/src/libs/ContactUtils.ts +++ b/src/libs/ContactUtils.ts @@ -1,4 +1,4 @@ -import type {LocaleContextProps} from '@components/LocaleContextProvider'; +import type {LocaleContextProps, LocalizedTranslate} from '@components/LocaleContextProvider'; import CONST from '@src/CONST'; import type {PersonalDetails} from '@src/types/onyx'; import type {DeviceContact, StringHolder} from './ContactImport/types'; @@ -28,7 +28,12 @@ function sortEmailObjects(emails: StringHolder[], localeCompare: LocaleContextPr }); } -const getContacts = (deviceContacts: DeviceContact[] | [], localeCompare: LocaleContextProps['localeCompare'], countryCode: number): Array> => { +const getContacts = ( + deviceContacts: DeviceContact[] | [], + localeCompare: LocaleContextProps['localeCompare'], + countryCode: number, + translate: LocalizedTranslate, +): Array> => { return deviceContacts .map((contact) => { const email = sortEmailObjects(contact?.emailAddresses ?? [], localeCompare)?.at(0) ?? ''; @@ -39,6 +44,7 @@ const getContacts = (deviceContacts: DeviceContact[] | [], localeCompare: Locale const lastName = contact?.lastName ?? ''; return getUserToInviteContactOption({ + translate, selectedOptions: [], optionsToExclude: [], searchValue: email || phoneNumber || firstName || '', diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index 745af115447d0..c20366b07035d 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -7,7 +7,7 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {SetNonNullable} from 'type-fest'; import {FallbackAvatar} from '@components/Icon/Expensicons'; -import type {LocaleContextProps} from '@components/LocaleContextProvider'; +import type {LocaleContextProps, LocalizedTranslate} from '@components/LocaleContextProvider'; import {getEnabledCategoriesCount} from '@libs/CategoryUtils'; import filterArrayByMatch from '@libs/filterArrayByMatch'; import {isReportMessageAttachment} from '@libs/isReportMessageAttachment'; @@ -465,6 +465,7 @@ function getAlternateText( option: OptionData, {showChatPreviewLine = false, forcePolicyNamePreview = false}: PreviewConfig, policyTags: OnyxEntry, + translate: LocalizedTranslate, isReportArchived: boolean | undefined, lastActorDetails: Partial | null = {}, ) { @@ -474,7 +475,7 @@ function getAlternateText( const isGroupChat = reportUtilsIsGroupChat(report); const isExpenseThread = isMoneyRequest(report); const formattedLastMessageText = - formatReportLastMessageText(Parser.htmlToText(option.lastMessageText ?? '')) || getLastMessageTextForReport({report, lastActorDetails, isReportArchived, policyTags}); + formatReportLastMessageText(Parser.htmlToText(option.lastMessageText ?? '')) || getLastMessageTextForReport({translate, report, lastActorDetails, isReportArchived, policyTags}); const reportPrefix = getReportSubtitlePrefix(report); const formattedLastMessageTextWithPrefix = reportPrefix + formattedLastMessageText; @@ -602,6 +603,7 @@ function getLastMessageTextForReport({ policy, isReportArchived = false, policyTags, + translate, }: { report: OnyxEntry; lastActorDetails: Partial | null; @@ -610,6 +612,7 @@ function getLastMessageTextForReport({ policy?: OnyxEntry; isReportArchived?: boolean; policyTags: OnyxEntry; + translate: LocalizedTranslate; }): string { const reportID = report?.reportID; const lastReportAction = reportID ? lastVisibleReportActions[reportID] : undefined; @@ -690,6 +693,7 @@ function getLastMessageTextForReport({ lastMessageTextFromReport = `[${translateLocal('common.attachment')}]`; } else if (isModifiedExpenseAction(lastReportAction)) { const properSchemaForModifiedExpenseMessage = getForReportActionTemp({ + translate, reportAction: lastReportAction, movedFromReport, movedToReport, @@ -832,6 +836,7 @@ function createOption( accountIDs: number[], personalDetails: OnyxInputOrEntry, report: OnyxInputOrEntry, + translate: LocalizedTranslate, policyTags: OnyxEntry = CONST.POLICY.DEFAULT_TAG_LIST, config?: PreviewConfig, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], @@ -909,11 +914,11 @@ function createOption( // If displaying chat preview line is needed, let's overwrite the default alternate text const lastActorDetails = personalDetails?.[report?.lastActorAccountID ?? String(CONST.DEFAULT_NUMBER_ID)] ?? {}; - result.lastMessageText = getLastMessageTextForReport({report, lastActorDetails, isReportArchived: !!result.private_isArchived, policyTags}); + result.lastMessageText = getLastMessageTextForReport({report, lastActorDetails, isReportArchived: !!result.private_isArchived, policyTags, translate}); result.alternateText = showPersonalDetails && personalDetail?.login ? personalDetail.login - : getAlternateText(result, {showChatPreviewLine, forcePolicyNamePreview}, policyTags, !!result.private_isArchived, lastActorDetails); + : getAlternateText(result, {showChatPreviewLine, forcePolicyNamePreview}, policyTags, translate, !!result.private_isArchived, lastActorDetails); const personalDetailsForCompute: PersonalDetailsList | undefined = personalDetails ?? undefined; const computedReportName = computeReportName(report, undefined, undefined, undefined, allReportNameValuePairs, personalDetailsForCompute, undefined); @@ -951,6 +956,7 @@ function createOption( function getReportOption( participant: Participant, policyTags: OnyxEntry, + translate: LocalizedTranslate, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], reportDrafts?: OnyxCollection, ): OptionData { @@ -961,6 +967,7 @@ function getReportOption( visibleParticipantAccountIDs, allPersonalDetails ?? {}, !isEmptyObject(report) ? report : undefined, + translate, policyTags, { showChatPreviewLine: false, @@ -1008,6 +1015,7 @@ function getReportDisplayOption( report: OnyxEntry, unknownUserDetails: OnyxEntry, policyTags: OnyxEntry, + translate: LocalizedTranslate, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], ): OptionData { const visibleParticipantAccountIDs = getParticipantsAccountIDsForDisplay(report, true); @@ -1016,6 +1024,7 @@ function getReportDisplayOption( visibleParticipantAccountIDs, allPersonalDetails ?? {}, !isEmptyObject(report) ? report : undefined, + translate, policyTags, { showChatPreviewLine: false, @@ -1052,7 +1061,8 @@ function getReportDisplayOption( */ function getPolicyExpenseReportOption( participant: Participant | SearchOptionData, - policyTags: OnyxEntry, + policyTags: OnyxCollection, + translate: LocalizedTranslate, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], ): SearchOptionData { const expenseReport = reportUtilsIsPolicyExpenseChat(participant) ? getReportOrDraftReport(participant.reportID) : null; @@ -1060,12 +1070,13 @@ function getPolicyExpenseReportOption( const visibleParticipantAccountIDs = Object.entries(expenseReport?.participants ?? {}) .filter(([, reportParticipant]) => reportParticipant && !isHiddenForCurrentUser(reportParticipant.notificationPreference)) .map(([accountID]) => Number(accountID)); - + const reportPolicyTags = expenseReport?.policyID ? policyTags?.[expenseReport.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; const option = createOption( visibleParticipantAccountIDs, allPersonalDetails ?? {}, !isEmptyObject(expenseReport) ? expenseReport : null, - policyTags, + translate, + reportPolicyTags, { showChatPreviewLine: false, forcePolicyNamePreview: false, @@ -1179,6 +1190,8 @@ function isReportSelected(reportOption: SearchOptionData, selectedOptions: Array function processReport( report: OnyxEntry | null, personalDetails: OnyxEntry, + translate: LocalizedTranslate, + policyTags: OnyxEntry = CONST.POLICY.DEFAULT_TAG_LIST, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], ): { reportMapEntry?: [number, Report]; // The entry to add to reportMapForAccountIDs if applicable @@ -1203,7 +1216,7 @@ function processReport( reportMapEntry, reportOption: { item: report, - ...createOption(accountIDs, personalDetails, report, undefined, reportAttributesDerived), + ...createOption(accountIDs, personalDetails, report, translate, policyTags, reportAttributesDerived), }, }; } @@ -1211,6 +1224,7 @@ function processReport( function createOptionList( personalDetails: OnyxEntry, policyTags: OnyxCollection, + translate: LocalizedTranslate, reports?: OnyxCollection, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], ) { @@ -1221,7 +1235,8 @@ function createOptionList( if (reports) { for (const report of Object.values(reports)) { - const {reportMapEntry, reportOption} = processReport(report, personalDetails, reportAttributesDerived); + const reportPolicyTags = report?.policyID ? policyTags?.[report?.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; + const {reportMapEntry, reportOption} = processReport(report, personalDetails, translate, reportPolicyTags, reportAttributesDerived); if (reportMapEntry) { const [accountID, reportValue] = reportMapEntry; @@ -1236,13 +1251,14 @@ function createOptionList( const allPersonalDetailsOptions = Object.values(personalDetails ?? {}).map((personalDetail) => { const report = reportMapForAccountIDs[personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID]; - const policyTagList = report.policyID ? policyTags?.[report.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; + const policyTagList = report?.policyID ? policyTags?.[report?.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; return { item: personalDetail, ...createOption( [personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID], personalDetails, report, + translate, policyTagList, { showPersonalDetails: true, @@ -1281,6 +1297,7 @@ function createFilteredOptionList( personalDetails: OnyxEntry, reports: OnyxCollection, policyTags: OnyxCollection, + translate: LocalizedTranslate, reportAttributesDerived: ReportAttributesDerivedValue['reports'] | undefined, options: { maxRecentReports?: number; @@ -1337,7 +1354,8 @@ function createFilteredOptionList( // Step 5: Process the limited set of reports (performance optimization) const reportOptions: Array> = []; for (const report of limitedReports) { - const {reportMapEntry, reportOption} = processReport(report, personalDetails, reportAttributesDerived); + const reportPolicyTags = report?.policyID ? policyTags?.[report?.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; + const {reportMapEntry, reportOption} = processReport(report, personalDetails, translate, reportPolicyTags, reportAttributesDerived); if (reportMapEntry) { const [accountID, reportValue] = reportMapEntry; @@ -1365,11 +1383,11 @@ function createFilteredOptionList( ? Object.values(personalDetails ?? {}).map((personalDetail) => { const accountID = personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID; const report = reportMapForAccountIDs[accountID]; - const reportPolicyTags = report.policyID ? policyTags?.[report.policyID] : undefined; + const reportPolicyTags = report?.policyID ? policyTags?.[report?.policyID] : undefined; return { item: personalDetail, - ...createOption([accountID], personalDetails, reportMapForAccountIDs[accountID], reportPolicyTags, {showPersonalDetails: true}, reportAttributesDerived), + ...createOption([accountID], personalDetails, reportMapForAccountIDs[accountID], translate, reportPolicyTags, {showPersonalDetails: true}, reportAttributesDerived), }; }) : []; @@ -1384,6 +1402,7 @@ function createOptionFromReport( report: Report, personalDetails: OnyxEntry, policyTags: OnyxEntry, + translate: LocalizedTranslate, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], config?: PreviewConfig, ) { @@ -1391,7 +1410,7 @@ function createOptionFromReport( return { item: report, - ...createOption(accountIDs, personalDetails, report, policyTags, config, reportAttributesDerived), + ...createOption(accountIDs, personalDetails, report, translate, policyTags, config, reportAttributesDerived), }; } @@ -1670,6 +1689,7 @@ function canCreateOptimisticPersonalDetailOption({ */ function getUserToInviteOption({ searchValue, + translate, loginsToExclude = {}, selectedOptions = [], showChatPreviewLine = false, @@ -1701,7 +1721,7 @@ function getUserToInviteOption({ }, }; - const userToInvite = createOption([optimisticAccountID], personalDetailsExtended, null, undefined, { + const userToInvite = createOption([optimisticAccountID], personalDetailsExtended, null, translate, undefined, { showChatPreviewLine, }); userToInvite.isOptimisticAccount = true; @@ -1966,7 +1986,12 @@ function isValidReport(option: SearchOption, config: IsValidReportsConfi * @param config - Configuration object specifying display preferences and filtering criteria * @returns Array of enriched and filtered report options ready for UI display */ -function prepareReportOptionsForDisplay(options: Array>, config: GetValidReportsConfig, policyTags: OnyxCollection): Array> { +function prepareReportOptionsForDisplay( + options: Array>, + config: GetValidReportsConfig, + policyTags: OnyxCollection, + translate: LocalizedTranslate, +): Array> { const { showChatPreviewLine = false, forcePolicyNamePreview = false, @@ -1996,7 +2021,7 @@ function prepareReportOptionsForDisplay(options: Array>, co * By default, generated options does not have the chat preview line enabled. * If showChatPreviewLine or forcePolicyNamePreview are true, let's generate and overwrite the alternate text. */ - const alternateText = getAlternateText(option, {showChatPreviewLine, forcePolicyNamePreview}, reportPolicyTags, !!option.private_isArchived); + const alternateText = getAlternateText(option, {showChatPreviewLine, forcePolicyNamePreview}, reportPolicyTags, translate, !!option.private_isArchived); const isSelected = isReportSelected(option, selectedOptions); let isOptionUnread = option.isUnread; @@ -2112,6 +2137,7 @@ function getValidOptions( draftComments: OnyxCollection | undefined, nvpDismissedProductTraining: OnyxEntry, policyTags: OnyxCollection, + translate: LocalizedTranslate, { excludeLogins = {}, includeSelectedOptions = false, @@ -2210,6 +2236,7 @@ function getValidOptions( shouldShowGBR, }, policyTags, + translate, ).at(0); } @@ -2227,6 +2254,7 @@ function getValidOptions( shouldShowGBR, }, policyTags, + translate, ); workspaceChats = prepareReportOptionsForDisplay( @@ -2240,6 +2268,7 @@ function getValidOptions( shouldShowGBR, }, policyTags, + translate, ); } else if (recentAttendees && recentAttendees?.length > 0) { recentAttendees.filter((attendee) => { @@ -2320,6 +2349,7 @@ function getValidOptions( userToInvite = filterUserToInvite( {currentUserOption: currentUserRef.current, recentReports: recentReportOptions, personalDetails: personalDetailsOptions}, searchString ?? '', + translate, countryCode, { excludeLogins: loginsToExclude, @@ -2338,6 +2368,7 @@ function getValidOptions( } type SearchOptionsConfig = { + translate: LocalizedTranslate; options: OptionList; nvpDismissedProductTraining: OnyxEntry; draftComments: OnyxCollection; @@ -2364,6 +2395,7 @@ function getSearchOptions({ nvpDismissedProductTraining, betas, policyTags, + translate, isUsedInChatFinder = true, includeReadOnly = true, searchQuery = '', @@ -2383,6 +2415,7 @@ function getSearchOptions({ draftComments, nvpDismissedProductTraining, policyTags, + translate, { betas, includeRecentReports, @@ -2497,6 +2530,7 @@ function formatMemberForList(member: SearchOptionData): MemberForList { function getMemberInviteOptions( personalDetails: Array>, nvpDismissedProductTraining: OnyxEntry, + translate: LocalizedTranslate, betas: Beta[] = [], excludeLogins: Record = {}, includeSelectedOptions = false, @@ -2507,6 +2541,7 @@ function getMemberInviteOptions( undefined, nvpDismissedProductTraining, {}, + translate, { betas, includeP2P: true, @@ -2580,7 +2615,8 @@ function formatSectionsFromSearchTerm( selectedOptions: SearchOptionData[], filteredRecentReports: SearchOptionData[], filteredPersonalDetails: SearchOptionData[], - policyTags: OnyxEntry, + policyTags: OnyxCollection, + translate: LocalizedTranslate, personalDetails: OnyxEntry = {}, shouldGetOptionDetails = false, filteredWorkspaceChats: SearchOptionData[] = [], @@ -2597,7 +2633,7 @@ function formatSectionsFromSearchTerm( ? selectedOptions.map((participant) => { const isReportPolicyExpenseChat = participant.isPolicyExpenseChat ?? false; return isReportPolicyExpenseChat - ? getPolicyExpenseReportOption(participant, policyTags, reportAttributesDerived) + ? getPolicyExpenseReportOption(participant, policyTags, translate, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }) : selectedOptions, @@ -2624,7 +2660,9 @@ function formatSectionsFromSearchTerm( data: shouldGetOptionDetails ? selectedParticipantsWithoutDetails.map((participant) => { const isReportPolicyExpenseChat = participant.isPolicyExpenseChat ?? false; - return isReportPolicyExpenseChat ? getPolicyExpenseReportOption(participant, policyTags, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); + return isReportPolicyExpenseChat + ? getPolicyExpenseReportOption(participant, policyTags, translate, reportAttributesDerived) + : getParticipantsOption(participant, personalDetails); }) : selectedParticipantsWithoutDetails, shouldShow: selectedParticipantsWithoutDetails.length > 0, @@ -2748,6 +2786,7 @@ function filterCurrentUserOption(currentUserOption: SearchOptionData | null | un function filterUserToInvite( options: Omit, searchValue: string, + translate: LocalizedTranslate, countryCode: number = CONST.DEFAULT_COUNTRY_CODE, config?: FilterUserToInviteConfig, ): SearchOptionData | null { @@ -2775,6 +2814,7 @@ function filterUserToInvite( searchValue, loginsToExclude, countryCode, + translate, ...config, }); } @@ -2809,7 +2849,7 @@ function filterSelfDMChat(report: SearchOptionData, searchTerms: string[]): Sear return isMatch ? report : undefined; } -function filterOptions(options: Options, searchInputValue: string, countryCode: number, policyTags: OnyxEntry, config?: FilterUserToInviteConfig): Options { +function filterOptions(options: Options, searchInputValue: string, translate: LocalizedTranslate, countryCode: number, config?: FilterUserToInviteConfig): Options { const trimmedSearchInput = searchInputValue.trim(); // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing @@ -2827,6 +2867,7 @@ function filterOptions(options: Options, searchInputValue: string, countryCode: currentUserOption, }, searchValue, + translate, countryCode, config, ); @@ -2882,10 +2923,10 @@ function combineOrderingOfReportsAndPersonalDetails( * Filters and orders the options based on the search input value. * Note that personal details that are part of the recent reports will always be shown as part of the recent reports (ie. DMs). */ -function filterAndOrderOptions(options: Options, searchInputValue: string, countryCode: number, policyTags: OnyxEntry, config: FilterAndOrderConfig = {}): Options { +function filterAndOrderOptions(options: Options, searchInputValue: string, translate: LocalizedTranslate, countryCode: number, config: FilterAndOrderConfig = {}): Options { let filterResult = options; if (searchInputValue.trim().length > 0) { - filterResult = filterOptions(options, searchInputValue, countryCode, policyTags, config); + filterResult = filterOptions(options, searchInputValue, translate, countryCode, config); } const orderedOptions = combineOrderingOfReportsAndPersonalDetails(filterResult, searchInputValue, config); diff --git a/src/libs/OptionsListUtils/types.ts b/src/libs/OptionsListUtils/types.ts index c13b856af8bfb..844f8fccce3b4 100644 --- a/src/libs/OptionsListUtils/types.ts +++ b/src/libs/OptionsListUtils/types.ts @@ -1,4 +1,5 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; +import {LocalizedTranslate} from '@components/LocaleContextProvider'; import type {OptionData} from '@libs/ReportUtils'; import type {AvatarSource} from '@libs/UserAvatarUtils'; import type {IOUAction} from '@src/CONST'; @@ -194,6 +195,7 @@ type GetOptionsConfig = { type GetUserToInviteConfig = { searchValue: string | undefined; + translate: LocalizedTranslate; loginsToExclude?: Record; reportActions?: ReportActions; firstName?: string; diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts index 9305820216465..1494c076aa7fe 100644 --- a/src/libs/SidebarUtils.ts +++ b/src/libs/SidebarUtils.ts @@ -1,7 +1,7 @@ import {Str} from 'expensify-common'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; -import type {LocaleContextProps} from '@components/LocaleContextProvider'; +import type {LocaleContextProps, LocalizedTranslate} from '@components/LocaleContextProvider'; import type {PartialPolicyForSidebar, ReportsToDisplayInLHN} from '@hooks/useSidebarOrderedReports'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -652,6 +652,7 @@ function getOptionData({ movedFromReport, movedToReport, policyTags, + translate, }: { report: OnyxEntry; oneTransactionThreadReport: OnyxEntry; @@ -663,6 +664,7 @@ function getOptionData({ invoiceReceiverPolicy?: OnyxEntry; reportAttributes: OnyxEntry; policyTags: OnyxEntry; + translate: LocalizedTranslate; card: Card | undefined; lastAction: ReportAction | undefined; localeCompare: LocaleContextProps['localeCompare']; @@ -793,7 +795,7 @@ function getOptionData({ const lastActorDisplayName = getLastActorDisplayName(lastActorDetails); let lastMessageTextFromReport = lastMessageTextFromReportProp; if (!lastMessageTextFromReport) { - lastMessageTextFromReport = getLastMessageTextForReport({report, lastActorDetails, movedFromReport, movedToReport, policy, isReportArchived, policyTags}); + lastMessageTextFromReport = getLastMessageTextForReport({report, lastActorDetails, movedFromReport, movedToReport, policy, isReportArchived, policyTags, translate}); } // We need to remove sms domain in case the last message text has a phone number mention with sms domain. diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index 0bdc52764bfa8..bffdb0ca222e6 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -55,6 +55,7 @@ type SelectedOption = ListItem & }; function useOptions() { + const {translate} = useLocalize(); const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState(''); const [selectedOptions, setSelectedOptions] = useState([]); const [betas] = useOnyx(ONYXKEYS.BETAS, {canBeMissing: true}); @@ -96,6 +97,7 @@ function useOptions() { draftComments, nvpDismissedProductTraining, policyTags, + translate, { betas: betas ?? [], includeSelfDM: true, @@ -107,7 +109,7 @@ function useOptions() { const areOptionsInitialized = !isLoading; - const options = filterAndOrderOptions(unselectedOptions, debouncedSearchTerm, countryCode, { + const options = filterAndOrderOptions(unselectedOptions, debouncedSearchTerm, translate, countryCode, { selectedOptions, maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, }); @@ -152,6 +154,7 @@ function useOptions() { personalDetails.find((option) => option.accountID === participant.accountID) ?? getUserToInviteOption({ searchValue: participant?.login, + translate, }); if (participantOption) { result.push({ @@ -258,6 +261,7 @@ function NewChatPage({ref}: NewChatPageProps) { recentReports, personalDetails, undefined, + translate, undefined, undefined, undefined, diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx index 4aa9b67aac22d..0d47188f504b8 100644 --- a/src/pages/RoomInvitePage.tsx +++ b/src/pages/RoomInvitePage.tsx @@ -90,7 +90,7 @@ function RoomInvitePage({ return {recentReports: [], personalDetails: [], userToInvite: null, currentUserOption: null}; } - const inviteOptions = getMemberInviteOptions(options.personalDetails, nvpDismissedProductTraining, betas ?? [], excludedUsers); + const inviteOptions = getMemberInviteOptions(options.personalDetails, nvpDismissedProductTraining, translate, betas ?? [], excludedUsers); // Update selectedOptions with the latest personalDetails information const detailsMap: Record = {}; for (const detail of inviteOptions.personalDetails) { @@ -111,16 +111,16 @@ function RoomInvitePage({ recentReports: [], currentUserOption: null, }; - }, [areOptionsInitialized, betas, excludedUsers, options.personalDetails, selectedOptions, nvpDismissedProductTraining]); + }, [areOptionsInitialized, options.personalDetails, nvpDismissedProductTraining, translate, betas, excludedUsers, selectedOptions]); const inviteOptions = useMemo(() => { if (debouncedSearchTerm.trim() === '') { return defaultOptions; } - const filteredOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, countryCode, undefined, {excludeLogins: excludedUsers}); + const filteredOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, translate, countryCode, {excludeLogins: excludedUsers}); return filteredOptions; - }, [debouncedSearchTerm, defaultOptions, excludedUsers, countryCode]); + }, [debouncedSearchTerm, defaultOptions, excludedUsers, countryCode, translate]); const sections = useMemo(() => { const sectionsArr: Sections = []; diff --git a/src/pages/Share/ShareDetailsPage.tsx b/src/pages/Share/ShareDetailsPage.tsx index 580e5eec9073d..1c356e6aab264 100644 --- a/src/pages/Share/ShareDetailsPage.tsx +++ b/src/pages/Share/ShareDetailsPage.tsx @@ -63,8 +63,8 @@ function ShareDetailsPage({route}: ShareDetailsPageProps) { const report: OnyxEntry = getReportOrDraftReport(reportOrAccountID); const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: false}); const displayReport = useMemo( - () => getReportDisplayOption(report, unknownUserDetails, policyTags, reportAttributesDerived), - [report, unknownUserDetails, policyTags, reportAttributesDerived], + () => getReportDisplayOption(report, unknownUserDetails, policyTags, translate, reportAttributesDerived), + [report, unknownUserDetails, policyTags, translate, reportAttributesDerived], ); const ancestors = useAncestors(report); diff --git a/src/pages/Share/ShareTab.tsx b/src/pages/Share/ShareTab.tsx index a59a6ae106514..01f1c29092f61 100644 --- a/src/pages/Share/ShareTab.tsx +++ b/src/pages/Share/ShareTab.tsx @@ -66,6 +66,7 @@ function ShareTab({ref}: ShareTabProps) { return defaultListOptions; } return getSearchOptions({ + translate, options, draftComments, nvpDismissedProductTraining, @@ -78,7 +79,7 @@ function ShareTab({ref}: ShareTabProps) { countryCode, policyTags, }); - }, [areOptionsInitialized, options, draftComments, nvpDismissedProductTraining, betas, textInputValue, countryCode, policyTags]); + }, [areOptionsInitialized, translate, options, draftComments, nvpDismissedProductTraining, betas, textInputValue, countryCode, policyTags]); const recentReportsOptions = useMemo(() => { if (textInputValue.trim() === '') { diff --git a/src/pages/Share/SubmitDetailsPage.tsx b/src/pages/Share/SubmitDetailsPage.tsx index 9c0c035555757..0e7d6d58e5195 100644 --- a/src/pages/Share/SubmitDetailsPage.tsx +++ b/src/pages/Share/SubmitDetailsPage.tsx @@ -100,7 +100,7 @@ function SubmitDetailsPage({ const selectedParticipants = unknownUserDetails ? [unknownUserDetails] : getMoneyRequestParticipantsFromReport(report, currentUserPersonalDetails.accountID); const participants = selectedParticipants.map((participant) => - participant?.accountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived), + participant?.accountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, translate, reportAttributesDerived), ); const trimmedComment = transaction?.comment?.comment?.trim() ?? ''; const transactionAmount = transaction?.amount ?? 0; diff --git a/src/pages/iou/SplitBillDetailsPage.tsx b/src/pages/iou/SplitBillDetailsPage.tsx index 931a1eab9e7ba..35d13248dbfd8 100644 --- a/src/pages/iou/SplitBillDetailsPage.tsx +++ b/src/pages/iou/SplitBillDetailsPage.tsx @@ -53,7 +53,7 @@ function SplitBillDetailsPage({route, report, reportAction}: SplitBillDetailsPag const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: true}); const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false}); const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector}); - const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: false}); + const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); // In case this is workspace split expense, we manually add the workspace as the second participant of the split expense // because we don't save any accountID in the report action's originalMessage other than the payee's accountID @@ -61,7 +61,7 @@ function SplitBillDetailsPage({route, report, reportAction}: SplitBillDetailsPag if (isPolicyExpenseChat(report)) { participants = [ getParticipantsOption({accountID: participantAccountIDs.at(0), selected: true, reportID: ''}, personalDetails), - getPolicyExpenseReportOption({...report, selected: true, reportID}, policyTags, reportAttributesDerived), + getPolicyExpenseReportOption({...report, selected: true, reportID}, policyTags, translate, reportAttributesDerived), ]; } else { participants = participantAccountIDs.map((accountID) => getParticipantsOption({accountID, selected: true, reportID: ''}, personalDetails)); diff --git a/src/pages/iou/request/MoneyRequestAccountantSelector.tsx b/src/pages/iou/request/MoneyRequestAccountantSelector.tsx index b9ea4abc7be40..241acbb6438f8 100644 --- a/src/pages/iou/request/MoneyRequestAccountantSelector.tsx +++ b/src/pages/iou/request/MoneyRequestAccountantSelector.tsx @@ -64,6 +64,7 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector}); const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, {canBeMissing: true}); const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); + const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); useEffect(() => { searchInServer(debouncedSearchTerm.trim()); @@ -81,7 +82,8 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType }, draftComments, nvpDismissedProductTraining, - undefined, + policyTags, + translate, { betas, excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, @@ -96,7 +98,19 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType ...optionList, ...orderedOptions, }; - }, [action, areOptionsInitialized, betas, didScreenTransitionEnd, draftComments, nvpDismissedProductTraining, options.personalDetails, options.reports, countryCode]); + }, [ + areOptionsInitialized, + didScreenTransitionEnd, + options.reports, + options.personalDetails, + draftComments, + nvpDismissedProductTraining, + policyTags, + translate, + betas, + action, + countryCode, + ]); const chatOptions = useMemo(() => { if (!areOptionsInitialized) { @@ -108,12 +122,12 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType headerMessage: '', }; } - const newOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, countryCode, undefined, { + const newOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, translate, countryCode, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, }); return newOptions; - }, [areOptionsInitialized, defaultOptions, debouncedSearchTerm, countryCode]); + }, [areOptionsInitialized, defaultOptions, debouncedSearchTerm, translate, countryCode]); /** * Returns the sections needed for the OptionsSelector @@ -132,7 +146,8 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType [], chatOptions.recentReports, chatOptions.personalDetails, - undefined, + policyTags, + translate, personalDetails, true, undefined, @@ -160,7 +175,9 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType title: undefined, data: [chatOptions.userToInvite].map((participant) => { const isPolicyExpenseChat = participant?.isPolicyExpenseChat ?? false; - return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant, undefined, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); + return isPolicyExpenseChat + ? getPolicyExpenseReportOption(participant, policyTags, translate, reportAttributesDerived) + : getParticipantsOption(participant, personalDetails); }), shouldShow: true, }); @@ -182,9 +199,10 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType chatOptions.personalDetails, chatOptions.userToInvite, debouncedSearchTerm, + policyTags, + translate, personalDetails, reportAttributesDerived, - translate, countryCode, ]); diff --git a/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx b/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx index 69d97e0766858..20fd9d5022189 100644 --- a/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx +++ b/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx @@ -66,7 +66,7 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde const policy = usePolicy(activePolicyID); const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false, canBeMissing: true}); const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector}); - const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${activePolicyID}`, {canBeMissing: true}); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}`, {canBeMissing: true}); const offlineMessage: string = isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; const isPaidGroupPolicy = useMemo(() => isPaidGroupPolicyFn(policy), [policy]); @@ -213,6 +213,7 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde orderedAvailableOptions.recentReports, orderedAvailableOptions.personalDetails, policyTags, + translate, personalDetails, true, undefined, @@ -250,7 +251,9 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde title: undefined, data: [orderedAvailableOptions.userToInvite].map((participant) => { const isPolicyExpenseChat = participant?.isPolicyExpenseChat ?? false; - return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant, policyTags, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); + return isPolicyExpenseChat + ? getPolicyExpenseReportOption(participant, policyTags, translate, reportAttributesDerived) + : getParticipantsOption(participant, personalDetails); }) as OptionData[], shouldShow: true, }); diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index aa8c003bc3c94..f5d94d044085f 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -119,7 +119,7 @@ function MoneyRequestParticipantsSelector({ const [currentUserLogin] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: true, selector: emailSelector}); const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector}); const [countryCode = CONST.DEFAULT_COUNTRY_CODE] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); - + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}`, {canBeMissing: true}); const [textInputAutoFocus, setTextInputAutoFocus] = useState(!isNative); const selectionListRef = useRef(null); const offlineMessage: string = isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; @@ -286,7 +286,8 @@ function MoneyRequestParticipantsSelector({ participants.map((participant) => ({...participant, reportID: participant.reportID})) as OptionData[], [], [], - undefined, + policyTags, + translate, personalDetails, true, undefined, @@ -335,7 +336,9 @@ function MoneyRequestParticipantsSelector({ title: undefined, data: [availableOptions.userToInvite].map((participant) => { const isPolicyExpenseChat = participant?.isPolicyExpenseChat ?? false; - return isPolicyExpenseChat ? getPolicyExpenseReportOption(participant, undefined, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); + return isPolicyExpenseChat + ? getPolicyExpenseReportOption(participant, policyTags, translate, reportAttributesDerived) + : getParticipantsOption(participant, personalDetails); }), shouldShow: true, }); @@ -352,9 +355,10 @@ function MoneyRequestParticipantsSelector({ didScreenTransitionEnd, searchTerm, participants, + policyTags, + translate, personalDetails, reportAttributesDerived, - translate, availableOptions.workspaceChats, availableOptions.selfDMChat, availableOptions.userToInvite, diff --git a/src/pages/iou/request/step/IOURequestStepAmount.tsx b/src/pages/iou/request/step/IOURequestStepAmount.tsx index fa1ecb58b93e6..daf1b33710396 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.tsx +++ b/src/pages/iou/request/step/IOURequestStepAmount.tsx @@ -199,7 +199,7 @@ function IOURequestStepAmount({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report, currentUserPersonalDetails.accountID); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, translate, reportAttributesDerived); }); const backendAmount = convertToBackendAmount(Number.parseFloat(amount)); diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 0af82a802dfa4..a8892f10a254d 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -293,9 +293,11 @@ function IOURequestStepConfirmation({ if (participant.isSender && iouType === CONST.IOU.TYPE.INVOICE) { return participant; } - return participant.accountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived, reportDrafts); + return participant.accountID + ? getParticipantsOption(participant, personalDetails) + : getReportOption(participant, policyTags, translate, reportAttributesDerived, reportDrafts); }) ?? [], - [transaction?.participants, iouType, personalDetails, policyTags, reportAttributesDerived, reportDrafts], + [transaction?.participants, iouType, personalDetails, policyTags, translate, reportAttributesDerived, reportDrafts], ); const isPolicyExpenseChat = useMemo(() => participants?.some((participant) => participant.isPolicyExpenseChat), [participants]); const shouldGenerateTransactionThreadReport = !isBetaEnabled(CONST.BETAS.NO_OPTIMISTIC_TRANSACTION_THREADS); diff --git a/src/pages/iou/request/step/IOURequestStepDistance.tsx b/src/pages/iou/request/step/IOURequestStepDistance.tsx index 2b7324245d277..53d98d1cb04f5 100644 --- a/src/pages/iou/request/step/IOURequestStepDistance.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistance.tsx @@ -321,7 +321,7 @@ function IOURequestStepDistance({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report, currentUserPersonalDetails.accountID); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, translate, reportAttributesDerived); }); setDistanceRequestData(participants); if (shouldSkipConfirmation) { diff --git a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx index 08b35078d3a20..506448f506555 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx @@ -193,7 +193,7 @@ function IOURequestStepDistanceManual({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report, currentUserPersonalDetails.accountID); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, translate, reportAttributesDerived); }); if (shouldSkipConfirmation) { setMoneyRequestPendingFields(transactionID, {waypoints: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD}); @@ -303,23 +303,24 @@ function IOURequestStepDistanceManual({ transaction, reportID, policy, + currentUserAccountIDParam, + currentUserEmailParam, + isASAPSubmitBetaEnabled, + currentUserPersonalDetails.accountID, shouldSkipConfirmation, personalDetails, policyTags, - reportAttributesDerived, translate, - currentUserEmailParam, - currentUserAccountIDParam, + reportAttributesDerived, lastSelectedDistanceRates, backToReport, - isASAPSubmitBetaEnabled, + transactionViolations, + quickAction, + policyRecentlyUsedCurrencies, customUnitRateID, navigateToConfirmationPage, defaultExpensePolicy, personalPolicy?.autoReporting, - transactionViolations, - currentUserPersonalDetails.accountID, - quickAction, ], ); diff --git a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx index 9336c5e9a88ca..b50bac6919ae8 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx @@ -323,7 +323,7 @@ function IOURequestStepDistanceMap({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report, currentUserPersonalDetails.accountID); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, translate, reportAttributesDerived); }); setDistanceRequestData(participants); if (shouldSkipConfirmation) { diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index 113ff5182e0e4..c77a9f26a1e26 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -420,7 +420,7 @@ function IOURequestStepScan({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report, currentUserPersonalDetails.accountID); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, translate, reportAttributesDerived); }); if (shouldSkipConfirmation) { @@ -540,12 +540,14 @@ function IOURequestStepScan({ shouldSkipConfirmation, personalDetails, policyTags, + translate, reportAttributesDerived, createTransaction, reportID, transactionTaxCode, transactionTaxAmount, quickAction, + policyRecentlyUsedCurrencies, policy, personalPolicy?.autoReporting, selfDMReportID, diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index 5ed8eefbe371f..bae4c6efe255e 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -476,7 +476,7 @@ function IOURequestStepScan({ const selectedParticipants = getMoneyRequestParticipantsFromReport(report, currentUserPersonalDetails.accountID); const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, reportAttributesDerived); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, translate, reportAttributesDerived); }); if (shouldSkipConfirmation) { @@ -595,12 +595,14 @@ function IOURequestStepScan({ shouldSkipConfirmation, personalDetails, policyTags, + translate, reportAttributesDerived, createTransaction, reportID, transactionTaxCode, transactionTaxAmount, quickAction, + policyRecentlyUsedCurrencies, policy, personalPolicy?.autoReporting, selfDMReportID, diff --git a/tests/perf-test/OptionsListUtils.perf-test.ts b/tests/perf-test/OptionsListUtils.perf-test.ts index 75569bed5edec..cf7757c5c91db 100644 --- a/tests/perf-test/OptionsListUtils.perf-test.ts +++ b/tests/perf-test/OptionsListUtils.perf-test.ts @@ -77,7 +77,7 @@ jest.mock('@react-navigation/native', () => { }; }); -const options = createOptionList(personalDetails, undefined, reports); +const options = createOptionList(personalDetails, undefined, jest.fn(), reports); const ValidOptionsConfig = { betas: mockedBetas, @@ -110,22 +110,36 @@ describe('OptionsListUtils', () => { /* Testing getSearchOptions */ test('[OptionsListUtils] getSearchOptions', async () => { await waitForBatchedUpdates(); - await measureFunction(() => getSearchOptions({options, betas: mockedBetas, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined})); + await measureFunction(() => getSearchOptions({options, betas: mockedBetas, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, translate: jest.fn()})); }); /* Testing getFilteredOptions */ test('[OptionsListUtils] getFilteredOptions with search value', async () => { await waitForBatchedUpdates(); - const formattedOptions = getValidOptions({reports: options.reports, personalDetails: options.personalDetails}, {}, nvpDismissedProductTraining, undefined, ValidOptionsConfig); + const formattedOptions = getValidOptions( + {reports: options.reports, personalDetails: options.personalDetails}, + {}, + nvpDismissedProductTraining, + undefined, + jest.fn(), + ValidOptionsConfig, + ); await measureFunction(() => { - filterAndOrderOptions(formattedOptions, SEARCH_VALUE, COUNTRY_CODE, undefined); + filterAndOrderOptions(formattedOptions, SEARCH_VALUE, jest.fn(), COUNTRY_CODE, undefined); }); }); test('[OptionsListUtils] getFilteredOptions with empty search value', async () => { await waitForBatchedUpdates(); - const formattedOptions = getValidOptions({reports: options.reports, personalDetails: options.personalDetails}, {}, nvpDismissedProductTraining, undefined, ValidOptionsConfig); + const formattedOptions = getValidOptions( + {reports: options.reports, personalDetails: options.personalDetails}, + {}, + nvpDismissedProductTraining, + undefined, + jest.fn(), + ValidOptionsConfig, + ); await measureFunction(() => { - filterAndOrderOptions(formattedOptions, '', COUNTRY_CODE, undefined); + filterAndOrderOptions(formattedOptions, '', jest.fn(), COUNTRY_CODE, undefined); }); }); @@ -133,7 +147,7 @@ describe('OptionsListUtils', () => { test('[OptionsListUtils] getShareDestinationOptions', async () => { await waitForBatchedUpdates(); await measureFunction(() => - getValidOptions({reports: options.reports, personalDetails: options.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + getValidOptions({reports: options.reports, personalDetails: options.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { betas: mockedBetas, includeMultipleParticipantReports: true, showChatPreviewLine: true, @@ -153,7 +167,7 @@ describe('OptionsListUtils', () => { /* Testing getMemberInviteOptions */ test('[OptionsListUtils] getMemberInviteOptions', async () => { await waitForBatchedUpdates(); - await measureFunction(() => getMemberInviteOptions(options.personalDetails, nvpDismissedProductTraining, mockedBetas)); + await measureFunction(() => getMemberInviteOptions(options.personalDetails, nvpDismissedProductTraining, jest.fn(), mockedBetas)); }); test('[OptionsListUtils] worst case scenario with a search term that matches a subset of selectedOptions, filteredRecentReports, and filteredPersonalDetails', async () => { @@ -199,6 +213,7 @@ describe('OptionsListUtils', () => { Object.values(filteredRecentReports), Object.values(filteredPersonalDetails), undefined, + jest.fn(), mockedPersonalDetails, true, ), @@ -211,6 +226,6 @@ describe('OptionsListUtils', () => { const mockedPersonalDetails = getMockedPersonalDetails(PERSONAL_DETAILS_COUNT); await waitForBatchedUpdates(); - await measureFunction(() => formatSectionsFromSearchTerm('', Object.values(selectedOptions), [], [], undefined, mockedPersonalDetails, true)); + await measureFunction(() => formatSectionsFromSearchTerm('', Object.values(selectedOptions), [], [], undefined, jest.fn(), mockedPersonalDetails, true)); }); }); diff --git a/tests/perf-test/SearchRouter.perf-test.tsx b/tests/perf-test/SearchRouter.perf-test.tsx index 5ea9e4ae02b35..22e8bfcd0562d 100644 --- a/tests/perf-test/SearchRouter.perf-test.tsx +++ b/tests/perf-test/SearchRouter.perf-test.tsx @@ -89,7 +89,7 @@ const getMockedPersonalDetails = (length = 100) => const mockedReports = getMockedReports(600); const mockedBetas = Object.values(CONST.BETAS); const mockedPersonalDetails = getMockedPersonalDetails(100); -const mockedOptions = createOptionList(mockedPersonalDetails, undefined, mockedReports); +const mockedOptions = createOptionList(mockedPersonalDetails, undefined, jest.fn(), mockedReports); beforeAll(() => Onyx.init({ diff --git a/tests/perf-test/SidebarUtils.perf-test.ts b/tests/perf-test/SidebarUtils.perf-test.ts index ca2680adb3594..e4d5a43efa2c4 100644 --- a/tests/perf-test/SidebarUtils.perf-test.ts +++ b/tests/perf-test/SidebarUtils.perf-test.ts @@ -90,6 +90,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }), ); }); diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index 133dc364ea474..ed3702aa09916 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -626,19 +626,19 @@ describe('OptionsListUtils', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}10`, reportNameValuePairs); await waitForBatchedUpdates(); - OPTIONS = createOptionList(PERSONAL_DETAILS, undefined, REPORTS); - OPTIONS_WITH_CONCIERGE = createOptionList(PERSONAL_DETAILS_WITH_CONCIERGE, undefined, REPORTS_WITH_CONCIERGE); - OPTIONS_WITH_CHRONOS = createOptionList(PERSONAL_DETAILS_WITH_CHRONOS, undefined, REPORTS_WITH_CHRONOS); - OPTIONS_WITH_RECEIPTS = createOptionList(PERSONAL_DETAILS_WITH_RECEIPTS, undefined, REPORTS_WITH_RECEIPTS); - OPTIONS_WITH_WORKSPACE_ROOM = createOptionList(PERSONAL_DETAILS, undefined, REPORTS_WITH_WORKSPACE_ROOMS); - OPTIONS_WITH_MANAGER_MCTEST = createOptionList(PERSONAL_DETAILS_WITH_MANAGER_MCTEST, undefined); + OPTIONS = createOptionList(PERSONAL_DETAILS, undefined, jest.fn(), REPORTS); + OPTIONS_WITH_CONCIERGE = createOptionList(PERSONAL_DETAILS_WITH_CONCIERGE, undefined, jest.fn(), REPORTS_WITH_CONCIERGE); + OPTIONS_WITH_CHRONOS = createOptionList(PERSONAL_DETAILS_WITH_CHRONOS, undefined, jest.fn(), REPORTS_WITH_CHRONOS); + OPTIONS_WITH_RECEIPTS = createOptionList(PERSONAL_DETAILS_WITH_RECEIPTS, undefined, jest.fn(), REPORTS_WITH_RECEIPTS); + OPTIONS_WITH_WORKSPACE_ROOM = createOptionList(PERSONAL_DETAILS, undefined, jest.fn(), REPORTS_WITH_WORKSPACE_ROOMS); + OPTIONS_WITH_MANAGER_MCTEST = createOptionList(PERSONAL_DETAILS_WITH_MANAGER_MCTEST, undefined, jest.fn()); }); describe('getSearchOptions()', () => { it('should return all options when no search value is provided', () => { // Given a set of options // When we call getSearchOptions with all betas - const results = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); + const results = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined, translate: jest.fn()}); // Then all personal details (including those that have reports) should be returned expect(results.personalDetails.length).toBe(10); @@ -663,6 +663,7 @@ describe('OptionsListUtils', () => { includeRecentReports: true, includeCurrentUser: true, policyTags: {}, + translate: jest.fn(), }); // Then the current user should be included in personalDetails @@ -690,6 +691,7 @@ describe('OptionsListUtils', () => { includeUserToInvite: false, includeRecentReports: true, policyTags: undefined, + translate: jest.fn(), }); // Then the current user should not be included in personalDetails @@ -713,6 +715,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, + jest.fn(), ); // When we call orderOptions() results = orderOptions(results); @@ -749,6 +752,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, + jest.fn(), ); // When we call orderOptions() results = orderOptions(results); @@ -776,7 +780,7 @@ 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: []}, {}, nvpDismissedProductTraining, undefined); + const results = getValidOptions({reports: [], personalDetails: []}, {}, nvpDismissedProductTraining, undefined, jest.fn()); // Then the result should be empty expect(results.personalDetails).toEqual([]); @@ -790,7 +794,13 @@ describe('OptionsListUtils', () => { it('should include Concierge by default in results', () => { // Given a set of reports and personalDetails that includes Concierge // When we call getValidOptions() - const results = getValidOptions({reports: OPTIONS_WITH_CONCIERGE.reports, personalDetails: OPTIONS_WITH_CONCIERGE.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const results = getValidOptions( + {reports: OPTIONS_WITH_CONCIERGE.reports, personalDetails: OPTIONS_WITH_CONCIERGE.personalDetails}, + {}, + nvpDismissedProductTraining, + undefined, + jest.fn(), + ); // Then the result should include all personalDetails except the currently logged in user expect(results.personalDetails.length).toBe(Object.values(OPTIONS_WITH_CONCIERGE.personalDetails).length - 1); @@ -809,6 +819,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, + jest.fn(), { excludeLogins: {[CONST.EMAIL.CONCIERGE]: true}, }, @@ -823,9 +834,16 @@ describe('OptionsListUtils', () => { 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() - const results = getValidOptions({reports: OPTIONS_WITH_CHRONOS.reports, personalDetails: OPTIONS_WITH_CHRONOS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { - excludeLogins: {[CONST.EMAIL.CHRONOS]: true}, - }); + const results = getValidOptions( + {reports: OPTIONS_WITH_CHRONOS.reports, personalDetails: OPTIONS_WITH_CHRONOS.personalDetails}, + {}, + nvpDismissedProductTraining, + undefined, + jest.fn(), + { + excludeLogins: {[CONST.EMAIL.CHRONOS]: true}, + }, + ); // Then the result should include all personalDetails except the currently logged in user and Chronos expect(results.personalDetails.length).toBe(Object.values(OPTIONS_WITH_CHRONOS.personalDetails).length - 2); @@ -844,6 +862,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, + jest.fn(), { excludeLogins: {[CONST.EMAIL.RECEIPTS]: true}, }, @@ -868,6 +887,7 @@ describe('OptionsListUtils', () => { }, }, undefined, + jest.fn(), { includeP2P: true, canShowManagerMcTest: true, @@ -889,6 +909,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, + jest.fn(), { includeP2P: true, canShowManagerMcTest: false, @@ -919,6 +940,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, + jest.fn(), {includeP2P: true, canShowManagerMcTest: true, betas: [CONST.BETAS.NEWDOT_MANAGER_MCTEST]}, ); @@ -964,7 +986,7 @@ describe('OptionsListUtils', () => { notificationPreference: 'hidden', }; // When we call getValidOptions with includeMultipleParticipantReports set to true - const results = getValidOptions({reports: [adminRoom], personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + const results = getValidOptions({reports: [adminRoom], personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { includeMultipleParticipantReports: true, }); const adminRoomOption = results.recentReports.find((report) => report.reportID === '1455140530846319'); @@ -1009,7 +1031,7 @@ describe('OptionsListUtils', () => { notificationPreference: 'hidden', brickRoadIndicator: CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR, }; - const results = getValidOptions({reports: [workspaceChat], personalDetails: []}, {}, nvpDismissedProductTraining, undefined, { + const results = getValidOptions({reports: [workspaceChat], personalDetails: []}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { includeMultipleParticipantReports: true, showRBR: true, }); @@ -1052,7 +1074,7 @@ describe('OptionsListUtils', () => { notificationPreference: 'hidden', brickRoadIndicator: CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR, }; - const results = getValidOptions({reports: [workspaceChat], personalDetails: []}, {}, nvpDismissedProductTraining, undefined, { + const results = getValidOptions({reports: [workspaceChat], personalDetails: []}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { includeMultipleParticipantReports: true, showRBR: false, }); @@ -1099,7 +1121,7 @@ describe('OptionsListUtils', () => { isBold: false, }; - const results = getValidOptions({reports: [inputOption], personalDetails: []}, {}, nvpDismissedProductTraining, undefined, { + const results = getValidOptions({reports: [inputOption], personalDetails: []}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { includeRecentReports: true, shouldUnreadBeBold: true, includeMultipleParticipantReports: true, @@ -1114,7 +1136,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, {}, nvpDismissedProductTraining, undefined, { + const results = getValidOptions(OPTIONS_WITH_WORKSPACE_ROOM, {}, nvpDismissedProductTraining, undefined, jest.fn(), { includeRecentReports: true, includeMultipleParticipantReports: true, includeP2P: true, @@ -1131,7 +1153,7 @@ describe('OptionsListUtils', () => { it('should exclude users with recent reports from personalDetails', () => { // Given a set of reports and personalDetails // When we call getValidOptions with no search value - const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); const reportLogins = new Set(results.recentReports.map((reportOption) => reportOption.login)); const personalDetailsOverlapWithReports = results.personalDetails.every((personalDetailOption) => reportLogins.has(personalDetailOption.login)); @@ -1144,7 +1166,7 @@ describe('OptionsListUtils', () => { it('should exclude selected options', () => { // Given a set of reports and personalDetails // When we call getValidOptions with excludeLogins param - const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { excludeLogins: {'peterparker@expensify.com': true}, }); @@ -1156,7 +1178,13 @@ describe('OptionsListUtils', () => { it('should include Concierge in the results by default', () => { // Given a set of report and personalDetails that include Concierge // When we call getValidOptions() - const results = getValidOptions({reports: OPTIONS_WITH_CONCIERGE.reports, personalDetails: OPTIONS_WITH_CONCIERGE.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const results = getValidOptions( + {reports: OPTIONS_WITH_CONCIERGE.reports, personalDetails: OPTIONS_WITH_CONCIERGE.personalDetails}, + {}, + nvpDismissedProductTraining, + undefined, + jest.fn(), + ); // Then the result should include all personalDetails except the currently logged in user expect(results.personalDetails.length).toBe(Object.values(OPTIONS_WITH_CONCIERGE.personalDetails).length - 1); @@ -1175,6 +1203,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, + jest.fn(), { excludeLogins: {[CONST.EMAIL.CONCIERGE]: true}, }, @@ -1190,9 +1219,16 @@ describe('OptionsListUtils', () => { it('should exclude Chronos from the results when it is specified in excludedLogins', () => { // given a set of reports and personalDetails that includes Chronos // When we call getValidOptions() with excludeLogins param - const results = getValidOptions({reports: OPTIONS_WITH_CHRONOS.reports, personalDetails: OPTIONS_WITH_CHRONOS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { - excludeLogins: {[CONST.EMAIL.CHRONOS]: true}, - }); + const results = getValidOptions( + {reports: OPTIONS_WITH_CHRONOS.reports, personalDetails: OPTIONS_WITH_CHRONOS.personalDetails}, + {}, + nvpDismissedProductTraining, + undefined, + jest.fn(), + { + excludeLogins: {[CONST.EMAIL.CHRONOS]: true}, + }, + ); // Then the result should include all personalDetails except the currently logged in user and Chronos expect(results.personalDetails.length).toBe(Object.values(OPTIONS_WITH_CHRONOS.personalDetails).length - 2); @@ -1212,6 +1248,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, + jest.fn(), { excludeLogins: {[CONST.EMAIL.RECEIPTS]: true}, }, @@ -1228,7 +1265,7 @@ describe('OptionsListUtils', () => { // Given a set of reports and personalDetails with multiple reports // When we call getValidOptions with maxRecentReportElements set to 2 const maxRecentReports = 2; - const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { maxRecentReportElements: maxRecentReports, }); @@ -1239,8 +1276,8 @@ describe('OptionsListUtils', () => { it('should show all reports when maxRecentReportElements is not specified', () => { // Given a set of reports and personalDetails // When we call getValidOptions without maxRecentReportElements - const resultsWithoutLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); - const resultsWithLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + const resultsWithoutLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); + const resultsWithLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { maxRecentReportElements: 2, }); @@ -1251,8 +1288,8 @@ describe('OptionsListUtils', () => { it('should not affect personalDetails count when maxRecentReportElements is specified', () => { // Given a set of reports and personalDetails // When we call getValidOptions with and without maxRecentReportElements - const resultsWithoutLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); - const resultsWithLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + const resultsWithoutLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); + const resultsWithLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { maxRecentReportElements: 2, }); @@ -1265,7 +1302,7 @@ describe('OptionsListUtils', () => { // When we call getValidOptions with both maxElements and maxRecentReportElements const maxRecentReports = 3; const maxTotalElements = 10; - const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { maxElements: maxTotalElements, maxRecentReportElements: maxRecentReports, }); @@ -1290,7 +1327,7 @@ describe('OptionsListUtils', () => { }, []); // When we call getValidOptions for share destination with an empty search value - const results = getValidOptions({reports: filteredReports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + const results = getValidOptions({reports: filteredReports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { betas: [], includeMultipleParticipantReports: true, showChatPreviewLine: true, @@ -1322,7 +1359,7 @@ describe('OptionsListUtils', () => { }, []); // When we call getValidOptions for share destination with an empty search value - const results = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + const results = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { betas: [], includeMultipleParticipantReports: true, showChatPreviewLine: true, @@ -1346,7 +1383,7 @@ describe('OptionsListUtils', () => { it('should sort personal details alphabetically', () => { // Given a set of personalDetails // When we call getMemberInviteOptions - const results = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, []); + const results = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, jest.fn(), []); // Then personal details should be sorted alphabetically expect(results.personalDetails.at(0)?.text).toBe('Black Panther'); @@ -1530,9 +1567,9 @@ describe('OptionsListUtils', () => { it('should return all options when search is empty', () => { // Given a set of options // When we call getSearchOptions with all betas - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined, translate: jest.fn()}); // When we pass the returned options to filterAndOrderOptions with an empty search value - const filteredOptions = filterAndOrderOptions(options, '', COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, '', jest.fn(), COUNTRY_CODE, undefined); // Then all options should be returned expect(filteredOptions.recentReports.length + filteredOptions.personalDetails.length).toBe(14); @@ -1542,9 +1579,9 @@ describe('OptionsListUtils', () => { const searchText = 'man'; // Given a set of options // When we call getSearchOptions with all betas - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined, translate: jest.fn()}); // When we pass the returned options to filterAndOrderOptions with a search value and sortByReportTypeInSearch param - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined, {sortByReportTypeInSearch: true}); + const filteredOptions = filterAndOrderOptions(options, searchText, jest.fn(), COUNTRY_CODE, {sortByReportTypeInSearch: true}); // Then we expect all options to be part of the recentReports list and reports should be first: expect(filteredOptions.personalDetails.length).toBe(0); @@ -1561,9 +1598,9 @@ describe('OptionsListUtils', () => { const searchText = 'mistersinister@marauders.com'; // Given a set of options // When we call getSearchOptions with all betas - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined, translate: jest.fn()}); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, searchText, jest.fn(), COUNTRY_CODE); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1575,9 +1612,9 @@ describe('OptionsListUtils', () => { const searchText = 'Archived'; // Given a set of options // When we call getSearchOptions with all betas - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined, translate: jest.fn()}); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, searchText, jest.fn(), COUNTRY_CODE); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1589,11 +1626,18 @@ describe('OptionsListUtils', () => { // cspell:disable-next-line const searchText = 'barryallen'; // Given a set of options created from PERSONAL_DETAILS_WITH_PERIODS - const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, {}, REPORTS); + const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, {}, jest.fn(), REPORTS); // When we call getSearchOptions with all betas - const options = getSearchOptions({options: OPTIONS_WITH_PERIODS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); + const options = getSearchOptions({ + options: OPTIONS_WITH_PERIODS, + draftComments: {}, + nvpDismissedProductTraining, + betas: [CONST.BETAS.ALL], + policyTags: undefined, + translate: jest.fn(), + }); // When we pass the returned options to filterAndOrderOptions with a search value and sortByReportTypeInSearch param - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined, {sortByReportTypeInSearch: true}); + const filteredOptions = filterAndOrderOptions(options, searchText, jest.fn(), COUNTRY_CODE, {sortByReportTypeInSearch: true}); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1605,9 +1649,16 @@ describe('OptionsListUtils', () => { const searchText = 'avengers'; // Given a set of options with workspace rooms // When we call getSearchOptions with all betas - const options = getSearchOptions({options: OPTIONS_WITH_WORKSPACE_ROOM, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); + const options = getSearchOptions({ + options: OPTIONS_WITH_WORKSPACE_ROOM, + draftComments: {}, + nvpDismissedProductTraining, + betas: [CONST.BETAS.ALL], + policyTags: undefined, + translate: jest.fn(), + }); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, searchText, jest.fn(), COUNTRY_CODE); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1618,9 +1669,9 @@ describe('OptionsListUtils', () => { it('should put exact match by login on the top of the list', () => { const searchText = 'reedrichards@expensify.com'; // Given a set of options with all betas - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined, translate: jest.fn()}); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, searchText, jest.fn(), COUNTRY_CODE); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1631,11 +1682,18 @@ describe('OptionsListUtils', () => { it('should prioritize options with matching display name over chat rooms', () => { const searchText = 'spider'; // Given a set of options with chat rooms - const OPTIONS_WITH_CHAT_ROOMS = createOptionList(PERSONAL_DETAILS, {}, REPORTS_WITH_CHAT_ROOM); + const OPTIONS_WITH_CHAT_ROOMS = createOptionList(PERSONAL_DETAILS, {}, jest.fn(), REPORTS_WITH_CHAT_ROOM); // When we call getSearchOptions with all betas - const options = getSearchOptions({options: OPTIONS_WITH_CHAT_ROOMS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); + const options = getSearchOptions({ + options: OPTIONS_WITH_CHAT_ROOMS, + draftComments: {}, + nvpDismissedProductTraining, + betas: [CONST.BETAS.ALL], + policyTags: undefined, + translate: jest.fn(), + }); // When we pass the returned options to filterAndOrderOptions with a search value - const filterOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); + const filterOptions = filterAndOrderOptions(options, searchText, jest.fn(), COUNTRY_CODE); // Then only two reports should be returned expect(filterOptions.recentReports.length).toBe(2); @@ -1647,9 +1705,9 @@ describe('OptionsListUtils', () => { renderLocaleContextProvider(); const searchText = 'fantastic'; // Given a set of options - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, translate: jest.fn()}); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, searchText, jest.fn(), COUNTRY_CODE); // Then only three reports should be returned expect(filteredOptions.recentReports.length).toBe(3); @@ -1662,9 +1720,9 @@ describe('OptionsListUtils', () => { it('should return the user to invite when the search value is a valid, non-existent email', () => { const searchText = 'test@email.com'; // Given a set of options - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, translate: jest.fn()}); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, searchText, jest.fn(), COUNTRY_CODE); // Then the user to invite should be returned expect(filteredOptions.userToInvite?.login).toBe(searchText); @@ -1673,11 +1731,11 @@ describe('OptionsListUtils', () => { it('should not return any results if the search value is on an excluded logins list', () => { const searchText = 'admin@expensify.com'; // Given a set of options with excluded logins list - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, }); // When we call filterAndOrderOptions with a search value and excluded logins list - const filterOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined, {excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT}); + const filterOptions = filterAndOrderOptions(options, searchText, jest.fn(), COUNTRY_CODE, {excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT}); // Then no personal details should be returned expect(filterOptions.recentReports.length).toBe(0); @@ -1686,9 +1744,9 @@ describe('OptionsListUtils', () => { it('should return the user to invite when the search value is a valid, non-existent email and the user is not excluded', () => { const searchText = 'test@email.com'; // Given a set of options - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, translate: jest.fn()}); // When we call filterAndOrderOptions with a search value and excludeLogins - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined, {excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT}); + const filteredOptions = filterAndOrderOptions(options, searchText, jest.fn(), COUNTRY_CODE, {excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT}); // Then the user to invite should be returned expect(filteredOptions.userToInvite?.login).toBe(searchText); @@ -1697,16 +1755,16 @@ describe('OptionsListUtils', () => { it('should return limited amount of recent reports if the limit is set', () => { const searchText = ''; // Given a set of options - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, translate: jest.fn()}); // When we call filterAndOrderOptions with a search value and maxRecentReportsToShow set to 2 - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined, {maxRecentReportsToShow: 2}); + const filteredOptions = filterAndOrderOptions(options, searchText, jest.fn(), COUNTRY_CODE, {maxRecentReportsToShow: 2}); // Then only two reports should be returned expect(filteredOptions.recentReports.length).toBe(2); // Note: in the past maxRecentReportsToShow: 0 would return all recent reports, this has changed, and is expected to return none now // When we call filterAndOrderOptions with a search value and maxRecentReportsToShow set to 0 - const limitToZeroOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined, {maxRecentReportsToShow: 0}); + const limitToZeroOptions = filterAndOrderOptions(options, searchText, jest.fn(), COUNTRY_CODE, {maxRecentReportsToShow: 0}); // Then no reports should be returned expect(limitToZeroOptions.recentReports.length).toBe(0); @@ -1715,9 +1773,9 @@ describe('OptionsListUtils', () => { it('should not return any user to invite if email exists on the personal details list', () => { const searchText = 'natasharomanoff@expensify.com'; // Given a set of options with all betas - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined, translate: jest.fn()}); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, searchText, jest.fn(), COUNTRY_CODE); // Then there should be one matching result expect(filteredOptions.personalDetails.length).toBe(1); @@ -1727,9 +1785,9 @@ describe('OptionsListUtils', () => { it('should not return any options if search value does not match any personal details (getMemberInviteOptions)', () => { // Given a set of options - const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, []); + const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, jest.fn(), []); // When we call filterAndOrderOptions with a search value that does not match any personal details - const filteredOptions = filterAndOrderOptions(options, 'magneto', COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, 'magneto', jest.fn(), COUNTRY_CODE); // Then no personal details should be returned expect(filteredOptions.personalDetails.length).toBe(0); @@ -1737,9 +1795,9 @@ describe('OptionsListUtils', () => { it('should return one personal detail if search value matches an email (getMemberInviteOptions)', () => { // Given a set of options - const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, []); + const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, jest.fn(), []); // When we call filterAndOrderOptions with a search value that matches an email - const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', jest.fn(), COUNTRY_CODE); // Then one personal detail should be returned expect(filteredOptions.personalDetails.length).toBe(1); @@ -1757,7 +1815,7 @@ describe('OptionsListUtils', () => { return filtered; }, []); // When we call getValidOptions for share destination with the filteredReports - const options = getValidOptions({reports: filteredReports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + const options = getValidOptions({reports: filteredReports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { betas: [], includeMultipleParticipantReports: true, showChatPreviewLine: true, @@ -1772,7 +1830,7 @@ describe('OptionsListUtils', () => { includeUserToInvite: false, }); // When we pass the returned options to filterAndOrderOptions with a search value that does not match the group chat name - const filteredOptions = filterAndOrderOptions(options, 'mutants', COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, 'mutants', jest.fn(), COUNTRY_CODE); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1790,7 +1848,7 @@ describe('OptionsListUtils', () => { }, []); // When we call getValidOptions for share destination with the filteredReports - const options = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + const options = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { betas: [], includeMultipleParticipantReports: true, showChatPreviewLine: true, @@ -1805,7 +1863,7 @@ describe('OptionsListUtils', () => { includeUserToInvite: false, }); // When we pass the returned options to filterAndOrderOptions with a search value that matches the group chat name - const filteredOptions = filterAndOrderOptions(options, 'Avengers Room', COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, 'Avengers Room', jest.fn(), COUNTRY_CODE); // Then one recent report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1823,7 +1881,7 @@ describe('OptionsListUtils', () => { }, []); // When we call getValidOptions for share destination with the filteredReports - const options = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, { + const options = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { betas: [], includeMultipleParticipantReports: true, showChatPreviewLine: true, @@ -1838,7 +1896,7 @@ describe('OptionsListUtils', () => { includeUserToInvite: false, }); // When we pass the returned options to filterAndOrderOptions with a search value that does not match the group chat name - const filteredOptions = filterAndOrderOptions(options, 'Mutants Lair', COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, 'Mutants Lair', jest.fn(), COUNTRY_CODE); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1846,9 +1904,9 @@ describe('OptionsListUtils', () => { it('should show the option from personal details when searching for personal detail with no existing report', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); // When we call filterAndOrderOptions with a search value that matches a personal detail with no existing report - const filteredOptions = filterAndOrderOptions(options, 'hulk', COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, 'hulk', jest.fn(), COUNTRY_CODE); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1860,9 +1918,9 @@ describe('OptionsListUtils', () => { it('should not return any options or user to invite if there are no search results and the string does not match a potential email or phone', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); // 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, undefined); + const filteredOptions = filterAndOrderOptions(options, 'marc@expensify', jest.fn(), COUNTRY_CODE); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1873,9 +1931,9 @@ describe('OptionsListUtils', () => { it('should not return any options but should return an user to invite if no matching options exist and the search value is a potential email', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); // 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, undefined); + const filteredOptions = filterAndOrderOptions(options, 'marc@expensify.com', jest.fn(), COUNTRY_CODE); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1886,9 +1944,9 @@ describe('OptionsListUtils', () => { it('should return user to invite when search term has a period with options for it that do not contain the period', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); // 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, undefined); + const filteredOptions = filterAndOrderOptions(options, 'peter.parker@expensify.com', jest.fn(), COUNTRY_CODE); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1898,9 +1956,9 @@ describe('OptionsListUtils', () => { it('should return user which has displayName with accent mark when search value without accent mark', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); // When we call filterAndOrderOptions with a search value without accent mark - const filteredOptions = filterAndOrderOptions(options, 'Timothee', COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, 'Timothee', jest.fn(), COUNTRY_CODE); // Then one personalDetails with accent mark should be returned expect(filteredOptions.personalDetails.length).toBe(1); @@ -1908,9 +1966,9 @@ describe('OptionsListUtils', () => { it('should not return options but should return an user to invite if no matching options exist and the search value is a potential phone number', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); // 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, undefined); + const filteredOptions = filterAndOrderOptions(options, '5005550006', jest.fn(), COUNTRY_CODE); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1923,9 +1981,9 @@ describe('OptionsListUtils', () => { it('should not return options but should return an user to invite if no matching options exist and the search value is a potential phone number with country code added', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); // 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, undefined); + const filteredOptions = filterAndOrderOptions(options, '+15005550006', jest.fn(), COUNTRY_CODE); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1938,9 +1996,9 @@ describe('OptionsListUtils', () => { it('should not return options but should return an user to invite if no matching options exist and the search value is a potential phone number with special characters added', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); // 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, undefined); + const filteredOptions = filterAndOrderOptions(options, '+1 (800)324-3233', jest.fn(), COUNTRY_CODE); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1953,9 +2011,9 @@ describe('OptionsListUtils', () => { it('should not return any options or user to invite if contact number contains alphabet characters', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); // When we call filterAndOrderOptions with a search value that does not match any personal details or reports - const filteredOptions = filterAndOrderOptions(options, '998243aaaa', COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, '998243aaaa', jest.fn(), COUNTRY_CODE); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -1966,9 +2024,9 @@ describe('OptionsListUtils', () => { it('should not return any options if search value does not match any personal details', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); // When we call filterAndOrderOptions with a search value that does not match any personal details - const filteredOptions = filterAndOrderOptions(options, 'magneto', COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, 'magneto', jest.fn(), COUNTRY_CODE); // Then no personal details should be returned expect(filteredOptions.personalDetails.length).toBe(0); @@ -1976,9 +2034,9 @@ describe('OptionsListUtils', () => { it('should return one recent report and no personal details if a search value provides an email', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); // When we call filterAndOrderOptions with a search value that matches an email - const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', COUNTRY_CODE, undefined, {sortByReportTypeInSearch: true}); + const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', jest.fn(), COUNTRY_CODE, {sortByReportTypeInSearch: true}); // Then one recent report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1990,9 +2048,9 @@ describe('OptionsListUtils', () => { it('should return all matching reports and personal details', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn()); // 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, undefined, {maxRecentReportsToShow: 5}); + const filteredOptions = filterAndOrderOptions(options, '.com', jest.fn(), COUNTRY_CODE, {maxRecentReportsToShow: 5}); // Then there should be 4 matching personal details expect(filteredOptions.personalDetails.length).toBe(5); @@ -2007,9 +2065,9 @@ describe('OptionsListUtils', () => { it('should return matching option when searching (getSearchOptions)', () => { // Given a set of options - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, translate: jest.fn()}); // When we call filterAndOrderOptions with a search value that matches a personal detail - const filteredOptions = filterAndOrderOptions(options, 'spider', COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, 'spider', jest.fn(), COUNTRY_CODE, undefined); // Then one personal detail should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -2019,9 +2077,9 @@ describe('OptionsListUtils', () => { it('should return latest lastVisibleActionCreated item on top when search value matches multiple items (getSearchOptions)', () => { // Given a set of options - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, translate: jest.fn()}); // When we call filterAndOrderOptions with a search value that matches multiple items - const filteredOptions = filterAndOrderOptions(options, 'fantastic', COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, 'fantastic', jest.fn(), COUNTRY_CODE, undefined); // Then only three reports should be returned expect(filteredOptions.recentReports.length).toBe(3); @@ -2034,11 +2092,11 @@ describe('OptionsListUtils', () => { .then(() => Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, PERSONAL_DETAILS_WITH_PERIODS)) .then(() => { // Given a set of options with periods - const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, undefined, REPORTS) as OptionList; + const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, undefined, jest.fn(), REPORTS) as OptionList; // When we call getSearchOptions - const results = getSearchOptions({options: OPTIONS_WITH_PERIODS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined}); + const results = getSearchOptions({options: OPTIONS_WITH_PERIODS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, translate: jest.fn()}); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredResults = filterAndOrderOptions(results, 'barry.allen@expensify.com', COUNTRY_CODE, undefined, {sortByReportTypeInSearch: true}); + const filteredResults = filterAndOrderOptions(results, 'barry.allen@expensify.com', jest.fn(), COUNTRY_CODE, {sortByReportTypeInSearch: true}); // Then only one report should be returned expect(filteredResults.recentReports.length).toBe(1); @@ -2054,9 +2112,9 @@ describe('OptionsListUtils', () => { OPTIONS.personalDetails = OPTIONS.personalDetails.flatMap((obj) => [obj, {...obj}]); // Given a set of options - const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); + const options = getSearchOptions({options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined, translate: jest.fn()}); // When we call filterAndOrderOptions with a an empty search value - const filteredOptions = filterAndOrderOptions(options, '', COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, '', jest.fn(), COUNTRY_CODE, undefined); const matchingEntries = filteredOptions.personalDetails.filter((detail) => detail.login === login); // Then there should be 2 unique login entries @@ -2067,12 +2125,19 @@ describe('OptionsListUtils', () => { it('should order self dm always on top if the search matches with the self dm login', () => { const searchTerm = 'tonystark@expensify.com'; - const OPTIONS_WITH_SELF_DM = createOptionList(PERSONAL_DETAILS, undefined, REPORTS_WITH_SELF_DM); + const OPTIONS_WITH_SELF_DM = createOptionList(PERSONAL_DETAILS, undefined, jest.fn(), REPORTS_WITH_SELF_DM); // Given a set of options with self dm and all betas - const options = getSearchOptions({options: OPTIONS_WITH_SELF_DM, draftComments: {}, nvpDismissedProductTraining, betas: [CONST.BETAS.ALL], policyTags: undefined}); + const options = getSearchOptions({ + options: OPTIONS_WITH_SELF_DM, + draftComments: {}, + nvpDismissedProductTraining, + betas: [CONST.BETAS.ALL], + policyTags: undefined, + translate: jest.fn(), + }); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchTerm, COUNTRY_CODE, undefined); + const filteredOptions = filterAndOrderOptions(options, searchTerm, jest.fn(), COUNTRY_CODE); // Then the self dm should be on top. expect(filteredOptions.recentReports.at(0)?.isSelfDM).toBe(true); @@ -2119,7 +2184,7 @@ describe('OptionsListUtils', () => { renderLocaleContextProvider(); // Given a set of reports and personal details // When we call createOptionList and extract the reports - const reports = createOptionList(PERSONAL_DETAILS, undefined, REPORTS).reports; + const reports = createOptionList(PERSONAL_DETAILS, undefined, jest.fn(), REPORTS).reports; // Then the returned reports should match the expected values expect(reports.at(10)?.subtitle).toBe(`Submits to Mister Fantastic`); @@ -2130,7 +2195,7 @@ describe('OptionsListUtils', () => { .then(() => Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, CONST.LOCALES.ES)) .then(() => { // When we call createOptionList again - const newReports = createOptionList(PERSONAL_DETAILS, undefined, REPORTS).reports; + const newReports = createOptionList(PERSONAL_DETAILS, undefined, jest.fn(), REPORTS).reports; // Then the returned reports should change to Spanish // cspell:disable-next-line expect(newReports.at(10)?.subtitle).toBe('Se envía a Mister Fantastic'); @@ -2210,7 +2275,7 @@ describe('OptionsListUtils', () => { }, }); // When we call createOptionList - const reports = createOptionList(PERSONAL_DETAILS, undefined, REPORTS).reports; + const reports = createOptionList(PERSONAL_DETAILS, undefined, jest.fn(), REPORTS).reports; const archivedReport = reports.find((report) => report.reportID === '10'); // Then the returned report should contain default archived reason @@ -2607,7 +2672,7 @@ describe('OptionsListUtils', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, transaction); await waitForBatchedUpdates(); - const result = createOption([1, 2], PERSONAL_DETAILS, report, CONST.POLICY.DEFAULT_TAG_LIST, {showChatPreviewLine: true}); + const result = createOption([1, 2], PERSONAL_DETAILS, report, jest.fn(), CONST.POLICY.DEFAULT_TAG_LIST, {showChatPreviewLine: true}); expect(result.alternateText).toBe('Iron Man owes ₫34'); }); @@ -2664,7 +2729,7 @@ describe('OptionsListUtils', () => { [iouAction.reportActionID]: iouAction, }); await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, transaction); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined, translate: jest.fn()}); const reportPreviewMessage = getReportPreviewMessage(iouReport, iouAction, true, false, null, true, reportPreviewAction); const expected = formatReportLastMessageText(Parser.htmlToText(reportPreviewMessage)); expect(lastMessage).toBe(expected); @@ -2691,7 +2756,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [movedTransactionAction.reportActionID]: movedTransactionAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined, translate: jest.fn()}); expect(lastMessage).toBe(Parser.htmlToText(getMovedTransactionMessage(movedTransactionAction))); }); describe('SUBMITTED action', () => { @@ -2709,7 +2774,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [submittedAction.reportActionID]: submittedAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined, translate: jest.fn()}); expect(lastMessage).toBe(Parser.htmlToText(translate(CONST.LOCALES.EN, 'iou.automaticallySubmitted'))); }); }); @@ -2728,7 +2793,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [approvedAction.reportActionID]: approvedAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined, translate: jest.fn()}); expect(lastMessage).toBe(Parser.htmlToText(translate(CONST.LOCALES.EN, 'iou.automaticallyApproved'))); }); }); @@ -2747,7 +2812,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [forwardedAction.reportActionID]: forwardedAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined, translate: jest.fn()}); expect(lastMessage).toBe(Parser.htmlToText(translate(CONST.LOCALES.EN, 'iou.automaticallyForwarded'))); }); }); @@ -2763,7 +2828,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [corporateForceUpgradeAction.reportActionID]: corporateForceUpgradeAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined, translate: jest.fn()}); expect(lastMessage).toBe(Parser.htmlToText(translate(CONST.LOCALES.EN, 'workspaceActions.forcedCorporateUpgrade'))); }); }); @@ -2778,7 +2843,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [takeControlAction.reportActionID]: takeControlAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined, translate: jest.fn()}); expect(lastMessage).toBe(Parser.htmlToText(getChangedApproverActionMessage(takeControlAction))); }); it('REROUTE action', async () => { @@ -2792,7 +2857,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [rerouteAction.reportActionID]: rerouteAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined, translate: jest.fn()}); expect(lastMessage).toBe(Parser.htmlToText(getChangedApproverActionMessage(rerouteAction))); }); it('MOVED action', async () => { @@ -2806,7 +2871,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [movedAction.reportActionID]: movedAction, }); - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined, translate: jest.fn()}); expect(lastMessage).toBe(Parser.htmlToText(getMovedActionMessage(movedAction, report))); }); it('should return last visible message text when last action is hidden (e.g. whisper)', async () => { @@ -2828,6 +2893,8 @@ describe('OptionsListUtils', () => { report, lastActorDetails: null, isReportArchived: false, + translate: jest.fn(), + policyTags: {}, }); expect(result).toBe(expectedVisibleText); }); diff --git a/tests/unit/SidebarUtilsTest.ts b/tests/unit/SidebarUtilsTest.ts index 20081ea99bd2a..2bdc85d2bce01 100644 --- a/tests/unit/SidebarUtilsTest.ts +++ b/tests/unit/SidebarUtilsTest.ts @@ -356,6 +356,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); const optionDataUnpinned = SidebarUtils.getOptionData({ report: MOCK_REPORT_UNPINNED, @@ -371,6 +372,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); expect(optionDataPinned?.isPinned).toBe(true); @@ -1172,6 +1174,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); // Then the alternate text should be equal to the message of the last action prepended with the last actor display name. @@ -1233,6 +1236,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); // Then the alternate text should be equal to the message of the last action prepended with the last actor display name. @@ -1297,6 +1301,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); // Then the alternate text should show @Hidden. @@ -1346,6 +1351,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); expect(optionData?.alternateText).toBe(`test message`); @@ -1386,6 +1392,7 @@ describe('SidebarUtils', () => { isReportArchived: true, lastActionReport: undefined, policyTags: undefined, + translate: jest.fn(), }); expect(optionData?.alternateText).toBe(`test message`); @@ -1423,6 +1430,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); expect(optionData?.alternateText).toBe(`test message`); @@ -1549,6 +1557,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); expect(optionData?.alternateText).toBe(formatReportLastMessageText(iouReport.reportName)); @@ -1591,6 +1600,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); expect(optionData?.alternateText).toBe(`${policy.name} ${CONST.DOT_SEPARATOR} test message`); @@ -1662,6 +1672,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); // Then the alternate text should be equal to the message of the last action prepended with the last actor display name. @@ -1722,6 +1733,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); expect(result?.alternateText).toBe(`You: moved this report to the Three's Workspace workspace`); @@ -1794,11 +1806,10 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); - expect(result?.alternateText).toBe(`You: ${getReportActionMessageText(lastAction)}`); }); - it('uses the 2nd-last visible message as alternateText when the latest action is a deleted IOU', async () => { const MOCK_REPORT: Report = { reportID: '1', @@ -1912,6 +1923,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); expect(result?.alternateText).toContain(`${getReportActionMessageText(lastAction)}`); @@ -1996,6 +2008,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); expect(result?.alternateText).toBe(`One: submitted`); @@ -2093,6 +2106,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); const reportPreviewMessage = getReportPreviewMessage(iouReport, iouAction, true, true, null, true, lastReportPreviewAction); @@ -2191,6 +2205,7 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, + translate: jest.fn(), }); const reportPreviewMessage = getReportPreviewMessage(iouReport, iouAction, true, true, null, true, lastReportPreviewAction); From e1a9f97f212ffc78b3bcb7e4a9207b5a4c7d0155 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 22 Dec 2025 16:18:56 +0100 Subject: [PATCH 17/39] fix tests --- tests/unit/OptionsListUtilsTest.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index 924124a5cb472..67804e365eca7 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -2024,10 +2024,12 @@ describe('OptionsListUtils', () => { it('should not return userToInvite for plain text name when shouldAcceptName is false', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, {includeUserToInvite: true}); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { + includeUserToInvite: true, + }); // When we call filterAndOrderOptions with a plain text name (not email or phone) without shouldAcceptName - const filteredOptions = filterAndOrderOptions(options, 'Jeff Amazon', COUNTRY_CODE, {shouldAcceptName: false}); + const filteredOptions = filterAndOrderOptions(options, 'Jeff Amazon', jest.fn(), COUNTRY_CODE, {shouldAcceptName: false}); // Then userToInvite should be null since plain names are not accepted by default expect(filteredOptions?.userToInvite).toBe(null); @@ -2035,10 +2037,12 @@ describe('OptionsListUtils', () => { it('should return userToInvite for plain text name when shouldAcceptName is true', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, {includeUserToInvite: true}); + const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, {}, nvpDismissedProductTraining, undefined, jest.fn(), { + includeUserToInvite: true, + }); // When we call filterAndOrderOptions with a plain text name (not email or phone) with shouldAcceptName - const filteredOptions = filterAndOrderOptions(options, 'Jeff', COUNTRY_CODE, {shouldAcceptName: true}); + const filteredOptions = filterAndOrderOptions(options, 'Jeff', jest.fn(), COUNTRY_CODE, {shouldAcceptName: true}); // Then userToInvite should be returned for the plain name expect(filteredOptions?.userToInvite?.text).toBe('jeff'); @@ -2911,7 +2915,7 @@ describe('OptionsListUtils', () => { }); // When getting the last message text for the report - const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false}); + const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false, policyTags: undefined, translate: jest.fn()}); // Then it should return the DYNAMIC_EXTERNAL_WORKFLOW_ROUTED message expect(lastMessage).toBe(Parser.htmlToText(getDynamicExternalWorkflowRoutedMessage(action, translateLocal))); From a7ed0f66842be0055a65b53f4005524db978b756 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 29 Dec 2025 12:28:11 +0100 Subject: [PATCH 18/39] fix lint --- .../LHNOptionsList/OptionRowLHNData.tsx | 3 --- src/libs/OptionsListUtils/types.ts | 2 +- src/libs/SidebarUtils.ts | 2 -- tests/perf-test/SidebarUtils.perf-test.ts | 1 - tests/unit/SidebarUtilsTest.ts | 17 ----------------- 5 files changed, 1 insertion(+), 24 deletions(-) diff --git a/src/components/LHNOptionsList/OptionRowLHNData.tsx b/src/components/LHNOptionsList/OptionRowLHNData.tsx index f3335b132a0da..44dce661d17ec 100644 --- a/src/components/LHNOptionsList/OptionRowLHNData.tsx +++ b/src/components/LHNOptionsList/OptionRowLHNData.tsx @@ -2,7 +2,6 @@ import {deepEqual} from 'fast-equals'; import React, {useMemo, useRef} from 'react'; import useCurrentReportID from '@hooks/useCurrentReportID'; import useGetExpensifyCardFromReportAction from '@hooks/useGetExpensifyCardFromReportAction'; -import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import usePrevious from '@hooks/usePrevious'; import SidebarUtils from '@libs/SidebarUtils'; @@ -58,12 +57,10 @@ function OptionRowLHNData({ const areReportErrorsEqual = useMemo(() => deepEqual(prevReportErrors, reportAttributes?.reportErrors), [prevReportErrors, reportAttributes?.reportErrors]); const card = useGetExpensifyCardFromReportAction({reportAction: lastAction, policyID: fullReport?.policyID}); - const {translate} = useLocalize(); const optionItem = useMemo(() => { // Note: ideally we'd have this as a dependent selector in onyx! const item = SidebarUtils.getOptionData({ - translate, report: fullReport, reportAttributes, oneTransactionThreadReport, diff --git a/src/libs/OptionsListUtils/types.ts b/src/libs/OptionsListUtils/types.ts index b01dc8a879084..dcd0b99ba8fd2 100644 --- a/src/libs/OptionsListUtils/types.ts +++ b/src/libs/OptionsListUtils/types.ts @@ -1,5 +1,5 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; -import {LocalizedTranslate} from '@components/LocaleContextProvider'; +import type {LocalizedTranslate} from '@components/LocaleContextProvider'; import type {OptionData} from '@libs/ReportUtils'; import type {AvatarSource} from '@libs/UserAvatarUtils'; import type {IOUAction} from '@src/CONST'; diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts index 263783feff500..f2933bb5bbb4f 100644 --- a/src/libs/SidebarUtils.ts +++ b/src/libs/SidebarUtils.ts @@ -646,7 +646,6 @@ function getOptionData({ invoiceReceiverPolicy, card, lastAction, - translate, localeCompare, isReportArchived, lastActionReport, @@ -665,7 +664,6 @@ function getOptionData({ invoiceReceiverPolicy?: OnyxEntry; reportAttributes: OnyxEntry; policyTags: OnyxEntry; - translate: LocalizedTranslate; card: Card | undefined; lastAction: ReportAction | undefined; translate: LocalizedTranslate; diff --git a/tests/perf-test/SidebarUtils.perf-test.ts b/tests/perf-test/SidebarUtils.perf-test.ts index 2870980cdb55b..4ba48caaf5cae 100644 --- a/tests/perf-test/SidebarUtils.perf-test.ts +++ b/tests/perf-test/SidebarUtils.perf-test.ts @@ -91,7 +91,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }), ); }); diff --git a/tests/unit/SidebarUtilsTest.ts b/tests/unit/SidebarUtilsTest.ts index 9a3f17f19f024..984e995e2e1cc 100644 --- a/tests/unit/SidebarUtilsTest.ts +++ b/tests/unit/SidebarUtilsTest.ts @@ -357,7 +357,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); const optionDataUnpinned = SidebarUtils.getOptionData({ report: MOCK_REPORT_UNPINNED, @@ -374,7 +373,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); expect(optionDataPinned?.isPinned).toBe(true); @@ -1177,7 +1175,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); // Then the alternate text should be equal to the message of the last action prepended with the last actor display name. @@ -1240,7 +1237,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); // Then the alternate text should be equal to the message of the last action prepended with the last actor display name. @@ -1306,7 +1302,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); // Then the alternate text should show @Hidden. @@ -1357,7 +1352,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); expect(optionData?.alternateText).toBe(`test message`); @@ -1399,7 +1393,6 @@ describe('SidebarUtils', () => { isReportArchived: true, lastActionReport: undefined, policyTags: undefined, - translate: jest.fn(), }); expect(optionData?.alternateText).toBe(`test message`); @@ -1438,7 +1431,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); expect(optionData?.alternateText).toBe(`test message`); @@ -1566,7 +1558,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); expect(optionData?.alternateText).toBe(formatReportLastMessageText(iouReport.reportName)); @@ -1610,7 +1601,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); expect(optionData?.alternateText).toBe(`${policy.name} ${CONST.DOT_SEPARATOR} test message`); @@ -1683,7 +1673,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); // Then the alternate text should be equal to the message of the last action prepended with the last actor display name. @@ -1745,7 +1734,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); expect(result?.alternateText).toBe(`You: moved this report to the Three's Workspace workspace`); @@ -1819,7 +1807,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); expect(result?.alternateText).toBe(`You: ${getReportActionMessageText(lastAction)}`); }); @@ -1937,7 +1924,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); expect(result?.alternateText).toContain(`${getReportActionMessageText(lastAction)}`); @@ -2024,7 +2010,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); expect(result?.alternateText).toBe(`One: submitted`); @@ -2123,7 +2108,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); const reportPreviewMessage = getReportPreviewMessage(iouReport, iouAction, true, true, null, true, lastReportPreviewAction); @@ -2223,7 +2207,6 @@ describe('SidebarUtils', () => { lastActionReport: undefined, isReportArchived: undefined, policyTags: undefined, - translate: jest.fn(), }); const reportPreviewMessage = getReportPreviewMessage(iouReport, iouAction, true, true, null, true, lastReportPreviewAction); From f444620da8e00ebadded4d277b63a2d77faee4a8 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Wed, 7 Jan 2026 11:53:09 +0100 Subject: [PATCH 19/39] fix lint --- src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 1 - src/pages/iou/request/step/IOURequestStepScan/index.native.tsx | 1 + src/pages/iou/request/step/IOURequestStepScan/index.tsx | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index c2415b548eba6..03bdf4f3920f7 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -1135,7 +1135,6 @@ function IOURequestStepConfirmation({ trackExpense, userLocation, submitPerDiemExpense, - policyRecentlyUsedCurrencies, ], ); diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index c9d69f7894474..facc7dd822ccc 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -791,6 +791,7 @@ function IOURequestStepScan({ cameraPermissionStatus, didCapturePhoto, isMultiScanEnabled, + askForPermissions, translate, showBlink, flash, diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index 4164f881b2cc5..2b9ba320de59a 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -621,7 +621,6 @@ function IOURequestStepScan({ policy, personalPolicy?.autoReporting, selfDMReportID, - policyRecentlyUsedCurrencies, ], ); From 11c05583e188cc2d35bc3bedca366b80f5c50b19 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Wed, 7 Jan 2026 12:06:04 +0100 Subject: [PATCH 20/39] fix lint --- src/components/LHNOptionsList/LHNOptionsList.tsx | 1 - src/libs/OptionsListUtils/index.ts | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/components/LHNOptionsList/LHNOptionsList.tsx b/src/components/LHNOptionsList/LHNOptionsList.tsx index 9dbf37b281623..b776f1d59cf58 100644 --- a/src/components/LHNOptionsList/LHNOptionsList.tsx +++ b/src/components/LHNOptionsList/LHNOptionsList.tsx @@ -239,7 +239,6 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio policy: itemPolicy, isReportArchived: !!itemReportNameValuePairs?.private_isArchived, policyTags: itemPolicyTags, - policyForMovingExpensesID, reportMetadata: itemReportMetadata, }); diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index 920db85604a49..3e8ff896cb45c 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -600,7 +600,6 @@ function getLastMessageTextForReport({ isReportArchived = false, policyTags, translate, - policyForMovingExpensesID, reportMetadata, }: { report: OnyxEntry; @@ -611,7 +610,6 @@ function getLastMessageTextForReport({ isReportArchived?: boolean; policyTags: OnyxEntry; translate: LocalizedTranslate; - policyForMovingExpensesID?: string; reportMetadata?: OnyxEntry; }): string { const reportID = report?.reportID; From ba16aadda3e2a92b34652c2aa14a1870859a37b3 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Thu, 15 Jan 2026 10:18:09 +0100 Subject: [PATCH 21/39] fix ts --- .../step/IOURequestStepDistanceOdometer.tsx | 3 ++- tests/unit/OptionsListUtilsTest.tsx | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx index a40afc8e479d1..4b50edbb2861c 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx @@ -105,6 +105,7 @@ function IOURequestStepDistanceOdometer({ const [skipConfirmation] = useOnyx(`${ONYXKEYS.COLLECTION.SKIP_CONFIRMATION}${transactionID}`, {canBeMissing: true}); const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {canBeMissing: true}); const policy = usePolicy(report?.policyID); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: false}); const personalPolicy = usePersonalPolicy(); const defaultExpensePolicy = useDefaultExpensePolicy(); @@ -360,7 +361,7 @@ function IOURequestStepDistanceOdometer({ const derivedReports = (reportAttributesDerived as ReportAttributesDerivedValue | undefined)?.reports; const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policy, derivedReports); + return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant, policyTags, translate, policy, derivedReports); }); if (shouldSkipConfirmation) { diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index b42bd1addc4e4..8664a1adaff0e 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -3195,7 +3195,7 @@ describe('OptionsListUtils', () => { isPolicyExpenseChat: true, }; - const option = getReportOption(participant, policy); + const option = getReportOption(participant, undefined, jest.fn(), policy, undefined); expect(option.text).toBe('Test Workspace'); expect(option.alternateText).toBe(translateLocal('workspace.common.workspace')); @@ -3250,7 +3250,7 @@ describe('OptionsListUtils', () => { isPolicyExpenseChat: true, }; - const option = getReportOption(participant, policy); + const option = getReportOption(participant, undefined, jest.fn(), policy, undefined); expect(option.text).toBe('Test Workspace with Submit'); // The submitsTo logic may or may not apply depending on complex approval rules @@ -3273,7 +3273,7 @@ describe('OptionsListUtils', () => { reportID, }; - const option = getReportOption(participant, undefined); + const option = getReportOption(participant, undefined, jest.fn(), undefined, undefined); expect(option.isDisabled).toBe(true); }); @@ -3309,7 +3309,7 @@ describe('OptionsListUtils', () => { isSelfDM: true, }; - const option = getReportOption(participant, undefined); + const option = getReportOption(participant, undefined, jest.fn(), undefined, undefined); // The option.isSelfDM is set by createOption based on the report type // Just verify the alternateText is correct for self DM @@ -3344,7 +3344,7 @@ describe('OptionsListUtils', () => { isInvoiceRoom: true, }; - const option = getReportOption(participant, undefined); + const option = getReportOption(participant, undefined, jest.fn(), undefined, undefined); expect(option.isInvoiceRoom).toBe(true); expect(option.alternateText).toBe(translateLocal('workspace.common.invoices')); @@ -3366,7 +3366,7 @@ describe('OptionsListUtils', () => { selected: true, }; - const option = getReportOption(participant, undefined); + const option = getReportOption(participant, undefined, jest.fn(), undefined, undefined); expect(option.isSelected).toBe(true); expect(option.selected).toBe(true); @@ -3387,7 +3387,7 @@ describe('OptionsListUtils', () => { reportID, }; - const option = getReportOption(participant, undefined); + const option = getReportOption(participant, undefined, jest.fn(), undefined, undefined); expect(option).toBeDefined(); expect(option.text).toBeDefined(); @@ -3409,7 +3409,7 @@ describe('OptionsListUtils', () => { }; // Test that the function works with reportAttributesDerived parameter (optional) - const option = getReportOption(participant, undefined, undefined); + const option = getReportOption(participant, undefined, jest.fn(), undefined, undefined); expect(option).toBeDefined(); }); @@ -3420,6 +3420,7 @@ describe('OptionsListUtils', () => { const result = getUserToInviteOption({ searchValue: 'Jeff Amazon', loginList: {}, + translate: jest.fn(), }); expect(result).toBeNull(); }); @@ -3429,6 +3430,7 @@ describe('OptionsListUtils', () => { searchValue: 'Jeff Amazon', shouldAcceptName: true, loginList: {}, + translate: jest.fn(), }); expect(result).not.toBeNull(); expect(result?.login).toBe('Jeff Amazon'); From 5e9a695c51452f16676052640c1f2a5c74bae9b6 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 19 Jan 2026 10:57:09 +0100 Subject: [PATCH 22/39] fix reassure tests --- tests/perf-test/SearchRouter.perf-test.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/perf-test/SearchRouter.perf-test.tsx b/tests/perf-test/SearchRouter.perf-test.tsx index 22e8bfcd0562d..0675adfa8b50b 100644 --- a/tests/perf-test/SearchRouter.perf-test.tsx +++ b/tests/perf-test/SearchRouter.perf-test.tsx @@ -45,6 +45,13 @@ jest.mock('@src/libs/Navigation/Navigation', () => ({ jest.mock('@src/hooks/useRootNavigationState'); +// Mock useLazyAsset hook to prevent async loading causing extra renders +jest.mock('@hooks/useLazyAsset', () => ({ + useMemoizedLazyExpensifyIcons: jest.fn(() => ({ + MagnifyingGlass: 'MagnifyingGlass', + })), +})); + jest.mock('@react-navigation/native', () => { const actualNav = jest.requireActual('@react-navigation/native'); return { From 0f70126bdc68d10c9318746d79735e43b838c104 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 19 Jan 2026 11:27:50 +0100 Subject: [PATCH 23/39] fix reassure test --- tests/perf-test/SearchRouter.perf-test.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/perf-test/SearchRouter.perf-test.tsx b/tests/perf-test/SearchRouter.perf-test.tsx index 0675adfa8b50b..316af7e4056ba 100644 --- a/tests/perf-test/SearchRouter.perf-test.tsx +++ b/tests/perf-test/SearchRouter.perf-test.tsx @@ -43,12 +43,17 @@ jest.mock('@src/libs/Navigation/Navigation', () => ({ isDisplayedInModal: jest.fn(() => false), })); -jest.mock('@src/hooks/useRootNavigationState'); +// Mock useRootNavigationState to return a stable value +jest.mock('@src/hooks/useRootNavigationState', () => { + return jest.fn(() => undefined); +}); // Mock useLazyAsset hook to prevent async loading causing extra renders +// Must include all icons used by SearchRouter and its children (SearchAutocompleteList) jest.mock('@hooks/useLazyAsset', () => ({ useMemoizedLazyExpensifyIcons: jest.fn(() => ({ MagnifyingGlass: 'MagnifyingGlass', + History: 'History', })), })); From 9ceca269abbe5c8aadd01d3e15d1703fecb081b2 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Wed, 21 Jan 2026 14:20:25 +0100 Subject: [PATCH 24/39] format --- src/hooks/useSearchSelector.base.ts | 31 +- src/libs/OptionsListUtils/index.ts | 69 ++- src/libs/actions/IOU/MoneyRequest.ts | 5 +- src/pages/Share/ShareDetailsPage.tsx | 2 +- .../iou/request/step/IOURequestStepAmount.tsx | 4 +- .../step/IOURequestStepConfirmation.tsx | 23 +- .../request/step/IOURequestStepDistance.tsx | 57 +- .../step/IOURequestStepDistanceManual.tsx | 36 +- .../step/IOURequestStepDistanceMap.tsx | 57 +- .../step/IOURequestStepDistanceOdometer.tsx | 2 +- .../step/IOURequestStepScan/index.native.tsx | 36 +- .../request/step/IOURequestStepScan/index.tsx | 36 +- tests/perf-test/OptionsListUtils.perf-test.ts | 2 +- tests/unit/OptionsListUtilsTest.tsx | 528 +++++++++++++----- 14 files changed, 703 insertions(+), 185 deletions(-) diff --git a/src/hooks/useSearchSelector.base.ts b/src/hooks/useSearchSelector.base.ts index ee6d9f80e1d1b..a1ed8305ac343 100644 --- a/src/hooks/useSearchSelector.base.ts +++ b/src/hooks/useSearchSelector.base.ts @@ -203,7 +203,7 @@ function useSearchSelectorBase({ policyTags, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_MEMBER_INVITE: - return getValidOptions(optionsWithContacts,allPolicies, draftComments, nvpDismissedProductTraining, policyTags, translate, loginList, { + return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, policyTags, translate, loginList, { betas: betas ?? [], includeP2P: true, includeSelectedOptions: false, @@ -215,7 +215,7 @@ function useSearchSelectorBase({ includeUserToInvite, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_GENERAL: - return getValidOptions(optionsWithContacts, allPolicies,draftComments, nvpDismissedProductTraining, policyTags, translate, loginList, { + return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, policyTags, translate, loginList, { ...getValidOptionsConfig, betas: betas ?? [], searchString: computedSearchTerm, @@ -249,7 +249,7 @@ function useSearchSelectorBase({ countryCode, ); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_SHARE_DESTINATION: - return getValidOptions(optionsWithContacts, allPolicies,draftComments, nvpDismissedProductTraining, policyTags, translate, loginList, { + return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, policyTags, translate, loginList, { betas, selectedOptions, includeMultipleParticipantReports: true, @@ -267,7 +267,7 @@ function useSearchSelectorBase({ includeUserToInvite, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_ATTENDEES: - return getValidOptions(optionsWithContacts, allPolicies,draftComments, nvpDismissedProductTraining, policyTags, translate, loginList, { + return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, policyTags, translate, loginList, { ...getValidOptionsConfig, betas: betas ?? [], includeP2P: true, @@ -285,7 +285,28 @@ function useSearchSelectorBase({ default: return getEmptyOptions(); } - }, [areOptionsInitialized, searchContext, translate, optionsWithContacts, draftComments, nvpDismissedProductTraining, betas, computedSearchTerm, maxResults, includeUserToInvite, countryCode, loginList, policyTags, allPolicies, excludeLogins, includeRecentReports, maxRecentReportsToShow, getValidOptionsConfig, selectedOptions, includeCurrentUser]); + }, [ + areOptionsInitialized, + searchContext, + translate, + optionsWithContacts, + draftComments, + nvpDismissedProductTraining, + betas, + computedSearchTerm, + maxResults, + includeUserToInvite, + countryCode, + loginList, + policyTags, + allPolicies, + excludeLogins, + includeRecentReports, + maxRecentReportsToShow, + getValidOptionsConfig, + selectedOptions, + includeCurrentUser, + ]); const isOptionSelected = useMemo(() => { return (option: OptionData) => diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index 629e50b871080..d775d21b6726e 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -479,7 +479,8 @@ function getAlternateText( const isExpenseThread = isMoneyRequest(report); const formattedLastMessageText = // eslint-disable-next-line @typescript-eslint/no-deprecated - formatReportLastMessageText(Parser.htmlToText(option.lastMessageText ?? '')) || getLastMessageTextForReport({translate: translateLocal, report, lastActorDetails, isReportArchived, policyTags}); + formatReportLastMessageText(Parser.htmlToText(option.lastMessageText ?? '')) || + getLastMessageTextForReport({translate: translateLocal, report, lastActorDetails, isReportArchived, policyTags}); const reportPrefix = getReportSubtitlePrefix(report); const formattedLastMessageTextWithPrefix = reportPrefix + formattedLastMessageText; @@ -2036,7 +2037,12 @@ function isValidReport(option: SearchOption, policy: OnyxEntry, * @param config - Configuration object specifying display preferences and filtering criteria * @returns Array of enriched and filtered report options ready for UI display */ -function prepareReportOptionsForDisplay(options: Array>, policiesCollection: OnyxCollection, config: GetValidReportsConfig, policyTags: OnyxCollection): Array> { +function prepareReportOptionsForDisplay( + options: Array>, + policiesCollection: OnyxCollection, + config: GetValidReportsConfig, + policyTags: OnyxCollection, +): Array> { const { showChatPreviewLine = false, forcePolicyNamePreview = false, @@ -2275,7 +2281,28 @@ function getValidOptions( [selfDMChats, workspaceChats, recentReportOptions] = optionsOrderAndGroupBy([isSelfDMChat, isWorkspaceChat], options.reports, recentReportComparator, maxElements, filteringFunction); if (selfDMChats.length > 0) { - selfDMChat = prepareReportOptionsForDisplay(selfDMChats, policiesCollection, { + selfDMChat = prepareReportOptionsForDisplay( + selfDMChats, + policiesCollection, + { + ...getValidReportsConfig, + selectedOptions, + shouldBoldTitleByDefault, + shouldSeparateSelfDMChat, + shouldSeparateWorkspaceChat, + shouldShowGBR, + }, + policyTags, + ).at(0); + } + + if (maxRecentReportElements) { + recentReportOptions = recentReportOptions.splice(0, maxRecentReportElements); + } + recentReportOptions = prepareReportOptionsForDisplay( + recentReportOptions, + policiesCollection, + { ...getValidReportsConfig, selectedOptions, shouldBoldTitleByDefault, @@ -2284,29 +2311,21 @@ function getValidOptions( shouldShowGBR, }, policyTags, - ).at(0); - } + ); - if (maxRecentReportElements) { - recentReportOptions = recentReportOptions.splice(0, maxRecentReportElements); - } - recentReportOptions = prepareReportOptionsForDisplay(recentReportOptions, policiesCollection, { - ...getValidReportsConfig, - selectedOptions, - shouldBoldTitleByDefault, - shouldSeparateSelfDMChat, - shouldSeparateWorkspaceChat, - shouldShowGBR, - }, policyTags); - - workspaceChats = prepareReportOptionsForDisplay(workspaceChats, policiesCollection, { - ...getValidReportsConfig, - selectedOptions, - shouldBoldTitleByDefault, - shouldSeparateSelfDMChat, - shouldSeparateWorkspaceChat, - shouldShowGBR, - }, policyTags); + workspaceChats = prepareReportOptionsForDisplay( + workspaceChats, + policiesCollection, + { + ...getValidReportsConfig, + selectedOptions, + shouldBoldTitleByDefault, + shouldSeparateSelfDMChat, + shouldSeparateWorkspaceChat, + shouldShowGBR, + }, + policyTags, + ); } else if (recentAttendees && recentAttendees?.length > 0) { recentAttendees.filter((attendee) => { const login = attendee.login ?? attendee.displayName; diff --git a/src/libs/actions/IOU/MoneyRequest.ts b/src/libs/actions/IOU/MoneyRequest.ts index 7eb0b674e08d1..a04c1b7e5ad6e 100644 --- a/src/libs/actions/IOU/MoneyRequest.ts +++ b/src/libs/actions/IOU/MoneyRequest.ts @@ -37,7 +37,6 @@ import { trackExpense, } from './index'; - type CreateTransactionParams = { transactions: Transaction[]; iouType: string; @@ -299,7 +298,7 @@ function handleMoneyRequestStepScanParticipants({ // to the confirmation step. // If the user is started this flow using the Create expense option (combined submit/track flow), they should be redirected to the participants page. if (!initialTransaction?.isFromGlobalCreate && !isArchivedExpenseReport && iouType !== CONST.IOU.TYPE.CREATE) { - const participants = getMoneyRequestParticipantOptions(currentUserAccountID, report, policy, personalDetails,policyTags,privateIsArchived, reportAttributesDerived); + const participants = getMoneyRequestParticipantOptions(currentUserAccountID, report, policy, personalDetails, policyTags, privateIsArchived, reportAttributesDerived); if (shouldSkipConfirmation) { const firstReceiptFile = files.at(0); @@ -507,7 +506,7 @@ function handleMoneyRequestStepDistanceNavigation({ // to the confirm step. // If the user started this flow using the Create expense option (combined submit/track flow), they should be redirected to the participants page. if (report?.reportID && !isArchivedExpenseReport && iouType !== CONST.IOU.TYPE.CREATE) { - const participants = getMoneyRequestParticipantOptions(currentUserAccountID, report, policy, personalDetails, policyTags,privateIsArchived, reportAttributesDerived); + const participants = getMoneyRequestParticipantOptions(currentUserAccountID, report, policy, personalDetails, policyTags, privateIsArchived, reportAttributesDerived); setDistanceRequestData?.(participants); if (shouldSkipConfirmation) { diff --git a/src/pages/Share/ShareDetailsPage.tsx b/src/pages/Share/ShareDetailsPage.tsx index 3c8c8884d05b8..20ee38616cf4a 100644 --- a/src/pages/Share/ShareDetailsPage.tsx +++ b/src/pages/Share/ShareDetailsPage.tsx @@ -67,7 +67,7 @@ function ShareDetailsPage({route}: ShareDetailsPageProps) { const privateIsArchived = privateIsArchivedMap[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`]; const ancestors = useAncestors(report); const displayReport = useMemo( - () => getReportDisplayOption(report, unknownUserDetails, policyTags,privateIsArchived, reportAttributesDerived), + () => getReportDisplayOption(report, unknownUserDetails, policyTags, privateIsArchived, reportAttributesDerived), [report, unknownUserDetails, policyTags, privateIsArchived, reportAttributesDerived], ); diff --git a/src/pages/iou/request/step/IOURequestStepAmount.tsx b/src/pages/iou/request/step/IOURequestStepAmount.tsx index 1a82d264e903c..eea62cd39021f 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.tsx +++ b/src/pages/iou/request/step/IOURequestStepAmount.tsx @@ -200,7 +200,9 @@ function IOURequestStepAmount({ const participants = selectedParticipants.map((participant) => { const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; const privateIsArchived = privateIsArchivedMap[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${participant.reportID}`]; - return participantAccountID ? getParticipantsOption(participant, personalDetails) : getReportOption(participant,policyTags, privateIsArchived, policy, reportAttributesDerived); + return participantAccountID + ? getParticipantsOption(participant, personalDetails) + : getReportOption(participant, policyTags, privateIsArchived, policy, reportAttributesDerived); }); const backendAmount = convertToBackendAmount(Number.parseFloat(amount)); diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index a88d42fcbd9d7..e20b94d28a40e 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -799,7 +799,28 @@ function IOURequestStepConfirmation({ }); } }, - [transactions, report, isDraftPolicy, action, currentUserPersonalDetails.login, currentUserPersonalDetails.accountID, policy, policyCategories, policyTags, isManualDistanceRequest, receiptFiles, transactionTaxCode, transactionTaxAmount, customUnitRateID, isOdometerDistanceRequest, privateIsArchivedMap, isASAPSubmitBetaEnabled, introSelected, activePolicyID, quickAction], + [ + transactions, + report, + isDraftPolicy, + action, + currentUserPersonalDetails.login, + currentUserPersonalDetails.accountID, + policy, + policyCategories, + policyTags, + isManualDistanceRequest, + receiptFiles, + transactionTaxCode, + transactionTaxAmount, + customUnitRateID, + isOdometerDistanceRequest, + privateIsArchivedMap, + isASAPSubmitBetaEnabled, + introSelected, + activePolicyID, + quickAction, + ], ); const createDistanceRequest = useCallback( diff --git a/src/pages/iou/request/step/IOURequestStepDistance.tsx b/src/pages/iou/request/step/IOURequestStepDistance.tsx index 278752772b1be..8911cb4e05c57 100644 --- a/src/pages/iou/request/step/IOURequestStepDistance.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistance.tsx @@ -312,7 +312,37 @@ function IOURequestStepDistance({ privateIsArchived: reportNameValuePairs?.private_isArchived, policyTags, }); - }, [iouType, report, policy, transaction, reportID, transactionID, reportAttributesDerived, personalDetails, waypoints, customUnitRateID, currentUserEmailParam, currentUserAccountIDParam, backTo, backToReport, shouldSkipConfirmation, defaultExpensePolicy, isArchived, personalPolicy?.autoReporting, isASAPSubmitBetaEnabled, transactionViolations, lastSelectedDistanceRates, setDistanceRequestData, translate, quickAction, policyRecentlyUsedCurrencies, introSelected, activePolicyID, reportNameValuePairs?.private_isArchived, policyTags]); + }, [ + iouType, + report, + policy, + transaction, + reportID, + transactionID, + reportAttributesDerived, + personalDetails, + waypoints, + customUnitRateID, + currentUserEmailParam, + currentUserAccountIDParam, + backTo, + backToReport, + shouldSkipConfirmation, + defaultExpensePolicy, + isArchived, + personalPolicy?.autoReporting, + isASAPSubmitBetaEnabled, + transactionViolations, + lastSelectedDistanceRates, + setDistanceRequestData, + translate, + quickAction, + policyRecentlyUsedCurrencies, + introSelected, + activePolicyID, + reportNameValuePairs?.private_isArchived, + policyTags, + ]); const getError = () => { // Get route error if available else show the invalid number of waypoints error. @@ -405,7 +435,30 @@ function IOURequestStepDistance({ } navigateToNextStep(); - }, [duplicateWaypointsError, atLeastTwoDifferentWaypointsError, hasRouteError, isLoadingRoute, isEditing, isLoading, isCreatingNewRequest, navigateToNextStep, transactionBackup, waypoints, transaction?.routes, transaction?.transactionID, report, navigateBack, parentReport, policy, policyTags, policyCategories, currentUserAccountIDParam, currentUserEmailParam, isASAPSubmitBetaEnabled, parentReportNextStep]); + }, [ + duplicateWaypointsError, + atLeastTwoDifferentWaypointsError, + hasRouteError, + isLoadingRoute, + isEditing, + isLoading, + isCreatingNewRequest, + navigateToNextStep, + transactionBackup, + waypoints, + transaction?.routes, + transaction?.transactionID, + report, + navigateBack, + parentReport, + policy, + policyTags, + policyCategories, + currentUserAccountIDParam, + currentUserEmailParam, + isASAPSubmitBetaEnabled, + parentReportNextStep, + ]); const renderItem = useCallback( ({item, drag, isActive, getIndex}: RenderItemParams) => ( diff --git a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx index 0dda83d380b75..a432a2e7ec306 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx @@ -205,7 +205,41 @@ function IOURequestStepDistanceManual({ policyTags, }); }, - [transactionID, isTransactionDraft, action, iouType, report, policy, transaction, reportID, reportAttributesDerived, personalDetails, customUnitRateID, currentUserEmailParam, currentUserAccountIDParam, backTo, backToReport, shouldSkipConfirmation, defaultExpensePolicy, isArchived, personalPolicy?.autoReporting, isASAPSubmitBetaEnabled, transactionViolations, lastSelectedDistanceRates, translate, quickAction, policyRecentlyUsedCurrencies, introSelected, activePolicyID, reportNameValuePairs?.private_isArchived, distance, parentReport, policyTags, policyCategories, parentReportNextStep], + [ + transactionID, + isTransactionDraft, + action, + iouType, + report, + policy, + transaction, + reportID, + reportAttributesDerived, + personalDetails, + customUnitRateID, + currentUserEmailParam, + currentUserAccountIDParam, + backTo, + backToReport, + shouldSkipConfirmation, + defaultExpensePolicy, + isArchived, + personalPolicy?.autoReporting, + isASAPSubmitBetaEnabled, + transactionViolations, + lastSelectedDistanceRates, + translate, + quickAction, + policyRecentlyUsedCurrencies, + introSelected, + activePolicyID, + reportNameValuePairs?.private_isArchived, + distance, + parentReport, + policyTags, + policyCategories, + parentReportNextStep, + ], ); const submitAndNavigateToNextPage = useCallback(() => { diff --git a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx index 1e18f8eac0276..f55b9384df884 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx @@ -313,7 +313,37 @@ function IOURequestStepDistanceMap({ policyTags, privateIsArchived: reportNameValuePairs?.private_isArchived, }); - }, [iouType, report, policy, transaction, reportID, transactionID, reportAttributesDerived, personalDetails, waypoints, customUnitRateID, currentUserEmailParam, currentUserAccountIDParam, backTo, backToReport, shouldSkipConfirmation, defaultExpensePolicy, isArchived, personalPolicy?.autoReporting, isASAPSubmitBetaEnabled, transactionViolations, lastSelectedDistanceRates, setDistanceRequestData, translate, quickAction, policyRecentlyUsedCurrencies, introSelected, activePolicyID, policyTags, reportNameValuePairs?.private_isArchived]); + }, [ + iouType, + report, + policy, + transaction, + reportID, + transactionID, + reportAttributesDerived, + personalDetails, + waypoints, + customUnitRateID, + currentUserEmailParam, + currentUserAccountIDParam, + backTo, + backToReport, + shouldSkipConfirmation, + defaultExpensePolicy, + isArchived, + personalPolicy?.autoReporting, + isASAPSubmitBetaEnabled, + transactionViolations, + lastSelectedDistanceRates, + setDistanceRequestData, + translate, + quickAction, + policyRecentlyUsedCurrencies, + introSelected, + activePolicyID, + policyTags, + reportNameValuePairs?.private_isArchived, + ]); const getError = () => { // Get route error if available else show the invalid number of waypoints error. @@ -406,7 +436,30 @@ function IOURequestStepDistanceMap({ } navigateToNextStep(); - }, [duplicateWaypointsError, atLeastTwoDifferentWaypointsError, hasRouteError, isLoadingRoute, isEditing, isLoading, isCreatingNewRequest, navigateToNextStep, transactionBackup, waypoints, transaction?.routes, transaction?.transactionID, report, navigateBack, parentReport, policy, policyTags, policyCategories, currentUserAccountIDParam, currentUserEmailParam, isASAPSubmitBetaEnabled, parentReportNextStep]); + }, [ + duplicateWaypointsError, + atLeastTwoDifferentWaypointsError, + hasRouteError, + isLoadingRoute, + isEditing, + isLoading, + isCreatingNewRequest, + navigateToNextStep, + transactionBackup, + waypoints, + transaction?.routes, + transaction?.transactionID, + report, + navigateBack, + parentReport, + policy, + policyTags, + policyCategories, + currentUserAccountIDParam, + currentUserEmailParam, + isASAPSubmitBetaEnabled, + parentReportNextStep, + ]); const renderItem = useCallback( ({item, drag, isActive, getIndex}: RenderItemParams) => ( diff --git a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx index caf86e1a489a2..bbcc0d62e67f6 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx @@ -369,7 +369,7 @@ function IOURequestStepDistanceOdometer({ const participantAccountID = participant?.accountID ?? CONST.DEFAULT_NUMBER_ID; return participantAccountID ? getParticipantsOption(participant, personalDetails) - : getReportOption(participant,policyTags, reportNameValuePairs?.private_isArchived, policy, derivedReports); + : getReportOption(participant, policyTags, reportNameValuePairs?.private_isArchived, policy, derivedReports); }); if (shouldSkipConfirmation) { diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index ea906515360af..dd5b7e10def5a 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -118,7 +118,7 @@ function IOURequestStepScan({ const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); - const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: true}) + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: true}); const defaultTaxCode = getDefaultTaxCode(policy, initialTransaction); const transactionTaxCode = (initialTransaction?.taxCode ? initialTransaction?.taxCode : defaultTaxCode) ?? ''; @@ -298,7 +298,39 @@ function IOURequestStepScan({ policyTags, }); }, - [iouType, policy, report, reportID, reportAttributesDerived, transactions, initialTransactionID, initialTransaction?.reportID, initialTransaction?.currency, initialTransaction?.isFromGlobalCreate, initialTransaction?.participants, transactionTaxCode, transactionTaxAmount, personalDetails, currentUserPersonalDetails.login, currentUserPersonalDetails.accountID, backTo, backToReport, shouldSkipConfirmation, defaultExpensePolicy, shouldGenerateTransactionThreadReport, isArchived, personalPolicy?.autoReporting, isASAPSubmitBetaEnabled, transactionViolations, quickAction, policyRecentlyUsedCurrencies, introSelected, activePolicyID, reportNameValuePairs?.private_isArchived, policyTags], + [ + iouType, + policy, + report, + reportID, + reportAttributesDerived, + transactions, + initialTransactionID, + initialTransaction?.reportID, + initialTransaction?.currency, + initialTransaction?.isFromGlobalCreate, + initialTransaction?.participants, + transactionTaxCode, + transactionTaxAmount, + personalDetails, + currentUserPersonalDetails.login, + currentUserPersonalDetails.accountID, + backTo, + backToReport, + shouldSkipConfirmation, + defaultExpensePolicy, + shouldGenerateTransactionThreadReport, + isArchived, + personalPolicy?.autoReporting, + isASAPSubmitBetaEnabled, + transactionViolations, + quickAction, + policyRecentlyUsedCurrencies, + introSelected, + activePolicyID, + reportNameValuePairs?.private_isArchived, + policyTags, + ], ); const updateScanAndNavigate = useCallback( diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index 118c7ec90cb82..64583ddc991e5 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -114,7 +114,7 @@ function IOURequestStepScan({ const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true}); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); - const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: true}) + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: true}); const [optimisticTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, { selector: transactionDraftValuesSelector, @@ -351,7 +351,39 @@ function IOURequestStepScan({ policyTags, }); }, - [iouType, policy, report, reportID, reportAttributesDerived, transactions, initialTransactionID, initialTransaction?.reportID, initialTransaction?.currency, initialTransaction?.isFromGlobalCreate, initialTransaction?.participants, transactionTaxCode, transactionTaxAmount, personalDetails, currentUserPersonalDetails.login, currentUserPersonalDetails.accountID, backTo, backToReport, shouldSkipConfirmation, defaultExpensePolicy, shouldGenerateTransactionThreadReport, isArchived, personalPolicy?.autoReporting, isASAPSubmitBetaEnabled, transactionViolations, quickAction, policyRecentlyUsedCurrencies, introSelected, activePolicyID, reportNameValuePairs?.private_isArchived, policyTags], + [ + iouType, + policy, + report, + reportID, + reportAttributesDerived, + transactions, + initialTransactionID, + initialTransaction?.reportID, + initialTransaction?.currency, + initialTransaction?.isFromGlobalCreate, + initialTransaction?.participants, + transactionTaxCode, + transactionTaxAmount, + personalDetails, + currentUserPersonalDetails.login, + currentUserPersonalDetails.accountID, + backTo, + backToReport, + shouldSkipConfirmation, + defaultExpensePolicy, + shouldGenerateTransactionThreadReport, + isArchived, + personalPolicy?.autoReporting, + isASAPSubmitBetaEnabled, + transactionViolations, + quickAction, + policyRecentlyUsedCurrencies, + introSelected, + activePolicyID, + reportNameValuePairs?.private_isArchived, + policyTags, + ], ); const updateScanAndNavigate = useCallback( diff --git a/tests/perf-test/OptionsListUtils.perf-test.ts b/tests/perf-test/OptionsListUtils.perf-test.ts index a2fe3535da51b..981d892da23a4 100644 --- a/tests/perf-test/OptionsListUtils.perf-test.ts +++ b/tests/perf-test/OptionsListUtils.perf-test.ts @@ -166,7 +166,7 @@ describe('OptionsListUtils', () => { test('[OptionsListUtils] getShareDestinationOptions', async () => { await waitForBatchedUpdates(); await measureFunction(() => - getValidOptions({reports: options.reports, personalDetails: options.personalDetails}, allPolicies, {}, nvpDismissedProductTraining, undefined, jest.fn(),loginList, { + getValidOptions({reports: options.reports, personalDetails: options.personalDetails}, allPolicies, {}, nvpDismissedProductTraining, undefined, jest.fn(), loginList, { betas: mockedBetas, includeMultipleParticipantReports: true, showChatPreviewLine: true, diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index 737b34700cf35..6237ebcf7f103 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -804,7 +804,7 @@ 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, undefined, translateLocal,loginList); + const results = getValidOptions({reports: [], personalDetails: []}, allPolicies, {}, nvpDismissedProductTraining, undefined, translateLocal, loginList); // Then the result should be empty expect(results.personalDetails).toEqual([]); @@ -1024,9 +1024,18 @@ describe('OptionsListUtils', () => { notificationPreference: 'hidden', }; // When we call getValidOptions with includeMultipleParticipantReports set to true - const results = getValidOptions({reports: [adminRoom], personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList, { - includeMultipleParticipantReports: true, - }); + const results = getValidOptions( + {reports: [adminRoom], personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + { + includeMultipleParticipantReports: true, + }, + ); const adminRoomOption = results.recentReports.find((report) => report.reportID === '1455140530846319'); // Then the result should include the admin room @@ -1069,7 +1078,7 @@ describe('OptionsListUtils', () => { notificationPreference: 'hidden', brickRoadIndicator: CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR, }; - const results = getValidOptions({reports: [workspaceChat], personalDetails: []}, allPolicies, {}, nvpDismissedProductTraining,undefined,translateLocal, loginList, { + const results = getValidOptions({reports: [workspaceChat], personalDetails: []}, allPolicies, {}, nvpDismissedProductTraining, undefined, translateLocal, loginList, { includeMultipleParticipantReports: true, showRBR: true, }); @@ -1112,7 +1121,7 @@ describe('OptionsListUtils', () => { notificationPreference: 'hidden', brickRoadIndicator: CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR, }; - const results = getValidOptions({reports: [workspaceChat], personalDetails: []}, allPolicies, {}, nvpDismissedProductTraining, undefined, translateLocal,loginList, { + const results = getValidOptions({reports: [workspaceChat], personalDetails: []}, allPolicies, {}, nvpDismissedProductTraining, undefined, translateLocal, loginList, { includeMultipleParticipantReports: true, showRBR: false, }); @@ -1159,7 +1168,7 @@ describe('OptionsListUtils', () => { isBold: false, }; - const results = getValidOptions({reports: [inputOption], personalDetails: []}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList, { + const results = getValidOptions({reports: [inputOption], personalDetails: []}, allPolicies, {}, nvpDismissedProductTraining, undefined, translateLocal, loginList, { includeRecentReports: true, shouldUnreadBeBold: true, includeMultipleParticipantReports: true, @@ -1174,7 +1183,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,undefined, translateLocal, loginList, { + const results = getValidOptions(OPTIONS_WITH_WORKSPACE_ROOM, allPolicies, {}, nvpDismissedProductTraining, undefined, translateLocal, loginList, { includeRecentReports: true, includeMultipleParticipantReports: true, includeP2P: true, @@ -1191,7 +1200,15 @@ describe('OptionsListUtils', () => { it('should exclude users with recent reports from personalDetails', () => { // Given a set of reports and personalDetails // When we call getValidOptions with no search value - const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList); + const results = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); const reportLogins = new Set(results.recentReports.map((reportOption) => reportOption.login)); const personalDetailsOverlapWithReports = results.personalDetails.every((personalDetailOption) => reportLogins.has(personalDetailOption.login)); @@ -1204,9 +1221,18 @@ describe('OptionsListUtils', () => { it('should exclude selected options', () => { // Given a set of reports and personalDetails // When we call getValidOptions with excludeLogins param - const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList, { - excludeLogins: {'peterparker@expensify.com': true}, - }); + const results = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + { + excludeLogins: {'peterparker@expensify.com': true}, + }, + ); // Then the option should not appear anywhere in either list expect(results.recentReports.every((option) => option.login !== 'peterparker@expensify.com')).toBe(true); @@ -1311,9 +1337,18 @@ describe('OptionsListUtils', () => { // Given a set of reports and personalDetails with multiple reports // When we call getValidOptions with maxRecentReportElements set to 2 const maxRecentReports = 2; - const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList, { - maxRecentReportElements: maxRecentReports, - }); + const results = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + { + maxRecentReportElements: maxRecentReports, + }, + ); // Then the recent reports should be limited to the specified number expect(results.recentReports.length).toBeLessThanOrEqual(maxRecentReports); @@ -1322,10 +1357,27 @@ describe('OptionsListUtils', () => { it('should show all reports when maxRecentReportElements is not specified', () => { // Given a set of reports and personalDetails // When we call getValidOptions without maxRecentReportElements - const resultsWithoutLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined,translateLocal, loginList); - const resultsWithLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining, undefined,translateLocal, loginList, { - maxRecentReportElements: 2, - }); + const resultsWithoutLimit = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); + const resultsWithLimit = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + { + maxRecentReportElements: 2, + }, + ); // Then the results without limit should have more or equal reports expect(resultsWithoutLimit.recentReports.length).toBeGreaterThanOrEqual(resultsWithLimit.recentReports.length); @@ -1334,10 +1386,27 @@ describe('OptionsListUtils', () => { it('should not affect personalDetails count when maxRecentReportElements is specified', () => { // Given a set of reports and personalDetails // When we call getValidOptions with and without maxRecentReportElements - const resultsWithoutLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList); - const resultsWithLimit = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining, undefined, translateLocal,loginList, { - maxRecentReportElements: 2, - }); + const resultsWithoutLimit = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); + const resultsWithLimit = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + { + maxRecentReportElements: 2, + }, + ); // Then personalDetails should remain the same regardless of maxRecentReportElements expect(resultsWithLimit.personalDetails.length).toBe(resultsWithoutLimit.personalDetails.length); @@ -1348,10 +1417,19 @@ describe('OptionsListUtils', () => { // When we call getValidOptions with both maxElements and maxRecentReportElements const maxRecentReports = 3; const maxTotalElements = 10; - const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList, { - maxElements: maxTotalElements, - maxRecentReportElements: maxRecentReports, - }); + const results = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + { + maxElements: maxTotalElements, + maxRecentReportElements: maxRecentReports, + }, + ); // Then recent reports should be limited by maxRecentReportElements expect(results.recentReports.length).toBeLessThanOrEqual(maxRecentReports); @@ -1373,20 +1451,29 @@ describe('OptionsListUtils', () => { }, []); // When we call getValidOptions for share destination with an empty search value - const results = getValidOptions({reports: filteredReports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList, { - betas: [], - includeMultipleParticipantReports: true, - showChatPreviewLine: true, - forcePolicyNamePreview: true, - includeThreads: true, - includeMoneyRequests: true, - includeTasks: true, - excludeLogins: {}, - includeOwnedWorkspaceChats: true, - includeSelfDM: true, - searchString: '', - includeUserToInvite: false, - }); + const results = getValidOptions( + {reports: filteredReports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + { + betas: [], + includeMultipleParticipantReports: true, + showChatPreviewLine: true, + forcePolicyNamePreview: true, + includeThreads: true, + includeMoneyRequests: true, + includeTasks: true, + excludeLogins: {}, + includeOwnedWorkspaceChats: true, + includeSelfDM: true, + searchString: '', + includeUserToInvite: false, + }, + ); // Then all the recent reports should be returned except the archived rooms and the hidden thread expect(results.recentReports.length).toBe(Object.values(OPTIONS.reports).length - 2); @@ -1405,20 +1492,29 @@ describe('OptionsListUtils', () => { }, []); // When we call getValidOptions for share destination with an empty search value - const results = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList, { - betas: [], - includeMultipleParticipantReports: true, - showChatPreviewLine: true, - forcePolicyNamePreview: true, - includeThreads: true, - includeMoneyRequests: true, - includeTasks: true, - excludeLogins: {}, - includeOwnedWorkspaceChats: true, - includeSelfDM: true, - searchString: '', - includeUserToInvite: false, - }); + const results = getValidOptions( + {reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + { + betas: [], + includeMultipleParticipantReports: true, + showChatPreviewLine: true, + forcePolicyNamePreview: true, + includeThreads: true, + includeMoneyRequests: true, + includeTasks: true, + excludeLogins: {}, + includeOwnedWorkspaceChats: true, + includeSelfDM: true, + searchString: '', + includeUserToInvite: false, + }, + ); // Then all recent reports should be returned except the archived rooms and the hidden thread expect(results.recentReports.length).toBe(Object.values(OPTIONS_WITH_WORKSPACE_ROOM.reports).length - 2); @@ -1824,9 +1920,18 @@ describe('OptionsListUtils', () => { it('should not return any results if the search value is on an excluded logins list', () => { const searchText = 'admin@expensify.com'; // Given a set of options with excluded logins list - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined,translateLocal, loginList, { - excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, - }); + const options = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + { + excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, + }, + ); // When we call filterAndOrderOptions with a search value and excluded logins list const filterOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, {excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT}); @@ -1916,20 +2021,29 @@ describe('OptionsListUtils', () => { return filtered; }, []); // When we call getValidOptions for share destination with the filteredReports - const options = getValidOptions({reports: filteredReports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining, undefined, translateLocal,loginList, { - betas: [], - includeMultipleParticipantReports: true, - showChatPreviewLine: true, - forcePolicyNamePreview: true, - includeThreads: true, - includeMoneyRequests: true, - includeTasks: true, - excludeLogins: {}, - includeOwnedWorkspaceChats: true, - includeSelfDM: true, - searchString: '', - includeUserToInvite: false, - }); + const options = getValidOptions( + {reports: filteredReports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + { + betas: [], + includeMultipleParticipantReports: true, + showChatPreviewLine: true, + forcePolicyNamePreview: true, + includeThreads: true, + includeMoneyRequests: true, + includeTasks: true, + excludeLogins: {}, + includeOwnedWorkspaceChats: true, + includeSelfDM: true, + searchString: '', + includeUserToInvite: false, + }, + ); // When we pass the returned options to filterAndOrderOptions with a search value that does not match the group chat name const filteredOptions = filterAndOrderOptions(options, 'mutants', translateLocal, COUNTRY_CODE, loginList); @@ -1949,20 +2063,29 @@ describe('OptionsListUtils', () => { }, []); // When we call getValidOptions for share destination with the filteredReports - const options = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined,translateLocal, loginList, { - betas: [], - includeMultipleParticipantReports: true, - showChatPreviewLine: true, - forcePolicyNamePreview: true, - includeThreads: true, - includeMoneyRequests: true, - includeTasks: true, - excludeLogins: {}, - includeOwnedWorkspaceChats: true, - includeSelfDM: true, - searchString: '', - includeUserToInvite: false, - }); + const options = getValidOptions( + {reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + { + betas: [], + includeMultipleParticipantReports: true, + showChatPreviewLine: true, + forcePolicyNamePreview: true, + includeThreads: true, + includeMoneyRequests: true, + includeTasks: true, + excludeLogins: {}, + includeOwnedWorkspaceChats: true, + includeSelfDM: true, + searchString: '', + includeUserToInvite: false, + }, + ); // When we pass the returned options to filterAndOrderOptions with a search value that matches the group chat name const filteredOptions = filterAndOrderOptions(options, 'Avengers Room', translateLocal, COUNTRY_CODE, loginList); @@ -1982,20 +2105,29 @@ describe('OptionsListUtils', () => { }, []); // When we call getValidOptions for share destination with the filteredReports - const options = getValidOptions({reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining, undefined,translateLocal, loginList, { - betas: [], - includeMultipleParticipantReports: true, - showChatPreviewLine: true, - forcePolicyNamePreview: true, - includeThreads: true, - includeMoneyRequests: true, - includeTasks: true, - excludeLogins: {}, - includeOwnedWorkspaceChats: true, - includeSelfDM: true, - searchString: '', - includeUserToInvite: false, - }); + const options = getValidOptions( + {reports: filteredReportsWithWorkspaceRooms, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + { + betas: [], + includeMultipleParticipantReports: true, + showChatPreviewLine: true, + forcePolicyNamePreview: true, + includeThreads: true, + includeMoneyRequests: true, + includeTasks: true, + excludeLogins: {}, + includeOwnedWorkspaceChats: true, + includeSelfDM: true, + searchString: '', + includeUserToInvite: false, + }, + ); // When we pass the returned options to filterAndOrderOptions with a search value that does not match the group chat name const filteredOptions = filterAndOrderOptions(options, 'Mutants Lair', translateLocal, COUNTRY_CODE, loginList); @@ -2005,7 +2137,15 @@ describe('OptionsListUtils', () => { it('should show the option from personal details when searching for personal detail with no existing report', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined,translateLocal, loginList); + const options = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); // When we call filterAndOrderOptions with a search value that matches a personal detail with no existing report const filteredOptions = filterAndOrderOptions(options, 'hulk', translateLocal, COUNTRY_CODE, loginList); @@ -2019,7 +2159,15 @@ describe('OptionsListUtils', () => { it('should not return any options or user to invite if there are no search results and the string does not match a potential email or phone', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList); + const options = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); // When we call filterAndOrderOptions with a search value that does not match any personal details or reports const filteredOptions = filterAndOrderOptions(options, 'marc@expensify', translateLocal, COUNTRY_CODE, loginList); @@ -2032,7 +2180,15 @@ describe('OptionsListUtils', () => { it('should not return any options but should return an user to invite if no matching options exist and the search value is a potential email', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList); + const options = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); // When we call filterAndOrderOptions with a search value that does not match any personal details or reports const filteredOptions = filterAndOrderOptions(options, 'marc@expensify.com', translateLocal, COUNTRY_CODE, loginList); @@ -2045,7 +2201,15 @@ describe('OptionsListUtils', () => { it('should return user to invite when search term has a period with options for it that do not contain the period', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList); + const options = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); // 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', translateLocal, COUNTRY_CODE, loginList); @@ -2057,7 +2221,15 @@ describe('OptionsListUtils', () => { it('should return user which has displayName with accent mark when search value without accent mark', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining, undefined, translateLocal, loginList); + const options = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); // When we call filterAndOrderOptions with a search value without accent mark const filteredOptions = filterAndOrderOptions(options, 'Timothee', translateLocal, COUNTRY_CODE, loginList); @@ -2067,7 +2239,15 @@ describe('OptionsListUtils', () => { it('should not return options but should return an user to invite if no matching options exist and the search value is a potential phone number', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList); + const options = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); // 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', translateLocal, COUNTRY_CODE, loginList); @@ -2082,7 +2262,15 @@ describe('OptionsListUtils', () => { it('should not return options but should return an user to invite if no matching options exist and the search value is a potential phone number with country code added', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList); + const options = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); // 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', translateLocal, COUNTRY_CODE, loginList); @@ -2097,7 +2285,15 @@ describe('OptionsListUtils', () => { it('should not return options but should return an user to invite if no matching options exist and the search value is a potential phone number with special characters added', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList); + const options = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); // 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', translateLocal, COUNTRY_CODE, loginList); @@ -2112,7 +2308,15 @@ describe('OptionsListUtils', () => { it('should not return any options or user to invite if contact number contains alphabet characters', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList); + const options = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); // When we call filterAndOrderOptions with a search value that does not match any personal details or reports const filteredOptions = filterAndOrderOptions(options, '998243aaaa', translateLocal, COUNTRY_CODE, loginList); @@ -2125,7 +2329,15 @@ describe('OptionsListUtils', () => { it('should not return any options if search value does not match any personal details', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined,translateLocal, loginList); + const options = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); // When we call filterAndOrderOptions with a search value that does not match any personal details const filteredOptions = filterAndOrderOptions(options, 'magneto', translateLocal, COUNTRY_CODE, loginList); @@ -2135,7 +2347,15 @@ describe('OptionsListUtils', () => { it('should return one recent report and no personal details if a search value provides an email', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList); + const options = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); // When we call filterAndOrderOptions with a search value that matches an email const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', translateLocal, COUNTRY_CODE, loginList, {sortByReportTypeInSearch: true}); @@ -2149,7 +2369,15 @@ describe('OptionsListUtils', () => { it('should return all matching reports and personal details', () => { // Given a set of options - const options = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, allPolicies, {}, nvpDismissedProductTraining,undefined, translateLocal, loginList); + const options = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + allPolicies, + {}, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + ); // When we call filterAndOrderOptions with a search value that matches both reports and personal details and maxRecentReportsToShow param const filteredOptions = filterAndOrderOptions(options, '.com', translateLocal, COUNTRY_CODE, loginList, {maxRecentReportsToShow: 5}); @@ -2195,7 +2423,14 @@ describe('OptionsListUtils', () => { // Given a set of options with periods const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, undefined, translateLocal, REPORTS) as OptionList; // When we call getSearchOptions - const results = getSearchOptions({options: OPTIONS_WITH_PERIODS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, translate: translateLocal, loginList}); + const results = getSearchOptions({ + options: OPTIONS_WITH_PERIODS, + draftComments: {}, + nvpDismissedProductTraining, + policyTags: undefined, + translate: translateLocal, + loginList, + }); // When we pass the returned options to filterAndOrderOptions with a search value const filteredResults = filterAndOrderOptions(results, 'barry.allen@expensify.com', translateLocal, COUNTRY_CODE, loginList, {sortByReportTypeInSearch: true}); @@ -3063,7 +3298,15 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, { [submittedAction.reportActionID]: submittedAction, }); - const lastMessage = getLastMessageTextForReport({translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, policy, reportMetadata, policyTags: undefined}); + const lastMessage = getLastMessageTextForReport({ + translate: translateLocal, + report, + lastActorDetails: null, + isReportArchived: false, + policy, + reportMetadata, + policyTags: undefined, + }); expect(lastMessage).toBe(translate(CONST.LOCALES.EN, 'iou.queuedToSubmitViaDEW')); }); @@ -3112,7 +3355,7 @@ describe('OptionsListUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, { [dewSubmitFailedAction.reportActionID]: dewSubmitFailedAction, }); - const lastMessage = getLastMessageTextForReport({translate: translateLocal, report, lastActorDetails: null, isReportArchived: false,policyTags: undefined}); + const lastMessage = getLastMessageTextForReport({translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, policyTags: undefined}); expect(lastMessage).toBe(translate(CONST.LOCALES.EN, 'iou.error.genericCreateFailureMessage')); }); }); @@ -3155,7 +3398,7 @@ 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,undefined, translateLocal, loginList); + const results = getValidOptions({reports: [], personalDetails: []}, policies, undefined, nvpDismissedProductTraining, undefined, translateLocal, loginList); expect(results).toBeDefined(); expect(results.recentReports).toBeDefined(); @@ -3164,7 +3407,7 @@ describe('OptionsListUtils', () => { it('should work with undefined policies', () => { const options = {reports: [], personalDetails: []}; - const results = getValidOptions(options, undefined, undefined, nvpDismissedProductTraining,undefined,translateLocal, loginList); + const results = getValidOptions(options, undefined, undefined, nvpDismissedProductTraining, undefined, translateLocal, loginList); expect(results).toBeDefined(); expect(results.recentReports).toBeDefined(); @@ -3173,7 +3416,7 @@ describe('OptionsListUtils', () => { it('should work with empty policies collection', () => { const options = {reports: [], personalDetails: []}; - const results = getValidOptions(options, {}, undefined, nvpDismissedProductTraining,undefined,translateLocal, loginList); + const results = getValidOptions(options, {}, undefined, nvpDismissedProductTraining, undefined, translateLocal, loginList); expect(results).toBeDefined(); expect(results.recentReports).toBeDefined(); @@ -3197,10 +3440,19 @@ describe('OptionsListUtils', () => { const policies = {[`${ONYXKEYS.COLLECTION.POLICY}${testPolicyID}`]: policy}; // Verify function works with policies parameter - const results = getValidOptions({reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, policies, undefined, nvpDismissedProductTraining,undefined,translateLocal, loginList, { - betas: [], - includeRecentReports: true, - }); + const results = getValidOptions( + {reports: OPTIONS.reports, personalDetails: OPTIONS.personalDetails}, + policies, + undefined, + nvpDismissedProductTraining, + undefined, + translateLocal, + loginList, + { + betas: [], + includeRecentReports: true, + }, + ); expect(results.recentReports).toBeDefined(); expect(Array.isArray(results.recentReports)).toBe(true); @@ -3241,7 +3493,7 @@ describe('OptionsListUtils', () => { isPolicyExpenseChat: true, }; - const option = getReportOption(participant,undefined, undefined, policy); + const option = getReportOption(participant, undefined, undefined, policy); expect(option.text).toBe('Test Workspace'); expect(option.alternateText).toBe(translateLocal('workspace.common.workspace')); @@ -3296,7 +3548,7 @@ describe('OptionsListUtils', () => { isPolicyExpenseChat: true, }; - const option = getReportOption(participant,undefined, undefined, policy); + const option = getReportOption(participant, undefined, undefined, policy); expect(option.text).toBe('Test Workspace with Submit'); // The submitsTo logic may or may not apply depending on complex approval rules @@ -3319,7 +3571,7 @@ describe('OptionsListUtils', () => { reportID, }; - const option = getReportOption(participant,undefined, undefined, POLICY); + const option = getReportOption(participant, undefined, undefined, POLICY); expect(option.isDisabled).toBe(true); }); @@ -3355,7 +3607,7 @@ describe('OptionsListUtils', () => { isSelfDM: true, }; - const option = getReportOption(participant,undefined, undefined, POLICY); + const option = getReportOption(participant, undefined, undefined, POLICY); // The option.isSelfDM is set by createOption based on the report type // Just verify the alternateText is correct for self DM @@ -3390,7 +3642,7 @@ describe('OptionsListUtils', () => { isInvoiceRoom: true, }; - const option = getReportOption(participant,undefined, undefined, POLICY); + const option = getReportOption(participant, undefined, undefined, POLICY); expect(option.isInvoiceRoom).toBe(true); expect(option.alternateText).toBe(translateLocal('workspace.common.invoices')); @@ -3431,7 +3683,7 @@ describe('OptionsListUtils', () => { }); await waitForBatchedUpdates(); - const option = getReportOption(participant,undefined, reportNameValuePair?.private_isArchived, POLICY); + const option = getReportOption(participant, undefined, reportNameValuePair?.private_isArchived, POLICY); expect(option.text).toBe(POLICY.name); expect(option.alternateText).toBeTruthy(); @@ -3475,7 +3727,7 @@ describe('OptionsListUtils', () => { }); await waitForBatchedUpdates(); - const option = getReportOption(participant,undefined, reportNameValuePair?.private_isArchived, POLICY, undefined, draftReports); + const option = getReportOption(participant, undefined, reportNameValuePair?.private_isArchived, POLICY, undefined, draftReports); expect(option.isDisabled).toBe(true); }); @@ -3497,7 +3749,7 @@ describe('OptionsListUtils', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report); await waitForBatchedUpdates(); - const option = getReportDisplayOption(report,undefined, undefined, reportNameValuePair?.private_isArchived); + const option = getReportDisplayOption(report, undefined, undefined, reportNameValuePair?.private_isArchived); expect(option).toBeDefined(); expect(option.reportID).toBe(reportID); @@ -3520,7 +3772,7 @@ describe('OptionsListUtils', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report); await waitForBatchedUpdates(); - const option = getReportDisplayOption(report,undefined, undefined, reportNameValuePair?.private_isArchived); + const option = getReportDisplayOption(report, undefined, undefined, reportNameValuePair?.private_isArchived); expect(option).toBeDefined(); expect(option.reportID).toBe(reportID); @@ -3540,7 +3792,7 @@ describe('OptionsListUtils', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report); await waitForBatchedUpdates(); - const option = getReportDisplayOption(report,undefined, undefined, undefined); + const option = getReportDisplayOption(report, undefined, undefined, undefined); expect(option).toBeDefined(); expect(option.reportID).toBe(reportID); @@ -3564,7 +3816,7 @@ describe('OptionsListUtils', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report); await waitForBatchedUpdates(); - const option = getReportDisplayOption(report,undefined, undefined, reportNameValuePair?.private_isArchived); + const option = getReportDisplayOption(report, undefined, undefined, reportNameValuePair?.private_isArchived); expect(option).toBeDefined(); expect(option.reportID).toBe(reportID); @@ -3588,7 +3840,7 @@ describe('OptionsListUtils', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report); await waitForBatchedUpdates(); - const option = getReportDisplayOption(report, undefined,undefined, reportNameValuePair?.private_isArchived); + const option = getReportDisplayOption(report, undefined, undefined, reportNameValuePair?.private_isArchived); expect(option).toBeDefined(); expect(option.reportID).toBe(reportID); @@ -3611,7 +3863,7 @@ describe('OptionsListUtils', () => { selected: true, }; - const option = getReportOption(participant, undefined,undefined, POLICY); + const option = getReportOption(participant, undefined, undefined, POLICY); expect(option.isSelected).toBe(true); expect(option.selected).toBe(true); @@ -3632,7 +3884,7 @@ describe('OptionsListUtils', () => { reportID, }; - const option = getReportOption(participant, undefined,undefined, undefined); + const option = getReportOption(participant, undefined, undefined, undefined); expect(option).toBeDefined(); expect(option.text).toBeDefined(); @@ -3654,7 +3906,7 @@ describe('OptionsListUtils', () => { }; // Test that the function works with reportAttributesDerived parameter (optional) - const option = getReportOption(participant,undefined, undefined, POLICY); + const option = getReportOption(participant, undefined, undefined, POLICY); expect(option).toBeDefined(); }); @@ -3675,7 +3927,7 @@ describe('OptionsListUtils', () => { searchValue: 'Jeff Amazon', shouldAcceptName: true, loginList: {}, - translate:translateLocal, + translate: translateLocal, }); expect(result).not.toBeNull(); expect(result?.login).toBe('Jeff Amazon'); From 263717c1d5b2ed6ba82f59e4ce8d6720b7e45dae Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Wed, 21 Jan 2026 14:36:25 +0100 Subject: [PATCH 25/39] fix lint --- src/libs/OptionsListUtils/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index d775d21b6726e..e0389fe66ce01 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -478,8 +478,8 @@ function getAlternateText( const isGroupChat = reportUtilsIsGroupChat(report); const isExpenseThread = isMoneyRequest(report); const formattedLastMessageText = - // eslint-disable-next-line @typescript-eslint/no-deprecated - formatReportLastMessageText(Parser.htmlToText(option.lastMessageText ?? '')) || + formatReportLastMessageText(Parser.htmlToText(option.lastMessageText ?? '')) || + // eslint-disable-next-line @typescript-eslint/no-deprecated getLastMessageTextForReport({translate: translateLocal, report, lastActorDetails, isReportArchived, policyTags}); const reportPrefix = getReportSubtitlePrefix(report); const formattedLastMessageTextWithPrefix = reportPrefix + formattedLastMessageText; @@ -1013,6 +1013,7 @@ function getReportOption( visibleParticipantAccountIDs, allPersonalDetails ?? {}, !isEmptyObject(report) ? report : undefined, + // eslint-disable-next-line @typescript-eslint/no-deprecated translateLocal, policyTags, { @@ -1070,6 +1071,7 @@ function getReportDisplayOption( visibleParticipantAccountIDs, allPersonalDetails ?? {}, !isEmptyObject(report) ? report : undefined, + // eslint-disable-next-line @typescript-eslint/no-deprecated translateLocal, policyTags, { From 92e2e2231da25a0cb12dae30eb74fc2cef8e0188 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Wed, 21 Jan 2026 15:34:24 +0100 Subject: [PATCH 26/39] format --- src/libs/OptionsListUtils/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index e0389fe66ce01..311c321a60ccf 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -478,8 +478,8 @@ function getAlternateText( const isGroupChat = reportUtilsIsGroupChat(report); const isExpenseThread = isMoneyRequest(report); const formattedLastMessageText = - formatReportLastMessageText(Parser.htmlToText(option.lastMessageText ?? '')) || - // eslint-disable-next-line @typescript-eslint/no-deprecated + formatReportLastMessageText(Parser.htmlToText(option.lastMessageText ?? '')) || + // eslint-disable-next-line @typescript-eslint/no-deprecated getLastMessageTextForReport({translate: translateLocal, report, lastActorDetails, isReportArchived, policyTags}); const reportPrefix = getReportSubtitlePrefix(report); const formattedLastMessageTextWithPrefix = reportPrefix + formattedLastMessageText; @@ -1013,7 +1013,7 @@ function getReportOption( visibleParticipantAccountIDs, allPersonalDetails ?? {}, !isEmptyObject(report) ? report : undefined, - // eslint-disable-next-line @typescript-eslint/no-deprecated + // eslint-disable-next-line @typescript-eslint/no-deprecated translateLocal, policyTags, { From 58e869ccb0d3eca3258ad71b29a6d79218fd59b5 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 26 Jan 2026 10:53:10 +0100 Subject: [PATCH 27/39] fix lint --- .../request/step/IOURequestStepDistanceGPS/index.native.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx b/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx index 9c8d0447f23cc..ed486340f9648 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx @@ -53,7 +53,7 @@ function IOURequestStepDistanceGPS({ const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE, {canBeMissing: true}); const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true}); - + const isEditing = action === CONST.IOU.ACTION.EDIT; const isCreatingNewRequest = !isEditing; // eslint-disable-next-line rulesdir/no-negated-variables @@ -62,6 +62,7 @@ function IOURequestStepDistanceGPS({ const personalPolicy = usePersonalPolicy(); const policy = usePolicy(report?.policyID); const isArchived = isArchivedReport(reportNameValuePairs); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policy?.id}`, {canBeMissing: true}); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); From 16ada43e5dcdca5e10e82913721bebf7239e5172 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 26 Jan 2026 10:58:08 +0100 Subject: [PATCH 28/39] prettier --- src/components/Search/SearchAutocompleteList.tsx | 1 - .../iou/request/step/IOURequestStepDistanceGPS/index.native.tsx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx index 085825f7a4d4d..aa5fe94a973ef 100644 --- a/src/components/Search/SearchAutocompleteList.tsx +++ b/src/components/Search/SearchAutocompleteList.tsx @@ -643,7 +643,6 @@ function SearchAutocompleteList({ statusAutocompleteList, feedAutoCompleteList, cardAutocompleteList, - translate, workspaceList, hasAutocompleteList, isAutocompleteList, diff --git a/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx b/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx index ed486340f9648..a909bd822ae83 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx @@ -53,7 +53,7 @@ function IOURequestStepDistanceGPS({ const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE, {canBeMissing: true}); const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true}); - + const isEditing = action === CONST.IOU.ACTION.EDIT; const isCreatingNewRequest = !isEditing; // eslint-disable-next-line rulesdir/no-negated-variables From 6eefe52fb4ddec80cf51e2fdd6f158676571a76f Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Tue, 27 Jan 2026 13:10:09 +0100 Subject: [PATCH 29/39] lint prettier --- src/libs/OptionsListUtils/index.ts | 3 ++- src/pages/workspace/WorkspaceMembersPage.tsx | 24 +++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index c95e90bf4223b..2bd2f931fcfd5 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -931,7 +931,8 @@ function createOption( const lastActorDetails = personalDetails?.[report?.lastActorAccountID ?? String(CONST.DEFAULT_NUMBER_ID)] ?? {}; // eslint-disable-next-line @typescript-eslint/no-deprecated result.lastMessageText = getLastMessageTextForReport({ - translate: translateLocal, + + translate, report, lastActorDetails, isReportArchived: !!result.private_isArchived, diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index e7c448e5c8208..02a9b2b822d68 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -474,7 +474,29 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers }); } return result; - }, [policy?.employeeList, policy?.owner, policy?.ownerAccountID, policyMemberEmailsToAccountIDs, isOffline, personalDetails, isPolicyAdmin, formatPhoneNumber, session?.accountID, styles.cursorDefault, styles.flex1, styles.pr3, styles.alignSelfStart, styles.alignSelfEnd, isControlPolicyWithWideLayout, StyleUtils, icons.FallbackAvatar, invitedPrimaryToSecondaryLogins, policyOwner, currentUserLogin, translate]); + }, [ + policy?.employeeList, + policy?.owner, + policy?.ownerAccountID, + policyMemberEmailsToAccountIDs, + isOffline, + personalDetails, + isPolicyAdmin, + formatPhoneNumber, + session?.accountID, + styles.cursorDefault, + styles.flex1, + styles.pr3, + styles.alignSelfStart, + styles.alignSelfEnd, + isControlPolicyWithWideLayout, + StyleUtils, + icons.FallbackAvatar, + invitedPrimaryToSecondaryLogins, + policyOwner, + currentUserLogin, + translate, + ]); const filterMember = useCallback((memberOption: MemberOption, searchQuery: string) => { const results = tokenizedSearch([memberOption], searchQuery, (option) => [option.text ?? '', option.alternateText ?? '']); From fce64d23f9f97f1586f0e6865fb3e5a99a1d22d6 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Tue, 27 Jan 2026 13:19:18 +0100 Subject: [PATCH 30/39] prettier --- src/libs/OptionsListUtils/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index 2bd2f931fcfd5..c52c5b31eff73 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -931,7 +931,6 @@ function createOption( const lastActorDetails = personalDetails?.[report?.lastActorAccountID ?? String(CONST.DEFAULT_NUMBER_ID)] ?? {}; // eslint-disable-next-line @typescript-eslint/no-deprecated result.lastMessageText = getLastMessageTextForReport({ - translate, report, lastActorDetails, From 189c159af236f49d9347a10585fac7dfbfdbcace Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Wed, 28 Jan 2026 14:15:33 +0100 Subject: [PATCH 31/39] remove translate changes --- src/components/OptionListContextProvider.tsx | 19 +- .../FilterDropdowns/UserSelectPopup.tsx | 5 +- .../Search/SearchAutocompleteList.tsx | 4 - .../Search/SearchFiltersChatsSelector.tsx | 10 +- .../SearchFiltersParticipantsSelector.tsx | 22 +- .../Search/SearchRouter/SearchRouter.tsx | 2 +- src/hooks/useContactImport.ts | 6 +- src/hooks/useFilteredOptions.ts | 4 +- src/hooks/useSearchSelector.base.ts | 9 - src/libs/ContactUtils.ts | 4 +- src/libs/OptionsListUtils/index.ts | 45 +-- src/libs/OptionsListUtils/types.ts | 1 - src/pages/NewChatPage.tsx | 6 +- src/pages/RoomInvitePage.tsx | 7 +- src/pages/Share/ShareTab.tsx | 2 - src/pages/iou/SplitBillDetailsPage.tsx | 2 +- .../MoneyRequestAccountantSelector.tsx | 9 +- .../request/MoneyRequestAttendeeSelector.tsx | 22 +- .../MoneyRequestParticipantsSelector.tsx | 26 +- tests/perf-test/OptionsListUtils.perf-test.ts | 14 +- tests/perf-test/SearchRouter.perf-test.tsx | 2 +- tests/unit/OptionsListUtilsTest.tsx | 284 +++++++++--------- 22 files changed, 185 insertions(+), 320 deletions(-) diff --git a/src/components/OptionListContextProvider.tsx b/src/components/OptionListContextProvider.tsx index e73d7e7bd5aa3..03a8492d663ca 100644 --- a/src/components/OptionListContextProvider.tsx +++ b/src/components/OptionListContextProvider.tsx @@ -1,7 +1,6 @@ import React, {createContext, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; -import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import usePrevious from '@hooks/usePrevious'; import {createOptionFromReport, createOptionList, processReport, shallowOptionsListCompare} from '@libs/OptionsListUtils'; @@ -61,15 +60,14 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { const currentUserAccountID = currentUserPersonalDetails.accountID; const hasInitialData = useMemo(() => Object.keys(personalDetails ?? {}).length > 0, [personalDetails]); const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); - const {translate} = useLocalize(); const loadOptions = useCallback(() => { - const optionLists = createOptionList(personalDetails, policyTags, translate, currentUserAccountID, reports, reportAttributes?.reports); + const optionLists = createOptionList(personalDetails, policyTags, currentUserAccountID, reports, reportAttributes?.reports); setOptions({ reports: optionLists.reports, personalDetails: optionLists.personalDetails, }); - }, [personalDetails, currentUserAccountID, reports, reportAttributes?.reports, policyTags, translate]); + }, [personalDetails, currentUserAccountID, reports, reportAttributes?.reports, policyTags]); /** * This effect is responsible for generating the options list when their data is not yet initialized @@ -126,7 +124,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { const report = changedReportsEntries[reportKey]; const reportID = reportKey.replace(ONYXKEYS.COLLECTION.REPORT, ''); const reportPolicyTags = report?.policyID ? policyTags?.[report?.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; - const {reportOption} = processReport(report, personalDetails, translate, reportPolicyTags, currentUserAccountID, reportAttributes?.reports); + const {reportOption} = processReport(report, personalDetails, reportPolicyTags, currentUserAccountID, reportAttributes?.reports); if (reportOption) { updatedReportsMap.set(reportID, reportOption); @@ -140,7 +138,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { reports: Array.from(updatedReportsMap.values()), }; }); - }, [changedReportsEntries, personalDetails, currentUserAccountID, reportAttributes?.reports, translate, policyTags]); + }, [changedReportsEntries, personalDetails, currentUserAccountID, reportAttributes?.reports, policyTags]); useEffect(() => { if (!changedReportActions || !areOptionsInitialized.current) { @@ -162,7 +160,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { const reportID = key.replace(ONYXKEYS.COLLECTION.REPORT_ACTIONS, ''); const report = updatedReportsMap.get(reportID)?.item; const reportPolicyTags = report?.policyID ? policyTags?.[report?.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; - const {reportOption} = processReport(updatedReportsMap.get(reportID)?.item, personalDetails, translate, reportPolicyTags, currentUserAccountID, reportAttributes?.reports); + const {reportOption} = processReport(updatedReportsMap.get(reportID)?.item, personalDetails, reportPolicyTags, currentUserAccountID, reportAttributes?.reports); if (reportOption) { updatedReportsMap.set(reportID, reportOption); @@ -174,7 +172,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { reports: Array.from(updatedReportsMap.values()), }; }); - }, [changedReportActions, personalDetails, currentUserAccountID, reportAttributes?.reports, policyTags, translate]); + }, [changedReportActions, personalDetails, currentUserAccountID, reportAttributes?.reports, policyTags ]); /** * This effect is used to update the options list when personal details change. @@ -195,7 +193,6 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { const {personalDetails: newPersonalDetailsOptions, reports: newReports} = createOptionList( personalDetails, policyTags, - translate, currentUserAccountID, reports, reportAttributes?.reports, @@ -233,7 +230,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { } const reportPolicyTags = report.policyID ? policyTags?.[report.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; - const newReportOption = createOptionFromReport(report, personalDetails, reportPolicyTags, translate, currentUserAccountID, reportAttributes?.reports, { + const newReportOption = createOptionFromReport(report, personalDetails, reportPolicyTags, currentUserAccountID, reportAttributes?.reports, { showPersonalDetails: true, }); const replaceIndex = options.reports.findIndex((option) => option.reportID === report.reportID); @@ -245,7 +242,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { } // since personal details are not a collection, we need to recreate the whole list from scratch - const newPersonalDetailsOptions = createOptionList(personalDetails, policyTags, translate, currentUserAccountID, reports, reportAttributes?.reports).personalDetails; + const newPersonalDetailsOptions = createOptionList(personalDetails, policyTags, currentUserAccountID, reports, reportAttributes?.reports).personalDetails; setOptions((prevOptions) => { const newOptions = {...prevOptions}; diff --git a/src/components/Search/FilterDropdowns/UserSelectPopup.tsx b/src/components/Search/FilterDropdowns/UserSelectPopup.tsx index 55dff1d5a486f..239f9140a2cda 100644 --- a/src/components/Search/FilterDropdowns/UserSelectPopup.tsx +++ b/src/components/Search/FilterDropdowns/UserSelectPopup.tsx @@ -105,7 +105,6 @@ function UserSelectPopup({value, closeOverlay, onChange, isSearchable}: UserSele draftComments, nvpDismissedProductTraining, policyTags, - translate, loginList, currentUserAccountID, currentUserEmail, @@ -123,7 +122,6 @@ function UserSelectPopup({value, closeOverlay, onChange, isSearchable}: UserSele draftComments, nvpDismissedProductTraining, policyTags, - translate, loginList, currentUserAccountID, currentUserEmail, @@ -135,7 +133,6 @@ function UserSelectPopup({value, closeOverlay, onChange, isSearchable}: UserSele return filterAndOrderOptions( optionsList, cleanSearchTerm, - translate, countryCode, loginList, currentUserEmail, @@ -147,7 +144,7 @@ function UserSelectPopup({value, closeOverlay, onChange, isSearchable}: UserSele canInviteUser: false, }, ); - }, [optionsList, cleanSearchTerm, translate, countryCode, loginList, currentUserEmail, currentUserAccountID]); + }, [optionsList, cleanSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID]); const listData = useMemo(() => { const personalDetailList = filteredOptions.personalDetails.map((participant) => ({ diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx index fedc3c4f2baf2..cd7c6be98ff52 100644 --- a/src/components/Search/SearchAutocompleteList.tsx +++ b/src/components/Search/SearchAutocompleteList.tsx @@ -208,7 +208,6 @@ function SearchAutocompleteList({ return defaultListOptions; } return getSearchOptions({ - translate, options, draftComments, nvpDismissedProductTraining, @@ -230,7 +229,6 @@ function SearchAutocompleteList({ }); }, [ areOptionsInitialized, - translate, options, draftComments, nvpDismissedProductTraining, @@ -434,7 +432,6 @@ function SearchAutocompleteList({ case CONST.SEARCH.SYNTAX_FILTER_KEYS.ATTENDEE: case CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPORTER: { const participants = getSearchOptions({ - translate, options, draftComments, nvpDismissedProductTraining, @@ -469,7 +466,6 @@ function SearchAutocompleteList({ } const filteredReports = getSearchOptions({ - translate, options, draftComments, nvpDismissedProductTraining, diff --git a/src/components/Search/SearchFiltersChatsSelector.tsx b/src/components/Search/SearchFiltersChatsSelector.tsx index 92edf583e4e0f..5b92e0d2003a3 100644 --- a/src/components/Search/SearchFiltersChatsSelector.tsx +++ b/src/components/Search/SearchFiltersChatsSelector.tsx @@ -74,7 +74,6 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen {...reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`], reportID: id}, personalDetails, reportPolicyTags, - translate, currentUserAccountID, reportAttributesDerived, ), @@ -83,7 +82,7 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen const alternateText = getAlternateText(report, {}, reportPolicyTags, isReportArchived, currentUserAccountID, {}); return {...report, alternateText}; }); - }, [selectedReportIDs, reports, policyTags, personalDetails, translate, currentUserAccountID, reportAttributesDerived, archivedReportsIdSet]); + }, [selectedReportIDs, reports, policyTags, personalDetails, currentUserAccountID, reportAttributesDerived, archivedReportsIdSet]); const defaultOptions = useMemo(() => { if (!areOptionsInitialized || !isScreenTransitionEnd) { @@ -100,7 +99,6 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen currentUserAccountID, currentUserEmail, policyTags, - translate, }); }, [ areOptionsInitialized, @@ -113,15 +111,14 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen currentUserAccountID, currentUserEmail, policyTags, - translate, ]); const chatOptions = useMemo(() => { - return filterAndOrderOptions(defaultOptions, cleanSearchTerm, translate, countryCode, loginList, currentUserEmail, currentUserAccountID, { + return filterAndOrderOptions(defaultOptions, cleanSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID, { selectedOptions, excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, }); - }, [defaultOptions, cleanSearchTerm, translate, countryCode, loginList, currentUserEmail, currentUserAccountID, selectedOptions]); + }, [defaultOptions, cleanSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID, selectedOptions]); const {sections, headerMessage} = useMemo(() => { const newSections: Section[] = []; @@ -135,7 +132,6 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen chatOptions.recentReports, chatOptions.personalDetails, undefined, - translate, currentUserAccountID, personalDetails, false, diff --git a/src/components/Search/SearchFiltersParticipantsSelector.tsx b/src/components/Search/SearchFiltersParticipantsSelector.tsx index 31381727ef7a1..b1ec846c4d9ff 100644 --- a/src/components/Search/SearchFiltersParticipantsSelector.tsx +++ b/src/components/Search/SearchFiltersParticipantsSelector.tsx @@ -76,7 +76,6 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: draftComments, nvpDismissedProductTraining, policyTags, - translate, loginList, currentUserAccountID, currentUserEmail, @@ -87,28 +86,14 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: }, countryCode, ); - }, [ - areOptionsInitialized, - options.reports, - options.personalDetails, - allPolicies, - draftComments, - nvpDismissedProductTraining, - policyTags, - translate, - loginList, - currentUserAccountID, - currentUserEmail, - personalDetails, - countryCode, - ]); + }, [areOptionsInitialized, options.reports, options.personalDetails, allPolicies, draftComments, nvpDismissedProductTraining, policyTags, loginList, currentUserAccountID, currentUserEmail, personalDetails, countryCode]); const unselectedOptions = useMemo(() => { return filterSelectedOptions(defaultOptions, new Set(selectedOptions.map((option) => option.accountID))); }, [defaultOptions, selectedOptions]); const chatOptions = useMemo(() => { - const filteredOptions = filterAndOrderOptions(unselectedOptions, cleanSearchTerm, translate, countryCode, loginList, currentUserEmail, currentUserAccountID, { + const filteredOptions = filterAndOrderOptions(unselectedOptions, cleanSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID, { selectedOptions, excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, @@ -123,7 +108,7 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: } return filteredOptions; - }, [unselectedOptions, cleanSearchTerm, translate, countryCode, loginList, currentUserEmail, currentUserAccountID, selectedOptions]); + }, [unselectedOptions, cleanSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID, selectedOptions]); const {sections, headerMessage} = useMemo(() => { const newSections: Section[] = []; @@ -137,7 +122,6 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: chatOptions.recentReports, chatOptions.personalDetails, undefined, - translate, currentUserAccountID, personalDetails, true, diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index 171cfa6c768d1..ba507ae0ce5c7 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -116,7 +116,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla return undefined; } const reportPolicyTags = report.policyID ? policyTags?.[report.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; - const option = createOptionFromReport(report, personalDetails, reportPolicyTags, translate, currentUserAccountID, undefined, {showPersonalDetails: true}); + const option = createOptionFromReport(report, personalDetails, reportPolicyTags, currentUserAccountID, undefined, {showPersonalDetails: true}); reportForContextualSearch = option; } diff --git a/src/hooks/useContactImport.ts b/src/hooks/useContactImport.ts index 69705e0c1c0d4..f24ee21fc9418 100644 --- a/src/hooks/useContactImport.ts +++ b/src/hooks/useContactImport.ts @@ -31,7 +31,7 @@ type UseContactImportResult = { function useContactImport(): UseContactImportResult { const [contactPermissionState, setContactPermissionState] = useState(RESULTS.UNAVAILABLE); const [contacts, setContacts] = useState>>([]); - const {localeCompare, translate} = useLocalize(); + const {localeCompare} = useLocalize(); const [countryCode = CONST.DEFAULT_COUNTRY_CODE] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST, {canBeMissing: true}); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); @@ -41,10 +41,10 @@ function useContactImport(): UseContactImportResult { const importAndSaveContacts = useCallback(() => { contactImport().then(({contactList, permissionStatus}: ContactImportResult) => { setContactPermissionState(permissionStatus); - const usersFromContact = getContacts(contactList, localeCompare, countryCode, translate, loginList, currentUserEmail, currentUserAccountID); + const usersFromContact = getContacts(contactList, localeCompare, countryCode, loginList, currentUserEmail, currentUserAccountID); setContacts(usersFromContact); }); - }, [localeCompare, countryCode, translate, loginList, currentUserEmail, currentUserAccountID]); + }, [localeCompare, countryCode, loginList, currentUserEmail, currentUserAccountID]); useContactPermissions({ importAndSaveContacts, diff --git a/src/hooks/useFilteredOptions.ts b/src/hooks/useFilteredOptions.ts index 9c5e670ac7a97..991001bf69481 100644 --- a/src/hooks/useFilteredOptions.ts +++ b/src/hooks/useFilteredOptions.ts @@ -6,7 +6,6 @@ import type {OptionList} from '@libs/OptionsListUtils/types'; import ONYXKEYS from '@src/ONYXKEYS'; import type Beta from '@src/types/onyx/Beta'; import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails'; -import useLocalize from './useLocalize'; import useOnyx from './useOnyx'; type UseFilteredOptionsConfig = { @@ -79,14 +78,13 @@ function useFilteredOptions(config: UseFilteredOptionsConfig = {}): UseFilteredO selector: reportsSelector, }); const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); - const {translate} = useLocalize(); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const totalReports = allReports ? Object.keys(allReports).length : 0; const options: OptionList | null = enabled && allReports && allPersonalDetails - ? createFilteredOptionList(allPersonalDetails, allReports, policyTags, translate, currentUserPersonalDetails.accountID, reportAttributesDerived, { + ? createFilteredOptionList(allPersonalDetails, allReports, policyTags, currentUserPersonalDetails.accountID, reportAttributesDerived, { maxRecentReports: reportsLimit, includeP2P, searchTerm, diff --git a/src/hooks/useSearchSelector.base.ts b/src/hooks/useSearchSelector.base.ts index ff699b1191034..ba054aff0c1d9 100644 --- a/src/hooks/useSearchSelector.base.ts +++ b/src/hooks/useSearchSelector.base.ts @@ -11,7 +11,6 @@ import type {PersonalDetails} from '@src/types/onyx'; import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails'; import useDebounce from './useDebounce'; import useDebouncedState from './useDebouncedState'; -import useLocalize from './useLocalize'; import useOnyx from './useOnyx'; type SearchSelectorContext = (typeof CONST.SEARCH_SELECTOR)[keyof Pick< @@ -169,7 +168,6 @@ function useSearchSelectorBase({ const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, {canBeMissing: true}); const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); - const {translate} = useLocalize(); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const currentUserAccountID = currentUserPersonalDetails.accountID; const currentUserEmail = currentUserPersonalDetails.email ?? ''; @@ -194,7 +192,6 @@ function useSearchSelectorBase({ switch (searchContext) { case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_SEARCH: return getSearchOptions({ - translate, options: optionsWithContacts, draftComments, nvpDismissedProductTraining, @@ -217,7 +214,6 @@ function useSearchSelectorBase({ draftComments, nvpDismissedProductTraining, policyTags, - translate, loginList, currentUserAccountID, currentUserEmail, @@ -241,7 +237,6 @@ function useSearchSelectorBase({ draftComments, nvpDismissedProductTraining, policyTags, - translate, loginList, currentUserAccountID, currentUserEmail, @@ -263,7 +258,6 @@ function useSearchSelectorBase({ draftComments, nvpDismissedProductTraining, policyTags, - translate, loginList, currentUserAccountID, currentUserEmail, @@ -290,7 +284,6 @@ function useSearchSelectorBase({ draftComments, nvpDismissedProductTraining, policyTags, - translate, loginList, currentUserAccountID, currentUserEmail, @@ -320,7 +313,6 @@ function useSearchSelectorBase({ draftComments, nvpDismissedProductTraining, policyTags, - translate, loginList, currentUserAccountID, currentUserEmail, @@ -347,7 +339,6 @@ function useSearchSelectorBase({ }, [ areOptionsInitialized, searchContext, - translate, optionsWithContacts, draftComments, nvpDismissedProductTraining, diff --git a/src/libs/ContactUtils.ts b/src/libs/ContactUtils.ts index 04c067f898f77..e8d073e5d5d2c 100644 --- a/src/libs/ContactUtils.ts +++ b/src/libs/ContactUtils.ts @@ -1,5 +1,5 @@ import type {OnyxEntry} from 'react-native-onyx'; -import type {LocaleContextProps, LocalizedTranslate} from '@components/LocaleContextProvider'; +import type {LocaleContextProps} from '@components/LocaleContextProvider'; import CONST from '@src/CONST'; import type {Login, PersonalDetails} from '@src/types/onyx'; import type {DeviceContact, StringHolder} from './ContactImport/types'; @@ -33,7 +33,6 @@ const getContacts = ( deviceContacts: DeviceContact[] | [], localeCompare: LocaleContextProps['localeCompare'], countryCode: number, - translate: LocalizedTranslate, loginList: OnyxEntry, currentUserEmail: string, currentUserAccountID: number, @@ -48,7 +47,6 @@ const getContacts = ( const lastName = contact?.lastName ?? ''; return getUserToInviteContactOption({ - translate, selectedOptions: [], optionsToExclude: [], searchValue: email || phoneNumber || firstName || '', diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index c52c5b31eff73..a10abecf9614c 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -848,7 +848,6 @@ function createOption( accountIDs: number[], personalDetails: OnyxInputOrEntry, report: OnyxInputOrEntry, - translate: LocalizedTranslate, policyTags: OnyxEntry, currentUserAccountID: number, config?: PreviewConfig, @@ -931,7 +930,7 @@ function createOption( const lastActorDetails = personalDetails?.[report?.lastActorAccountID ?? String(CONST.DEFAULT_NUMBER_ID)] ?? {}; // eslint-disable-next-line @typescript-eslint/no-deprecated result.lastMessageText = getLastMessageTextForReport({ - translate, + translate: translateLocal, report, lastActorDetails, isReportArchived: !!result.private_isArchived, @@ -1013,8 +1012,6 @@ function getReportOption( visibleParticipantAccountIDs, personalDetails ?? {}, !isEmptyObject(report) ? report : undefined, - // eslint-disable-next-line @typescript-eslint/no-deprecated - translateLocal, policyTags, currentUserAccountID, { @@ -1074,8 +1071,6 @@ function getReportDisplayOption( visibleParticipantAccountIDs, personalDetails ?? {}, !isEmptyObject(report) ? report : undefined, - // eslint-disable-next-line @typescript-eslint/no-deprecated - translateLocal, policyTags, currentUserAccountID, { @@ -1115,7 +1110,6 @@ function getReportDisplayOption( function getPolicyExpenseReportOption( participant: Participant | SearchOptionData, policyTags: OnyxCollection, - translate: LocalizedTranslate, currentUserAccountID: number, personalDetails: OnyxEntry, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], @@ -1130,7 +1124,6 @@ function getPolicyExpenseReportOption( visibleParticipantAccountIDs, personalDetails ?? {}, !isEmptyObject(expenseReport) ? expenseReport : null, - translate, reportPolicyTags, currentUserAccountID, { @@ -1246,7 +1239,6 @@ function isReportSelected(reportOption: SearchOptionData, selectedOptions: Array function processReport( report: OnyxEntry | null, personalDetails: OnyxEntry, - translate: LocalizedTranslate, policyTags: OnyxEntry, currentUserAccountID: number, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], @@ -1273,7 +1265,7 @@ function processReport( reportMapEntry, reportOption: { item: report, - ...createOption(accountIDs, personalDetails, report, translate, policyTags, currentUserAccountID, undefined, reportAttributesDerived), + ...createOption(accountIDs, personalDetails, report, policyTags, currentUserAccountID, undefined, reportAttributesDerived), }, }; } @@ -1281,7 +1273,6 @@ function processReport( function createOptionList( personalDetails: OnyxEntry, policyTags: OnyxCollection, - translate: LocalizedTranslate, currentUserAccountID: number, reports?: OnyxCollection, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], @@ -1294,7 +1285,7 @@ function createOptionList( if (reports) { for (const report of Object.values(reports)) { const reportPolicyTags = report?.policyID ? policyTags?.[report?.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; - const {reportMapEntry, reportOption} = processReport(report, personalDetails, translate, reportPolicyTags, currentUserAccountID, reportAttributesDerived); + const {reportMapEntry, reportOption} = processReport(report, personalDetails, reportPolicyTags, currentUserAccountID, reportAttributesDerived); if (reportMapEntry) { const [accountID, reportValue] = reportMapEntry; @@ -1316,7 +1307,6 @@ function createOptionList( [personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID], personalDetails, report, - translate, policyTagList, currentUserAccountID, { @@ -1356,7 +1346,6 @@ function createFilteredOptionList( personalDetails: OnyxEntry, reports: OnyxCollection, policyTags: OnyxCollection, - translate: LocalizedTranslate, currentUserAccountID: number, reportAttributesDerived: ReportAttributesDerivedValue['reports'] | undefined, options: { @@ -1415,7 +1404,7 @@ function createFilteredOptionList( const reportOptions: Array> = []; for (const report of limitedReports) { const reportPolicyTags = report?.policyID ? policyTags?.[report?.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; - const {reportMapEntry, reportOption} = processReport(report, personalDetails, translate, reportPolicyTags, currentUserAccountID, reportAttributesDerived); + const {reportMapEntry, reportOption} = processReport(report, personalDetails, reportPolicyTags, currentUserAccountID, reportAttributesDerived); if (reportMapEntry) { const [accountID, reportValue] = reportMapEntry; @@ -1451,7 +1440,6 @@ function createFilteredOptionList( [accountID], personalDetails, reportMapForAccountIDs[accountID], - translate, reportPolicyTags, currentUserAccountID, {showPersonalDetails: true}, @@ -1471,7 +1459,6 @@ function createOptionFromReport( report: Report, personalDetails: OnyxEntry, policyTags: OnyxEntry, - translate: LocalizedTranslate, currentUserAccountID: number, reportAttributesDerived?: ReportAttributesDerivedValue['reports'], config?: PreviewConfig, @@ -1480,7 +1467,7 @@ function createOptionFromReport( return { item: report, - ...createOption(accountIDs, personalDetails, report, translate, policyTags, currentUserAccountID, config, reportAttributesDerived), + ...createOption(accountIDs, personalDetails, report, policyTags, currentUserAccountID, config, reportAttributesDerived), }; } @@ -1759,7 +1746,6 @@ function canCreateOptimisticPersonalDetailOption({ */ function getUserToInviteOption({ searchValue, - translate, loginsToExclude = {}, selectedOptions = [], showChatPreviewLine = false, @@ -1796,7 +1782,7 @@ function getUserToInviteOption({ login: searchValue, }, }; - const userToInvite = createOption([optimisticAccountID], personalDetailsExtended, null, translate, undefined, currentUserAccountID, { + const userToInvite = createOption([optimisticAccountID], personalDetailsExtended, null, undefined, currentUserAccountID, { showChatPreviewLine, }); userToInvite.isOptimisticAccount = true; @@ -2217,7 +2203,6 @@ function getValidOptions( draftComments: OnyxCollection | undefined, nvpDismissedProductTraining: OnyxEntry, policyTags: OnyxCollection, - translate: LocalizedTranslate, loginList: OnyxEntry, currentUserAccountID: number, currentUserEmail: string, @@ -2443,7 +2428,6 @@ function getValidOptions( userToInvite = filterUserToInvite( {currentUserOption: currentUserRef.current, recentReports: recentReportOptions, personalDetails: personalDetailsOptions}, searchString ?? '', - translate, loginList, currentUserEmail, currentUserAccountID, @@ -2466,7 +2450,6 @@ function getValidOptions( } type SearchOptionsConfig = { - translate: LocalizedTranslate; options: OptionList; nvpDismissedProductTraining: OnyxEntry; draftComments: OnyxCollection; @@ -2497,7 +2480,6 @@ function getSearchOptions({ nvpDismissedProductTraining, betas, policyTags, - translate, isUsedInChatFinder = true, includeReadOnly = true, searchQuery = '', @@ -2521,7 +2503,6 @@ function getSearchOptions({ draftComments, nvpDismissedProductTraining, policyTags, - translate, loginList, currentUserAccountID, currentUserEmail, @@ -2646,7 +2627,6 @@ function formatMemberForList(member: SearchOptionData): MemberForList { function getMemberInviteOptions( personalDetails: Array>, nvpDismissedProductTraining: OnyxEntry, - translate: LocalizedTranslate, loginList: OnyxEntry, currentUserAccountID: number, currentUserEmail: string, @@ -2661,7 +2641,6 @@ function getMemberInviteOptions( undefined, nvpDismissedProductTraining, {}, - translate, loginList, currentUserAccountID, currentUserEmail, @@ -2739,7 +2718,6 @@ function formatSectionsFromSearchTerm( filteredRecentReports: SearchOptionData[], filteredPersonalDetails: SearchOptionData[], policyTags: OnyxCollection, - translate: LocalizedTranslate, currentUserAccountID: number, personalDetails: OnyxEntry = {}, shouldGetOptionDetails = false, @@ -2757,7 +2735,7 @@ function formatSectionsFromSearchTerm( ? selectedOptions.map((participant) => { const isReportPolicyExpenseChat = participant.isPolicyExpenseChat ?? false; return isReportPolicyExpenseChat - ? getPolicyExpenseReportOption(participant, policyTags, translate, currentUserAccountID, personalDetails, reportAttributesDerived) + ? getPolicyExpenseReportOption(participant, policyTags, currentUserAccountID, personalDetails, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }) : selectedOptions, @@ -2785,7 +2763,7 @@ function formatSectionsFromSearchTerm( ? selectedParticipantsWithoutDetails.map((participant) => { const isReportPolicyExpenseChat = participant.isPolicyExpenseChat ?? false; return isReportPolicyExpenseChat - ? getPolicyExpenseReportOption(participant, policyTags, translate, currentUserAccountID, personalDetails, reportAttributesDerived) + ? getPolicyExpenseReportOption(participant, policyTags, currentUserAccountID, personalDetails, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }) : selectedParticipantsWithoutDetails, @@ -2910,7 +2888,6 @@ function filterCurrentUserOption(currentUserOption: SearchOptionData | null | un function filterUserToInvite( options: Omit, searchValue: string, - translate: LocalizedTranslate, loginList: OnyxEntry, currentUserEmail: string, currentUserAccountID: number, @@ -2941,7 +2918,6 @@ function filterUserToInvite( searchValue, loginsToExclude, countryCode, - translate, loginList, currentUserEmail, currentUserAccountID, @@ -2982,7 +2958,6 @@ function filterSelfDMChat(report: SearchOptionData, searchTerms: string[]): Sear function filterOptions( options: Options, searchInputValue: string, - translate: LocalizedTranslate, countryCode: number, loginList: OnyxEntry, currentUserEmail: string, @@ -3006,7 +2981,6 @@ function filterOptions( currentUserOption, }, searchValue, - translate, loginList, currentUserEmail, currentUserAccountID, @@ -3068,7 +3042,6 @@ function combineOrderingOfReportsAndPersonalDetails( function filterAndOrderOptions( options: Options, searchInputValue: string, - translate: LocalizedTranslate, countryCode: number, loginList: OnyxEntry, currentUserEmail: string, @@ -3077,7 +3050,7 @@ function filterAndOrderOptions( ): Options { let filterResult = options; if (searchInputValue.trim().length > 0) { - filterResult = filterOptions(options, searchInputValue, translate, countryCode, loginList, currentUserEmail, currentUserAccountID, config); + filterResult = filterOptions(options, searchInputValue, countryCode, loginList, currentUserEmail, currentUserAccountID, config); } const orderedOptions = combineOrderingOfReportsAndPersonalDetails(filterResult, searchInputValue, config); diff --git a/src/libs/OptionsListUtils/types.ts b/src/libs/OptionsListUtils/types.ts index 12d70479cee7d..1ef59e47de844 100644 --- a/src/libs/OptionsListUtils/types.ts +++ b/src/libs/OptionsListUtils/types.ts @@ -202,7 +202,6 @@ type GetOptionsConfig = { type GetUserToInviteConfig = { searchValue: string | undefined; - translate: LocalizedTranslate; searchInputValue?: string; loginsToExclude?: Record; reportActions?: ReportActions; diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index 6da321bbf00cd..43f5babf7383c 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -57,7 +57,6 @@ type SelectedOption = ListItem & }; function useOptions() { - const {translate} = useLocalize(); const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState(''); const [selectedOptions, setSelectedOptions] = useState([]); const [betas] = useOnyx(ONYXKEYS.BETAS, {canBeMissing: true}); @@ -105,7 +104,6 @@ function useOptions() { draftComments, nvpDismissedProductTraining, policyTags, - translate, loginList, currentUserAccountID, currentUserEmail, @@ -122,7 +120,7 @@ function useOptions() { const areOptionsInitialized = !isLoading; - const options = filterAndOrderOptions(unselectedOptions, debouncedSearchTerm, translate, countryCode, loginList, currentUserEmail, currentUserAccountID, { + const options = filterAndOrderOptions(unselectedOptions, debouncedSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID, { selectedOptions, maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, }); @@ -165,7 +163,6 @@ function useOptions() { personalDetails.find((option) => option.accountID === participant.accountID) ?? getUserToInviteOption({ searchValue: participant?.login, - translate, loginList, currentUserEmail: personalData.email ?? '', currentUserAccountID: personalData.accountID, @@ -276,7 +273,6 @@ function NewChatPage({ref}: NewChatPageProps) { recentReports, personalDetails, undefined, - translate, currentUserAccountID, allPersonalDetails, undefined, diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx index 906d32522ca53..3ef0b2aa90c8a 100644 --- a/src/pages/RoomInvitePage.tsx +++ b/src/pages/RoomInvitePage.tsx @@ -99,7 +99,6 @@ function RoomInvitePage({ const inviteOptions = getMemberInviteOptions( options.personalDetails, nvpDismissedProductTraining, - translate, loginList, currentUserAccountID, currentUserEmail, @@ -126,18 +125,18 @@ function RoomInvitePage({ recentReports: [], currentUserOption: null, }; - }, [areOptionsInitialized, options.personalDetails, nvpDismissedProductTraining, translate, loginList, currentUserAccountID, currentUserEmail, betas, excludedUsers, selectedOptions]); + }, [areOptionsInitialized, options.personalDetails, nvpDismissedProductTraining, loginList, currentUserAccountID, currentUserEmail, betas, excludedUsers, selectedOptions]); const inviteOptions = useMemo(() => { if (debouncedSearchTerm.trim() === '') { return defaultOptions; } - const filteredOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, translate, countryCode, loginList, currentUserEmail, currentUserAccountID, { + const filteredOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID, { excludeLogins: excludedUsers, }); return filteredOptions; - }, [debouncedSearchTerm, defaultOptions, translate, countryCode, loginList, currentUserEmail, currentUserAccountID, excludedUsers]); + }, [debouncedSearchTerm, defaultOptions, countryCode, loginList, currentUserEmail, currentUserAccountID, excludedUsers]); const sections = useMemo(() => { const sectionsArr: Sections = []; diff --git a/src/pages/Share/ShareTab.tsx b/src/pages/Share/ShareTab.tsx index 82b553538fd54..138c2eaaf8599 100644 --- a/src/pages/Share/ShareTab.tsx +++ b/src/pages/Share/ShareTab.tsx @@ -71,7 +71,6 @@ function ShareTab({ref}: ShareTabProps) { return defaultListOptions; } return getSearchOptions({ - translate, options, draftComments, nvpDismissedProductTraining, @@ -89,7 +88,6 @@ function ShareTab({ref}: ShareTabProps) { }); }, [ areOptionsInitialized, - translate, options, draftComments, nvpDismissedProductTraining, diff --git a/src/pages/iou/SplitBillDetailsPage.tsx b/src/pages/iou/SplitBillDetailsPage.tsx index 9b8593fbe7ba1..48bce5817e08a 100644 --- a/src/pages/iou/SplitBillDetailsPage.tsx +++ b/src/pages/iou/SplitBillDetailsPage.tsx @@ -74,7 +74,7 @@ function SplitBillDetailsPage({route, report, reportAction}: SplitBillDetailsPag if (isPolicyExpenseChat(report)) { participants = [ getParticipantsOption({accountID: participantAccountIDs.at(0), selected: true, reportID: ''}, personalDetails), - getPolicyExpenseReportOption({...report, selected: true, reportID}, policyTags, translate, currentUserPersonalDetails.accountID, personalDetails, reportAttributesDerived), + getPolicyExpenseReportOption({...report, selected: true, reportID}, policyTags, currentUserPersonalDetails.accountID, personalDetails, reportAttributesDerived), ]; } else { participants = participantAccountIDs.map((accountID) => getParticipantsOption({accountID, selected: true, reportID: ''}, personalDetails)); diff --git a/src/pages/iou/request/MoneyRequestAccountantSelector.tsx b/src/pages/iou/request/MoneyRequestAccountantSelector.tsx index cc9f33bba950c..55460c79917ed 100644 --- a/src/pages/iou/request/MoneyRequestAccountantSelector.tsx +++ b/src/pages/iou/request/MoneyRequestAccountantSelector.tsx @@ -91,7 +91,6 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType draftComments, nvpDismissedProductTraining, policyTags, - translate, loginList, currentUserAccountID, currentUserEmail, @@ -119,7 +118,6 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType draftComments, nvpDismissedProductTraining, policyTags, - translate, loginList, betas, action, @@ -139,12 +137,12 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType headerMessage: '', }; } - const newOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, translate, countryCode, loginList, currentUserEmail, currentUserAccountID, { + const newOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, }); return newOptions; - }, [areOptionsInitialized, defaultOptions, debouncedSearchTerm, translate, countryCode, loginList, currentUserEmail, currentUserAccountID]); + }, [areOptionsInitialized, defaultOptions, debouncedSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID]); /** * Returns the sections needed for the OptionsSelector @@ -164,7 +162,6 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType chatOptions.recentReports, chatOptions.personalDetails, policyTags, - translate, currentUserAccountID, personalDetails, true, @@ -198,7 +195,7 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType data: [chatOptions.userToInvite].map((participant) => { const isPolicyExpenseChat = participant?.isPolicyExpenseChat ?? false; return isPolicyExpenseChat - ? getPolicyExpenseReportOption(participant, policyTags, translate, currentUserAccountID, personalDetails, reportAttributesDerived) + ? getPolicyExpenseReportOption(participant, policyTags, currentUserAccountID, personalDetails, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }), shouldShow: true, diff --git a/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx b/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx index 9e9b5c1dfa7da..d71ae123de469 100644 --- a/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx +++ b/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx @@ -216,7 +216,6 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde orderedAvailableOptions.recentReports, orderedAvailableOptions.personalDetails, policyTags, - translate, currentUserAccountID, personalDetails, true, @@ -260,7 +259,7 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde data: [orderedAvailableOptions.userToInvite].map((participant) => { const isPolicyExpenseChat = participant?.isPolicyExpenseChat ?? false; return isPolicyExpenseChat - ? getPolicyExpenseReportOption(participant, policyTags, translate, currentUserAccountID, personalDetails, reportAttributesDerived) + ? getPolicyExpenseReportOption(participant, policyTags, currentUserAccountID, personalDetails, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }) as OptionData[], shouldShow: true, @@ -276,24 +275,7 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde ); return [newSections, headerMessage]; - }, [ - areOptionsInitialized, - didScreenTransitionEnd, - searchTerm, - initialSelectedOptions, - attendees, - orderedAvailableOptions.recentReports, - orderedAvailableOptions.personalDetails, - orderedAvailableOptions.userToInvite, - personalDetails, - reportAttributesDerived, - loginList, - countryCode, - policyTags, - translate, - currentUserAccountID, - currentUserEmail, - ]); + }, [areOptionsInitialized, didScreenTransitionEnd, searchTerm, initialSelectedOptions, orderedAvailableOptions.recentReports, orderedAvailableOptions.personalDetails, orderedAvailableOptions.userToInvite, policyTags, currentUserAccountID, personalDetails, reportAttributesDerived, loginList, currentUserEmail, countryCode, attendees, translate]); const optionLength = useMemo(() => { if (!areOptionsInitialized) { diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index aa9673f6e6593..0122c8e3c12cc 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -293,7 +293,6 @@ function MoneyRequestParticipantsSelector({ [], [], policyTags, - translate, currentUserAccountID, personalDetails, true, @@ -348,7 +347,7 @@ function MoneyRequestParticipantsSelector({ data: [availableOptions.userToInvite].map((participant) => { const isPolicyExpenseChat = participant?.isPolicyExpenseChat ?? false; return isPolicyExpenseChat - ? getPolicyExpenseReportOption(participant, policyTags, translate, currentUserAccountID, personalDetails, reportAttributesDerived) + ? getPolicyExpenseReportOption(participant, policyTags, currentUserAccountID, personalDetails, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }), shouldShow: true, @@ -361,28 +360,7 @@ function MoneyRequestParticipantsSelector({ } return [newSections, headerMessage]; - }, [ - areOptionsInitialized, - didScreenTransitionEnd, - searchTerm, - participants, - policyTags, - translate, - personalDetails, - reportAttributesDerived, - availableOptions.workspaceChats, - availableOptions.selfDMChat, - availableOptions.userToInvite, - availableOptions.recentReports, - availableOptions.personalDetails, - isWorkspacesOnly, - loginList, - isPerDiemRequest, - showImportContacts, - inputHelperText, - currentUserAccountID, - currentUserEmail, - ]); + }, [areOptionsInitialized, didScreenTransitionEnd, searchTerm, participants, policyTags, currentUserAccountID, personalDetails, reportAttributesDerived, translate, availableOptions.workspaceChats, availableOptions.selfDMChat, availableOptions.userToInvite, availableOptions.recentReports, availableOptions.personalDetails, isWorkspacesOnly, loginList, currentUserEmail, isPerDiemRequest, showImportContacts, inputHelperText]); /** * Removes a selected option from list if already selected. If not already selected add this option to the list. diff --git a/tests/perf-test/OptionsListUtils.perf-test.ts b/tests/perf-test/OptionsListUtils.perf-test.ts index 1a24d8b844d5e..eff0ccbbb0bad 100644 --- a/tests/perf-test/OptionsListUtils.perf-test.ts +++ b/tests/perf-test/OptionsListUtils.perf-test.ts @@ -93,7 +93,7 @@ jest.mock('@react-navigation/native', () => { }; }); -const options = createOptionList(personalDetails, undefined, jest.fn(), MOCK_CURRENT_USER_ACCOUNT_ID, reports); +const options = createOptionList(personalDetails, undefined, MOCK_CURRENT_USER_ACCOUNT_ID, reports); const ValidOptionsConfig = { betas: mockedBetas, @@ -138,7 +138,6 @@ describe('OptionsListUtils', () => { currentUserAccountID: MOCK_CURRENT_USER_ACCOUNT_ID, currentUserEmail: MOCK_CURRENT_USER_EMAIL, policyTags: undefined, - translate: jest.fn(), }), ); }); @@ -152,14 +151,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - jest.fn(), loginList, MOCK_CURRENT_USER_ACCOUNT_ID, MOCK_CURRENT_USER_EMAIL, ValidOptionsConfig, ); await measureFunction(() => { - filterAndOrderOptions(formattedOptions, SEARCH_VALUE, jest.fn(), COUNTRY_CODE, loginList, MOCK_CURRENT_USER_EMAIL, MOCK_CURRENT_USER_ACCOUNT_ID); + filterAndOrderOptions(formattedOptions, SEARCH_VALUE, COUNTRY_CODE, loginList, MOCK_CURRENT_USER_EMAIL, MOCK_CURRENT_USER_ACCOUNT_ID); }); }); test('[OptionsListUtils] getFilteredOptions with empty search value', async () => { @@ -170,14 +168,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - jest.fn(), loginList, MOCK_CURRENT_USER_ACCOUNT_ID, MOCK_CURRENT_USER_EMAIL, ValidOptionsConfig, ); await measureFunction(() => { - filterAndOrderOptions(formattedOptions, '', jest.fn(), COUNTRY_CODE, loginList, MOCK_CURRENT_USER_EMAIL, MOCK_CURRENT_USER_ACCOUNT_ID); + filterAndOrderOptions(formattedOptions, '', COUNTRY_CODE, loginList, MOCK_CURRENT_USER_EMAIL, MOCK_CURRENT_USER_ACCOUNT_ID); }); }); @@ -191,7 +188,6 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - jest.fn(), loginList, MOCK_CURRENT_USER_ACCOUNT_ID, MOCK_CURRENT_USER_EMAIL, @@ -220,7 +216,6 @@ describe('OptionsListUtils', () => { getMemberInviteOptions( options.personalDetails, nvpDismissedProductTraining, - jest.fn(), loginList, MOCK_CURRENT_USER_ACCOUNT_ID, MOCK_CURRENT_USER_EMAIL, @@ -275,7 +270,6 @@ describe('OptionsListUtils', () => { Object.values(filteredRecentReports), Object.values(filteredPersonalDetails), undefined, - jest.fn(), MOCK_CURRENT_USER_ACCOUNT_ID, mockedPersonalDetails, true, @@ -290,7 +284,7 @@ describe('OptionsListUtils', () => { await waitForBatchedUpdates(); await measureFunction(() => - formatSectionsFromSearchTerm('', Object.values(selectedOptions), [], [], undefined, jest.fn(), MOCK_CURRENT_USER_ACCOUNT_ID, mockedPersonalDetails, true), + formatSectionsFromSearchTerm('', Object.values(selectedOptions), [], [], undefined, MOCK_CURRENT_USER_ACCOUNT_ID, mockedPersonalDetails, true), ); }); }); diff --git a/tests/perf-test/SearchRouter.perf-test.tsx b/tests/perf-test/SearchRouter.perf-test.tsx index cb7f0c6a4ee22..317a2b4f24ef0 100644 --- a/tests/perf-test/SearchRouter.perf-test.tsx +++ b/tests/perf-test/SearchRouter.perf-test.tsx @@ -106,7 +106,7 @@ const MOCK_CURRENT_USER_ACCOUNT_ID = 1; const mockedReports = getMockedReports(600); const mockedBetas = Object.values(CONST.BETAS); const mockedPersonalDetails = getMockedPersonalDetails(100); -const mockedOptions = createOptionList(mockedPersonalDetails, undefined, jest.fn(), MOCK_CURRENT_USER_ACCOUNT_ID, mockedReports); +const mockedOptions = createOptionList(mockedPersonalDetails, undefined, MOCK_CURRENT_USER_ACCOUNT_ID, mockedReports); beforeAll(() => Onyx.init({ diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index d2bfffe9c12c1..3b685e522345c 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -640,12 +640,12 @@ describe('OptionsListUtils', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}10`, reportNameValuePairs); await waitForBatchedUpdates(); - OPTIONS = createOptionList(PERSONAL_DETAILS, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, REPORTS); - OPTIONS_WITH_CONCIERGE = createOptionList(PERSONAL_DETAILS_WITH_CONCIERGE, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_CONCIERGE); - OPTIONS_WITH_CHRONOS = createOptionList(PERSONAL_DETAILS_WITH_CHRONOS, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_CHRONOS); - OPTIONS_WITH_RECEIPTS = createOptionList(PERSONAL_DETAILS_WITH_RECEIPTS, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_RECEIPTS); - OPTIONS_WITH_WORKSPACE_ROOM = createOptionList(PERSONAL_DETAILS, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_WORKSPACE_ROOMS); - OPTIONS_WITH_MANAGER_MCTEST = createOptionList(PERSONAL_DETAILS_WITH_MANAGER_MCTEST, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID); + OPTIONS = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS); + OPTIONS_WITH_CONCIERGE = createOptionList(PERSONAL_DETAILS_WITH_CONCIERGE, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_CONCIERGE); + OPTIONS_WITH_CHRONOS = createOptionList(PERSONAL_DETAILS_WITH_CHRONOS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_CHRONOS); + OPTIONS_WITH_RECEIPTS = createOptionList(PERSONAL_DETAILS_WITH_RECEIPTS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_RECEIPTS); + OPTIONS_WITH_WORKSPACE_ROOM = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_WORKSPACE_ROOMS); + OPTIONS_WITH_MANAGER_MCTEST = createOptionList(PERSONAL_DETAILS_WITH_MANAGER_MCTEST, undefined, CURRENT_USER_ACCOUNT_ID); }); describe('getSearchOptions()', () => { @@ -657,7 +657,6 @@ describe('OptionsListUtils', () => { draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - translate: translateLocal, loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, @@ -687,7 +686,6 @@ describe('OptionsListUtils', () => { includeRecentReports: true, includeCurrentUser: true, policyTags: {}, - translate: translateLocal, loginList, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, @@ -718,7 +716,6 @@ describe('OptionsListUtils', () => { includeUserToInvite: false, includeRecentReports: true, policyTags: undefined, - translate: translateLocal, loginList, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, @@ -746,7 +743,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -787,7 +784,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -824,7 +821,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -848,7 +845,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -872,7 +869,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -896,7 +893,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -923,7 +920,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -952,7 +949,7 @@ describe('OptionsListUtils', () => { }, }, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -978,7 +975,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1013,7 +1010,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1072,7 +1069,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1128,7 +1125,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1182,7 +1179,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1240,7 +1237,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1277,7 +1274,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1303,7 +1300,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1331,7 +1328,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1354,7 +1351,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1377,7 +1374,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1401,7 +1398,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1426,7 +1423,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1454,7 +1451,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1480,7 +1477,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1502,7 +1499,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1513,7 +1510,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1535,7 +1532,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1546,7 +1543,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1570,7 +1567,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1606,7 +1603,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1649,7 +1646,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1678,7 +1675,7 @@ describe('OptionsListUtils', () => { it('should sort personal details alphabetically', () => { // Given a set of personalDetails // When we call getMemberInviteOptions - const results = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, translateLocal, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, []); + const results = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, []); // Then personal details should be sorted alphabetically expect(results.personalDetails.at(0)?.text).toBe('Black Panther'); @@ -1871,14 +1868,13 @@ describe('OptionsListUtils', () => { draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - translate: translateLocal, loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with an empty search value - const filteredOptions = filterAndOrderOptions(options, '', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, '', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then all options should be returned expect(filteredOptions.recentReports.length + filteredOptions.personalDetails.length).toBe(14); @@ -1894,13 +1890,12 @@ describe('OptionsListUtils', () => { nvpDismissedProductTraining, loginList, policyTags: undefined, - translate: translateLocal, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with a search value and sortByReportTypeInSearch param - const filteredOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { sortByReportTypeInSearch: true, }); @@ -1925,13 +1920,13 @@ describe('OptionsListUtils', () => { nvpDismissedProductTraining, loginList, policyTags: undefined, - translate: translateLocal, + betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1949,13 +1944,13 @@ describe('OptionsListUtils', () => { nvpDismissedProductTraining, loginList, policyTags: undefined, - translate: translateLocal, + betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1967,21 +1962,21 @@ describe('OptionsListUtils', () => { // cspell:disable-next-line const searchText = 'barryallen'; // Given a set of options created from PERSONAL_DETAILS_WITH_PERIODS - const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, REPORTS); + const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS); // When we call getSearchOptions with all betas const options = getSearchOptions({ options: OPTIONS_WITH_PERIODS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - translate: translateLocal, + loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with a search value and sortByReportTypeInSearch param - const filteredOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { sortByReportTypeInSearch: true, }); @@ -2000,14 +1995,14 @@ describe('OptionsListUtils', () => { draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - translate: translateLocal, + loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -2023,14 +2018,13 @@ describe('OptionsListUtils', () => { draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - translate: translateLocal, loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -2041,21 +2035,21 @@ describe('OptionsListUtils', () => { it('should prioritize options with matching display name over chat rooms', () => { const searchText = 'spider'; // Given a set of options with chat rooms - const OPTIONS_WITH_CHAT_ROOMS = createOptionList(PERSONAL_DETAILS, {}, translateLocal, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_CHAT_ROOM); + const OPTIONS_WITH_CHAT_ROOMS = createOptionList(PERSONAL_DETAILS, {}, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_CHAT_ROOM); // When we call getSearchOptions with all betas const options = getSearchOptions({ options: OPTIONS_WITH_CHAT_ROOMS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - translate: translateLocal, + loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with a search value - const filterOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filterOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then only two reports should be returned expect(filterOptions.recentReports.length).toBe(2); @@ -2072,13 +2066,13 @@ describe('OptionsListUtils', () => { draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - translate: translateLocal, + loginList, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then only three reports should be returned expect(filteredOptions.recentReports.length).toBe(3); @@ -2095,14 +2089,14 @@ describe('OptionsListUtils', () => { options: OPTIONS, draftComments: {}, policyTags: undefined, - translate: translateLocal, + loginList, nvpDismissedProductTraining, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then the user to invite should be returned expect(filteredOptions.userToInvite?.login).toBe(searchText); @@ -2117,7 +2111,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -2126,7 +2120,7 @@ describe('OptionsListUtils', () => { }, ); // When we call filterAndOrderOptions with a search value and excluded logins list - const filterOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { + const filterOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, }); @@ -2145,10 +2139,10 @@ describe('OptionsListUtils', () => { currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, policyTags: undefined, - translate: translateLocal, + }); // When we call filterAndOrderOptions with a search value and excludeLogins - const filteredOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, }); @@ -2167,10 +2161,10 @@ describe('OptionsListUtils', () => { currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, policyTags: undefined, - translate: translateLocal, + }); // When we call filterAndOrderOptions with a search value and maxRecentReportsToShow set to 2 - const filteredOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { maxRecentReportsToShow: 2, }); @@ -2179,7 +2173,7 @@ describe('OptionsListUtils', () => { // Note: in the past maxRecentReportsToShow: 0 would return all recent reports, this has changed, and is expected to return none now // When we call filterAndOrderOptions with a search value and maxRecentReportsToShow set to 0 - const limitToZeroOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { + const limitToZeroOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { maxRecentReportsToShow: 0, }); @@ -2199,10 +2193,10 @@ describe('OptionsListUtils', () => { currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, policyTags: undefined, - translate: translateLocal, + }); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then there should be one matching result expect(filteredOptions.personalDetails.length).toBe(1); @@ -2212,9 +2206,9 @@ describe('OptionsListUtils', () => { it('should not return any options if search value does not match any personal details (getMemberInviteOptions)', () => { // Given a set of options - const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, translateLocal, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, []); + const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, []); // When we call filterAndOrderOptions with a search value that does not match any personal details - const filteredOptions = filterAndOrderOptions(options, 'magneto', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'magneto', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no personal details should be returned expect(filteredOptions.personalDetails.length).toBe(0); @@ -2222,9 +2216,9 @@ describe('OptionsListUtils', () => { it('should return one personal detail if search value matches an email (getMemberInviteOptions)', () => { // Given a set of options - const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, translateLocal, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, []); + const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, []); // When we call filterAndOrderOptions with a search value that matches an email - const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then one personal detail should be returned expect(filteredOptions.personalDetails.length).toBe(1); @@ -2248,7 +2242,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -2268,7 +2262,7 @@ describe('OptionsListUtils', () => { }, ); // When we pass the returned options to filterAndOrderOptions with a search value that does not match the group chat name - const filteredOptions = filterAndOrderOptions(options, 'mutants', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'mutants', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2292,7 +2286,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -2312,7 +2306,7 @@ describe('OptionsListUtils', () => { }, ); // When we pass the returned options to filterAndOrderOptions with a search value that matches the group chat name - const filteredOptions = filterAndOrderOptions(options, 'Avengers Room', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'Avengers Room', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then one recent report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -2336,7 +2330,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -2356,7 +2350,7 @@ describe('OptionsListUtils', () => { }, ); // When we pass the returned options to filterAndOrderOptions with a search value that does not match the group chat name - const filteredOptions = filterAndOrderOptions(options, 'Mutants Lair', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'Mutants Lair', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2370,13 +2364,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // When we call filterAndOrderOptions with a search value that matches a personal detail with no existing report - const filteredOptions = filterAndOrderOptions(options, 'hulk', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'hulk', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2394,13 +2388,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // When we call filterAndOrderOptions with a search value that does not match any personal details or reports - const filteredOptions = filterAndOrderOptions(options, 'marc@expensify', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'marc@expensify', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2417,13 +2411,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // When we call filterAndOrderOptions with a search value that does not match any personal details or reports - const filteredOptions = filterAndOrderOptions(options, 'marc@expensify.com', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'marc@expensify.com', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2440,13 +2434,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'peter.parker@expensify.com', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2462,13 +2456,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // When we call filterAndOrderOptions with a search value without accent mark - const filteredOptions = filterAndOrderOptions(options, 'Timothee', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'Timothee', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then one personalDetails with accent mark should be returned expect(filteredOptions.personalDetails.length).toBe(1); @@ -2482,13 +2476,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, '5005550006', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2507,13 +2501,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, '+15005550006', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2532,13 +2526,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, '+1 (800)324-3233', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2557,13 +2551,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // When we call filterAndOrderOptions with a search value that does not match any personal details or reports - const filteredOptions = filterAndOrderOptions(options, '998243aaaa', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, '998243aaaa', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2580,13 +2574,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // When we call filterAndOrderOptions with a search value that does not match any personal details - const filteredOptions = filterAndOrderOptions(options, 'magneto', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'magneto', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no personal details should be returned expect(filteredOptions.personalDetails.length).toBe(0); @@ -2600,13 +2594,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // When we call filterAndOrderOptions with a search value that matches an email - const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { + const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { sortByReportTypeInSearch: true, }); @@ -2626,13 +2620,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // When we call filterAndOrderOptions with a search value that matches both reports and personal details and maxRecentReportsToShow param - const filteredOptions = filterAndOrderOptions(options, '.com', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { + const filteredOptions = filterAndOrderOptions(options, '.com', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { maxRecentReportsToShow: 5, }); @@ -2657,10 +2651,10 @@ describe('OptionsListUtils', () => { currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, policyTags: undefined, - translate: translateLocal, + }); // When we call filterAndOrderOptions with a search value that matches a personal detail - const filteredOptions = filterAndOrderOptions(options, 'spider', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'spider', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then one personal detail should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -2678,10 +2672,10 @@ describe('OptionsListUtils', () => { currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, policyTags: undefined, - translate: translateLocal, + }); // When we call filterAndOrderOptions with a search value that matches multiple items - const filteredOptions = filterAndOrderOptions(options, 'fantastic', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'fantastic', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then only three reports should be returned expect(filteredOptions.recentReports.length).toBe(3); @@ -2694,14 +2688,14 @@ describe('OptionsListUtils', () => { .then(() => Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, PERSONAL_DETAILS_WITH_PERIODS)) .then(() => { // Given a set of options with periods - const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, REPORTS); + const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS); // When we call getSearchOptions const results = getSearchOptions({ options: OPTIONS_WITH_PERIODS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - translate: translateLocal, + loginList, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, @@ -2710,7 +2704,7 @@ describe('OptionsListUtils', () => { const filteredResults = filterAndOrderOptions( results, 'barry.allen@expensify.com', - translateLocal, + COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, @@ -2739,14 +2733,14 @@ describe('OptionsListUtils', () => { draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - translate: translateLocal, + loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we call filterAndOrderOptions with a an empty search value - const filteredOptions = filterAndOrderOptions(options, '', translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, '', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); const matchingEntries = filteredOptions.personalDetails.filter((detail) => detail.login === login); // Then there should be 2 unique login entries @@ -2757,7 +2751,7 @@ describe('OptionsListUtils', () => { it('should order self dm always on top if the search matches with the self dm login', () => { const searchTerm = 'tonystark@expensify.com'; - const OPTIONS_WITH_SELF_DM = createOptionList(PERSONAL_DETAILS, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_SELF_DM); + const OPTIONS_WITH_SELF_DM = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_SELF_DM); // Given a set of options with self dm and all betas const options = getSearchOptions({ @@ -2765,14 +2759,14 @@ describe('OptionsListUtils', () => { draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - translate: translateLocal, + loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchTerm, translateLocal, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchTerm, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then the self dm should be on top. expect(filteredOptions.recentReports.at(0)?.isSelfDM).toBe(true); @@ -2819,7 +2813,7 @@ describe('OptionsListUtils', () => { renderLocaleContextProvider(); // Given a set of reports and personal details // When we call createOptionList and extract the reports - const reports = createOptionList(PERSONAL_DETAILS, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, REPORTS).reports; + const reports = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS).reports; // Then the returned reports should match the expected values expect(reports.at(10)?.subtitle).toBe(`Submits to Mister Fantastic`); @@ -2830,7 +2824,7 @@ describe('OptionsListUtils', () => { .then(() => Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, CONST.LOCALES.ES)) .then(() => { // When we call createOptionList again - const newReports = createOptionList(PERSONAL_DETAILS, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, REPORTS).reports; + const newReports = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS).reports; // Then the returned reports should change to Spanish // cspell:disable-next-line expect(newReports.at(10)?.subtitle).toBe('Se envía a Mister Fantastic'); @@ -2910,7 +2904,7 @@ describe('OptionsListUtils', () => { }, }); // When we call createOptionList - const reports = createOptionList(PERSONAL_DETAILS, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, REPORTS).reports; + const reports = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS).reports; const archivedReport = reports.find((report) => report.reportID === '10'); // Then the returned report should contain default archived reason @@ -3324,7 +3318,7 @@ describe('OptionsListUtils', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, transaction); await waitForBatchedUpdates(); - const result = createOption([1, 2], PERSONAL_DETAILS, report, translateLocal, CONST.POLICY.DEFAULT_TAG_LIST, CURRENT_USER_ACCOUNT_ID, {showChatPreviewLine: true}); + const result = createOption([1, 2], PERSONAL_DETAILS, report, CONST.POLICY.DEFAULT_TAG_LIST, CURRENT_USER_ACCOUNT_ID, {showChatPreviewLine: true}); expect(result.alternateText).toBe('Iron Man owes ₫34'); }); @@ -3416,7 +3410,7 @@ describe('OptionsListUtils', () => { [movedTransactionAction.reportActionID]: movedTransactionAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3441,7 +3435,7 @@ describe('OptionsListUtils', () => { [submittedAction.reportActionID]: submittedAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3467,7 +3461,7 @@ describe('OptionsListUtils', () => { [approvedAction.reportActionID]: approvedAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3493,7 +3487,7 @@ describe('OptionsListUtils', () => { [forwardedAction.reportActionID]: forwardedAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3516,7 +3510,7 @@ describe('OptionsListUtils', () => { [corporateForceUpgradeAction.reportActionID]: corporateForceUpgradeAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3538,7 +3532,7 @@ describe('OptionsListUtils', () => { [takeControlAction.reportActionID]: takeControlAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3559,7 +3553,7 @@ describe('OptionsListUtils', () => { [rerouteAction.reportActionID]: rerouteAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3580,7 +3574,7 @@ describe('OptionsListUtils', () => { [movedAction.reportActionID]: movedAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3605,7 +3599,7 @@ describe('OptionsListUtils', () => { // When getting the last message text for the report const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3632,7 +3626,7 @@ describe('OptionsListUtils', () => { const expectedVisibleText = ''; const result = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3682,7 +3676,7 @@ describe('OptionsListUtils', () => { [submittedAction.reportActionID]: submittedAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3717,7 +3711,7 @@ describe('OptionsListUtils', () => { [dewSubmitFailedAction.reportActionID]: dewSubmitFailedAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3747,7 +3741,7 @@ describe('OptionsListUtils', () => { [dewSubmitFailedAction.reportActionID]: dewSubmitFailedAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -4135,7 +4129,7 @@ describe('OptionsListUtils', () => { undefined, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -4148,7 +4142,7 @@ describe('OptionsListUtils', () => { it('should work with undefined policies', () => { const options = {reports: [], personalDetails: []}; - const results = getValidOptions(options, undefined, undefined, nvpDismissedProductTraining, undefined, translateLocal, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL); + const results = getValidOptions(options, undefined, undefined, nvpDismissedProductTraining, undefined, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL); expect(results).toBeDefined(); expect(results.recentReports).toBeDefined(); @@ -4157,7 +4151,7 @@ describe('OptionsListUtils', () => { it('should work with empty policies collection', () => { const options = {reports: [], personalDetails: []}; - const results = getValidOptions(options, {}, undefined, nvpDismissedProductTraining, undefined, translateLocal, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL); + const results = getValidOptions(options, {}, undefined, nvpDismissedProductTraining, undefined, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL); expect(results).toBeDefined(); expect(results.recentReports).toBeDefined(); @@ -4187,7 +4181,7 @@ describe('OptionsListUtils', () => { undefined, nvpDismissedProductTraining, undefined, - translateLocal, + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -4899,7 +4893,7 @@ describe('OptionsListUtils', () => { selected: true, }; - const option = getPolicyExpenseReportOption(participant, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, testPersonalDetails); + const option = getPolicyExpenseReportOption(participant, undefined, CURRENT_USER_ACCOUNT_ID, testPersonalDetails); expect(option).toBeDefined(); expect(option.text).toBe('Test Workspace Policy'); @@ -4960,7 +4954,7 @@ describe('OptionsListUtils', () => { isPolicyExpenseChat: true, }; - const option = getPolicyExpenseReportOption(participant, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, testPersonalDetails); + const option = getPolicyExpenseReportOption(participant, undefined, CURRENT_USER_ACCOUNT_ID, testPersonalDetails); expect(option).toBeDefined(); expect(option.text).toBe('Team Workspace'); @@ -5004,7 +4998,7 @@ describe('OptionsListUtils', () => { }; // Should not throw when personalDetails is empty - const option = getPolicyExpenseReportOption(participant, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, {}); + const option = getPolicyExpenseReportOption(participant, undefined, CURRENT_USER_ACCOUNT_ID, {}); expect(option).toBeDefined(); expect(option.text).toBe('Workspace Without Details'); @@ -5048,7 +5042,7 @@ describe('OptionsListUtils', () => { }; // Should not throw when personalDetails is undefined - const option = getPolicyExpenseReportOption(participant, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, undefined); + const option = getPolicyExpenseReportOption(participant, undefined, CURRENT_USER_ACCOUNT_ID, undefined); expect(option).toBeDefined(); expect(option.text).toBe('Workspace Undefined Details'); @@ -5100,10 +5094,10 @@ describe('OptionsListUtils', () => { selected: false, }; - const optionSelected = getPolicyExpenseReportOption(participantSelected, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, {}); + const optionSelected = getPolicyExpenseReportOption(participantSelected, undefined, CURRENT_USER_ACCOUNT_ID, {}); // eslint-disable-next-line rulesdir/no-negated-variables - const optionNotSelected = getPolicyExpenseReportOption(participantNotSelected, undefined, translateLocal, CURRENT_USER_ACCOUNT_ID, {}); + const optionNotSelected = getPolicyExpenseReportOption(participantNotSelected, undefined, CURRENT_USER_ACCOUNT_ID, {}); expect(optionSelected.isSelected).toBe(true); expect(optionSelected.selected).toBe(true); @@ -5117,7 +5111,6 @@ describe('OptionsListUtils', () => { const result = getUserToInviteOption({ searchValue: 'Jeff Amazon', loginList: {}, - translate: translateLocal, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); @@ -5129,7 +5122,6 @@ describe('OptionsListUtils', () => { searchValue: 'Jeff Amazon', shouldAcceptName: true, loginList: {}, - translate: translateLocal, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); From 96769b000f5145f3bfffab840e980e8ee3746cb7 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Wed, 28 Jan 2026 14:24:17 +0100 Subject: [PATCH 32/39] lint issues and prettier --- src/components/OptionListContextProvider.tsx | 14 +- .../FilterDropdowns/UserSelectPopup.tsx | 2 +- .../Search/SearchFiltersChatsSelector.tsx | 27 +- .../SearchFiltersParticipantsSelector.tsx | 15 +- src/hooks/useContactImport.ts | 4 +- src/hooks/useSearchSelector.base.ts | 152 ++++------ src/libs/OptionsListUtils/index.ts | 6 +- src/libs/OptionsListUtils/types.ts | 1 - src/pages/RoomInvitePage.tsx | 12 +- src/pages/Share/ShareTab.tsx | 14 +- src/pages/iou/SplitBillDetailsPage.tsx | 2 +- .../MoneyRequestAccountantSelector.tsx | 6 +- .../request/MoneyRequestAttendeeSelector.tsx | 19 +- .../MoneyRequestParticipantsSelector.tsx | 23 +- tests/perf-test/OptionsListUtils.perf-test.ts | 6 +- tests/perf-test/SearchRouter.perf-test.tsx | 2 +- tests/unit/OptionsListUtilsTest.tsx | 271 +++++++++--------- 17 files changed, 268 insertions(+), 308 deletions(-) diff --git a/src/components/OptionListContextProvider.tsx b/src/components/OptionListContextProvider.tsx index 03a8492d663ca..2bdaa334d725d 100644 --- a/src/components/OptionListContextProvider.tsx +++ b/src/components/OptionListContextProvider.tsx @@ -172,7 +172,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { reports: Array.from(updatedReportsMap.values()), }; }); - }, [changedReportActions, personalDetails, currentUserAccountID, reportAttributes?.reports, policyTags ]); + }, [changedReportActions, personalDetails, currentUserAccountID, reportAttributes?.reports, policyTags]); /** * This effect is used to update the options list when personal details change. @@ -190,13 +190,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { // Handle initial personal details load. This initialization is required here specifically to prevent // UI freezing that occurs when resetting the app from the troubleshooting page. if (!prevPersonalDetails) { - const {personalDetails: newPersonalDetailsOptions, reports: newReports} = createOptionList( - personalDetails, - policyTags, - currentUserAccountID, - reports, - reportAttributes?.reports, - ); + const {personalDetails: newPersonalDetailsOptions, reports: newReports} = createOptionList(personalDetails, policyTags, currentUserAccountID, reports, reportAttributes?.reports); setOptions((prevOptions) => ({ ...prevOptions, personalDetails: newPersonalDetailsOptions, @@ -230,7 +224,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { } const reportPolicyTags = report.policyID ? policyTags?.[report.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; - const newReportOption = createOptionFromReport(report, personalDetails, reportPolicyTags, currentUserAccountID, reportAttributes?.reports, { + const newReportOption = createOptionFromReport(report, personalDetails, reportPolicyTags, currentUserAccountID, reportAttributes?.reports, { showPersonalDetails: true, }); const replaceIndex = options.reports.findIndex((option) => option.reportID === report.reportID); @@ -242,7 +236,7 @@ function OptionsListContextProvider({children}: OptionsListProviderProps) { } // since personal details are not a collection, we need to recreate the whole list from scratch - const newPersonalDetailsOptions = createOptionList(personalDetails, policyTags, currentUserAccountID, reports, reportAttributes?.reports).personalDetails; + const newPersonalDetailsOptions = createOptionList(personalDetails, policyTags, currentUserAccountID, reports, reportAttributes?.reports).personalDetails; setOptions((prevOptions) => { const newOptions = {...prevOptions}; diff --git a/src/components/Search/FilterDropdowns/UserSelectPopup.tsx b/src/components/Search/FilterDropdowns/UserSelectPopup.tsx index 239f9140a2cda..a7e7c448e7abd 100644 --- a/src/components/Search/FilterDropdowns/UserSelectPopup.tsx +++ b/src/components/Search/FilterDropdowns/UserSelectPopup.tsx @@ -144,7 +144,7 @@ function UserSelectPopup({value, closeOverlay, onChange, isSearchable}: UserSele canInviteUser: false, }, ); - }, [optionsList, cleanSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID]); + }, [optionsList, cleanSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID]); const listData = useMemo(() => { const personalDetailList = filteredOptions.personalDetails.map((participant) => ({ diff --git a/src/components/Search/SearchFiltersChatsSelector.tsx b/src/components/Search/SearchFiltersChatsSelector.tsx index 5b92e0d2003a3..ed013d4e015af 100644 --- a/src/components/Search/SearchFiltersChatsSelector.tsx +++ b/src/components/Search/SearchFiltersChatsSelector.tsx @@ -70,19 +70,13 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen const reportObj = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`]; const reportPolicyTags = reportObj?.policyID ? policyTags?.[reportObj.policyID] : CONST.POLICY.DEFAULT_TAG_LIST; const report = getSelectedOptionData( - createOptionFromReport( - {...reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`], reportID: id}, - personalDetails, - reportPolicyTags, - currentUserAccountID, - reportAttributesDerived, - ), + createOptionFromReport({...reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`], reportID: id}, personalDetails, reportPolicyTags, currentUserAccountID, reportAttributesDerived), ); const isReportArchived = archivedReportsIdSet.has(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`); const alternateText = getAlternateText(report, {}, reportPolicyTags, isReportArchived, currentUserAccountID, {}); return {...report, alternateText}; }); - }, [selectedReportIDs, reports, policyTags, personalDetails, currentUserAccountID, reportAttributesDerived, archivedReportsIdSet]); + }, [selectedReportIDs, reports, policyTags, personalDetails, currentUserAccountID, reportAttributesDerived, archivedReportsIdSet]); const defaultOptions = useMemo(() => { if (!areOptionsInitialized || !isScreenTransitionEnd) { @@ -100,25 +94,14 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen currentUserEmail, policyTags, }); - }, [ - areOptionsInitialized, - isScreenTransitionEnd, - options, - draftComments, - nvpDismissedProductTraining, - countryCode, - loginList, - currentUserAccountID, - currentUserEmail, - policyTags, - ]); + }, [areOptionsInitialized, isScreenTransitionEnd, options, draftComments, nvpDismissedProductTraining, countryCode, loginList, currentUserAccountID, currentUserEmail, policyTags]); const chatOptions = useMemo(() => { - return filterAndOrderOptions(defaultOptions, cleanSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID, { + return filterAndOrderOptions(defaultOptions, cleanSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID, { selectedOptions, excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, }); - }, [defaultOptions, cleanSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID, selectedOptions]); + }, [defaultOptions, cleanSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID, selectedOptions]); const {sections, headerMessage} = useMemo(() => { const newSections: Section[] = []; diff --git a/src/components/Search/SearchFiltersParticipantsSelector.tsx b/src/components/Search/SearchFiltersParticipantsSelector.tsx index b1ec846c4d9ff..f2af974b3f9df 100644 --- a/src/components/Search/SearchFiltersParticipantsSelector.tsx +++ b/src/components/Search/SearchFiltersParticipantsSelector.tsx @@ -86,7 +86,20 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: }, countryCode, ); - }, [areOptionsInitialized, options.reports, options.personalDetails, allPolicies, draftComments, nvpDismissedProductTraining, policyTags, loginList, currentUserAccountID, currentUserEmail, personalDetails, countryCode]); + }, [ + areOptionsInitialized, + options.reports, + options.personalDetails, + allPolicies, + draftComments, + nvpDismissedProductTraining, + policyTags, + loginList, + currentUserAccountID, + currentUserEmail, + personalDetails, + countryCode, + ]); const unselectedOptions = useMemo(() => { return filterSelectedOptions(defaultOptions, new Set(selectedOptions.map((option) => option.accountID))); diff --git a/src/hooks/useContactImport.ts b/src/hooks/useContactImport.ts index f24ee21fc9418..d6b054568db9e 100644 --- a/src/hooks/useContactImport.ts +++ b/src/hooks/useContactImport.ts @@ -41,10 +41,10 @@ function useContactImport(): UseContactImportResult { const importAndSaveContacts = useCallback(() => { contactImport().then(({contactList, permissionStatus}: ContactImportResult) => { setContactPermissionState(permissionStatus); - const usersFromContact = getContacts(contactList, localeCompare, countryCode, loginList, currentUserEmail, currentUserAccountID); + const usersFromContact = getContacts(contactList, localeCompare, countryCode, loginList, currentUserEmail, currentUserAccountID); setContacts(usersFromContact); }); - }, [localeCompare, countryCode, loginList, currentUserEmail, currentUserAccountID]); + }, [localeCompare, countryCode, loginList, currentUserEmail, currentUserAccountID]); useContactPermissions({ importAndSaveContacts, diff --git a/src/hooks/useSearchSelector.base.ts b/src/hooks/useSearchSelector.base.ts index ba054aff0c1d9..05e0bf4b62492 100644 --- a/src/hooks/useSearchSelector.base.ts +++ b/src/hooks/useSearchSelector.base.ts @@ -208,49 +208,29 @@ function useSearchSelectorBase({ policyTags, }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_MEMBER_INVITE: - return getValidOptions( - optionsWithContacts, - allPolicies, - draftComments, - nvpDismissedProductTraining, - policyTags, - loginList, - currentUserAccountID, - currentUserEmail, - { - betas: betas ?? [], - includeP2P: true, - includeSelectedOptions: false, - excludeLogins, - includeRecentReports, - maxElements: maxResults, - maxRecentReportElements: maxRecentReportsToShow, - searchString: computedSearchTerm, - includeUserToInvite, - personalDetails, - }, - ); + return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, policyTags, loginList, currentUserAccountID, currentUserEmail, { + betas: betas ?? [], + includeP2P: true, + includeSelectedOptions: false, + excludeLogins, + includeRecentReports, + maxElements: maxResults, + maxRecentReportElements: maxRecentReportsToShow, + searchString: computedSearchTerm, + includeUserToInvite, + personalDetails, + }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_GENERAL: - return getValidOptions( - optionsWithContacts, - allPolicies, - draftComments, - nvpDismissedProductTraining, - policyTags, - loginList, - currentUserAccountID, - currentUserEmail, - { - ...getValidOptionsConfig, - betas: betas ?? [], - searchString: computedSearchTerm, - maxElements: maxResults, - maxRecentReportElements: maxRecentReportsToShow, - includeUserToInvite, - excludeLogins, - personalDetails, - }, - ); + return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, policyTags, loginList, currentUserAccountID, currentUserEmail, { + ...getValidOptionsConfig, + betas: betas ?? [], + searchString: computedSearchTerm, + maxElements: maxResults, + maxRecentReportElements: maxRecentReportsToShow, + includeUserToInvite, + excludeLogins, + personalDetails, + }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_SHARE_LOG: return getValidOptions( optionsWithContacts, @@ -278,61 +258,41 @@ function useSearchSelectorBase({ countryCode, ); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_SHARE_DESTINATION: - return getValidOptions( - optionsWithContacts, - allPolicies, - draftComments, - nvpDismissedProductTraining, - policyTags, - loginList, - currentUserAccountID, - currentUserEmail, - { - betas, - selectedOptions, - includeMultipleParticipantReports: true, - showChatPreviewLine: true, - forcePolicyNamePreview: true, - includeThreads: true, - includeMoneyRequests: true, - includeTasks: true, - excludeLogins, - loginsToExclude: excludeLogins, - includeOwnedWorkspaceChats: true, - includeSelfDM: true, - searchString: computedSearchTerm, - maxElements: maxResults, - includeUserToInvite, - personalDetails, - }, - ); + return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, policyTags, loginList, currentUserAccountID, currentUserEmail, { + betas, + selectedOptions, + includeMultipleParticipantReports: true, + showChatPreviewLine: true, + forcePolicyNamePreview: true, + includeThreads: true, + includeMoneyRequests: true, + includeTasks: true, + excludeLogins, + loginsToExclude: excludeLogins, + includeOwnedWorkspaceChats: true, + includeSelfDM: true, + searchString: computedSearchTerm, + maxElements: maxResults, + includeUserToInvite, + personalDetails, + }); case CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_ATTENDEES: - return getValidOptions( - optionsWithContacts, - allPolicies, - draftComments, - nvpDismissedProductTraining, - policyTags, - loginList, - currentUserAccountID, - currentUserEmail, - { - ...getValidOptionsConfig, - betas: betas ?? [], - includeP2P: true, - includeSelectedOptions: false, - excludeLogins, - loginsToExclude: excludeLogins, - includeRecentReports, - maxElements: maxResults, - maxRecentReportElements: maxRecentReportsToShow, - searchString: computedSearchTerm, - includeUserToInvite, - includeCurrentUser, - shouldAcceptName: true, - personalDetails, - }, - ); + return getValidOptions(optionsWithContacts, allPolicies, draftComments, nvpDismissedProductTraining, policyTags, loginList, currentUserAccountID, currentUserEmail, { + ...getValidOptionsConfig, + betas: betas ?? [], + includeP2P: true, + includeSelectedOptions: false, + excludeLogins, + loginsToExclude: excludeLogins, + includeRecentReports, + maxElements: maxResults, + maxRecentReportElements: maxRecentReportsToShow, + searchString: computedSearchTerm, + includeUserToInvite, + includeCurrentUser, + shouldAcceptName: true, + personalDetails, + }); default: return getEmptyOptions(); } diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index a10abecf9614c..da450cca2b07d 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -928,8 +928,8 @@ function createOption( // If displaying chat preview line is needed, let's overwrite the default alternate text const lastActorDetails = personalDetails?.[report?.lastActorAccountID ?? String(CONST.DEFAULT_NUMBER_ID)] ?? {}; - // eslint-disable-next-line @typescript-eslint/no-deprecated result.lastMessageText = getLastMessageTextForReport({ + // eslint-disable-next-line @typescript-eslint/no-deprecated translate: translateLocal, report, lastActorDetails, @@ -1265,7 +1265,7 @@ function processReport( reportMapEntry, reportOption: { item: report, - ...createOption(accountIDs, personalDetails, report, policyTags, currentUserAccountID, undefined, reportAttributesDerived), + ...createOption(accountIDs, personalDetails, report, policyTags, currentUserAccountID, undefined, reportAttributesDerived), }, }; } @@ -1467,7 +1467,7 @@ function createOptionFromReport( return { item: report, - ...createOption(accountIDs, personalDetails, report, policyTags, currentUserAccountID, config, reportAttributesDerived), + ...createOption(accountIDs, personalDetails, report, policyTags, currentUserAccountID, config, reportAttributesDerived), }; } diff --git a/src/libs/OptionsListUtils/types.ts b/src/libs/OptionsListUtils/types.ts index 1ef59e47de844..e2976ee392418 100644 --- a/src/libs/OptionsListUtils/types.ts +++ b/src/libs/OptionsListUtils/types.ts @@ -1,5 +1,4 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; -import type {LocalizedTranslate} from '@components/LocaleContextProvider'; import type {OptionData} from '@libs/ReportUtils'; import type {AvatarSource} from '@libs/UserAvatarUtils'; import type {IOUAction} from '@src/CONST'; diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx index 3ef0b2aa90c8a..a97ba383ac4b3 100644 --- a/src/pages/RoomInvitePage.tsx +++ b/src/pages/RoomInvitePage.tsx @@ -96,15 +96,7 @@ function RoomInvitePage({ return {recentReports: [], personalDetails: [], userToInvite: null, currentUserOption: null}; } - const inviteOptions = getMemberInviteOptions( - options.personalDetails, - nvpDismissedProductTraining, - loginList, - currentUserAccountID, - currentUserEmail, - betas ?? [], - excludedUsers, - ); + const inviteOptions = getMemberInviteOptions(options.personalDetails, nvpDismissedProductTraining, loginList, currentUserAccountID, currentUserEmail, betas ?? [], excludedUsers); // Update selectedOptions with the latest personalDetails information const detailsMap: Record = {}; for (const detail of inviteOptions.personalDetails) { @@ -136,7 +128,7 @@ function RoomInvitePage({ }); return filteredOptions; - }, [debouncedSearchTerm, defaultOptions, countryCode, loginList, currentUserEmail, currentUserAccountID, excludedUsers]); + }, [debouncedSearchTerm, defaultOptions, countryCode, loginList, currentUserEmail, currentUserAccountID, excludedUsers]); const sections = useMemo(() => { const sectionsArr: Sections = []; diff --git a/src/pages/Share/ShareTab.tsx b/src/pages/Share/ShareTab.tsx index 138c2eaaf8599..af4f017c6a63f 100644 --- a/src/pages/Share/ShareTab.tsx +++ b/src/pages/Share/ShareTab.tsx @@ -86,19 +86,7 @@ function ShareTab({ref}: ShareTabProps) { currentUserAccountID, currentUserEmail, }); - }, [ - areOptionsInitialized, - options, - draftComments, - nvpDismissedProductTraining, - betas, - textInputValue, - countryCode, - policyTags, - loginList, - currentUserAccountID, - currentUserEmail, - ]); + }, [areOptionsInitialized, options, draftComments, nvpDismissedProductTraining, betas, textInputValue, countryCode, policyTags, loginList, currentUserAccountID, currentUserEmail]); const recentReportsOptions = useMemo(() => { if (textInputValue.trim() === '') { diff --git a/src/pages/iou/SplitBillDetailsPage.tsx b/src/pages/iou/SplitBillDetailsPage.tsx index 48bce5817e08a..0bcbe96623d06 100644 --- a/src/pages/iou/SplitBillDetailsPage.tsx +++ b/src/pages/iou/SplitBillDetailsPage.tsx @@ -74,7 +74,7 @@ function SplitBillDetailsPage({route, report, reportAction}: SplitBillDetailsPag if (isPolicyExpenseChat(report)) { participants = [ getParticipantsOption({accountID: participantAccountIDs.at(0), selected: true, reportID: ''}, personalDetails), - getPolicyExpenseReportOption({...report, selected: true, reportID}, policyTags, currentUserPersonalDetails.accountID, personalDetails, reportAttributesDerived), + getPolicyExpenseReportOption({...report, selected: true, reportID}, policyTags, currentUserPersonalDetails.accountID, personalDetails, reportAttributesDerived), ]; } else { participants = participantAccountIDs.map((accountID) => getParticipantsOption({accountID, selected: true, reportID: ''}, personalDetails)); diff --git a/src/pages/iou/request/MoneyRequestAccountantSelector.tsx b/src/pages/iou/request/MoneyRequestAccountantSelector.tsx index 55460c79917ed..23ce8fb8143b3 100644 --- a/src/pages/iou/request/MoneyRequestAccountantSelector.tsx +++ b/src/pages/iou/request/MoneyRequestAccountantSelector.tsx @@ -137,12 +137,12 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType headerMessage: '', }; } - const newOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID, { + const newOptions = filterAndOrderOptions(defaultOptions, debouncedSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, }); return newOptions; - }, [areOptionsInitialized, defaultOptions, debouncedSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID]); + }, [areOptionsInitialized, defaultOptions, debouncedSearchTerm, countryCode, loginList, currentUserEmail, currentUserAccountID]); /** * Returns the sections needed for the OptionsSelector @@ -195,7 +195,7 @@ function MoneyRequestAccountantSelector({onFinish, onAccountantSelected, iouType data: [chatOptions.userToInvite].map((participant) => { const isPolicyExpenseChat = participant?.isPolicyExpenseChat ?? false; return isPolicyExpenseChat - ? getPolicyExpenseReportOption(participant, policyTags, currentUserAccountID, personalDetails, reportAttributesDerived) + ? getPolicyExpenseReportOption(participant, policyTags, currentUserAccountID, personalDetails, reportAttributesDerived) : getParticipantsOption(participant, personalDetails); }), shouldShow: true, diff --git a/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx b/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx index d71ae123de469..95c87fddd80ca 100644 --- a/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx +++ b/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx @@ -275,7 +275,24 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde ); return [newSections, headerMessage]; - }, [areOptionsInitialized, didScreenTransitionEnd, searchTerm, initialSelectedOptions, orderedAvailableOptions.recentReports, orderedAvailableOptions.personalDetails, orderedAvailableOptions.userToInvite, policyTags, currentUserAccountID, personalDetails, reportAttributesDerived, loginList, currentUserEmail, countryCode, attendees, translate]); + }, [ + areOptionsInitialized, + didScreenTransitionEnd, + searchTerm, + initialSelectedOptions, + orderedAvailableOptions.recentReports, + orderedAvailableOptions.personalDetails, + orderedAvailableOptions.userToInvite, + policyTags, + currentUserAccountID, + personalDetails, + reportAttributesDerived, + loginList, + currentUserEmail, + countryCode, + attendees, + translate, + ]); const optionLength = useMemo(() => { if (!areOptionsInitialized) { diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index 0122c8e3c12cc..a07db650cd250 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -360,7 +360,28 @@ function MoneyRequestParticipantsSelector({ } return [newSections, headerMessage]; - }, [areOptionsInitialized, didScreenTransitionEnd, searchTerm, participants, policyTags, currentUserAccountID, personalDetails, reportAttributesDerived, translate, availableOptions.workspaceChats, availableOptions.selfDMChat, availableOptions.userToInvite, availableOptions.recentReports, availableOptions.personalDetails, isWorkspacesOnly, loginList, currentUserEmail, isPerDiemRequest, showImportContacts, inputHelperText]); + }, [ + areOptionsInitialized, + didScreenTransitionEnd, + searchTerm, + participants, + policyTags, + currentUserAccountID, + personalDetails, + reportAttributesDerived, + translate, + availableOptions.workspaceChats, + availableOptions.selfDMChat, + availableOptions.userToInvite, + availableOptions.recentReports, + availableOptions.personalDetails, + isWorkspacesOnly, + loginList, + currentUserEmail, + isPerDiemRequest, + showImportContacts, + inputHelperText, + ]); /** * Removes a selected option from list if already selected. If not already selected add this option to the list. diff --git a/tests/perf-test/OptionsListUtils.perf-test.ts b/tests/perf-test/OptionsListUtils.perf-test.ts index eff0ccbbb0bad..6610e3a5bb34c 100644 --- a/tests/perf-test/OptionsListUtils.perf-test.ts +++ b/tests/perf-test/OptionsListUtils.perf-test.ts @@ -174,7 +174,7 @@ describe('OptionsListUtils', () => { ValidOptionsConfig, ); await measureFunction(() => { - filterAndOrderOptions(formattedOptions, '', COUNTRY_CODE, loginList, MOCK_CURRENT_USER_EMAIL, MOCK_CURRENT_USER_ACCOUNT_ID); + filterAndOrderOptions(formattedOptions, '', COUNTRY_CODE, loginList, MOCK_CURRENT_USER_EMAIL, MOCK_CURRENT_USER_ACCOUNT_ID); }); }); @@ -283,8 +283,6 @@ describe('OptionsListUtils', () => { const mockedPersonalDetails = getMockedPersonalDetails(PERSONAL_DETAILS_COUNT); await waitForBatchedUpdates(); - await measureFunction(() => - formatSectionsFromSearchTerm('', Object.values(selectedOptions), [], [], undefined, MOCK_CURRENT_USER_ACCOUNT_ID, mockedPersonalDetails, true), - ); + await measureFunction(() => formatSectionsFromSearchTerm('', Object.values(selectedOptions), [], [], undefined, MOCK_CURRENT_USER_ACCOUNT_ID, mockedPersonalDetails, true)); }); }); diff --git a/tests/perf-test/SearchRouter.perf-test.tsx b/tests/perf-test/SearchRouter.perf-test.tsx index 317a2b4f24ef0..d152cd6bdb19c 100644 --- a/tests/perf-test/SearchRouter.perf-test.tsx +++ b/tests/perf-test/SearchRouter.perf-test.tsx @@ -106,7 +106,7 @@ const MOCK_CURRENT_USER_ACCOUNT_ID = 1; const mockedReports = getMockedReports(600); const mockedBetas = Object.values(CONST.BETAS); const mockedPersonalDetails = getMockedPersonalDetails(100); -const mockedOptions = createOptionList(mockedPersonalDetails, undefined, MOCK_CURRENT_USER_ACCOUNT_ID, mockedReports); +const mockedOptions = createOptionList(mockedPersonalDetails, undefined, MOCK_CURRENT_USER_ACCOUNT_ID, mockedReports); beforeAll(() => Onyx.init({ diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index 3b685e522345c..6904f60ea6271 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -640,12 +640,12 @@ describe('OptionsListUtils', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}10`, reportNameValuePairs); await waitForBatchedUpdates(); - OPTIONS = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS); - OPTIONS_WITH_CONCIERGE = createOptionList(PERSONAL_DETAILS_WITH_CONCIERGE, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_CONCIERGE); - OPTIONS_WITH_CHRONOS = createOptionList(PERSONAL_DETAILS_WITH_CHRONOS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_CHRONOS); - OPTIONS_WITH_RECEIPTS = createOptionList(PERSONAL_DETAILS_WITH_RECEIPTS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_RECEIPTS); - OPTIONS_WITH_WORKSPACE_ROOM = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_WORKSPACE_ROOMS); - OPTIONS_WITH_MANAGER_MCTEST = createOptionList(PERSONAL_DETAILS_WITH_MANAGER_MCTEST, undefined, CURRENT_USER_ACCOUNT_ID); + OPTIONS = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS); + OPTIONS_WITH_CONCIERGE = createOptionList(PERSONAL_DETAILS_WITH_CONCIERGE, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_CONCIERGE); + OPTIONS_WITH_CHRONOS = createOptionList(PERSONAL_DETAILS_WITH_CHRONOS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_CHRONOS); + OPTIONS_WITH_RECEIPTS = createOptionList(PERSONAL_DETAILS_WITH_RECEIPTS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_RECEIPTS); + OPTIONS_WITH_WORKSPACE_ROOM = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_WORKSPACE_ROOMS); + OPTIONS_WITH_MANAGER_MCTEST = createOptionList(PERSONAL_DETAILS_WITH_MANAGER_MCTEST, undefined, CURRENT_USER_ACCOUNT_ID); }); describe('getSearchOptions()', () => { @@ -743,7 +743,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -784,7 +784,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -821,7 +821,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -845,7 +845,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -869,7 +869,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -893,7 +893,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -920,7 +920,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -949,7 +949,7 @@ describe('OptionsListUtils', () => { }, }, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -975,7 +975,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1010,7 +1010,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1069,7 +1069,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1125,7 +1125,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1179,7 +1179,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1237,7 +1237,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1274,7 +1274,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1300,7 +1300,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1328,7 +1328,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1351,7 +1351,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1374,7 +1374,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1398,7 +1398,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1423,7 +1423,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1451,7 +1451,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1477,7 +1477,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1499,7 +1499,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1510,7 +1510,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1532,7 +1532,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1543,7 +1543,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1567,7 +1567,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1603,7 +1603,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1646,7 +1646,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -1675,7 +1675,7 @@ describe('OptionsListUtils', () => { it('should sort personal details alphabetically', () => { // Given a set of personalDetails // When we call getMemberInviteOptions - const results = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, []); + const results = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, []); // Then personal details should be sorted alphabetically expect(results.personalDetails.at(0)?.text).toBe('Black Panther'); @@ -1874,7 +1874,7 @@ describe('OptionsListUtils', () => { currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with an empty search value - const filteredOptions = filterAndOrderOptions(options, '', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, '', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then all options should be returned expect(filteredOptions.recentReports.length + filteredOptions.personalDetails.length).toBe(14); @@ -1895,7 +1895,7 @@ describe('OptionsListUtils', () => { currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with a search value and sortByReportTypeInSearch param - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { sortByReportTypeInSearch: true, }); @@ -1920,13 +1920,13 @@ describe('OptionsListUtils', () => { nvpDismissedProductTraining, loginList, policyTags: undefined, - + betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1944,13 +1944,13 @@ describe('OptionsListUtils', () => { nvpDismissedProductTraining, loginList, policyTags: undefined, - + betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -1962,21 +1962,21 @@ describe('OptionsListUtils', () => { // cspell:disable-next-line const searchText = 'barryallen'; // Given a set of options created from PERSONAL_DETAILS_WITH_PERIODS - const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS); + const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS); // When we call getSearchOptions with all betas const options = getSearchOptions({ options: OPTIONS_WITH_PERIODS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - + loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with a search value and sortByReportTypeInSearch param - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { sortByReportTypeInSearch: true, }); @@ -1995,14 +1995,14 @@ describe('OptionsListUtils', () => { draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - + loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -2024,7 +2024,7 @@ describe('OptionsListUtils', () => { currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then only one report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -2035,21 +2035,21 @@ describe('OptionsListUtils', () => { it('should prioritize options with matching display name over chat rooms', () => { const searchText = 'spider'; // Given a set of options with chat rooms - const OPTIONS_WITH_CHAT_ROOMS = createOptionList(PERSONAL_DETAILS, {}, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_CHAT_ROOM); + const OPTIONS_WITH_CHAT_ROOMS = createOptionList(PERSONAL_DETAILS, {}, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_CHAT_ROOM); // When we call getSearchOptions with all betas const options = getSearchOptions({ options: OPTIONS_WITH_CHAT_ROOMS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - + loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we pass the returned options to filterAndOrderOptions with a search value - const filterOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filterOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then only two reports should be returned expect(filterOptions.recentReports.length).toBe(2); @@ -2066,13 +2066,13 @@ describe('OptionsListUtils', () => { draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - + loginList, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then only three reports should be returned expect(filteredOptions.recentReports.length).toBe(3); @@ -2089,14 +2089,14 @@ describe('OptionsListUtils', () => { options: OPTIONS, draftComments: {}, policyTags: undefined, - + loginList, nvpDismissedProductTraining, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then the user to invite should be returned expect(filteredOptions.userToInvite?.login).toBe(searchText); @@ -2111,7 +2111,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -2120,7 +2120,7 @@ describe('OptionsListUtils', () => { }, ); // When we call filterAndOrderOptions with a search value and excluded logins list - const filterOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { + const filterOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, }); @@ -2139,10 +2139,9 @@ describe('OptionsListUtils', () => { currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, policyTags: undefined, - }); // When we call filterAndOrderOptions with a search value and excludeLogins - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT, }); @@ -2161,10 +2160,9 @@ describe('OptionsListUtils', () => { currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, policyTags: undefined, - }); // When we call filterAndOrderOptions with a search value and maxRecentReportsToShow set to 2 - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { maxRecentReportsToShow: 2, }); @@ -2173,7 +2171,7 @@ describe('OptionsListUtils', () => { // Note: in the past maxRecentReportsToShow: 0 would return all recent reports, this has changed, and is expected to return none now // When we call filterAndOrderOptions with a search value and maxRecentReportsToShow set to 0 - const limitToZeroOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { + const limitToZeroOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { maxRecentReportsToShow: 0, }); @@ -2193,10 +2191,9 @@ describe('OptionsListUtils', () => { currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, policyTags: undefined, - }); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchText, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then there should be one matching result expect(filteredOptions.personalDetails.length).toBe(1); @@ -2206,9 +2203,9 @@ describe('OptionsListUtils', () => { it('should not return any options if search value does not match any personal details (getMemberInviteOptions)', () => { // Given a set of options - const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, []); + const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, []); // 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); + const filteredOptions = filterAndOrderOptions(options, 'magneto', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no personal details should be returned expect(filteredOptions.personalDetails.length).toBe(0); @@ -2216,9 +2213,9 @@ describe('OptionsListUtils', () => { it('should return one personal detail if search value matches an email (getMemberInviteOptions)', () => { // Given a set of options - const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, []); + const options = getMemberInviteOptions(OPTIONS.personalDetails, nvpDismissedProductTraining, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, []); // 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); + const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then one personal detail should be returned expect(filteredOptions.personalDetails.length).toBe(1); @@ -2242,7 +2239,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -2262,7 +2259,7 @@ describe('OptionsListUtils', () => { }, ); // When we pass the returned options to filterAndOrderOptions with a search value that does not match the group chat name - const filteredOptions = filterAndOrderOptions(options, 'mutants', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'mutants', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2286,7 +2283,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -2306,7 +2303,7 @@ describe('OptionsListUtils', () => { }, ); // When we pass the returned options to filterAndOrderOptions with a search value that matches the group chat name - const filteredOptions = filterAndOrderOptions(options, 'Avengers Room', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'Avengers Room', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then one recent report should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -2330,7 +2327,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -2350,7 +2347,7 @@ describe('OptionsListUtils', () => { }, ); // When we pass the returned options to filterAndOrderOptions with a search value that does not match the group chat name - const filteredOptions = filterAndOrderOptions(options, 'Mutants Lair', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'Mutants Lair', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2364,13 +2361,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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); + const filteredOptions = filterAndOrderOptions(options, 'hulk', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2388,13 +2385,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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); + const filteredOptions = filterAndOrderOptions(options, 'marc@expensify', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2411,13 +2408,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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); + const filteredOptions = filterAndOrderOptions(options, 'marc@expensify.com', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2434,13 +2431,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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); + const filteredOptions = filterAndOrderOptions(options, 'peter.parker@expensify.com', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2456,13 +2453,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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); + const filteredOptions = filterAndOrderOptions(options, 'Timothee', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then one personalDetails with accent mark should be returned expect(filteredOptions.personalDetails.length).toBe(1); @@ -2476,13 +2473,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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); + const filteredOptions = filterAndOrderOptions(options, '5005550006', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2501,13 +2498,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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); + const filteredOptions = filterAndOrderOptions(options, '+15005550006', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2526,13 +2523,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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); + const filteredOptions = filterAndOrderOptions(options, '+1 (800)324-3233', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2551,13 +2548,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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); + const filteredOptions = filterAndOrderOptions(options, '998243aaaa', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no recent reports or personal details should be returned expect(filteredOptions.recentReports.length).toBe(0); @@ -2574,13 +2571,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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); + const filteredOptions = filterAndOrderOptions(options, 'magneto', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then no personal details should be returned expect(filteredOptions.personalDetails.length).toBe(0); @@ -2594,13 +2591,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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, { + const filteredOptions = filterAndOrderOptions(options, 'peterparker@expensify.com', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { sortByReportTypeInSearch: true, }); @@ -2620,13 +2617,13 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, ); // 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, { + const filteredOptions = filterAndOrderOptions(options, '.com', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID, { maxRecentReportsToShow: 5, }); @@ -2651,10 +2648,9 @@ describe('OptionsListUtils', () => { currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, policyTags: undefined, - }); // When we call filterAndOrderOptions with a search value that matches a personal detail - const filteredOptions = filterAndOrderOptions(options, 'spider', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'spider', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then one personal detail should be returned expect(filteredOptions.recentReports.length).toBe(1); @@ -2672,10 +2668,9 @@ describe('OptionsListUtils', () => { currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, policyTags: undefined, - }); // When we call filterAndOrderOptions with a search value that matches multiple items - const filteredOptions = filterAndOrderOptions(options, 'fantastic', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, 'fantastic', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then only three reports should be returned expect(filteredOptions.recentReports.length).toBe(3); @@ -2688,14 +2683,14 @@ describe('OptionsListUtils', () => { .then(() => Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, PERSONAL_DETAILS_WITH_PERIODS)) .then(() => { // Given a set of options with periods - const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS); + const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS); // When we call getSearchOptions const results = getSearchOptions({ options: OPTIONS_WITH_PERIODS, draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - + loginList, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, @@ -2704,7 +2699,7 @@ describe('OptionsListUtils', () => { const filteredResults = filterAndOrderOptions( results, 'barry.allen@expensify.com', - + COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, @@ -2733,14 +2728,14 @@ describe('OptionsListUtils', () => { draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - + loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we call filterAndOrderOptions with a an empty search value - const filteredOptions = filterAndOrderOptions(options, '', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, '', COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); const matchingEntries = filteredOptions.personalDetails.filter((detail) => detail.login === login); // Then there should be 2 unique login entries @@ -2751,7 +2746,7 @@ describe('OptionsListUtils', () => { it('should order self dm always on top if the search matches with the self dm login', () => { const searchTerm = 'tonystark@expensify.com'; - const OPTIONS_WITH_SELF_DM = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_SELF_DM); + const OPTIONS_WITH_SELF_DM = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS_WITH_SELF_DM); // Given a set of options with self dm and all betas const options = getSearchOptions({ @@ -2759,14 +2754,14 @@ describe('OptionsListUtils', () => { draftComments: {}, nvpDismissedProductTraining, policyTags: undefined, - + loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, }); // When we call filterAndOrderOptions with a search value - const filteredOptions = filterAndOrderOptions(options, searchTerm, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); + const filteredOptions = filterAndOrderOptions(options, searchTerm, COUNTRY_CODE, loginList, CURRENT_USER_EMAIL, CURRENT_USER_ACCOUNT_ID); // Then the self dm should be on top. expect(filteredOptions.recentReports.at(0)?.isSelfDM).toBe(true); @@ -2813,7 +2808,7 @@ describe('OptionsListUtils', () => { renderLocaleContextProvider(); // Given a set of reports and personal details // When we call createOptionList and extract the reports - const reports = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS).reports; + const reports = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS).reports; // Then the returned reports should match the expected values expect(reports.at(10)?.subtitle).toBe(`Submits to Mister Fantastic`); @@ -2824,7 +2819,7 @@ describe('OptionsListUtils', () => { .then(() => Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, CONST.LOCALES.ES)) .then(() => { // When we call createOptionList again - const newReports = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS).reports; + const newReports = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS).reports; // Then the returned reports should change to Spanish // cspell:disable-next-line expect(newReports.at(10)?.subtitle).toBe('Se envía a Mister Fantastic'); @@ -2904,7 +2899,7 @@ describe('OptionsListUtils', () => { }, }); // When we call createOptionList - const reports = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS).reports; + const reports = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, REPORTS).reports; const archivedReport = reports.find((report) => report.reportID === '10'); // Then the returned report should contain default archived reason @@ -3318,7 +3313,7 @@ describe('OptionsListUtils', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, transaction); await waitForBatchedUpdates(); - const result = createOption([1, 2], PERSONAL_DETAILS, report, CONST.POLICY.DEFAULT_TAG_LIST, CURRENT_USER_ACCOUNT_ID, {showChatPreviewLine: true}); + const result = createOption([1, 2], PERSONAL_DETAILS, report, CONST.POLICY.DEFAULT_TAG_LIST, CURRENT_USER_ACCOUNT_ID, {showChatPreviewLine: true}); expect(result.alternateText).toBe('Iron Man owes ₫34'); }); @@ -3410,7 +3405,7 @@ describe('OptionsListUtils', () => { [movedTransactionAction.reportActionID]: movedTransactionAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3435,7 +3430,7 @@ describe('OptionsListUtils', () => { [submittedAction.reportActionID]: submittedAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3461,7 +3456,7 @@ describe('OptionsListUtils', () => { [approvedAction.reportActionID]: approvedAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3487,7 +3482,7 @@ describe('OptionsListUtils', () => { [forwardedAction.reportActionID]: forwardedAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3510,7 +3505,7 @@ describe('OptionsListUtils', () => { [corporateForceUpgradeAction.reportActionID]: corporateForceUpgradeAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3532,7 +3527,7 @@ describe('OptionsListUtils', () => { [takeControlAction.reportActionID]: takeControlAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3553,7 +3548,7 @@ describe('OptionsListUtils', () => { [rerouteAction.reportActionID]: rerouteAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3574,7 +3569,7 @@ describe('OptionsListUtils', () => { [movedAction.reportActionID]: movedAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3599,7 +3594,7 @@ describe('OptionsListUtils', () => { // When getting the last message text for the report const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3626,7 +3621,7 @@ describe('OptionsListUtils', () => { const expectedVisibleText = ''; const result = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3676,7 +3671,7 @@ describe('OptionsListUtils', () => { [submittedAction.reportActionID]: submittedAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3711,7 +3706,7 @@ describe('OptionsListUtils', () => { [dewSubmitFailedAction.reportActionID]: dewSubmitFailedAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -3741,7 +3736,7 @@ describe('OptionsListUtils', () => { [dewSubmitFailedAction.reportActionID]: dewSubmitFailedAction, }); const lastMessage = getLastMessageTextForReport({ - translate: translateLocal, + translate: translateLocal, report, lastActorDetails: null, isReportArchived: false, @@ -4129,7 +4124,7 @@ describe('OptionsListUtils', () => { undefined, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -4142,7 +4137,7 @@ describe('OptionsListUtils', () => { it('should work with undefined policies', () => { const options = {reports: [], personalDetails: []}; - const results = getValidOptions(options, undefined, undefined, nvpDismissedProductTraining, undefined, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL); + const results = getValidOptions(options, undefined, undefined, nvpDismissedProductTraining, undefined, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL); expect(results).toBeDefined(); expect(results.recentReports).toBeDefined(); @@ -4151,7 +4146,7 @@ describe('OptionsListUtils', () => { it('should work with empty policies collection', () => { const options = {reports: [], personalDetails: []}; - const results = getValidOptions(options, {}, undefined, nvpDismissedProductTraining, undefined, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL); + const results = getValidOptions(options, {}, undefined, nvpDismissedProductTraining, undefined, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL); expect(results).toBeDefined(); expect(results.recentReports).toBeDefined(); @@ -4181,7 +4176,7 @@ describe('OptionsListUtils', () => { undefined, nvpDismissedProductTraining, undefined, - + loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, @@ -4893,7 +4888,7 @@ describe('OptionsListUtils', () => { selected: true, }; - const option = getPolicyExpenseReportOption(participant, undefined, CURRENT_USER_ACCOUNT_ID, testPersonalDetails); + const option = getPolicyExpenseReportOption(participant, undefined, CURRENT_USER_ACCOUNT_ID, testPersonalDetails); expect(option).toBeDefined(); expect(option.text).toBe('Test Workspace Policy'); @@ -4954,7 +4949,7 @@ describe('OptionsListUtils', () => { isPolicyExpenseChat: true, }; - const option = getPolicyExpenseReportOption(participant, undefined, CURRENT_USER_ACCOUNT_ID, testPersonalDetails); + const option = getPolicyExpenseReportOption(participant, undefined, CURRENT_USER_ACCOUNT_ID, testPersonalDetails); expect(option).toBeDefined(); expect(option.text).toBe('Team Workspace'); @@ -4998,7 +4993,7 @@ describe('OptionsListUtils', () => { }; // Should not throw when personalDetails is empty - const option = getPolicyExpenseReportOption(participant, undefined, CURRENT_USER_ACCOUNT_ID, {}); + const option = getPolicyExpenseReportOption(participant, undefined, CURRENT_USER_ACCOUNT_ID, {}); expect(option).toBeDefined(); expect(option.text).toBe('Workspace Without Details'); @@ -5042,7 +5037,7 @@ describe('OptionsListUtils', () => { }; // Should not throw when personalDetails is undefined - const option = getPolicyExpenseReportOption(participant, undefined, CURRENT_USER_ACCOUNT_ID, undefined); + const option = getPolicyExpenseReportOption(participant, undefined, CURRENT_USER_ACCOUNT_ID, undefined); expect(option).toBeDefined(); expect(option.text).toBe('Workspace Undefined Details'); @@ -5094,10 +5089,10 @@ describe('OptionsListUtils', () => { selected: false, }; - const optionSelected = getPolicyExpenseReportOption(participantSelected, undefined, CURRENT_USER_ACCOUNT_ID, {}); + const optionSelected = getPolicyExpenseReportOption(participantSelected, undefined, CURRENT_USER_ACCOUNT_ID, {}); // eslint-disable-next-line rulesdir/no-negated-variables - const optionNotSelected = getPolicyExpenseReportOption(participantNotSelected, undefined, CURRENT_USER_ACCOUNT_ID, {}); + const optionNotSelected = getPolicyExpenseReportOption(participantNotSelected, undefined, CURRENT_USER_ACCOUNT_ID, {}); expect(optionSelected.isSelected).toBe(true); expect(optionSelected.selected).toBe(true); From 4efb22808a9615b1b3fe90150229b56179e2953f Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Thu, 29 Jan 2026 09:13:22 +0100 Subject: [PATCH 33/39] fix --- src/libs/OptionsListUtils/types.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/OptionsListUtils/types.ts b/src/libs/OptionsListUtils/types.ts index e2976ee392418..d1e2d633870ad 100644 --- a/src/libs/OptionsListUtils/types.ts +++ b/src/libs/OptionsListUtils/types.ts @@ -201,7 +201,6 @@ type GetOptionsConfig = { type GetUserToInviteConfig = { searchValue: string | undefined; - searchInputValue?: string; loginsToExclude?: Record; reportActions?: ReportActions; firstName?: string; From 1b1c87d126fd55017b9252074ead1c620c04cee1 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 2 Feb 2026 11:19:27 +0100 Subject: [PATCH 34/39] disable lint issue as there are already too many changes --- src/libs/OptionsListUtils/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index 5e2ce6f6af291..1cc85ea5b17cc 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -2272,6 +2272,8 @@ function getRestrictedLogins( /** * Options are reports and personal details. This function filters out the options that are not valid to be displayed. */ +// fix it in the sepearte issue +// eslint-disable-next-line @typescript-eslint/max-params function getValidOptions( options: OptionList, policiesCollection: OnyxCollection, From 94a9129d9340bdfdca6a420b488776dca5f9efe7 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Tue, 3 Feb 2026 11:32:45 +0100 Subject: [PATCH 35/39] typecheck and spellcheck --- src/libs/OptionsListUtils/index.ts | 2 +- tests/unit/OptionsListUtilsTest.tsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index d89fd2cbccecd..7370b1b8865be 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -2225,7 +2225,7 @@ function getRestrictedLogins( /** * Options are reports and personal details. This function filters out the options that are not valid to be displayed. */ -// fix it in the sepearte issue +// fix it in the separate issue // eslint-disable-next-line @typescript-eslint/max-params function getValidOptions( options: OptionList, diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index e61ffa1885d11..186bb29374590 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -2589,6 +2589,7 @@ describe('OptionsListUtils', () => { {}, nvpDismissedProductTraining, loginList, + {}, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, { From 75ddbd6c3d1e424c33dc1daeb219d1e191eb7568 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Wed, 4 Feb 2026 14:25:21 +0100 Subject: [PATCH 36/39] resolve comments --- .../FilterDropdowns/UserSelectPopup.tsx | 2 +- .../Search/SearchFiltersChatsSelector.tsx | 3 +- .../SearchFiltersParticipantsSelector.tsx | 6 ++-- src/libs/ModifiedExpenseMessage.ts | 36 ++++++++----------- src/libs/OptionsListUtils/index.ts | 3 +- src/pages/NewChatPage.tsx | 4 +-- 6 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/components/Search/FilterDropdowns/UserSelectPopup.tsx b/src/components/Search/FilterDropdowns/UserSelectPopup.tsx index a7e7c448e7abd..19148a5e5bba9 100644 --- a/src/components/Search/FilterDropdowns/UserSelectPopup.tsx +++ b/src/components/Search/FilterDropdowns/UserSelectPopup.tsx @@ -69,7 +69,7 @@ function UserSelectPopup({value, closeOverlay, onChange, isSearchable}: UserSele const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false, canBeMissing: true}); const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, {canBeMissing: true}); const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); - const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: false}); + const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: true}); const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true}); const initialSelectedOptions = useMemo(() => { return value.reduce((acc, id) => { diff --git a/src/components/Search/SearchFiltersChatsSelector.tsx b/src/components/Search/SearchFiltersChatsSelector.tsx index 4b0aecda30124..7ec9c1d614ff2 100644 --- a/src/components/Search/SearchFiltersChatsSelector.tsx +++ b/src/components/Search/SearchFiltersChatsSelector.tsx @@ -115,7 +115,7 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen selectedOptions, chatOptions.recentReports, chatOptions.personalDetails, - undefined, + policyTags, currentUserAccountID, personalDetails, false, @@ -154,6 +154,7 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen selectedReportIDs, translate, currentUserAccountID, + policyTags, ]); useEffect(() => { diff --git a/src/components/Search/SearchFiltersParticipantsSelector.tsx b/src/components/Search/SearchFiltersParticipantsSelector.tsx index bdab208609b53..6746984dc4986 100644 --- a/src/components/Search/SearchFiltersParticipantsSelector.tsx +++ b/src/components/Search/SearchFiltersParticipantsSelector.tsx @@ -191,7 +191,7 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate, } return filteredOptions; - }, [unselectedOptions, cleanSearchTerm, countryCode, loginList, selectedOptions, shouldAllowNameOnlyOptions, searchTerm, currentUserEmail, currentUserAccountID, policyTags]); + }, [unselectedOptions, cleanSearchTerm, countryCode, loginList, selectedOptions, shouldAllowNameOnlyOptions, searchTerm, currentUserEmail, currentUserAccountID]); const {sections, headerMessage} = useMemo(() => { const newSections: Section[] = []; @@ -204,7 +204,7 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate, selectedOptions, chatOptions.recentReports, chatOptions.personalDetails, - undefined, + policyTags, currentUserAccountID, personalDetails, true, @@ -265,7 +265,7 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate, sections: newSections, headerMessage: message, }; - }, [areOptionsInitialized, cleanSearchTerm, selectedOptions, chatOptions, personalDetails, reportAttributesDerived, translate, formatPhoneNumber, currentUserAccountID]); + }, [areOptionsInitialized, cleanSearchTerm, selectedOptions, chatOptions, personalDetails, reportAttributesDerived, translate, formatPhoneNumber, currentUserAccountID, policyTags]); const resetChanges = useCallback(() => { setSelectedOptions([]); diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index c23c05bbc2b42..ab77a39c035b6 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -642,7 +642,7 @@ function getForReportActionTemp({ const splittedTag = getTagArrayFromName(transactionTag); const splittedOldTag = getTagArrayFromName(oldTransactionTag); const localizedTagListName = translate('common.tag'); - const sortedTagKeys = getSortedTagKeys(policyTags); + const sortedTagKeys = getSortedTagKeys(policyTags ?? CONST.POLICY.DEFAULT_TAG_LIST); for (const [index, policyTagKey] of sortedTagKeys.entries()) { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing @@ -693,30 +693,17 @@ function getForReportActionTemp({ const hasModifiedBillable = isReportActionOriginalMessageAnObject && 'oldBillable' in reportActionOriginalMessage && 'billable' in reportActionOriginalMessage; if (hasModifiedBillable) { - buildMessageFragmentForValue( - translate, - reportActionOriginalMessage?.billable ?? '', - reportActionOriginalMessage?.oldBillable ?? '', - translate('iou.expense'), - true, - setFragments, - removalFragments, - changeFragments, - ); + const oldBillable = reportActionOriginalMessage?.oldBillable === 'billable' ? translate('common.billable').toLowerCase() : translate('common.nonBillable').toLowerCase(); + const newBillable = reportActionOriginalMessage?.billable === 'billable' ? translate('common.billable').toLowerCase() : translate('common.nonBillable').toLowerCase(); + buildMessageFragmentForValue(translate, newBillable, oldBillable, translate('iou.expense'), true, setFragments, removalFragments, changeFragments); } const hasModifiedReimbursable = isReportActionOriginalMessageAnObject && 'oldReimbursable' in reportActionOriginalMessage && 'reimbursable' in reportActionOriginalMessage; if (hasModifiedReimbursable) { - buildMessageFragmentForValue( - translate, - reportActionOriginalMessage?.reimbursable ?? '', - reportActionOriginalMessage?.oldReimbursable ?? '', - translate('iou.expense'), - true, - setFragments, - removalFragments, - changeFragments, - ); + const oldReimbursable = + reportActionOriginalMessage?.oldReimbursable === 'reimbursable' ? translate('iou.reimbursable').toLowerCase() : translate('iou.nonReimbursable').toLowerCase(); + const newReimbursable = reportActionOriginalMessage?.reimbursable === 'reimbursable' ? translate('iou.reimbursable').toLowerCase() : translate('iou.nonReimbursable').toLowerCase(); + buildMessageFragmentForValue(translate, newReimbursable, oldReimbursable, translate('iou.expense'), true, setFragments, removalFragments, changeFragments); } const hasModifiedAttendees = isReportActionOriginalMessageAnObject && 'oldAttendees' in reportActionOriginalMessage && 'newAttendees' in reportActionOriginalMessage; @@ -741,6 +728,13 @@ function getForReportActionTemp({ getMessageLine(translate, `\n${translate('iou.removed')}`, removalFragments); if (message === '') { + // If we don't have enough structured information to build a detailed message but we + // know the change was AI-generated, fall back to an AI-attributed generic summary so + // users can still understand that Concierge updated the expense automatically. + if (reportActionOriginalMessage?.aiGenerated) { + return `${translate('iou.changedTheExpense')} ${translate('iou.basedOnAI')}`; + } + return translate('iou.changedTheExpense'); } return `${message.substring(1, message.length)}`; diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index 44067df7655bc..27a41e76242f9 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -698,6 +698,7 @@ function getLastMessageTextForReport({ movedFromReport, movedToReport, policyTags, + policy, }); lastMessageTextFromReport = formatReportLastMessageText(properSchemaForModifiedExpenseMessage, true); } else if (isMovedTransactionAction(lastReportAction)) { @@ -943,8 +944,8 @@ function createOption( // If displaying chat preview line is needed, let's overwrite the default alternate text const lastActorDetails = personalDetails?.[report?.lastActorAccountID ?? String(CONST.DEFAULT_NUMBER_ID)] ?? {}; - // eslint-disable-next-line @typescript-eslint/no-deprecated result.lastMessageText = getLastMessageTextForReport({ + // eslint-disable-next-line @typescript-eslint/no-deprecated translate: translateLocal, report, lastActorDetails, diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index 43f5babf7383c..cf422e196d9b9 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -241,7 +241,7 @@ function NewChatPage({ref}: NewChatPageProps) { const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false, canBeMissing: true}); const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector}); const selectionListRef = useRef(null); - + const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {canBeMissing: true}); const allPersonalDetails = usePersonalDetails(); const {singleExecution} = useSingleExecution(); @@ -272,7 +272,7 @@ function NewChatPage({ref}: NewChatPageProps) { selectedOptions as OptionData[], recentReports, personalDetails, - undefined, + policyTags, currentUserAccountID, allPersonalDetails, undefined, From aadb30c7e2dd62eabff0162dba681a982b8c9658 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Thu, 5 Feb 2026 14:11:54 +0100 Subject: [PATCH 37/39] typecheck --- tests/unit/OptionsListUtilsTest.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index 8affbafd7a8c3..3f6127c276b14 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -3006,7 +3006,7 @@ describe('OptionsListUtils', () => { }; // When we call createOptionList with this privateIsArchivedMap - const result = createOptionList(PERSONAL_DETAILS, CURRENT_USER_ACCOUNT_ID, privateIsArchivedMap, REPORTS); + const result = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, privateIsArchivedMap, REPORTS); // Then the personal detail option for account 1 (Mister Fantastic) should have private_isArchived set const misterFantasticOption = result.personalDetails.find((pd) => pd.item?.accountID === 1); @@ -3019,7 +3019,7 @@ describe('OptionsListUtils', () => { const emptyMap: PrivateIsArchivedMap = {}; // When we call createOptionList with an empty privateIsArchivedMap - const result = createOptionList(PERSONAL_DETAILS, CURRENT_USER_ACCOUNT_ID, emptyMap, REPORTS); + const result = createOptionList(PERSONAL_DETAILS, undefined, CURRENT_USER_ACCOUNT_ID, emptyMap, REPORTS); // Then no personal details options should have private_isArchived set const optionsWithArchived = result.personalDetails.filter((pd) => pd.private_isArchived); From 8bb74e60a05cb3554ff3992bab657f92a4e6fbc5 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Thu, 5 Feb 2026 14:18:38 +0100 Subject: [PATCH 38/39] lint errors --- src/pages/iou/request/step/IOURequestStepDistance.tsx | 2 -- src/pages/workspace/WorkspaceMembersPage.tsx | 1 - 2 files changed, 3 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepDistance.tsx b/src/pages/iou/request/step/IOURequestStepDistance.tsx index 7e7e3509fc46c..77cb7e21afe54 100644 --- a/src/pages/iou/request/step/IOURequestStepDistance.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistance.tsx @@ -327,7 +327,6 @@ function IOURequestStepDistance({ report, policy, transaction, - reportID, transactionID, reportAttributesDerived, personalDetails, @@ -340,7 +339,6 @@ function IOURequestStepDistance({ shouldSkipConfirmation, defaultExpensePolicy, isArchived, - personalPolicy?.autoReporting, isASAPSubmitBetaEnabled, transactionViolations, lastSelectedDistanceRates, diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index ff29de537d536..ed1bed9c4d7df 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -502,7 +502,6 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers invitedPrimaryToSecondaryLogins, policyOwner, currentUserLogin, - translate, ]); const filterMember = useCallback((memberOption: MemberOption, searchQuery: string) => { From 1d9d64f0f0a804712d178eae97d1a62591934b0d Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Mon, 9 Feb 2026 10:07:10 +0100 Subject: [PATCH 39/39] typecheck fix --- tests/unit/OptionsListUtilsTest.tsx | 87 ++++++++++++++++------------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index 8be3b92de80fc..529388addcaaf 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -631,6 +631,7 @@ describe('OptionsListUtils', () => { const loginList = {}; const CURRENT_USER_ACCOUNT_ID = 2; const CURRENT_USER_EMAIL = 'tonystark@expensify.com'; + const POLICY_TAGS = {}; const reportNameValuePairs = { private_isArchived: DateUtils.getDBTime(), @@ -685,7 +686,7 @@ describe('OptionsListUtils', () => { options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, - policyTags: undefined, + policyTags: POLICY_TAGS, loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, @@ -715,7 +716,7 @@ describe('OptionsListUtils', () => { includeUserToInvite: false, includeRecentReports: true, includeCurrentUser: true, - policyTags: {}, + policyTags: POLICY_TAGS, loginList, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, @@ -746,7 +747,7 @@ describe('OptionsListUtils', () => { maxResults: undefined, includeUserToInvite: false, includeRecentReports: true, - policyTags: undefined, + policyTags: POLICY_TAGS, loginList, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, @@ -1916,7 +1917,7 @@ describe('OptionsListUtils', () => { options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, - policyTags: undefined, + policyTags: POLICY_TAGS, loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, @@ -1939,7 +1940,7 @@ describe('OptionsListUtils', () => { draftComments: {}, nvpDismissedProductTraining, loginList, - policyTags: undefined, + policyTags: POLICY_TAGS, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, @@ -1970,7 +1971,7 @@ describe('OptionsListUtils', () => { draftComments: {}, nvpDismissedProductTraining, loginList, - policyTags: undefined, + policyTags: POLICY_TAGS, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, @@ -1995,7 +1996,7 @@ describe('OptionsListUtils', () => { draftComments: {}, nvpDismissedProductTraining, loginList, - policyTags: undefined, + policyTags: POLICY_TAGS, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, @@ -2015,13 +2016,13 @@ describe('OptionsListUtils', () => { // cspell:disable-next-line const searchText = 'barryallen'; // Given a set of options created from PERSONAL_DETAILS_WITH_PERIODS - const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, undefined, CURRENT_USER_ACCOUNT_ID, EMPTY_PRIVATE_IS_ARCHIVED_MAP, REPORTS); + const OPTIONS_WITH_PERIODS = createOptionList(PERSONAL_DETAILS_WITH_PERIODS, POLICY_TAGS, CURRENT_USER_ACCOUNT_ID, EMPTY_PRIVATE_IS_ARCHIVED_MAP, REPORTS); // When we call getSearchOptions with all betas const options = getSearchOptions({ options: OPTIONS_WITH_PERIODS, draftComments: {}, nvpDismissedProductTraining, - policyTags: undefined, + policyTags: POLICY_TAGS, loginList, betas: [CONST.BETAS.ALL], @@ -2048,7 +2049,7 @@ describe('OptionsListUtils', () => { options: OPTIONS_WITH_WORKSPACE_ROOM, draftComments: {}, nvpDismissedProductTraining, - policyTags: undefined, + policyTags: POLICY_TAGS, loginList, betas: [CONST.BETAS.ALL], @@ -2072,7 +2073,7 @@ describe('OptionsListUtils', () => { options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, - policyTags: undefined, + policyTags: POLICY_TAGS, loginList, betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, @@ -2097,7 +2098,7 @@ describe('OptionsListUtils', () => { options: OPTIONS_WITH_CHAT_ROOMS, draftComments: {}, nvpDismissedProductTraining, - policyTags: undefined, + policyTags: POLICY_TAGS, loginList, betas: [CONST.BETAS.ALL], @@ -2122,7 +2123,7 @@ describe('OptionsListUtils', () => { options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, - policyTags: undefined, + policyTags: POLICY_TAGS, loginList, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, @@ -2146,7 +2147,7 @@ describe('OptionsListUtils', () => { const options = getSearchOptions({ options: OPTIONS, draftComments: {}, - policyTags: undefined, + policyTags: POLICY_TAGS, loginList, nvpDismissedProductTraining, @@ -2197,7 +2198,7 @@ describe('OptionsListUtils', () => { nvpDismissedProductTraining, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, - policyTags: undefined, + policyTags: POLICY_TAGS, personalDetails: PERSONAL_DETAILS, }); // When we call filterAndOrderOptions with a search value and excludeLogins @@ -2219,7 +2220,7 @@ describe('OptionsListUtils', () => { nvpDismissedProductTraining, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, - policyTags: undefined, + policyTags: POLICY_TAGS, personalDetails: PERSONAL_DETAILS, }); // When we call filterAndOrderOptions with a search value and maxRecentReportsToShow set to 2 @@ -2251,7 +2252,7 @@ describe('OptionsListUtils', () => { betas: [CONST.BETAS.ALL], currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, - policyTags: undefined, + policyTags: POLICY_TAGS, personalDetails: PERSONAL_DETAILS, }); // When we call filterAndOrderOptions with a search value @@ -2458,7 +2459,7 @@ describe('OptionsListUtils', () => { }, }; - const OPTIONS_WITH_GROUP_CHAT = createOptionList(PERSONAL_DETAILS, CURRENT_USER_ACCOUNT_ID, EMPTY_PRIVATE_IS_ARCHIVED_MAP, REPORTS_WITH_GROUP_CHAT); + const OPTIONS_WITH_GROUP_CHAT = createOptionList(PERSONAL_DETAILS, POLICY_TAGS, CURRENT_USER_ACCOUNT_ID, EMPTY_PRIVATE_IS_ARCHIVED_MAP, REPORTS_WITH_GROUP_CHAT); // When we call getSearchOptions with a search query that matches a participant display name const options = getSearchOptions({ @@ -2471,6 +2472,7 @@ describe('OptionsListUtils', () => { currentUserEmail: CURRENT_USER_EMAIL, personalDetails: PERSONAL_DETAILS, searchQuery: 'Spider-Man', + policyTags: POLICY_TAGS, }); // Then one report should be returned @@ -2498,7 +2500,7 @@ describe('OptionsListUtils', () => { }, }; - const OPTIONS_WITH_GROUP_CHAT = createOptionList(PERSONAL_DETAILS, CURRENT_USER_ACCOUNT_ID, EMPTY_PRIVATE_IS_ARCHIVED_MAP, REPORTS_WITH_GROUP_CHAT); + const OPTIONS_WITH_GROUP_CHAT = createOptionList(PERSONAL_DETAILS, POLICY_TAGS, CURRENT_USER_ACCOUNT_ID, EMPTY_PRIVATE_IS_ARCHIVED_MAP, REPORTS_WITH_GROUP_CHAT); // When we call getSearchOptions with a search query that matches a participant login const options = getSearchOptions({ @@ -2511,6 +2513,7 @@ describe('OptionsListUtils', () => { currentUserEmail: CURRENT_USER_EMAIL, personalDetails: PERSONAL_DETAILS, searchQuery: 'peterparker@expensify.com', + policyTags: POLICY_TAGS, }); // Then one report should be returned @@ -2538,7 +2541,7 @@ describe('OptionsListUtils', () => { }, }; - const OPTIONS_WITH_GROUP_CHAT = createOptionList(PERSONAL_DETAILS, CURRENT_USER_ACCOUNT_ID, EMPTY_PRIVATE_IS_ARCHIVED_MAP, REPORTS_WITH_GROUP_CHAT); + const OPTIONS_WITH_GROUP_CHAT = createOptionList(PERSONAL_DETAILS, POLICY_TAGS, CURRENT_USER_ACCOUNT_ID, EMPTY_PRIVATE_IS_ARCHIVED_MAP, REPORTS_WITH_GROUP_CHAT); // When we call getSearchOptions with a search query that matches a participant name const options = getSearchOptions({ @@ -2551,6 +2554,7 @@ describe('OptionsListUtils', () => { currentUserEmail: CURRENT_USER_EMAIL, personalDetails: PERSONAL_DETAILS, searchQuery: 'Black Panther', + policyTags: POLICY_TAGS, }); // Then one report should be returned @@ -2578,7 +2582,7 @@ describe('OptionsListUtils', () => { }, }; - const OPTIONS_WITH_GROUP_CHAT = createOptionList(PERSONAL_DETAILS, CURRENT_USER_ACCOUNT_ID, EMPTY_PRIVATE_IS_ARCHIVED_MAP, REPORTS_WITH_GROUP_CHAT); + const OPTIONS_WITH_GROUP_CHAT = createOptionList(PERSONAL_DETAILS, POLICY_TAGS, CURRENT_USER_ACCOUNT_ID, EMPTY_PRIVATE_IS_ARCHIVED_MAP, REPORTS_WITH_GROUP_CHAT); // When we call getSearchOptions with a search query that does not match any participant const options = getSearchOptions({ @@ -2591,6 +2595,7 @@ describe('OptionsListUtils', () => { currentUserEmail: CURRENT_USER_EMAIL, personalDetails: PERSONAL_DETAILS, searchQuery: 'Wolverine', + policyTags: POLICY_TAGS, }); // Then no reports should be returned @@ -2617,6 +2622,7 @@ describe('OptionsListUtils', () => { const OPTIONS_WITH_GROUP_CHAT_NO_PARTICIPANTS = createOptionList( PERSONAL_DETAILS, + POLICY_TAGS, CURRENT_USER_ACCOUNT_ID, EMPTY_PRIVATE_IS_ARCHIVED_MAP, REPORTS_WITH_GROUP_CHAT_NO_PARTICIPANTS, @@ -2632,6 +2638,7 @@ describe('OptionsListUtils', () => { currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, personalDetails: PERSONAL_DETAILS, + policyTags: POLICY_TAGS, }); // When we pass the returned options to filterAndOrderOptions with any search value @@ -2962,7 +2969,7 @@ describe('OptionsListUtils', () => { loginList, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, - policyTags: undefined, + policyTags: POLICY_TAGS, personalDetails: PERSONAL_DETAILS, }); // When we call filterAndOrderOptions with a search value that matches a personal detail @@ -2983,7 +2990,7 @@ describe('OptionsListUtils', () => { loginList, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, currentUserEmail: CURRENT_USER_EMAIL, - policyTags: undefined, + policyTags: POLICY_TAGS, personalDetails: PERSONAL_DETAILS, }); // When we call filterAndOrderOptions with a search value that matches multiple items @@ -3006,7 +3013,7 @@ describe('OptionsListUtils', () => { options: OPTIONS_WITH_PERIODS, draftComments: {}, nvpDismissedProductTraining, - policyTags: undefined, + policyTags: POLICY_TAGS, loginList, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, @@ -3045,7 +3052,7 @@ describe('OptionsListUtils', () => { options: OPTIONS, draftComments: {}, nvpDismissedProductTraining, - policyTags: undefined, + policyTags: POLICY_TAGS, loginList, betas: [CONST.BETAS.ALL], @@ -3072,7 +3079,7 @@ describe('OptionsListUtils', () => { options: OPTIONS_WITH_SELF_DM, draftComments: {}, nvpDismissedProductTraining, - policyTags: undefined, + policyTags: POLICY_TAGS, loginList, betas: [CONST.BETAS.ALL], @@ -3745,7 +3752,7 @@ describe('OptionsListUtils', () => { lastActorDetails: null, isReportArchived: false, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, - policyTags: {}, + policyTags: POLICY_TAGS, }); const reportPreviewMessage = getReportPreviewMessage(iouReport, iouAction, true, false, null, true, reportPreviewAction); const expected = formatReportLastMessageText(Parser.htmlToText(reportPreviewMessage)); @@ -3779,7 +3786,7 @@ describe('OptionsListUtils', () => { lastActorDetails: null, isReportArchived: false, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, - policyTags: undefined, + policyTags: POLICY_TAGS, }); expect(lastMessage).toBe(Parser.htmlToText(getMovedTransactionMessage(translateLocal, movedTransactionAction))); }); @@ -3804,7 +3811,7 @@ describe('OptionsListUtils', () => { lastActorDetails: null, isReportArchived: false, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, - policyTags: undefined, + policyTags: POLICY_TAGS, }); expect(lastMessage).toBe(Parser.htmlToText(translate(CONST.LOCALES.EN, 'iou.automaticallySubmitted'))); }); @@ -3830,7 +3837,7 @@ describe('OptionsListUtils', () => { lastActorDetails: null, isReportArchived: false, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, - policyTags: undefined, + policyTags: POLICY_TAGS, }); expect(lastMessage).toBe(Parser.htmlToText(translate(CONST.LOCALES.EN, 'iou.automaticallyApproved'))); }); @@ -3856,7 +3863,7 @@ describe('OptionsListUtils', () => { lastActorDetails: null, isReportArchived: false, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, - policyTags: undefined, + policyTags: POLICY_TAGS, }); expect(lastMessage).toBe(Parser.htmlToText(translate(CONST.LOCALES.EN, 'iou.automaticallyForwarded'))); }); @@ -3879,7 +3886,7 @@ describe('OptionsListUtils', () => { lastActorDetails: null, isReportArchived: false, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, - policyTags: undefined, + policyTags: POLICY_TAGS, }); expect(lastMessage).toBe(Parser.htmlToText(translate(CONST.LOCALES.EN, 'workspaceActions.forcedCorporateUpgrade'))); }); @@ -3901,7 +3908,7 @@ describe('OptionsListUtils', () => { lastActorDetails: null, isReportArchived: false, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, - policyTags: undefined, + policyTags: POLICY_TAGS, }); expect(lastMessage).toBe(Parser.htmlToText(getChangedApproverActionMessage(translateLocal, takeControlAction))); }); @@ -3922,7 +3929,7 @@ describe('OptionsListUtils', () => { lastActorDetails: null, isReportArchived: false, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, - policyTags: undefined, + policyTags: POLICY_TAGS, }); expect(lastMessage).toBe(Parser.htmlToText(getChangedApproverActionMessage(translateLocal, rerouteAction))); }); @@ -3943,7 +3950,7 @@ describe('OptionsListUtils', () => { lastActorDetails: null, isReportArchived: false, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, - policyTags: undefined, + policyTags: POLICY_TAGS, }); expect(lastMessage).toBe(Parser.htmlToText(getMovedActionMessage(translateLocal, movedAction, report))); }); @@ -3968,7 +3975,7 @@ describe('OptionsListUtils', () => { lastActorDetails: null, isReportArchived: false, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, - policyTags: undefined, + policyTags: POLICY_TAGS, }); // Then it should return the DYNAMIC_EXTERNAL_WORKFLOW_ROUTED message @@ -3994,7 +4001,7 @@ describe('OptionsListUtils', () => { report, lastActorDetails: null, isReportArchived: false, - policyTags: {}, + policyTags: POLICY_TAGS, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, }); expect(result).toBe(expectedVisibleText); @@ -4046,7 +4053,7 @@ describe('OptionsListUtils', () => { isReportArchived: false, policy, reportMetadata, - policyTags: undefined, + policyTags: POLICY_TAGS, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, }); expect(lastMessage).toBe(translate(CONST.LOCALES.EN, 'iou.queuedToSubmitViaDEW')); @@ -4080,7 +4087,7 @@ describe('OptionsListUtils', () => { lastActorDetails: null, isReportArchived: false, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, - policyTags: undefined, + policyTags: POLICY_TAGS, }); expect(lastMessage).toBe(customErrorMessage); }); @@ -4110,7 +4117,7 @@ describe('OptionsListUtils', () => { lastActorDetails: null, isReportArchived: false, currentUserAccountID: CURRENT_USER_ACCOUNT_ID, - policyTags: undefined, + policyTags: POLICY_TAGS, }); expect(lastMessage).toBe(translate(CONST.LOCALES.EN, 'iou.error.genericCreateFailureMessage')); });