diff --git a/src/components/LHNOptionsList/LHNOptionsList.tsx b/src/components/LHNOptionsList/LHNOptionsList.tsx index b6abe464bedb..326b2ad1605a 100644 --- a/src/components/LHNOptionsList/LHNOptionsList.tsx +++ b/src/components/LHNOptionsList/LHNOptionsList.tsx @@ -159,8 +159,9 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio const reportID = item.reportID; const itemParentReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${item.parentReportID}`]; const itemReportNameValuePairs = reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`]; + const chatReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${item.chatReportID}`]; const itemReportActions = reportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`]; - const itemOneTransactionThreadReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${getOneTransactionThreadReportID(reportID, itemReportActions, isOffline)}`]; + const itemOneTransactionThreadReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${getOneTransactionThreadReportID(item, chatReport, itemReportActions, isOffline)}`]; const itemParentReportActions = reportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${item?.parentReportID}`]; const itemParentReportAction = item?.parentReportActionID ? itemParentReportActions?.[item?.parentReportActionID] : undefined; const itemReportAttributes = reportAttributes?.[reportID]; diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index a07c28609187..4e4ddeb49f1f 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -428,6 +428,7 @@ function MoneyReportHeader({ } return getReportPrimaryAction({ report: moneyRequestReport, + chatReport, reportTransactions: transactions, violations, policy, @@ -435,7 +436,7 @@ function MoneyReportHeader({ reportActions, isChatReportArchived, }); - }, [isPaidAnimationRunning, moneyRequestReport, reportNameValuePairs, policy, transactions, violations, reportActions, isChatReportArchived]); + }, [isPaidAnimationRunning, moneyRequestReport, reportNameValuePairs, policy, transactions, violations, reportActions, isChatReportArchived, chatReport]); const confirmExport = useCallback(() => { setExportModalStatus(null); @@ -627,18 +628,19 @@ function MoneyReportHeader({ if (!moneyRequestReport) { return []; } - return getSecondaryReportActions( - moneyRequestReport, - transactions, + return getSecondaryReportActions({ + report: moneyRequestReport, + chatReport, + reportTransactions: transactions, violations, policy, reportNameValuePairs, reportActions, policies, - isBetaEnabled(CONST.BETAS.RETRACT_NEWDOT), + canUseRetractNewDot: isBetaEnabled(CONST.BETAS.RETRACT_NEWDOT), isChatReportArchived, - ); - }, [moneyRequestReport, transactions, violations, policy, reportNameValuePairs, reportActions, policies, isBetaEnabled, isChatReportArchived]); + }); + }, [moneyRequestReport, transactions, violations, policy, reportNameValuePairs, reportActions, policies, isBetaEnabled, chatReport, isChatReportArchived]); const secondaryActionsImplementation: Record< ValueOf, diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx index 90fdf0bf884e..55335348ce6e 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx @@ -125,6 +125,7 @@ function MoneyRequestReportActionsList({ const isFocused = useIsFocused(); const route = useRoute>(); const reportTransactionIDs = transactions.map((transaction) => transaction.transactionID); + const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.chatReportID)}`, {canBeMissing: true}); const reportID = report?.reportID; const linkedReportActionID = route?.params?.reportActionID; @@ -137,7 +138,7 @@ function MoneyRequestReportActionsList({ const transactionsWithoutPendingDelete = useMemo(() => transactions.filter((t) => !isTransactionPendingDelete(t)), [transactions]); const mostRecentIOUReportActionID = useMemo(() => getMostRecentIOURequestActionID(reportActions), [reportActions]); - const transactionThreadReportID = getOneTransactionThreadReportID(reportID, reportActions ?? [], false, reportTransactionIDs); + const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, reportActions ?? [], false, reportTransactionIDs); const firstVisibleReportActionID = useMemo(() => getFirstVisibleReportActionID(reportActions, isOffline), [reportActions, isOffline]); const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`, {canBeMissing: true}); const [currentUserAccountID] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false, selector: (session) => session?.accountID}); diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportView.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportView.tsx index fb1c265787c5..25564056e75e 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportView.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportView.tsx @@ -93,6 +93,7 @@ function MoneyRequestReportView({report, policy, reportMetadata, shouldDisplayRe const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP, {canBeMissing: true}); const [isComposerFullSize] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE}${reportID}`, {initialValue: false, canBeMissing: true}); const {reportPendingAction, reportErrors} = getReportOfflinePendingActionAndErrors(report); + const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.chatReportID)}`, {canBeMissing: true}); const {reportActions: unfilteredReportActions, hasNewerActions, hasOlderActions} = usePaginatedReportActions(reportID); const reportActions = getFilteredReportActionsForReportView(unfilteredReportActions); @@ -103,7 +104,7 @@ function MoneyRequestReportView({report, policy, reportMetadata, shouldDisplayRe }); const reportTransactionIDs = transactions?.map((transaction) => transaction.transactionID); - const transactionThreadReportID = getOneTransactionThreadReportID(reportID, reportActions ?? [], isOffline, reportTransactionIDs); + const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, reportActions ?? [], isOffline, reportTransactionIDs); const prevTransactions = usePrevious(transactions); diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index 55eae6c81e99..e8c89856f12c 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -413,7 +413,7 @@ function ReportPreview({ numberOfRequests === 1 && (!!formattedMerchant || !!formattedDescription) && !(hasOnlyTransactionsWithPendingRoutes && !totalDisplaySpend); const shouldShowSubtitle = !areAllTransactionsScanning && (shouldShowSingleRequestMerchantOrDescription || numberOfRequests > 1) && !isDisplayAmountZero(getDisplayAmount()); - const isPayAtEndExpense = isPayAtEndExpenseReport(iouReportID, transactions); + const isPayAtEndExpense = isPayAtEndExpenseReport(iouReport, transactions); const [archiveReason] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, {selector: getArchiveReason, canBeMissing: false}); const getPendingMessageProps: () => PendingMessageProps = () => { diff --git a/src/libs/DebugUtils.ts b/src/libs/DebugUtils.ts index fdd4493c9460..cb11bfa51340 100644 --- a/src/libs/DebugUtils.ts +++ b/src/libs/DebugUtils.ts @@ -1325,7 +1325,7 @@ function validateTransactionViolationJSON(json: string) { /** * Gets the reason for showing LHN row */ -function getReasonForShowingRowInLHN(report: OnyxEntry, hasRBR = false, isReportArchived = false): TranslationPaths | null { +function getReasonForShowingRowInLHN(report: OnyxEntry, chatReport: OnyxEntry, hasRBR = false, isReportArchived = false): TranslationPaths | null { if (!report) { return null; } @@ -1334,6 +1334,7 @@ function getReasonForShowingRowInLHN(report: OnyxEntry, hasRBR = false, const reason = reasonForReportToBeInOptionList({ report, + chatReport, // We can't pass report.reportID because it will cause reason to always be isFocused currentReportId: '-1', isInFocusMode: !!isInFocusMode, @@ -1390,6 +1391,7 @@ type RBRReasonAndReportAction = { */ function getReasonAndReportActionForRBRInLHNRow( report: Report, + chatReport: OnyxEntry, reportActions: OnyxEntry, transactions: OnyxCollection, hasViolations: boolean, @@ -1397,7 +1399,7 @@ function getReasonAndReportActionForRBRInLHNRow( isArchivedReport = false, ): RBRReasonAndReportAction | null { const {reason, reportAction} = - SidebarUtils.getReasonAndReportActionThatHasRedBrickRoad(report, reportActions, hasViolations, reportErrors, transactions, transactionViolations, isArchivedReport) ?? {}; + SidebarUtils.getReasonAndReportActionThatHasRedBrickRoad(report, chatReport, reportActions, hasViolations, reportErrors, transactions, transactionViolations, isArchivedReport) ?? {}; if (reason) { return {reason: `debug.reasonRBR.${reason}`, reportAction}; diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 76fdd527b2df..1b3dd5affacf 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -392,10 +392,12 @@ Onyx.connect({ const reportActionsArray = Object.values(reportActions[1] ?? {}); let sortedReportActions = getSortedReportActions(reportActionsArray, true); allSortedReportActions[reportID] = sortedReportActions; + const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; + const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`]; // If the report is a one-transaction report and has , we need to return the combined reportActions so that the LHN can display modifications // to the transaction thread or the report itself - const transactionThreadReportID = getOneTransactionThreadReportID(reportID, actions[reportActions[0]]); + const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, actions[reportActions[0]]); if (transactionThreadReportID) { const transactionThreadReportActionsArray = Object.values(actions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`] ?? {}); sortedReportActions = getCombinedReportActions(sortedReportActions, transactionThreadReportID, transactionThreadReportActionsArray, reportID); @@ -408,7 +410,6 @@ Onyx.connect({ lastReportActions[reportID] = firstReportAction; } - const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; const isWriteActionAllowed = canUserPerformWriteAction(report); // The report is only visible if it is the last action not deleted that @@ -927,7 +928,8 @@ function createOption(accountIDs: number[], personalDetails: OnyxInputOrEntry | ReportAction[], chatReportID?: string) { - if (!chatReportID) { +function getSendMoneyFlowOneTransactionThreadID(actions: OnyxEntry | ReportAction[], chatReport: OnyxEntry) { + if (!chatReport) { return undefined; } @@ -1195,7 +1195,7 @@ function getSendMoneyFlowOneTransactionThreadID(actions: OnyxEntry, + chatReport: OnyxEntry, reportActions: OnyxEntry | ReportAction[], isOffline: boolean | undefined = undefined, reportTransactionIDs?: string[], ): string | undefined { // If the report is not an IOU, Expense report, or Invoice, it shouldn't be treated as one-transaction report. - const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; if (report?.type !== CONST.REPORT.TYPE.IOU && report?.type !== CONST.REPORT.TYPE.EXPENSE && report?.type !== CONST.REPORT.TYPE.INVOICE) { return; } @@ -1255,7 +1255,7 @@ function getOneTransactionThreadReportID( return; } - const sendMoneyFlowID = getSendMoneyFlowOneTransactionThreadID(reportActions, report?.chatReportID); + const sendMoneyFlowID = getSendMoneyFlowOneTransactionThreadID(reportActions, chatReport); if (sendMoneyFlowID) { return sendMoneyFlowID; diff --git a/src/libs/ReportPrimaryActionUtils.ts b/src/libs/ReportPrimaryActionUtils.ts index 969fbd72a5da..dbe6fbd3ac5a 100644 --- a/src/libs/ReportPrimaryActionUtils.ts +++ b/src/libs/ReportPrimaryActionUtils.ts @@ -1,4 +1,4 @@ -import type {OnyxCollection} from 'react-native-onyx'; +import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; import type {Policy, Report, ReportAction, ReportNameValuePairs, Transaction, TransactionViolation} from '@src/types/onyx'; @@ -48,6 +48,7 @@ import { type GetReportPrimaryActionParams = { report: Report; + chatReport: OnyxEntry; reportTransactions: Transaction[]; violations: OnyxCollection; policy?: Policy; @@ -225,7 +226,7 @@ function isExportAction(report: Report, policy?: Policy, reportActions?: ReportA return false; } -function isRemoveHoldAction(report: Report, reportTransactions: Transaction[]) { +function isRemoveHoldAction(report: Report, chatReport: OnyxEntry, reportTransactions: Transaction[]) { const isReportOnHold = reportTransactions.some(isOnHoldTransactionUtils); if (!isReportOnHold) { @@ -233,7 +234,7 @@ function isRemoveHoldAction(report: Report, reportTransactions: Transaction[]) { } const reportActions = getAllReportActions(report.reportID); - const transactionThreadReportID = getOneTransactionThreadReportID(report.reportID, reportActions); + const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, reportActions); if (!transactionThreadReportID) { return false; @@ -299,7 +300,7 @@ function getAllExpensesToHoldIfApplicable(report?: Report, reportActions?: Repor } function getReportPrimaryAction(params: GetReportPrimaryActionParams): ValueOf | '' { - const {report, reportTransactions, violations, policy, reportNameValuePairs, reportActions, isChatReportArchived} = params; + const {report, reportTransactions, violations, policy, reportNameValuePairs, reportActions, isChatReportArchived, chatReport} = params; const isPayActionWithAllExpensesHeld = isPrimaryPayAction(report, policy, reportNameValuePairs, isChatReportArchived) && hasOnlyHeldExpenses(report?.reportID); @@ -315,7 +316,7 @@ function getReportPrimaryAction(params: GetReportPrimaryActionParams): ValueOf, reportTransactions: Transaction[], reportActions?: ReportAction[]): boolean { + const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, reportActions); const isOneExpenseReport = reportTransactions.length === 1; const transaction = reportTransactions.at(0); @@ -484,17 +484,30 @@ function isReopenAction(report: Report, policy?: Policy): boolean { return true; } -function getSecondaryReportActions( - report: Report, - reportTransactions: Transaction[], - violations: OnyxCollection, - policy?: Policy, - reportNameValuePairs?: ReportNameValuePairs, - reportActions?: ReportAction[], - policies?: OnyxCollection, - canUseRetractNewDot?: boolean, +function getSecondaryReportActions({ + report, + chatReport, + reportTransactions, + violations, + policy, + reportNameValuePairs, + reportActions, + policies, + canUseRetractNewDot, isChatReportArchived = false, -): Array> { +}: { + report: Report; + chatReport: OnyxEntry; + reportTransactions: Transaction[]; + violations: OnyxCollection; + policy?: Policy; + reportNameValuePairs?: ReportNameValuePairs; + reportActions?: ReportAction[]; + policies?: OnyxCollection; + canUseRetractNewDot?: boolean; + canUseNewDotSplits?: boolean; + isChatReportArchived?: boolean; +}): Array> { const options: Array> = []; if (isPrimaryPayAction(report, policy, reportNameValuePairs) && hasOnlyHeldExpenses(report?.reportID)) { @@ -537,7 +550,7 @@ function getSecondaryReportActions( options.push(CONST.REPORT.SECONDARY_ACTIONS.REOPEN); } - if (isHoldAction(report, reportTransactions, reportActions)) { + if (isHoldAction(report, chatReport, reportTransactions, reportActions)) { options.push(CONST.REPORT.SECONDARY_ACTIONS.HOLD); } diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index fb0dc176ab66..5431c3a8499c 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2212,33 +2212,35 @@ function hasOnlyNonReimbursableTransactions(iouReportID: string | undefined): bo /** * Checks if a report has only one transaction associated with it */ -function isOneTransactionReport(reportID: string | undefined): boolean { - const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`] ?? ([] as ReportAction[]); - return getOneTransactionThreadReportID(reportID, reportActions) !== null; +function isOneTransactionReport(report: OnyxEntry): boolean { + const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.reportID}`] ?? ([] as ReportAction[]); + const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`]; + return getOneTransactionThreadReportID(report, chatReport, reportActions) !== null; } /* * Whether the report contains only one expense and the expense should be paid later */ -function isPayAtEndExpenseReport(reportID: string | undefined, transactions: Transaction[] | undefined): boolean { - if ((!!transactions && transactions.length !== 1) || !isOneTransactionReport(reportID)) { +function isPayAtEndExpenseReport(report: OnyxEntry, transactions: Transaction[] | undefined): boolean { + if ((!!transactions && transactions.length !== 1) || !isOneTransactionReport(report)) { return false; } - return isPayAtEndExpense(transactions?.[0] ?? getReportTransactions(reportID).at(0)); + return isPayAtEndExpense(transactions?.[0] ?? getReportTransactions(report?.reportID).at(0)); } - /** * Checks if a report is a transaction thread associated with a report that has only one transaction */ -function isOneTransactionThread(reportID: string | undefined, parentReportID: string | undefined, threadParentReportAction: OnyxEntry): boolean { - if (!reportID || !parentReportID) { +function isOneTransactionThread(report: OnyxEntry, parentReport: OnyxEntry, threadParentReportAction: OnyxEntry) { + if (!report || !parentReport) { return false; } - const parentReportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReportID}`] ?? ([] as ReportAction[]); - const transactionThreadReportID = getOneTransactionThreadReportID(parentReportID, parentReportActions); - return reportID === transactionThreadReportID && !isSentMoneyReportAction(threadParentReportAction); + const parentReportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReport?.reportID}`] ?? ([] as ReportAction[]); + + const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${parentReport?.chatReportID}`]; + const transactionThreadReportID = getOneTransactionThreadReportID(parentReport, chatReport, parentReportActions); + return report?.reportID === transactionThreadReportID && !isSentMoneyReportAction(threadParentReportAction); } /** @@ -2254,8 +2256,9 @@ function isReportTransactionThread(report: OnyxEntry) { function getDisplayedReportID(reportID: string): string { const report = getReport(reportID, allReports); const parentReportID = report?.parentReportID; + const parentReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${parentReportID}`]; const parentReportAction = getReportAction(parentReportID, report?.parentReportActionID); - return parentReportID && isOneTransactionThread(reportID, parentReportID, parentReportAction) ? parentReportID : reportID; + return parentReportID && isOneTransactionThread(report, parentReport, parentReportAction) ? parentReportID : reportID; } /** @@ -3026,7 +3029,7 @@ function getIcons( const isManager = currentUserAccountID === report?.managerID; // For one transaction IOUs, display a simplified report icon - if (isOneTransactionReport(report?.reportID)) { + if (isOneTransactionReport(report)) { return [ownerIcon]; } @@ -7802,13 +7805,14 @@ function getAllReportErrors(report: OnyxEntry, reportActions: OnyxEntry< function hasReportErrorsOtherThanFailedReceipt( report: Report, + chatReport: OnyxEntry, doesReportHaveViolations: boolean, transactionViolations: OnyxCollection, reportAttributes?: ReportAttributesDerivedValue['reports'], ) { const allReportErrors = reportAttributes?.[report?.reportID]?.reportErrors ?? {}; const transactionReportActions = getAllReportActions(report.reportID); - const oneTransactionThreadReportID = getOneTransactionThreadReportID(report.reportID, transactionReportActions, undefined); + const oneTransactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, transactionReportActions, undefined); let doesTransactionThreadReportHasViolations = false; if (oneTransactionThreadReportID) { const transactionReport = getReport(oneTransactionThreadReportID, allReports); @@ -7823,6 +7827,7 @@ function hasReportErrorsOtherThanFailedReceipt( type ShouldReportBeInOptionListParams = { report: OnyxEntry; + chatReport: OnyxEntry; currentReportId: string | undefined; isInFocusMode: boolean; betas: OnyxEntry; @@ -7837,6 +7842,7 @@ type ShouldReportBeInOptionListParams = { function reasonForReportToBeInOptionList({ report, + chatReport, currentReportId, isInFocusMode, betas, @@ -7896,8 +7902,10 @@ function reasonForReportToBeInOptionList({ return null; } + const parentReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`]; + // If this is a transaction thread associated with a report that only has one transaction, omit it - if (isOneTransactionThread(report.reportID, report.parentReportID, parentReportAction)) { + if (isOneTransactionThread(report, parentReport, parentReportAction)) { return null; } @@ -7953,7 +7961,7 @@ function reasonForReportToBeInOptionList({ // All unread chats (even archived ones) in GSD mode will be shown. This is because GSD mode is specifically for focusing the user on the most relevant chats, primarily, the unread ones if (isInFocusMode) { - const oneTransactionThreadReportID = getOneTransactionThreadReportID(report.reportID, allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`]); + const oneTransactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`]); const oneTransactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${oneTransactionThreadReportID}`]; return isUnread(report, oneTransactionThreadReport) && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE ? CONST.REPORT_IN_LHN_REASONS.IS_UNREAD @@ -8492,7 +8500,7 @@ function shouldReportShowSubscript(report: OnyxEntry): boolean { return true; } - if (isExpenseReport(report) && isOneTransactionReport(report?.reportID)) { + if (isExpenseReport(report) && isOneTransactionReport(report)) { return true; } @@ -8593,7 +8601,9 @@ function getOriginalReportID(reportID: string | undefined, reportAction: OnyxInp } const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`]; const currentReportAction = reportAction?.reportActionID ? reportActions?.[reportAction.reportActionID] : undefined; - const transactionThreadReportID = getOneTransactionThreadReportID(reportID, reportActions ?? ([] as ReportAction[])); + const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; + const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`]; + const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, reportActions ?? ([] as ReportAction[])); const isThreadReportParentAction = reportAction?.childReportID?.toString() === reportID; if (Object.keys(currentReportAction ?? {}).length === 0) { return isThreadReportParentAction ? getReport(reportID, allReports)?.parentReportID : (transactionThreadReportID ?? reportID); @@ -10706,11 +10716,13 @@ function getChatListItemReportName(action: ReportAction & {reportName?: string}, */ function generateReportAttributes({ report, + chatReport, reportActions, transactionViolations, reportNameValuePairs, }: { report: OnyxEntry; + chatReport: OnyxEntry; reportActions?: OnyxCollection; transactionViolations: OnyxCollection; reportNameValuePairs: OnyxCollection; @@ -10724,7 +10736,7 @@ function generateReportAttributes({ const hasAnyViolations = hasViolationsToDisplayInLHN || (!isReportSettled && isCurrentUserReportOwner && doesReportHasViolations); const reportErrors = getAllReportErrors(report, reportActionsList); const hasErrors = Object.entries(reportErrors ?? {}).length > 0; - const oneTransactionThreadReportID = getOneTransactionThreadReportID(report?.reportID, reportActionsList); + const oneTransactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, reportActionsList); const parentReportAction = report?.parentReportActionID ? parentReportActionsList?.[report.parentReportActionID] : undefined; const isReportArchived = !!reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`]?.private_isArchived; const requiresAttention = requiresAttentionFromCurrentUser(report, parentReportAction, isReportArchived); diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts index 6d0d37e1b91b..a4b3e5ff8e4b 100644 --- a/src/libs/SidebarUtils.ts +++ b/src/libs/SidebarUtils.ts @@ -228,9 +228,11 @@ function getOrderedReportIDs( const doesReportHaveViolations = shouldDisplayViolationsRBRInLHN(report, transactionViolations); const isHidden = isHiddenForCurrentUser(report); const isFocused = report.reportID === currentReportId; - const hasErrorsOtherThanFailedReceipt = hasReportErrorsOtherThanFailedReceipt(report, doesReportHaveViolations, transactionViolations, reportAttributes); + const chatReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`]; + const parentReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`]; + const hasErrorsOtherThanFailedReceipt = hasReportErrorsOtherThanFailedReceipt(report, chatReport, doesReportHaveViolations, transactionViolations, reportAttributes); const isReportInAccessible = report?.errorFields?.notFound; - if (isOneTransactionThread(report.reportID, report.parentReportID, parentReportAction)) { + if (isOneTransactionThread(report, parentReport, parentReportAction)) { return; } if (hasErrorsOtherThanFailedReceipt && !isReportInAccessible) { @@ -258,6 +260,7 @@ function getOrderedReportIDs( if ( shouldReportBeInOptionList({ report, + chatReport, currentReportId, isInFocusMode, betas, @@ -350,6 +353,7 @@ type ReasonAndReportActionThatHasRedBrickRoad = { function getReasonAndReportActionThatHasRedBrickRoad( report: Report, + chatReport: OnyxEntry, reportActions: OnyxEntry, hasViolations: boolean, reportErrors: Errors, @@ -384,7 +388,7 @@ function getReasonAndReportActionThatHasRedBrickRoad( }; } const parentReportAction = getReportAction(report?.parentReportID, report?.parentReportActionID); - const transactionThreadReportID = getOneTransactionThreadReportID(report.reportID, reportActions ?? []); + const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, reportActions ?? []); if (transactionThreadReportID) { const transactionID = getTransactionID(transactionThreadReportID); const transaction = transactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; @@ -407,6 +411,7 @@ function getReasonAndReportActionThatHasRedBrickRoad( function shouldShowRedBrickRoad( report: Report, + chatReport: OnyxEntry, reportActions: OnyxEntry, hasViolations: boolean, reportErrors: Errors, @@ -414,7 +419,7 @@ function shouldShowRedBrickRoad( transactionViolations?: OnyxCollection, isReportArchived = false, ) { - return !!getReasonAndReportActionThatHasRedBrickRoad(report, reportActions, hasViolations, reportErrors, transactions, transactionViolations, isReportArchived); + return !!getReasonAndReportActionThatHasRedBrickRoad(report, chatReport, reportActions, hasViolations, reportErrors, transactions, transactionViolations, isReportArchived); } /** diff --git a/src/libs/UnreadIndicatorUpdater/index.ts b/src/libs/UnreadIndicatorUpdater/index.ts index 7c3dd1fe1951..9beb2c5ba7ae 100644 --- a/src/libs/UnreadIndicatorUpdater/index.ts +++ b/src/libs/UnreadIndicatorUpdater/index.ts @@ -40,7 +40,8 @@ Onyx.connect({ function getUnreadReportsForUnreadIndicator(reports: OnyxCollection, currentReportID: string | undefined) { return Object.values(reports ?? {}).filter((report) => { const notificationPreference = ReportUtils.getReportNotificationPreference(report); - const oneTransactionThreadReportID = getOneTransactionThreadReportID(report?.reportID, allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.reportID}`]); + const chatReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`]; + const oneTransactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.reportID}`]); const oneTransactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${oneTransactionThreadReportID}`]; const nameValuePairs = allReportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`]; const isReportArchived = ReportUtils.isArchivedReport(nameValuePairs); @@ -48,6 +49,7 @@ function getUnreadReportsForUnreadIndicator(reports: OnyxCollection, cur ReportUtils.isUnread(report, oneTransactionThreadReport) && ReportUtils.shouldReportBeInOptionList({ report, + chatReport, currentReportId: currentReportID, betas: [], policies: {}, diff --git a/src/libs/WorkspacesSettingsUtils.ts b/src/libs/WorkspacesSettingsUtils.ts index e92259e5c55c..c328a2a18d5d 100644 --- a/src/libs/WorkspacesSettingsUtils.ts +++ b/src/libs/WorkspacesSettingsUtils.ts @@ -5,14 +5,12 @@ import type {LocaleContextProps} from '@components/LocaleContextProvider'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Policy, ReimbursementAccount, Report, ReportActions, ReportAttributesDerivedValue} from '@src/types/onyx'; +import type {Policy, ReimbursementAccount, Report, ReportAttributesDerivedValue} from '@src/types/onyx'; import type {PolicyConnectionSyncProgress, Unit} from '@src/types/onyx/Policy'; import {isConnectionInProgress} from './actions/connections'; import {shouldShowQBOReimbursableExportDestinationAccountError} from './actions/connections/QuickbooksOnline'; import {convertToDisplayString} from './CurrencyUtils'; import {isPolicyAdmin, shouldShowCustomUnitsError, shouldShowEmployeeListError, shouldShowPolicyError, shouldShowSyncError, shouldShowTaxRateError} from './PolicyUtils'; -import {getOneTransactionThreadReportID} from './ReportActionsUtils'; -import {isUnread} from './ReportUtils'; type CheckingMethod = () => boolean; @@ -149,33 +147,6 @@ function getWorkspacesBrickRoads(reports: OnyxCollection, policies: Onyx return workspacesBrickRoadsMap; } -/** - * @returns a map where the keys are policyIDs and the values are truthy booleans if policy has unread content - */ -function getWorkspacesUnreadStatuses(reports: OnyxCollection, reportActions: OnyxCollection): Record { - if (!reports) { - return {}; - } - - const workspacesUnreadStatuses: Record = {}; - - Object.values(reports).forEach((report) => { - const policyID = report?.policyID; - if (!policyID || workspacesUnreadStatuses[policyID]) { - return; - } - - const currentReportActions = reportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`] ?? {}; - const oneTransactionThreadReportID = getOneTransactionThreadReportID(report.reportID, currentReportActions); - const oneTransactionThreadReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${oneTransactionThreadReportID}`]; - // When the only message of a report is deleted lastVisibleActionCreated is not reset leading to wrongly - // setting it Unread so we add additional condition here to avoid read workspace indicator from being bold. - workspacesUnreadStatuses[policyID] = isUnread(report, oneTransactionThreadReport) && !!report.lastActorAccountID; - }); - - return workspacesUnreadStatuses; -} - /** * @param unit Unit * @returns translation key for the unit @@ -264,7 +235,6 @@ export { getChatTabBrickRoadReport, getBrickRoadForPolicy, getWorkspacesBrickRoads, - getWorkspacesUnreadStatuses, hasGlobalWorkspaceSettingsRBR, hasWorkspaceSettingsRBR, getChatTabBrickRoad, diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index cbf3fcc69fee..8bb0c87978d2 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -4120,7 +4120,7 @@ function getUpdateMoneyRequestParams( value: getOutstandingChildRequest(updatedMoneyRequestReport), }, ); - if (isOneTransactionThread(transactionThreadReportID, iouReport?.reportID, undefined)) { + if (isOneTransactionThread(transactionThread ?? undefined, iouReport ?? undefined, undefined)) { optimisticData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`, @@ -9080,7 +9080,7 @@ function canApproveIOU( if (hasOnlyPendingCardOrScanningTransactions) { return false; } - const isPayAtEndExpenseReport = isPayAtEndExpenseReportReportUtils(iouReport?.reportID, reportTransactions); + const isPayAtEndExpenseReport = isPayAtEndExpenseReportReportUtils(iouReport ?? undefined, reportTransactions); const isClosedReport = isClosedReportUtil(iouReport); return ( reportTransactions.length > 0 && isCurrentUserManager && !isOpenExpenseReport && !isApproved && !iouSettled && !isArchivedExpenseReport && !isPayAtEndExpenseReport && !isClosedReport @@ -9151,7 +9151,7 @@ function canIOUBePaid( const {reimbursableSpend} = getMoneyRequestSpendBreakdown(iouReport); const isAutoReimbursable = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES ? false : canBeAutoReimbursed(iouReport, policy); const shouldBeApproved = canApproveIOU(iouReport, policy, transactions); - const isPayAtEndExpenseReport = isPayAtEndExpenseReportReportUtils(iouReport?.reportID, transactions); + const isPayAtEndExpenseReport = isPayAtEndExpenseReportReportUtils(iouReport ?? undefined, transactions); return ( isPayer && !isOpenExpenseReport && diff --git a/src/libs/actions/OnyxDerived/configs/reportAttributes.ts b/src/libs/actions/OnyxDerived/configs/reportAttributes.ts index 4a63376d167f..6c9084d79b33 100644 --- a/src/libs/actions/OnyxDerived/configs/reportAttributes.ts +++ b/src/libs/actions/OnyxDerived/configs/reportAttributes.ts @@ -109,9 +109,11 @@ export default createOnyxDerivedValueConfig({ return acc; } + const chatReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${report.chatReportID}`]; const reportActionsList = reportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`]; const {hasAnyViolations, requiresAttention, isReportArchived, reportErrors} = generateReportAttributes({ report, + chatReport, reportActions, transactionViolations, reportNameValuePairs, @@ -119,7 +121,7 @@ export default createOnyxDerivedValueConfig({ let brickRoadStatus; // if report has errors or violations, show red dot - if (SidebarUtils.shouldShowRedBrickRoad(report, reportActionsList, hasAnyViolations, reportErrors, transactions, transactionViolations, !!isReportArchived)) { + if (SidebarUtils.shouldShowRedBrickRoad(report, chatReport, reportActionsList, hasAnyViolations, reportErrors, transactions, transactionViolations, !!isReportArchived)) { brickRoadStatus = CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR; } // if report does not have error, check if it should show green dot diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 178000941a8d..d43a88dcf505 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -1621,8 +1621,10 @@ function markAllMessagesAsRead() { return; } + const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report.chatReportID}`]; const oneTransactionThreadReportID = ReportActionsUtils.getOneTransactionThreadReportID( - report.reportID, + report, + chatReport, allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`], ); const oneTransactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${oneTransactionThreadReportID}`]; @@ -1689,7 +1691,8 @@ function markCommentAsUnread(reportID: string | undefined, reportAction: ReportA }, null); const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; - const transactionThreadReportID = ReportActionsUtils.getOneTransactionThreadReportID(reportID, reportActions ?? []); + const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`]; + const transactionThreadReportID = ReportActionsUtils.getOneTransactionThreadReportID(report, chatReport, reportActions ?? []); const transactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`]; // If no action created date is provided, use the last action's from other user diff --git a/src/libs/markAllPolicyReportsAsRead.ts b/src/libs/markAllPolicyReportsAsRead.ts index 698b0637e482..3f46c34644e5 100644 --- a/src/libs/markAllPolicyReportsAsRead.ts +++ b/src/libs/markAllPolicyReportsAsRead.ts @@ -28,7 +28,8 @@ export default function markAllPolicyReportsAsRead(policyID: string) { let delay = 0; Object.keys(allReports ?? {}).forEach((key: string) => { const report = allReports?.[key]; - const oneTransactionThreadReportID = getOneTransactionThreadReportID(report?.reportID, allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.reportID}`]); + const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`]; + const oneTransactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.reportID}`]); const oneTransactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${oneTransactionThreadReportID}`]; if (report?.policyID !== policyID || !isUnread(report, oneTransactionThreadReport)) { return; diff --git a/src/pages/Debug/Report/DebugReportPage.tsx b/src/pages/Debug/Report/DebugReportPage.tsx index 21f895f9af85..eef069c96fa4 100644 --- a/src/pages/Debug/Report/DebugReportPage.tsx +++ b/src/pages/Debug/Report/DebugReportPage.tsx @@ -52,6 +52,7 @@ function DebugReportPage({ const StyleUtils = useStyleUtils(); const theme = useTheme(); const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {canBeMissing: true}); + const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`, {canBeMissing: true}); const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {canBeMissing: true}); const [transactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {canBeMissing: true}); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true}); @@ -72,10 +73,10 @@ function DebugReportPage({ const hasViolations = !!shouldDisplayViolations || shouldDisplayReportViolations; const {reason: reasonGBR, reportAction: reportActionGBR} = DebugUtils.getReasonAndReportActionForGBRInLHNRow(report, isReportArchived) ?? {}; const {reason: reasonRBR, reportAction: reportActionRBR} = - DebugUtils.getReasonAndReportActionForRBRInLHNRow(report, reportActions, transactions, hasViolations, reportAttributes?.reportErrors ?? {}, isReportArchived) ?? {}; + DebugUtils.getReasonAndReportActionForRBRInLHNRow(report, chatReport, reportActions, transactions, hasViolations, reportAttributes?.reportErrors ?? {}, isReportArchived) ?? {}; const hasRBR = !!reasonRBR; const hasGBR = !hasRBR && !!reasonGBR; - const reasonLHN = DebugUtils.getReasonForShowingRowInLHN(report, hasRBR, isReportArchived); + const reasonLHN = DebugUtils.getReasonForShowingRowInLHN(report, chatReport, hasRBR, isReportArchived); return [ { @@ -120,7 +121,7 @@ function DebugReportPage({ : undefined, }, ]; - }, [report, transactionViolations, reportID, reportActions, transactions, reportAttributes?.reportErrors, isReportArchived, translate]); + }, [chatReport, report, transactionViolations, reportID, reportActions, transactions, reportAttributes?.reportErrors, isReportArchived, translate]); const DebugDetailsTab = useCallback( () => ( diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 2ad1f27fb469..10159d27a8ab 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -147,6 +147,7 @@ function ReportDetailsPage({policies, report, route, reportMetadata}: ReportDeta const backTo = route.params.backTo; const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`, {canBeMissing: true}); + const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report.chatReportID}`, {canBeMissing: true}); const [parentReportAction] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`, { selector: (actions) => (report?.parentReportActionID ? actions?.[report.parentReportActionID] : undefined), @@ -159,7 +160,7 @@ function ReportDetailsPage({policies, report, route, reportMetadata}: ReportDeta const {removeTransaction} = useSearchContext(); - const transactionThreadReportID = useMemo(() => getOneTransactionThreadReportID(report.reportID, reportActions ?? [], isOffline), [report.reportID, reportActions, isOffline]); + const transactionThreadReportID = useMemo(() => getOneTransactionThreadReportID(report, chatReport, reportActions ?? [], isOffline), [reportActions, isOffline, report, chatReport]); /* eslint-disable @typescript-eslint/prefer-nullish-coalescing */ const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`, {canBeMissing: true}); diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index 7d64ded33e7f..69495d8225dc 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -258,6 +258,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) { ); const reportID = report?.reportID; + const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`, {canBeMissing: true}); const prevReport = usePrevious(report); const prevUserLeavingStatus = usePrevious(userLeavingStatus); const lastReportIDFromRoute = usePrevious(reportIDFromRoute); @@ -268,6 +269,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) { const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP, {canBeMissing: true}); const {reportActions: unfilteredReportActions, linkedAction, sortedAllReportActions, hasNewerActions, hasOlderActions} = usePaginatedReportActions(reportID, reportActionIDFromRoute); const reportActions = getFilteredReportActionsForReportView(unfilteredReportActions); + const [childReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${linkedAction?.childReportID}`, {canBeMissing: true}); const [isBannerVisible, setIsBannerVisible] = useState(true); const [scrollPosition, setScrollPosition] = useState({}); @@ -299,7 +301,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) { canBeMissing: false, }); const reportTransactionIDs = reportTransactions?.map((transaction) => transaction.transactionID); - const transactionThreadReportID = getOneTransactionThreadReportID(reportID, reportActions ?? [], isOffline, reportTransactionIDs); + const transactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, reportActions ?? [], isOffline, reportTransactionIDs); const [transactionThreadReportActions = {}] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`, {canBeMissing: true}); const combinedReportActions = getCombinedReportActions(reportActions, transactionThreadReportID ?? null, Object.values(transactionThreadReportActions)); const lastReportAction = [...combinedReportActions, parentReportAction].find((action) => canEditReportAction(action) && !isMoneyRequestAction(action)); @@ -395,11 +397,11 @@ function ReportScreen({route, navigation}: ReportScreenProps) { } useEffect(() => { - if (!transactionThreadReportID || !route?.params?.reportActionID || !isOneTransactionThread(linkedAction?.childReportID, reportID, linkedAction)) { + if (!transactionThreadReportID || !route?.params?.reportActionID || !isOneTransactionThread(childReport, report, linkedAction)) { return; } navigation.setParams({reportActionID: ''}); - }, [transactionThreadReportID, route?.params?.reportActionID, linkedAction, reportID, navigation]); + }, [transactionThreadReportID, route?.params?.reportActionID, linkedAction, reportID, navigation, report, childReport]); const {isEditingDisabled, isCurrentReportLoadedFromOnyx} = useIsReportReadyToDisplay(report, reportIDFromRoute); diff --git a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx index 7febb8a9f72e..9e9448625364 100755 --- a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -165,12 +165,13 @@ function BaseReportActionContextMenu({ const [download] = useOnyx(`${ONYXKEYS.COLLECTION.DOWNLOAD}${sourceID}`, {canBeMissing: true}); const [childReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportAction?.childReportID}`, {canBeMissing: true}); + const [childChatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${childReport?.chatReportID}`, {canBeMissing: true}); const parentReportAction = getReportAction(childReport?.parentReportID, childReport?.parentReportActionID); const {reportActions: paginatedReportActions} = usePaginatedReportActions(childReport?.reportID); const transactionThreadReportID = useMemo( - () => getOneTransactionThreadReportID(childReport?.reportID, paginatedReportActions ?? [], isOffline), - [childReport?.reportID, paginatedReportActions, isOffline], + () => getOneTransactionThreadReportID(childReport, childChatReport, paginatedReportActions ?? [], isOffline), + [paginatedReportActions, isOffline, childReport, childChatReport], ); const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`, {canBeMissing: true}); diff --git a/tests/perf-test/ReportUtils.perf-test.ts b/tests/perf-test/ReportUtils.perf-test.ts index f53465bbaf4e..8b496a8ed659 100644 --- a/tests/perf-test/ReportUtils.perf-test.ts +++ b/tests/perf-test/ReportUtils.perf-test.ts @@ -20,6 +20,7 @@ import { import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PersonalDetails, Policy, Report, ReportAction} from '@src/types/onyx'; +import {chatReportR14932 as chatReport} from '../../__mocks__/reportData/reports'; import createCollection from '../utils/collections/createCollection'; import createPersonalDetails from '../utils/collections/personalDetails'; import createRandomPolicy from '../utils/collections/policies'; @@ -163,7 +164,9 @@ describe('ReportUtils', () => { const policies = getMockedPolicies(); await waitForBatchedUpdates(); - await measureFunction(() => shouldReportBeInOptionList({report, currentReportId, isInFocusMode, betas, policies, doesReportHaveViolations: false, excludeEmptyChats: false})); + await measureFunction(() => + shouldReportBeInOptionList({report, chatReport, currentReportId, isInFocusMode, betas, policies, doesReportHaveViolations: false, excludeEmptyChats: false}), + ); }); test('[ReportUtils] getWorkspaceIcon on 1k policies', async () => { diff --git a/tests/ui/LHNItemsPresence.tsx b/tests/ui/LHNItemsPresence.tsx index 85ebf1f00677..28ec91ce3c26 100644 --- a/tests/ui/LHNItemsPresence.tsx +++ b/tests/ui/LHNItemsPresence.tsx @@ -15,6 +15,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PersonalDetailsList, Report, ReportAction, ViolationName} from '@src/types/onyx'; import type {ReportCollectionDataSet} from '@src/types/onyx/Report'; +import {chatReportR14932} from '../../__mocks__/reportData/reports'; import * as LHNTestUtils from '../utils/LHNTestUtils'; import * as TestHelper from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; @@ -431,7 +432,7 @@ describe('SidebarLinksData', () => { it('should not display the single transaction thread', async () => { // Given the SidebarLinks are rendered LHNTestUtils.getDefaultRenderedSidebarLinks(); - const expenseReport = buildOptimisticExpenseReport('212', '123', 100, 122, 'USD'); + const expenseReport = buildOptimisticExpenseReport(chatReportR14932.reportID, '123', 100, 122, 'USD'); const expenseTransaction = buildOptimisticTransaction({ transactionParams: { amount: 100, @@ -456,7 +457,7 @@ describe('SidebarLinksData', () => { [`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport.reportID}`]: transactionThreadReport, }); - await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`, expenseReport); + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${chatReportR14932.reportID}`, chatReportR14932); await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, { [expenseCreatedAction.reportActionID]: expenseCreatedAction, }); diff --git a/tests/unit/DebugUtilsTest.ts b/tests/unit/DebugUtilsTest.ts index cbd00134ae5a..ebd56700048d 100644 --- a/tests/unit/DebugUtilsTest.ts +++ b/tests/unit/DebugUtilsTest.ts @@ -11,6 +11,7 @@ import type {Report, ReportAction, ReportActions, Transaction} from '@src/types/ import type {JoinWorkspaceResolution} from '@src/types/onyx/OriginalMessage'; import type {ReportCollectionDataSet} from '@src/types/onyx/Report'; import type {ReportActionsCollectionDataSet} from '@src/types/onyx/ReportAction'; +import {chatReportR14932} from '../../__mocks__/reportData/reports'; import type ReportActionName from '../../src/types/onyx/ReportActionName'; import createRandomReportAction from '../utils/collections/reportActions'; import createRandomReport from '../utils/collections/reports'; @@ -734,38 +735,47 @@ describe('DebugUtils', () => { Onyx.clear(); }); it('returns null when report is not defined', () => { - const reason = DebugUtils.getReasonForShowingRowInLHN(undefined); + const reason = DebugUtils.getReasonForShowingRowInLHN(undefined, chatReportR14932); expect(reason).toBeNull(); }); it('returns correct reason when report has a valid draft comment', async () => { await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}1`, 'Hello world!'); - const reason = DebugUtils.getReasonForShowingRowInLHN(baseReport); + const reason = DebugUtils.getReasonForShowingRowInLHN(baseReport, chatReportR14932); expect(reason).toBe('debug.reasonVisibleInLHN.hasDraftComment'); }); it('returns correct reason when report has GBR', () => { - const reason = DebugUtils.getReasonForShowingRowInLHN({ - ...baseReport, - lastMentionedTime: '2024-08-10 18:70:44.171', - lastReadTime: '2024-08-08 18:70:44.171', - }); + const reason = DebugUtils.getReasonForShowingRowInLHN( + { + ...baseReport, + lastMentionedTime: '2024-08-10 18:70:44.171', + lastReadTime: '2024-08-08 18:70:44.171', + }, + chatReportR14932, + ); expect(reason).toBe('debug.reasonVisibleInLHN.hasGBR'); }); it('returns correct reason when report is pinned', () => { - const reason = DebugUtils.getReasonForShowingRowInLHN({ - ...baseReport, - isPinned: true, - }); + const reason = DebugUtils.getReasonForShowingRowInLHN( + { + ...baseReport, + isPinned: true, + }, + chatReportR14932, + ); expect(reason).toBe('debug.reasonVisibleInLHN.pinnedByUser'); }); it('returns correct reason when report has add workspace room errors', () => { - const reason = DebugUtils.getReasonForShowingRowInLHN({ - ...baseReport, - errorFields: { - addWorkspaceRoom: { - error: 'Something happened', + const reason = DebugUtils.getReasonForShowingRowInLHN( + { + ...baseReport, + errorFields: { + addWorkspaceRoom: { + error: 'Something happened', + }, }, }, - }); + chatReportR14932, + ); expect(reason).toBe('debug.reasonVisibleInLHN.hasAddWorkspaceRoomErrors'); }); it('returns correct reason when report is unread', async () => { @@ -773,18 +783,21 @@ describe('DebugUtils', () => { await Onyx.set(ONYXKEYS.SESSION, { accountID: 1234, }); - const reason = DebugUtils.getReasonForShowingRowInLHN({ - ...baseReport, - participants: { - // eslint-disable-next-line @typescript-eslint/naming-convention - 1234: { - notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, + const reason = DebugUtils.getReasonForShowingRowInLHN( + { + ...baseReport, + participants: { + // eslint-disable-next-line @typescript-eslint/naming-convention + 1234: { + notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, + }, }, + lastVisibleActionCreated: '2024-08-10 18:70:44.171', + lastReadTime: '2024-08-08 18:70:44.171', + lastMessageText: 'Hello world!', }, - lastVisibleActionCreated: '2024-08-10 18:70:44.171', - lastReadTime: '2024-08-08 18:70:44.171', - lastMessageText: 'Hello world!', - }); + chatReportR14932, + ); expect(reason).toBe('debug.reasonVisibleInLHN.isUnread'); }); it('returns correct reason when report is archived', async () => { @@ -798,20 +811,24 @@ describe('DebugUtils', () => { { ...baseReport, }, + chatReportR14932, false, isReportArchived.current, ); expect(reason).toBe('debug.reasonVisibleInLHN.isArchived'); }); it('returns correct reason when report is self DM', () => { - const reason = DebugUtils.getReasonForShowingRowInLHN({ - ...baseReport, - chatType: CONST.REPORT.CHAT_TYPE.SELF_DM, - }); + const reason = DebugUtils.getReasonForShowingRowInLHN( + { + ...baseReport, + chatType: CONST.REPORT.CHAT_TYPE.SELF_DM, + }, + chatReportR14932, + ); expect(reason).toBe('debug.reasonVisibleInLHN.isSelfDM'); }); it('returns correct reason when report is temporarily focused', () => { - const reason = DebugUtils.getReasonForShowingRowInLHN(baseReport); + const reason = DebugUtils.getReasonForShowingRowInLHN(baseReport, chatReportR14932); expect(reason).toBe('debug.reasonVisibleInLHN.isFocused'); }); it('returns correct reason when report has one transaction thread with violations', async () => { @@ -869,7 +886,7 @@ describe('DebugUtils', () => { }, ], }); - const reason = DebugUtils.getReasonForShowingRowInLHN(MOCK_TRANSACTION_REPORT, true); + const reason = DebugUtils.getReasonForShowingRowInLHN(MOCK_TRANSACTION_REPORT, chatReportR14932, true); expect(reason).toBe('debug.reasonVisibleInLHN.hasRBR'); }); it('returns correct reason when report has violations', async () => { @@ -927,11 +944,11 @@ describe('DebugUtils', () => { }, ], }); - const reason = DebugUtils.getReasonForShowingRowInLHN(MOCK_EXPENSE_REPORT, true); + const reason = DebugUtils.getReasonForShowingRowInLHN(MOCK_EXPENSE_REPORT, chatReportR14932, true); expect(reason).toBe('debug.reasonVisibleInLHN.hasRBR'); }); it('returns correct reason when report has errors', () => { - const reason = DebugUtils.getReasonForShowingRowInLHN(baseReport, true); + const reason = DebugUtils.getReasonForShowingRowInLHN(baseReport, chatReportR14932, true); expect(reason).toBe('debug.reasonVisibleInLHN.hasRBR'); }); }); @@ -1114,6 +1131,7 @@ describe('DebugUtils', () => { { reportID: '1', }, + chatReportR14932, undefined, {}, false, @@ -1167,6 +1185,7 @@ describe('DebugUtils', () => { DebugUtils.getReasonAndReportActionForRBRInLHNRow( // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style MOCK_REPORTS[`${ONYXKEYS.COLLECTION.REPORT}1`] as Report, + chatReportR14932, undefined, {}, false, @@ -1230,7 +1249,7 @@ describe('DebugUtils', () => { }, }); const reportErrors = getAllReportErrors(MOCK_IOU_REPORT, MOCK_REPORT_ACTIONS); - const {reportAction} = DebugUtils.getReasonAndReportActionForRBRInLHNRow(MOCK_IOU_REPORT, MOCK_REPORT_ACTIONS, {}, false, reportErrors) ?? {}; + const {reportAction} = DebugUtils.getReasonAndReportActionForRBRInLHNRow(MOCK_IOU_REPORT, chatReportR14932, MOCK_REPORT_ACTIONS, {}, false, reportErrors) ?? {}; expect(reportAction).toMatchObject(MOCK_REPORT_ACTIONS['3']); }); }); @@ -1289,7 +1308,7 @@ describe('DebugUtils', () => { }, }); const reportErrors = getAllReportErrors(MOCK_IOU_REPORT, MOCK_REPORT_ACTIONS); - const {reportAction} = DebugUtils.getReasonAndReportActionForRBRInLHNRow(MOCK_IOU_REPORT, MOCK_REPORT_ACTIONS, {}, false, reportErrors) ?? {}; + const {reportAction} = DebugUtils.getReasonAndReportActionForRBRInLHNRow(MOCK_IOU_REPORT, chatReportR14932, MOCK_REPORT_ACTIONS, {}, false, reportErrors) ?? {}; expect(reportAction).toMatchObject(MOCK_REPORT_ACTIONS['3']); }); }); @@ -1349,7 +1368,7 @@ describe('DebugUtils', () => { }, }); const reportErrors = getAllReportErrors(MOCK_CHAT_REPORT, MOCK_CHAT_REPORT_ACTIONS); - const {reportAction} = DebugUtils.getReasonAndReportActionForRBRInLHNRow(MOCK_CHAT_REPORT, MOCK_CHAT_REPORT_ACTIONS, {}, false, reportErrors) ?? {}; + const {reportAction} = DebugUtils.getReasonAndReportActionForRBRInLHNRow(MOCK_CHAT_REPORT, chatReportR14932, MOCK_CHAT_REPORT_ACTIONS, {}, false, reportErrors) ?? {}; expect(reportAction).toMatchObject(MOCK_CHAT_REPORT_ACTIONS['1']); }); it('returns correct report action which is a split bill and has an error', async () => { @@ -1412,7 +1431,7 @@ describe('DebugUtils', () => { }, }); const reportErrors = getAllReportErrors(MOCK_CHAT_REPORT, MOCK_REPORT_ACTIONS); - const {reportAction} = DebugUtils.getReasonAndReportActionForRBRInLHNRow(MOCK_CHAT_REPORT, MOCK_REPORT_ACTIONS, {}, false, reportErrors) ?? {}; + const {reportAction} = DebugUtils.getReasonAndReportActionForRBRInLHNRow(MOCK_CHAT_REPORT, chatReportR14932, MOCK_REPORT_ACTIONS, {}, false, reportErrors) ?? {}; expect(reportAction).toMatchObject(MOCK_REPORT_ACTIONS['3']); }); it("returns undefined if there's no report action is a report preview or a split bill", async () => { @@ -1469,7 +1488,7 @@ describe('DebugUtils', () => { }, }); const reportErrors = getAllReportErrors(MOCK_IOU_REPORT, MOCK_REPORT_ACTIONS); - const {reportAction} = DebugUtils.getReasonAndReportActionForRBRInLHNRow(MOCK_IOU_REPORT, MOCK_REPORT_ACTIONS, {}, false, reportErrors) ?? {}; + const {reportAction} = DebugUtils.getReasonAndReportActionForRBRInLHNRow(MOCK_IOU_REPORT, chatReportR14932, MOCK_REPORT_ACTIONS, {}, false, reportErrors) ?? {}; expect(reportAction).toMatchObject(MOCK_REPORT_ACTIONS['3']); }); }); @@ -1521,6 +1540,7 @@ describe('DebugUtils', () => { { reportID: '1', }, + chatReportR14932, MOCK_REPORT_ACTIONS, {}, false, @@ -1552,7 +1572,7 @@ describe('DebugUtils', () => { }; const reportErrors = getAllReportErrors(mockedReport, mockedReportActions); - const {reason} = DebugUtils.getReasonAndReportActionForRBRInLHNRow(mockedReport, mockedReportActions, {}, false, reportErrors) ?? {}; + const {reason} = DebugUtils.getReasonAndReportActionForRBRInLHNRow(mockedReport, chatReportR14932, mockedReportActions, {}, false, reportErrors) ?? {}; expect(reason).toBe('debug.reasonRBR.hasErrors'); }); it('returns correct reason when there are violations', () => { @@ -1561,6 +1581,7 @@ describe('DebugUtils', () => { { reportID: '1', }, + chatReportR14932, undefined, {}, true, @@ -1574,6 +1595,7 @@ describe('DebugUtils', () => { { reportID: '1', }, + chatReportR14932, undefined, {}, true, @@ -1616,7 +1638,7 @@ describe('DebugUtils', () => { }, ], }); - const {reason} = DebugUtils.getReasonAndReportActionForRBRInLHNRow(report, {}, {}, false, {}) ?? {}; + const {reason} = DebugUtils.getReasonAndReportActionForRBRInLHNRow(report, chatReportR14932, {}, {}, false, {}) ?? {}; expect(reason).toBe('debug.reasonRBR.hasTransactionThreadViolations'); }); }); diff --git a/tests/unit/ReportActionsUtilsTest.ts b/tests/unit/ReportActionsUtilsTest.ts index 9aa8fde27534..63e441cc30cc 100644 --- a/tests/unit/ReportActionsUtilsTest.ts +++ b/tests/unit/ReportActionsUtilsTest.ts @@ -355,14 +355,13 @@ describe('ReportActionsUtils', () => { }); describe('getOneTransactionThreadReportID', () => { - const IOUReportID = 'REPORT_IOU'; - const IOUExpenseReportID = 'REPORT_EXPENSE'; - const IOUTransactionID = 'TRANSACTION_IOU'; - const IOUExpenseTransactionID = 'TRANSACTION_EXPENSE'; - + const IOUReportID = `${ONYXKEYS.COLLECTION.REPORT}REPORT_IOU` as const; + const IOUTransactionID = `${ONYXKEYS.COLLECTION.TRANSACTION}TRANSACTION_IOU` as const; + const IOUExpenseTransactionID = `${ONYXKEYS.COLLECTION.TRANSACTION}TRANSACTION_EXPENSE` as const; + const mockChatReportID = `${ONYXKEYS.COLLECTION.REPORT}${mockChatReport.reportID}` as const; const mockedReports: Record<`${typeof ONYXKEYS.COLLECTION.REPORT}${string}`, Report> = { - [`${ONYXKEYS.COLLECTION.REPORT}${IOUReportID}`]: {...mockIOUReport, reportID: IOUReportID}, - [`${ONYXKEYS.COLLECTION.REPORT}${IOUExpenseReportID}`]: {...mockIOUReport, type: CONST.REPORT.TYPE.EXPENSE, reportID: IOUExpenseReportID}, + [IOUReportID]: {...mockIOUReport, reportID: IOUReportID}, + [mockChatReportID]: mockChatReport, }; const linkedCreateAction = { @@ -393,32 +392,30 @@ describe('ReportActionsUtils', () => { }, }; - beforeEach(async () => { - await Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, mockedReports); - }); - it('should return the childReportID for a valid single IOU action', () => { - const result = getOneTransactionThreadReportID(IOUReportID, [linkedCreateAction], false, [IOUTransactionID]); + const result = getOneTransactionThreadReportID(mockedReports[IOUReportID], mockedReports[mockChatReportID], [linkedCreateAction], false, [IOUTransactionID]); expect(result).toEqual(linkedCreateAction.childReportID); }); it('should return undefined for action with a transaction that is not linked to it', () => { - const result = getOneTransactionThreadReportID(IOUReportID, [unlinkedCreateAction], false, [IOUTransactionID]); + const result = getOneTransactionThreadReportID(mockedReports[IOUReportID], mockedReports[mockChatReportID], [unlinkedCreateAction], false, [IOUTransactionID]); expect(result).toBeUndefined(); }); it('should return undefined if multiple IOU actions are present', () => { - const result = getOneTransactionThreadReportID(IOUReportID, [linkedCreateAction, linkedCreateAction], false, [IOUTransactionID]); + const result = getOneTransactionThreadReportID(mockedReports[IOUReportID], mockedReports[mockChatReportID], [linkedCreateAction, linkedCreateAction], false, [IOUTransactionID]); expect(result).toBeUndefined(); }); it('should skip actions where original message type is PAY', () => { - const result = getOneTransactionThreadReportID(IOUReportID, [linkedPayAction, linkedCreateAction], false, [IOUTransactionID]); + const result = getOneTransactionThreadReportID(mockedReports[IOUReportID], mockedReports[mockChatReportID], [linkedPayAction, linkedCreateAction], false, [IOUTransactionID]); expect(result).toEqual(linkedCreateAction.childReportID); }); it('should return undefined if no valid IOU actions are present', () => { - const result = getOneTransactionThreadReportID(IOUReportID, [unlinkedCreateAction, linkedDeleteAction, linkedPayAction], false, [IOUTransactionID]); + const result = getOneTransactionThreadReportID(mockedReports[IOUReportID], mockedReports[mockChatReportID], [unlinkedCreateAction, linkedDeleteAction, linkedPayAction], false, [ + IOUTransactionID, + ]); expect(result).toBeUndefined(); }); }); @@ -857,13 +854,13 @@ describe('ReportActionsUtils', () => { }); describe('getSendMoneyFlowOneTransactionThreadID', () => { - const mockChatReportID = 'REPORT'; - const mockDMChatReportID = 'REPORT_DM'; - const childReportID = 'childReport123'; + const mockChatReportID = `${ONYXKEYS.COLLECTION.REPORT}REPORT` as const; + const mockDMChatReportID = `${ONYXKEYS.COLLECTION.REPORT}REPORT_DM` as const; + const childReportID = `${ONYXKEYS.COLLECTION.REPORT}childReport123` as const; const mockedReports: Record<`${typeof ONYXKEYS.COLLECTION.REPORT}${string}`, Report> = { - [`${ONYXKEYS.COLLECTION.REPORT}${mockChatReportID}`]: {...mockChatReport, reportID: mockChatReportID}, - [`${ONYXKEYS.COLLECTION.REPORT}${mockDMChatReportID}`]: { + [mockChatReportID]: {...mockChatReport, reportID: mockChatReportID}, + [mockDMChatReportID]: { ...mockChatReport, reportID: mockDMChatReportID, chatType: undefined, @@ -872,10 +869,6 @@ describe('ReportActionsUtils', () => { }, }; - beforeEach(async () => { - await Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, mockedReports); - }); - const createAction = { ...mockIOUAction, childReportID, @@ -895,27 +888,27 @@ describe('ReportActionsUtils', () => { }; it('should return undefined for a single non-IOU action', () => { - expect(getSendMoneyFlowOneTransactionThreadID([nonIOUAction], mockDMChatReportID)).toBeUndefined(); + expect(getSendMoneyFlowOneTransactionThreadID([nonIOUAction], mockedReports[mockDMChatReportID])).toBeUndefined(); }); it('should return undefined for multiple IOU actions regardless of type', () => { - expect(getSendMoneyFlowOneTransactionThreadID([payAction, payAction], mockDMChatReportID)).toBeUndefined(); + expect(getSendMoneyFlowOneTransactionThreadID([payAction, payAction], mockedReports[mockDMChatReportID])).toBeUndefined(); }); it('should return undefined for a single IOU action that is not `Pay`', () => { - expect(getSendMoneyFlowOneTransactionThreadID([createAction], mockDMChatReportID)).toBeUndefined(); + expect(getSendMoneyFlowOneTransactionThreadID([createAction], mockedReports[mockDMChatReportID])).toBeUndefined(); }); it('should return the appropriate childReportID for a valid single `Pay` IOU action in DM chat', () => { - expect(getSendMoneyFlowOneTransactionThreadID([payAction], mockDMChatReportID)).toEqual(childReportID); + expect(getSendMoneyFlowOneTransactionThreadID([payAction], mockedReports[mockDMChatReportID])).toEqual(childReportID); }); it('should return undefined for a valid single `Pay` IOU action in a chat that is not DM', () => { - expect(getSendMoneyFlowOneTransactionThreadID([payAction], mockChatReportID)).toBeUndefined(); + expect(getSendMoneyFlowOneTransactionThreadID([payAction], mockedReports[mockChatReportID])).toBeUndefined(); }); it('should return undefined for a valid `Pay` IOU action in DM chat that has also a create IOU action', () => { - expect(getSendMoneyFlowOneTransactionThreadID([payAction, createAction], mockDMChatReportID)).toBeUndefined(); + expect(getSendMoneyFlowOneTransactionThreadID([payAction, createAction], mockedReports[mockDMChatReportID])).toBeUndefined(); }); }); diff --git a/tests/unit/ReportPrimaryActionUtilsTest.ts b/tests/unit/ReportPrimaryActionUtilsTest.ts index 1344e3160551..82de834ed80b 100644 --- a/tests/unit/ReportPrimaryActionUtilsTest.ts +++ b/tests/unit/ReportPrimaryActionUtilsTest.ts @@ -5,6 +5,7 @@ import {getReportPrimaryAction, getTransactionThreadPrimaryAction} from '@libs/R import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy, Report, ReportAction, Transaction, TransactionViolation} from '@src/types/onyx'; +import {chatReportR14932 as chatReport} from '../../__mocks__/reportData/reports'; import * as InvoiceData from '../data/Invoice'; import type {InvoiceTestData} from '../data/Invoice'; @@ -50,7 +51,7 @@ describe('getPrimaryAction', () => { } as unknown as Report; await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); - expect(getReportPrimaryAction({report, reportTransactions: [], violations: {}, policy: {} as Policy})).toBe(CONST.REPORT.PRIMARY_ACTIONS.ADD_EXPENSE); + expect(getReportPrimaryAction({report, chatReport, reportTransactions: [], violations: {}, policy: {} as Policy})).toBe(CONST.REPORT.PRIMARY_ACTIONS.ADD_EXPENSE); }); it('should return SUBMIT for expense report with manual submit', async () => { @@ -69,7 +70,7 @@ describe('getPrimaryAction', () => { reportID: `${REPORT_ID}`, } as unknown as Transaction; - expect(getReportPrimaryAction({report, reportTransactions: [transaction], violations: {}, policy: policy as Policy})).toBe(CONST.REPORT.PRIMARY_ACTIONS.SUBMIT); + expect(getReportPrimaryAction({report, chatReport, reportTransactions: [transaction], violations: {}, policy: policy as Policy})).toBe(CONST.REPORT.PRIMARY_ACTIONS.SUBMIT); }); it('should return Approve for report being processed', async () => { @@ -93,7 +94,7 @@ describe('getPrimaryAction', () => { }, } as unknown as Transaction; - expect(getReportPrimaryAction({report, reportTransactions: [transaction], violations: {}, policy: policy as Policy})).toBe(CONST.REPORT.PRIMARY_ACTIONS.APPROVE); + expect(getReportPrimaryAction({report, chatReport, reportTransactions: [transaction], violations: {}, policy: policy as Policy})).toBe(CONST.REPORT.PRIMARY_ACTIONS.APPROVE); }); it('should return empty for report being processed but transactions are scanning', async () => { @@ -120,7 +121,7 @@ describe('getPrimaryAction', () => { }, } as unknown as Transaction; - expect(getReportPrimaryAction({report, reportTransactions: [transaction], violations: {}, policy: policy as Policy})).toBe(''); + expect(getReportPrimaryAction({report, chatReport, reportTransactions: [transaction], violations: {}, policy: policy as Policy})).toBe(''); }); it('should return PAY for submitted invoice report', async () => { @@ -139,7 +140,7 @@ describe('getPrimaryAction', () => { reportID: `${REPORT_ID}`, } as unknown as Transaction; - expect(getReportPrimaryAction({report, reportTransactions: [transaction], violations: {}, policy: policy as Policy})).toBe(CONST.REPORT.PRIMARY_ACTIONS.PAY); + expect(getReportPrimaryAction({report, chatReport, reportTransactions: [transaction], violations: {}, policy: policy as Policy})).toBe(CONST.REPORT.PRIMARY_ACTIONS.PAY); }); it('should return PAY for expense report with payments enabled', async () => { @@ -158,7 +159,7 @@ describe('getPrimaryAction', () => { reportID: `${REPORT_ID}`, } as unknown as Transaction; - expect(getReportPrimaryAction({report, reportTransactions: [transaction], violations: {}, policy: policy as Policy})).toBe(CONST.REPORT.PRIMARY_ACTIONS.PAY); + expect(getReportPrimaryAction({report, chatReport, reportTransactions: [transaction], violations: {}, policy: policy as Policy})).toBe(CONST.REPORT.PRIMARY_ACTIONS.PAY); }); it('should return EXPORT TO ACCOUNTING for finished reports', async () => { @@ -184,7 +185,9 @@ describe('getPrimaryAction', () => { reportID: `${REPORT_ID}`, } as unknown as Transaction; - expect(getReportPrimaryAction({report, reportTransactions: [transaction], violations: {}, policy: policy as Policy})).toBe(CONST.REPORT.PRIMARY_ACTIONS.EXPORT_TO_ACCOUNTING); + expect(getReportPrimaryAction({report, chatReport, reportTransactions: [transaction], violations: {}, policy: policy as Policy})).toBe( + CONST.REPORT.PRIMARY_ACTIONS.EXPORT_TO_ACCOUNTING, + ); }); it('should not return EXPORT TO ACCOUNTING for reports marked manually as exported', async () => { @@ -210,7 +213,7 @@ describe('getPrimaryAction', () => { {actionName: CONST.REPORT.ACTIONS.TYPE.EXPORTED_TO_INTEGRATION, reportActionID: '1', created: '2025-01-01', originalMessage: {markedManually: true}}, ] as unknown as ReportAction[]; - expect(getReportPrimaryAction({report, reportTransactions: [], violations: {}, policy: policy as Policy, reportNameValuePairs: {}, reportActions})).toBe(''); + expect(getReportPrimaryAction({report, chatReport, reportTransactions: [], violations: {}, policy: policy as Policy, reportNameValuePairs: {}, reportActions})).toBe(''); }); it('should return REMOVE HOLD for reports with transactions on hold', async () => { @@ -257,7 +260,7 @@ describe('getPrimaryAction', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${REPORT_ID}`, {[REPORT_ACTION_ID]: reportAction}); await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${CHILD_REPORT_ID}`, {[HOLD_ACTION_ID]: holdAction}); - expect(getReportPrimaryAction({report, reportTransactions: [transaction], violations: {}, policy: policy as Policy})).toBe(CONST.REPORT.PRIMARY_ACTIONS.REMOVE_HOLD); + expect(getReportPrimaryAction({report, chatReport, reportTransactions: [transaction], violations: {}, policy: policy as Policy})).toBe(CONST.REPORT.PRIMARY_ACTIONS.REMOVE_HOLD); }); it('should return MARK AS CASH if has all RTER violations', async () => { @@ -289,6 +292,7 @@ describe('getPrimaryAction', () => { expect( getReportPrimaryAction({ report, + chatReport, reportTransactions: [transaction], violations: {[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`]: [violation]}, policy: policy as Policy, @@ -322,6 +326,7 @@ describe('getPrimaryAction', () => { expect( getReportPrimaryAction({ report, + chatReport, reportTransactions: [transaction], violations: {[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`]: [violation]}, policy: policy as Policy, @@ -331,13 +336,13 @@ describe('getPrimaryAction', () => { it('should return an empty string for invoice report when the chat report is archived', async () => { // Given the invoice data - const {policy, convertedInvoiceChat: chatReport}: InvoiceTestData = InvoiceData; + const {policy, convertedInvoiceChat: invoiceChatReport}: InvoiceTestData = InvoiceData; const report = { type: CONST.REPORT.TYPE.INVOICE, ownerAccountID: CURRENT_USER_ACCOUNT_ID, statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, - chatReportID: chatReport.chatReportID, + chatReportID: invoiceChatReport.chatReportID, } as unknown as Report; await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); @@ -353,8 +358,17 @@ describe('getPrimaryAction', () => { const {result: isChatReportArchived} = renderHook(() => useReportIsArchived(report?.chatReportID)); // Then the getReportPrimaryAction should return the empty string - // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style - expect(getReportPrimaryAction({report, reportTransactions: [transaction], violations: {}, policy: policy as Policy, isChatReportArchived: isChatReportArchived.current})).toBe(''); + expect( + getReportPrimaryAction({ + report, + chatReport: invoiceChatReport, + reportTransactions: [transaction], + violations: {}, + // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style + policy: policy as Policy, + isChatReportArchived: isChatReportArchived.current, + }), + ).toBe(''); }); }); @@ -508,6 +522,7 @@ describe('getTransactionThreadPrimaryAction', () => { expect( getReportPrimaryAction({ report, + chatReport, reportTransactions: [transaction], violations: {}, policy: policy as Policy, diff --git a/tests/unit/ReportSecondaryActionUtilsTest.ts b/tests/unit/ReportSecondaryActionUtilsTest.ts index 8d4b9da32f20..f1b0166059d5 100644 --- a/tests/unit/ReportSecondaryActionUtilsTest.ts +++ b/tests/unit/ReportSecondaryActionUtilsTest.ts @@ -6,6 +6,7 @@ import * as ReportUtils from '@src/libs/ReportUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy, Report, ReportAction, Transaction, TransactionViolation} from '@src/types/onyx'; import {actionR14932, originalMessageR14932} from '../../__mocks__/reportData/actions'; +import {chatReportR14932 as chatReport} from '../../__mocks__/reportData/reports'; const EMPLOYEE_ACCOUNT_ID = 1; const EMPLOYEE_EMAIL = 'employee@mail.com'; @@ -48,7 +49,7 @@ describe('getSecondaryAction', () => { const policy = {} as unknown as Policy; const result = [CONST.REPORT.SECONDARY_ACTIONS.DOWNLOAD_CSV, CONST.REPORT.SECONDARY_ACTIONS.DOWNLOAD_PDF, CONST.REPORT.SECONDARY_ACTIONS.VIEW_DETAILS]; - expect(getSecondaryReportActions(report, [], {}, policy)).toEqual(result); + expect(getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy})).toEqual(result); }); it('includes ADD_EXPENSE option for empty report', async () => { @@ -71,7 +72,7 @@ describe('getSecondaryAction', () => { transactionID: TRANSACTION_ID, } as unknown as Transaction; - const result = getSecondaryReportActions(report, [transaction], {}, policy, undefined, undefined, undefined, true); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [transaction], violations: {}, policy, canUseRetractNewDot: true}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.ADD_EXPENSE)).toBe(true); }); @@ -92,7 +93,7 @@ describe('getSecondaryAction', () => { } as unknown as Policy; await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); - const result = getSecondaryReportActions(report, [], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.SUBMIT)).toBe(true); }); @@ -113,7 +114,7 @@ describe('getSecondaryAction', () => { } as unknown as Policy; await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); - const result = getSecondaryReportActions(report, [], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.SUBMIT)).toBe(true); }); @@ -144,7 +145,7 @@ describe('getSecondaryAction', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); - const result = getSecondaryReportActions(report, [transaction], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [transaction], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.APPROVE)).toBe(true); }); @@ -172,7 +173,13 @@ describe('getSecondaryAction', () => { }, } as unknown as TransactionViolation; - const result = getSecondaryReportActions(report, [transaction], {[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`]: [violation]}, policy); + const result = getSecondaryReportActions({ + report, + chatReport, + reportTransactions: [transaction], + violations: {[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`]: [violation]}, + policy, + }); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.APPROVE)).toBe(true); }); @@ -199,7 +206,13 @@ describe('getSecondaryAction', () => { }, } as unknown as TransactionViolation; - const result = getSecondaryReportActions(report, [transaction], {[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`]: [violation]}, policy); + const result = getSecondaryReportActions({ + report, + chatReport, + reportTransactions: [transaction], + violations: {[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`]: [violation]}, + policy, + }); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.APPROVE)).toBe(true); }); @@ -223,7 +236,7 @@ describe('getSecondaryAction', () => { }, } as unknown as Transaction; - const result = getSecondaryReportActions(report, [transaction], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [transaction], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.APPROVE)).toBe(false); }); @@ -237,7 +250,7 @@ describe('getSecondaryAction', () => { } as unknown as Report; const policy = {approver: EMPLOYEE_EMAIL} as unknown as Policy; - const result = getSecondaryReportActions(report, [], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.UNAPPROVE)).toBe(true); }); @@ -253,7 +266,7 @@ describe('getSecondaryAction', () => { role: CONST.POLICY.ROLE.ADMIN, } as unknown as Policy; - const result = getSecondaryReportActions(report, [], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.CANCEL_PAYMENT)).toBe(true); }); @@ -281,16 +294,17 @@ describe('getSecondaryAction', () => { } as unknown as ReportAction; await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${REPORT_ID}`, {[ACTION_ID]: reportAction}); - const result = getSecondaryReportActions( + const result = getSecondaryReportActions({ report, - [ + chatReport, + reportTransactions: [ { transactionID: TRANSACTION_ID, } as unknown as Transaction, ], - {}, + violations: {}, policy, - ); + }); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.CANCEL_PAYMENT)).toBe(true); }); @@ -307,7 +321,7 @@ describe('getSecondaryAction', () => { } as unknown as Policy; await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); - const result = getSecondaryReportActions(report, [], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.EXPORT_TO_ACCOUNTING)).toBe(true); }); @@ -325,7 +339,7 @@ describe('getSecondaryAction', () => { connections: {[CONST.POLICY.CONNECTIONS.NAME.QBD]: {}}, } as unknown as Policy; - const result = getSecondaryReportActions(report, [], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.EXPORT_TO_ACCOUNTING)).toBe(true); }); @@ -342,7 +356,7 @@ describe('getSecondaryAction', () => { connections: {[CONST.POLICY.CONNECTIONS.NAME.QBD]: {config: {autosync: {enabled: true}}}}, } as unknown as Policy; - const result = getSecondaryReportActions(report, [], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.EXPORT_TO_ACCOUNTING)).toBe(true); }); @@ -357,7 +371,7 @@ describe('getSecondaryAction', () => { } as unknown as Policy; await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); - const result = getSecondaryReportActions(report, [], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.MARK_AS_EXPORTED)).toBe(true); }); @@ -375,7 +389,7 @@ describe('getSecondaryAction', () => { connections: {[CONST.POLICY.CONNECTIONS.NAME.QBD]: {}}, } as unknown as Policy; - const result = getSecondaryReportActions(report, [], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.MARK_AS_EXPORTED)).toBe(true); }); @@ -392,7 +406,7 @@ describe('getSecondaryAction', () => { connections: {[CONST.POLICY.CONNECTIONS.NAME.QBD]: {config: {autosync: {enabled: true}}}}, } as unknown as Policy; - const result = getSecondaryReportActions(report, [], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.MARK_AS_EXPORTED)).toBe(true); }); @@ -408,7 +422,7 @@ describe('getSecondaryAction', () => { connections: {[CONST.POLICY.CONNECTIONS.NAME.QBD]: {config: {export: {exporter: EMPLOYEE_EMAIL}, autoSync: {enabled: false}}}}, } as unknown as Policy; - const result = getSecondaryReportActions(report, [], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.MARK_AS_EXPORTED)).toBe(true); }); @@ -425,7 +439,7 @@ describe('getSecondaryAction', () => { role: CONST.POLICY.ROLE.ADMIN, } as unknown as Policy; - const result = getSecondaryReportActions(report, [], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.MARK_AS_EXPORTED)).toBe(true); }); @@ -445,7 +459,7 @@ describe('getSecondaryAction', () => { jest.spyOn(ReportUtils, 'canHoldUnholdReportAction').mockReturnValueOnce({canHoldRequest: true, canUnholdRequest: true}); jest.spyOn(ReportActionsUtils, 'getOneTransactionThreadReportID').mockReturnValueOnce(originalMessageR14932.IOUTransactionID); - const result = getSecondaryReportActions(report, [transaction], {}, policy, undefined, [actionR14932]); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [transaction], violations: {}, policy, reportActions: [actionR14932]}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.HOLD)).toBe(true); }); @@ -477,7 +491,7 @@ describe('getSecondaryAction', () => { await Onyx.merge(ONYXKEYS.SESSION, {email: EMPLOYEE_EMAIL, accountID: EMPLOYEE_ACCOUNT_ID}); await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, personalDetails); - const result = getSecondaryReportActions(report, [], {}, policy, undefined, undefined, policies, true); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy, policies, canUseRetractNewDot: true}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.CHANGE_WORKSPACE)).toBe(true); }); @@ -510,7 +524,7 @@ describe('getSecondaryAction', () => { await Onyx.merge(ONYXKEYS.SESSION, {email: EMPLOYEE_EMAIL, accountID: EMPLOYEE_ACCOUNT_ID}); await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, personalDetails); - const result = getSecondaryReportActions(report, [], {}, policy, undefined, undefined, policies, true); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy, policies, canUseRetractNewDot: true}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.CHANGE_WORKSPACE)).toBe(true); }); @@ -556,7 +570,15 @@ describe('getSecondaryAction', () => { await Onyx.merge(ONYXKEYS.SESSION, {email: EMPLOYEE_EMAIL, accountID: EMPLOYEE_ACCOUNT_ID}); await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, personalDetails); - const result = getSecondaryReportActions(report, [], {}, oldPolicy, undefined, undefined, policies, true); + const result = getSecondaryReportActions({ + report, + chatReport, + reportTransactions: [], + violations: {}, + policy: oldPolicy, + policies, + canUseRetractNewDot: true, + }); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.CHANGE_WORKSPACE)).toBe(true); }); @@ -602,7 +624,7 @@ describe('getSecondaryAction', () => { await Onyx.merge(ONYXKEYS.SESSION, {email: APPROVER_EMAIL, accountID: APPROVER_ACCOUNT_ID}); await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, personalDetails); - const result = getSecondaryReportActions(report, [], {}, policy, undefined, undefined, policies, true); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy, policies, canUseRetractNewDot: true}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.CHANGE_WORKSPACE)).toBe(true); }); @@ -650,7 +672,7 @@ describe('getSecondaryAction', () => { await Onyx.merge(ONYXKEYS.SESSION, {email: ADMIN_EMAIL, accountID: ADMIN_ACCOUNT_ID}); await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, personalDetails); - const result = getSecondaryReportActions(report, [], {}, policy, undefined, undefined, policies, true); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [], violations: {}, policy, policies, canUseRetractNewDot: true}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.CHANGE_WORKSPACE)).toBe(true); }); @@ -665,7 +687,7 @@ describe('getSecondaryAction', () => { const policy = {} as unknown as Policy; await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); - const result = getSecondaryReportActions(report, [{} as Transaction], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [{} as Transaction], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.DELETE)).toBe(true); }); @@ -698,7 +720,7 @@ describe('getSecondaryAction', () => { const policy = {} as unknown as Policy; - const result = getSecondaryReportActions(report, [transaction], {}, policy, undefined, reportActions); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [transaction], violations: {}, policy, reportActions}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.DELETE)).toBe(true); }); @@ -732,7 +754,7 @@ describe('getSecondaryAction', () => { const policy = {} as unknown as Policy; - const result = getSecondaryReportActions(report, [transaction], {}, policy, undefined, reportActions); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [transaction], violations: {}, policy, reportActions}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.DELETE)).toBe(true); }); @@ -781,7 +803,7 @@ describe('getSecondaryAction', () => { const policy = {} as unknown as Policy; - const result = getSecondaryReportActions(report, [transaction1, transaction2], {}, policy, undefined, reportActions); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [transaction1, transaction2], violations: {}, policy, reportActions}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.DELETE)).toBe(false); }); @@ -804,7 +826,7 @@ describe('getSecondaryAction', () => { const policy = {} as unknown as Policy; await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); - const result = getSecondaryReportActions(report, [transaction], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [transaction], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.DELETE)).toBe(true); }); @@ -833,7 +855,7 @@ describe('getSecondaryAction', () => { const policy = {} as unknown as Policy; await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); - const result = getSecondaryReportActions(report, [transaction1, transaction2], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [transaction1, transaction2], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.DELETE)).toBe(true); }); @@ -860,7 +882,7 @@ describe('getSecondaryAction', () => { const policy = {} as unknown as Policy; await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); - const result = getSecondaryReportActions(report, [transaction], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [transaction], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.DELETE)).toBe(false); }); @@ -891,7 +913,7 @@ describe('getSecondaryAction', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${POLICY_ID}`, policy); - const result = getSecondaryReportActions(report, [transaction], {}, policy); + const result = getSecondaryReportActions({report, chatReport, reportTransactions: [transaction], violations: {}, policy}); expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.DELETE)).toBe(false); }); }); diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index c6ad307cada7..a7904fb0c456 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -1818,7 +1818,18 @@ describe('ReportUtils', () => { const currentReportId = report.reportID; const isInFocusMode = true; const betas = [CONST.BETAS.DEFAULT_ROOMS]; - expect(shouldReportBeInOptionList({report, currentReportId, isInFocusMode, betas, policies: {}, doesReportHaveViolations: false, excludeEmptyChats: false})).toBeTruthy(); + expect( + shouldReportBeInOptionList({ + report, + chatReport: mockedChatReport, + currentReportId, + isInFocusMode, + betas, + policies: {}, + doesReportHaveViolations: false, + excludeEmptyChats: false, + }), + ).toBeTruthy(); }); it('should return true when the report has outstanding violations', async () => { @@ -1862,6 +1873,7 @@ describe('ReportUtils', () => { expect( shouldReportBeInOptionList({ report: transactionThreadReport, + chatReport: mockedChatReport, currentReportId, isInFocusMode, betas, @@ -1881,7 +1893,16 @@ describe('ReportUtils', () => { const isInFocusMode = true; const betas = [CONST.BETAS.DEFAULT_ROOMS]; expect( - shouldReportBeInOptionList({report: chatReport, currentReportId, isInFocusMode, betas, policies: {}, doesReportHaveViolations: false, excludeEmptyChats: false}), + shouldReportBeInOptionList({ + report: chatReport, + chatReport: mockedChatReport, + currentReportId, + isInFocusMode, + betas, + policies: {}, + doesReportHaveViolations: false, + excludeEmptyChats: false, + }), ).toBeTruthy(); }); @@ -1893,7 +1914,18 @@ describe('ReportUtils', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${report.reportID}`, 'fake draft'); - expect(shouldReportBeInOptionList({report, currentReportId, isInFocusMode, betas, policies: {}, doesReportHaveViolations: false, excludeEmptyChats: false})).toBeTruthy(); + expect( + shouldReportBeInOptionList({ + report, + chatReport: mockedChatReport, + currentReportId, + isInFocusMode, + betas, + policies: {}, + doesReportHaveViolations: false, + excludeEmptyChats: false, + }), + ).toBeTruthy(); }); it('should return true when the report is pinned', () => { @@ -1904,7 +1936,18 @@ describe('ReportUtils', () => { const currentReportId = '3'; const isInFocusMode = false; const betas = [CONST.BETAS.DEFAULT_ROOMS]; - expect(shouldReportBeInOptionList({report, currentReportId, isInFocusMode, betas, policies: {}, doesReportHaveViolations: false, excludeEmptyChats: false})).toBeTruthy(); + expect( + shouldReportBeInOptionList({ + report, + chatReport: mockedChatReport, + currentReportId, + isInFocusMode, + betas, + policies: {}, + doesReportHaveViolations: false, + excludeEmptyChats: false, + }), + ).toBeTruthy(); }); it('should return true when the report is unread and we are in the focus mode', async () => { @@ -1928,7 +1971,18 @@ describe('ReportUtils', () => { accountID: 1, }); - expect(shouldReportBeInOptionList({report, currentReportId, isInFocusMode, betas, policies: {}, doesReportHaveViolations: false, excludeEmptyChats: false})).toBeTruthy(); + expect( + shouldReportBeInOptionList({ + report, + chatReport: mockedChatReport, + currentReportId, + isInFocusMode, + betas, + policies: {}, + doesReportHaveViolations: false, + excludeEmptyChats: false, + }), + ).toBeTruthy(); }); it('should return true when the report is an archived report and we are in the default mode', async () => { @@ -1950,6 +2004,7 @@ describe('ReportUtils', () => { expect( shouldReportBeInOptionList({ report: archivedReport, + chatReport: mockedChatReport, currentReportId, isInFocusMode, betas, @@ -1980,6 +2035,7 @@ describe('ReportUtils', () => { expect( shouldReportBeInOptionList({ report: archivedReport, + chatReport: mockedChatReport, currentReportId, isInFocusMode, betas, @@ -2003,6 +2059,7 @@ describe('ReportUtils', () => { expect( shouldReportBeInOptionList({ report, + chatReport: mockedChatReport, currentReportId, isInFocusMode, betas, @@ -2026,7 +2083,18 @@ describe('ReportUtils', () => { const currentReportId = ''; const isInFocusMode = true; const betas = [CONST.BETAS.DEFAULT_ROOMS]; - expect(shouldReportBeInOptionList({report, currentReportId, isInFocusMode, betas, policies: {}, doesReportHaveViolations: false, excludeEmptyChats: false})).toBeFalsy(); + expect( + shouldReportBeInOptionList({ + report, + chatReport: mockedChatReport, + currentReportId, + isInFocusMode, + betas, + policies: {}, + doesReportHaveViolations: false, + excludeEmptyChats: false, + }), + ).toBeFalsy(); }); it('should return false when the report does not have participants', () => { @@ -2034,7 +2102,18 @@ describe('ReportUtils', () => { const currentReportId = ''; const isInFocusMode = true; const betas = [CONST.BETAS.DEFAULT_ROOMS]; - expect(shouldReportBeInOptionList({report, currentReportId, isInFocusMode, betas, policies: {}, doesReportHaveViolations: false, excludeEmptyChats: false})).toBeFalsy(); + expect( + shouldReportBeInOptionList({ + report, + chatReport: mockedChatReport, + currentReportId, + isInFocusMode, + betas, + policies: {}, + doesReportHaveViolations: false, + excludeEmptyChats: false, + }), + ).toBeFalsy(); }); it('should return false when the report is the report that the user cannot access due to policy restrictions', () => { @@ -2045,7 +2124,18 @@ describe('ReportUtils', () => { const currentReportId = ''; const isInFocusMode = false; const betas: Beta[] = []; - expect(shouldReportBeInOptionList({report, currentReportId, isInFocusMode, betas, policies: {}, doesReportHaveViolations: false, excludeEmptyChats: false})).toBeFalsy(); + expect( + shouldReportBeInOptionList({ + report, + chatReport: mockedChatReport, + currentReportId, + isInFocusMode, + betas, + policies: {}, + doesReportHaveViolations: false, + excludeEmptyChats: false, + }), + ).toBeFalsy(); }); it('should return false when the report is the single transaction thread', async () => { @@ -2079,6 +2169,7 @@ describe('ReportUtils', () => { expect( shouldReportBeInOptionList({ report: transactionThreadReport, + chatReport: mockedChatReport, currentReportId, isInFocusMode, betas, @@ -2094,7 +2185,18 @@ describe('ReportUtils', () => { const currentReportId = ''; const isInFocusMode = false; const betas = [CONST.BETAS.DEFAULT_ROOMS]; - expect(shouldReportBeInOptionList({report, currentReportId, isInFocusMode, betas, policies: {}, doesReportHaveViolations: false, excludeEmptyChats: true})).toBeFalsy(); + expect( + shouldReportBeInOptionList({ + report, + chatReport: mockedChatReport, + currentReportId, + isInFocusMode, + betas, + policies: {}, + doesReportHaveViolations: false, + excludeEmptyChats: true, + }), + ).toBeFalsy(); }); it('should return false when the user’s email is domain-based and the includeDomainEmail is false', () => { @@ -2105,6 +2207,7 @@ describe('ReportUtils', () => { expect( shouldReportBeInOptionList({ report, + chatReport: mockedChatReport, currentReportId, isInFocusMode, betas, @@ -2148,7 +2251,18 @@ describe('ReportUtils', () => { [parentReportAction.reportActionID]: parentReportAction, }); - expect(shouldReportBeInOptionList({report, currentReportId, isInFocusMode, betas, policies: {}, doesReportHaveViolations: false, excludeEmptyChats: false})).toBeFalsy(); + expect( + shouldReportBeInOptionList({ + report, + chatReport: mockedChatReport, + currentReportId, + isInFocusMode, + betas, + policies: {}, + doesReportHaveViolations: false, + excludeEmptyChats: false, + }), + ).toBeFalsy(); }); it('should return false when the report is read and we are in the focus mode', () => { @@ -2156,7 +2270,18 @@ describe('ReportUtils', () => { const currentReportId = ''; const isInFocusMode = true; const betas = [CONST.BETAS.DEFAULT_ROOMS]; - expect(shouldReportBeInOptionList({report, currentReportId, isInFocusMode, betas, policies: {}, doesReportHaveViolations: false, excludeEmptyChats: false})).toBeFalsy(); + expect( + shouldReportBeInOptionList({ + report, + chatReport: mockedChatReport, + currentReportId, + isInFocusMode, + betas, + policies: {}, + doesReportHaveViolations: false, + excludeEmptyChats: false, + }), + ).toBeFalsy(); }); it('should return false when the empty report has deleted action with child comment but isDeletedParentAction is false', async () => { @@ -2179,7 +2304,16 @@ describe('ReportUtils', () => { [iouReportAction.reportActionID]: iouReportAction, }); expect( - shouldReportBeInOptionList({report, currentReportId: '', isInFocusMode: false, betas: [], policies: {}, doesReportHaveViolations: false, excludeEmptyChats: true}), + shouldReportBeInOptionList({ + report, + chatReport: mockedChatReport, + currentReportId: '', + isInFocusMode: false, + betas: [], + policies: {}, + doesReportHaveViolations: false, + excludeEmptyChats: true, + }), ).toBeFalsy(); }); }); diff --git a/tests/unit/SidebarUtilsTest.ts b/tests/unit/SidebarUtilsTest.ts index c5eefb061980..c7a11a594700 100644 --- a/tests/unit/SidebarUtilsTest.ts +++ b/tests/unit/SidebarUtilsTest.ts @@ -13,6 +13,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy, Report, ReportAction, ReportActions, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx'; import type {ReportCollectionDataSet} from '@src/types/onyx/Report'; import type {TransactionViolationsCollectionDataSet} from '@src/types/onyx/TransactionViolation'; +import {chatReportR14932} from '../../__mocks__/reportData/reports'; import createRandomPolicy from '../utils/collections/policies'; import createRandomReportAction from '../utils/collections/reportActions'; import createRandomReport from '../utils/collections/reports'; @@ -96,6 +97,7 @@ describe('SidebarUtils', () => { const {reason} = SidebarUtils.getReasonAndReportActionThatHasRedBrickRoad( MOCK_REPORT, + chatReportR14932, MOCK_REPORT_ACTIONS, false, {}, @@ -125,6 +127,7 @@ describe('SidebarUtils', () => { const {reason} = SidebarUtils.getReasonAndReportActionThatHasRedBrickRoad( MOCK_REPORT, + chatReportR14932, MOCK_REPORT_ACTIONS, false, reportErrors, @@ -149,6 +152,7 @@ describe('SidebarUtils', () => { const {reason} = SidebarUtils.getReasonAndReportActionThatHasRedBrickRoad( MOCK_REPORT, + chatReportR14932, MOCK_REPORT_ACTIONS, true, {}, @@ -191,6 +195,7 @@ describe('SidebarUtils', () => { const {reason} = SidebarUtils.getReasonAndReportActionThatHasRedBrickRoad( MOCK_REPORT, + chatReportR14932, MOCK_REPORT_ACTIONS, false, reportErrors, @@ -220,6 +225,7 @@ describe('SidebarUtils', () => { const {reason} = SidebarUtils.getReasonAndReportActionThatHasRedBrickRoad( MOCK_REPORT, + chatReportR14932, MOCK_REPORT_ACTIONS, false, reportErrors, @@ -262,6 +268,7 @@ describe('SidebarUtils', () => { const {reportAction} = SidebarUtils.getReasonAndReportActionThatHasRedBrickRoad( MOCK_REPORT, + chatReportR14932, MOCK_REPORT_ACTIONS, false, reportErrors, @@ -285,6 +292,7 @@ describe('SidebarUtils', () => { const {result: isReportArchived} = renderHook(() => useReportIsArchived(MOCK_REPORT?.reportID)); const result = SidebarUtils.getReasonAndReportActionThatHasRedBrickRoad( MOCK_REPORT, + chatReportR14932, MOCK_REPORT_ACTIONS, false, {}, @@ -368,6 +376,7 @@ describe('SidebarUtils', () => { const {result: isReportArchived} = renderHook(() => useReportIsArchived(MOCK_REPORT?.reportID)); const result = SidebarUtils.getReasonAndReportActionThatHasRedBrickRoad( MOCK_REPORT, + chatReportR14932, MOCK_REPORT_ACTIONS, false, {}, @@ -440,6 +449,7 @@ describe('SidebarUtils', () => { const {result: isReportArchived} = renderHook(() => useReportIsArchived(MOCK_REPORT?.reportID)); const result = SidebarUtils.shouldShowRedBrickRoad( MOCK_REPORT, + chatReportR14932, MOCK_REPORT_ACTIONS, false, {}, @@ -509,6 +519,7 @@ describe('SidebarUtils', () => { const {result: isReportArchived} = renderHook(() => useReportIsArchived(MOCK_REPORT?.reportID)); const result = SidebarUtils.shouldShowRedBrickRoad( MOCK_REPORT, + chatReportR14932, MOCK_REPORT_ACTIONS, false, {}, @@ -536,6 +547,7 @@ describe('SidebarUtils', () => { const {result: isReportArchived} = renderHook(() => useReportIsArchived(MOCK_REPORT?.reportID)); const result = SidebarUtils.shouldShowRedBrickRoad( MOCK_REPORT, + chatReportR14932, MOCK_REPORT_ACTIONS, false, reportErrors, @@ -556,7 +568,16 @@ describe('SidebarUtils', () => { const MOCK_TRANSACTION_VIOLATIONS: OnyxCollection = {}; const {result: isReportArchived} = renderHook(() => useReportIsArchived(MOCK_REPORT?.reportID)); - const result = SidebarUtils.shouldShowRedBrickRoad(MOCK_REPORT, MOCK_REPORT_ACTIONS, true, {}, MOCK_TRANSACTIONS, MOCK_TRANSACTION_VIOLATIONS, isReportArchived.current); + const result = SidebarUtils.shouldShowRedBrickRoad( + MOCK_REPORT, + chatReportR14932, + MOCK_REPORT_ACTIONS, + true, + {}, + MOCK_TRANSACTIONS, + MOCK_TRANSACTION_VIOLATIONS, + isReportArchived.current, + ); expect(result).toBe(true); }); @@ -589,6 +610,7 @@ describe('SidebarUtils', () => { const {result: isReportArchived} = renderHook(() => useReportIsArchived(MOCK_REPORT?.reportID)); const result = SidebarUtils.shouldShowRedBrickRoad( MOCK_REPORT, + chatReportR14932, MOCK_REPORT_ACTIONS, false, reportErrors, @@ -616,6 +638,7 @@ describe('SidebarUtils', () => { const {result: isReportArchived} = renderHook(() => useReportIsArchived(MOCK_REPORT?.reportID)); const result = SidebarUtils.shouldShowRedBrickRoad( MOCK_REPORT, + chatReportR14932, MOCK_REPORT_ACTIONS, false, reportErrors, @@ -636,7 +659,16 @@ describe('SidebarUtils', () => { const MOCK_TRANSACTION_VIOLATIONS: OnyxCollection = {}; const {result: isReportArchived} = renderHook(() => useReportIsArchived(MOCK_REPORT?.reportID)); - const result = SidebarUtils.shouldShowRedBrickRoad(MOCK_REPORT, MOCK_REPORT_ACTIONS, false, {}, MOCK_TRANSACTIONS, MOCK_TRANSACTION_VIOLATIONS, isReportArchived.current); + const result = SidebarUtils.shouldShowRedBrickRoad( + MOCK_REPORT, + chatReportR14932, + MOCK_REPORT_ACTIONS, + false, + {}, + MOCK_TRANSACTIONS, + MOCK_TRANSACTION_VIOLATIONS, + isReportArchived.current, + ); expect(result).toBe(false); }); @@ -658,7 +690,16 @@ describe('SidebarUtils', () => { // Simulate how components determined if a report is archived by using this hook const {result: isReportArchived} = renderHook(() => useReportIsArchived(MOCK_REPORT?.reportID)); - const result = SidebarUtils.shouldShowRedBrickRoad(MOCK_REPORT, MOCK_REPORT_ACTIONS, false, {}, MOCK_TRANSACTIONS, MOCK_TRANSACTION_VIOLATIONS, isReportArchived.current); + const result = SidebarUtils.shouldShowRedBrickRoad( + MOCK_REPORT, + chatReportR14932, + MOCK_REPORT_ACTIONS, + false, + {}, + MOCK_TRANSACTIONS, + MOCK_TRANSACTION_VIOLATIONS, + isReportArchived.current, + ); expect(result).toBe(false); });