From 5f268fd07ef0302443fd3fba631837c64cd2d244 Mon Sep 17 00:00:00 2001 From: cretadn22 Date: Thu, 30 Jul 2026 01:06:52 +0700 Subject: [PATCH 1/3] createDraftTransactionAndNavigateToParticipantSelector by adding reportActions parameter --- src/libs/ReportUtils.ts | 11 ++++------- src/pages/DynamicReportDetailsPage.tsx | 12 +++++++++--- .../report/actionContents/ChatActionableButtons.tsx | 3 +++ tests/actions/IOU/CreateDraftTransactionTest.ts | 8 ++++++++ tests/actions/IOUTest/TrackExpenseTest.ts | 2 ++ tests/unit/ReportUtilsTest.ts | 13 +++++++++++++ 6 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 3a9a1d5b01d7..fc30cd81d30e 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -11703,6 +11703,8 @@ type CreateDraftTransactionParams = { reportID: string | undefined; actionName: IOUAction; reportActionID: string | undefined; + /** Report actions of the report identified by reportID, used to find the linked track-expense action */ + reportActions: OnyxEntry; introSelected: OnyxEntry; draftTransactionIDs: string[] | undefined; activePolicy: OnyxEntry; @@ -11731,6 +11733,7 @@ function createDraftTransactionAndNavigateToParticipantSelector({ reportID, actionName, reportActionID, + reportActions, introSelected, draftTransactionIDs, activePolicy, @@ -11753,13 +11756,7 @@ function createDraftTransactionAndNavigateToParticipantSelector({ return; } - const reportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`] ?? ([] as ReportAction[]); - - if (!reportActions) { - return; - } - - const linkedTrackedExpenseReportAction = Object.values(reportActions) + const linkedTrackedExpenseReportAction = Object.values(reportActions ?? {}) .filter(Boolean) .find((action) => isMoneyRequestAction(action) && getOriginalMessage(action)?.IOUTransactionID === transactionID); diff --git a/src/pages/DynamicReportDetailsPage.tsx b/src/pages/DynamicReportDetailsPage.tsx index afe176c49ade..d6aad7775d32 100644 --- a/src/pages/DynamicReportDetailsPage.tsx +++ b/src/pages/DynamicReportDetailsPage.tsx @@ -214,6 +214,10 @@ function DynamicReportDetailsPage({policy, report, route, reportMetadata, report const {reportActions} = usePaginatedReportActions(report.reportID); const [reportActionsForOriginalReportID] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`); + // The report from which a tracked expense would be submitted/categorized/shared, and its actions - + // createDraftTransactionAndNavigateToParticipantSelector uses them to find the linked track-expense action + const actionReportID = getOriginalReportID(report.reportID, parentReportAction, reportActionsForOriginalReportID); + const [actionReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${actionReportID}`); const {removeTransaction} = useSearchSelectionActions(); @@ -516,7 +520,6 @@ function DynamicReportDetailsPage({policy, report, route, reportMetadata, report } if (isTrackExpenseReport && !isDeletedParentAction) { - const actionReportID = getOriginalReportID(report.reportID, parentReportAction, reportActionsForOriginalReportID); const whisperAction = getTrackExpenseActionableWhisper(iouTransactionID, moneyRequestReport?.reportID, moneyRequestReportActions); const actionableWhisperReportActionID = whisperAction?.reportActionID; const currentUserLocalCurrency = currentUserPersonalDetails.localCurrencyCode ?? CONST.CURRENCY.USD; @@ -526,6 +529,7 @@ function DynamicReportDetailsPage({policy, report, route, reportMetadata, report if (!isSelfDMExpenseSplit || hasWorkspaceToSubmitTo) { const baseSubmitParams = { reportID: actionReportID, + reportActions: actionReportActions, reportActionID: actionableWhisperReportActionID, introSelected, draftTransactionIDs, @@ -607,6 +611,7 @@ function DynamicReportDetailsPage({policy, report, route, reportMetadata, report action: () => { createDraftTransactionAndNavigateToParticipantSelector({ reportID: actionReportID, + reportActions: actionReportActions, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: actionableWhisperReportActionID, introSelected, @@ -633,6 +638,7 @@ function DynamicReportDetailsPage({policy, report, route, reportMetadata, report action: () => { createDraftTransactionAndNavigateToParticipantSelector({ reportID: actionReportID, + reportActions: actionReportActions, actionName: CONST.IOU.ACTION.SHARE, reportActionID: actionableWhisperReportActionID, introSelected, @@ -769,8 +775,8 @@ function DynamicReportDetailsPage({policy, report, route, reportMetadata, report styles.ph2, shouldOpenRoomMembersPage, navigateBackFromReportDetailsPath, - parentReportAction, - reportActionsForOriginalReportID, + actionReportID, + actionReportActions, iouTransactionID, moneyRequestReport?.reportID, moneyRequestReportActions, diff --git a/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx b/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx index a9c38a12fbe7..9d3e69672f1a 100644 --- a/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx +++ b/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx @@ -59,6 +59,8 @@ function ChatActionableButtons({action, originalReportID, reportID, hasPendingFo const {translate} = useLocalize(); const lastWorkspaceNumber = useLastWorkspaceNumber(); const actionOwnerReportID = originalReportID ?? reportID; + // Used by createDraftTransactionAndNavigateToParticipantSelector to find the linked track-expense action + const [actionOwnerReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${getNonEmptyStringOnyxID(actionOwnerReportID)}`); const [originalReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(originalReportID)}`); const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(reportID)}`); const actionOwnerReport = originalReport ?? report; @@ -188,6 +190,7 @@ function ChatActionableButtons({action, originalReportID, reportID, hasPendingFo if (isActionableTrackExpense(action)) { const baseDraftTransactionParams = { reportID: actionOwnerReportID, + reportActions: actionOwnerReportActions, reportActionID: action.reportActionID, introSelected, draftTransactionIDs, diff --git a/tests/actions/IOU/CreateDraftTransactionTest.ts b/tests/actions/IOU/CreateDraftTransactionTest.ts index c94b8220e67a..b57692244c8c 100644 --- a/tests/actions/IOU/CreateDraftTransactionTest.ts +++ b/tests/actions/IOU/CreateDraftTransactionTest.ts @@ -159,6 +159,7 @@ describe('actions/IOU', () => { // When createDraftTransactionAndNavigateToParticipantSelector is called with draftTransactionIDs createDraftTransactionAndNavigateToParticipantSelector({ reportID: selfDMReport.reportID, + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID, introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM}, @@ -211,6 +212,7 @@ describe('actions/IOU', () => { // When createDraftTransactionAndNavigateToParticipantSelector is called with empty allTransactionDrafts createDraftTransactionAndNavigateToParticipantSelector({ reportID: selfDMReport.reportID, + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID, introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM}, @@ -252,6 +254,7 @@ describe('actions/IOU', () => { // When createDraftTransactionAndNavigateToParticipantSelector is called with undefined transaction createDraftTransactionAndNavigateToParticipantSelector({ reportID: selfDMReport.reportID, + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: 'some-report-action-id', introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM}, @@ -288,6 +291,7 @@ describe('actions/IOU', () => { // When createDraftTransactionAndNavigateToParticipantSelector is called with undefined reportID createDraftTransactionAndNavigateToParticipantSelector({ reportID: undefined, + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: 'some-report-action-id', introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM}, @@ -366,6 +370,7 @@ describe('actions/IOU', () => { // When the expense is submitted to the employer, skipping the destination picker createDraftTransactionAndNavigateToParticipantSelector({ reportID: selfDMReport.reportID, + reportActions: undefined, actionName: CONST.IOU.ACTION.SUBMIT, reportActionID: '1', introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM}, @@ -402,6 +407,7 @@ describe('actions/IOU', () => { // When the expense is submitted to the employer and there is no workspace to submit to createDraftTransactionAndNavigateToParticipantSelector({ reportID: selfDMReport.reportID, + reportActions: undefined, actionName: CONST.IOU.ACTION.SUBMIT, reportActionID: '1', introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM}, @@ -432,6 +438,7 @@ describe('actions/IOU', () => { // When the expense is submitted to the employer and there is no workspace to submit to createDraftTransactionAndNavigateToParticipantSelector({ reportID: selfDMReport.reportID, + reportActions: undefined, actionName: CONST.IOU.ACTION.SUBMIT, reportActionID: '1', introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM}, @@ -461,6 +468,7 @@ describe('actions/IOU', () => { // When the expense is submitted to the employer createDraftTransactionAndNavigateToParticipantSelector({ reportID: selfDMReport.reportID, + reportActions: undefined, actionName: CONST.IOU.ACTION.SUBMIT, reportActionID: '1', introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM}, diff --git a/tests/actions/IOUTest/TrackExpenseTest.ts b/tests/actions/IOUTest/TrackExpenseTest.ts index ef1d84c4492d..63f2f18511c6 100644 --- a/tests/actions/IOUTest/TrackExpenseTest.ts +++ b/tests/actions/IOUTest/TrackExpenseTest.ts @@ -380,6 +380,7 @@ describe('actions/IOU/TrackExpense', () => { const reportActionableTrackExpense = Object.values(selfDMReportActions ?? {}).find((reportAction) => isActionableTrackExpense(reportAction)); createDraftTransactionAndNavigateToParticipantSelector({ reportID: selfDMReport.reportID, + reportActions: selfDMReportActions, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: reportActionableTrackExpense?.reportActionID, introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM}, @@ -1451,6 +1452,7 @@ describe('actions/IOU/TrackExpense', () => { // When a draft is created for categorization createDraftTransactionAndNavigateToParticipantSelector({ reportID: selfDMReport.reportID, + reportActions: selfDMReportActions, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: actionableWhisper?.reportActionID, introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM}, diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index 1c92c0a8e44b..005b5647da32 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -17560,6 +17560,7 @@ describe('ReportUtils', () => { createDraftTransactionAndNavigateToParticipantSelector({ reportID: '1', + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: '1', introSelected: undefined, @@ -17602,6 +17603,7 @@ describe('ReportUtils', () => { // When we call createDraftTransactionAndNavigateToParticipantSelector with the restricted policy createDraftTransactionAndNavigateToParticipantSelector({ reportID: '1', + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: '1', introSelected: undefined, @@ -17642,6 +17644,7 @@ describe('ReportUtils', () => { // When we call createDraftTransactionAndNavigateToParticipantSelector createDraftTransactionAndNavigateToParticipantSelector({ reportID: '1', + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: '1', introSelected: undefined, @@ -17685,6 +17688,7 @@ describe('ReportUtils', () => { // When we call createDraftTransactionAndNavigateToParticipantSelector createDraftTransactionAndNavigateToParticipantSelector({ reportID: '1', + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: '1', introSelected: undefined, @@ -17730,6 +17734,7 @@ describe('ReportUtils', () => { // When we call createDraftTransactionAndNavigateToParticipantSelector with undefined activePolicy createDraftTransactionAndNavigateToParticipantSelector({ reportID: '2', + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: '2', introSelected: undefined, @@ -17762,6 +17767,7 @@ describe('ReportUtils', () => { // When we call createDraftTransactionAndNavigateToParticipantSelector with undefined activePolicy createDraftTransactionAndNavigateToParticipantSelector({ reportID: '1', + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: '1', introSelected: undefined, @@ -17815,6 +17821,7 @@ describe('ReportUtils', () => { // When we call createDraftTransactionAndNavigateToParticipantSelector with undefined activePolicy createDraftTransactionAndNavigateToParticipantSelector({ reportID: '1', + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: '1', introSelected: undefined, @@ -17864,6 +17871,7 @@ describe('ReportUtils', () => { // When we call createDraftTransactionAndNavigateToParticipantSelector createDraftTransactionAndNavigateToParticipantSelector({ reportID: '1', + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: '1', introSelected: undefined, @@ -17912,6 +17920,7 @@ describe('ReportUtils', () => { // When we call with amountOwed = 0 createDraftTransactionAndNavigateToParticipantSelector({ reportID: '1', + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: '1', introSelected: undefined, @@ -17953,6 +17962,7 @@ describe('ReportUtils', () => { // When we call with amountOwed = 50 createDraftTransactionAndNavigateToParticipantSelector({ reportID: '1', + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: '1', introSelected: undefined, @@ -17996,6 +18006,7 @@ describe('ReportUtils', () => { // When we pass the policy via policies param with no activePolicy createDraftTransactionAndNavigateToParticipantSelector({ reportID: '1', + reportActions: undefined, actionName: CONST.IOU.ACTION.CATEGORIZE, reportActionID: '1', introSelected: undefined, @@ -18034,6 +18045,7 @@ describe('ReportUtils', () => { // When we call with SUBMIT action and policies containing a valid policy createDraftTransactionAndNavigateToParticipantSelector({ reportID: '1', + reportActions: undefined, actionName: CONST.IOU.ACTION.SUBMIT, reportActionID: '1', introSelected: undefined, @@ -18065,6 +18077,7 @@ describe('ReportUtils', () => { // When we call with a non-SUBMIT, non-CATEGORIZE, non-SHARE action and empty policies createDraftTransactionAndNavigateToParticipantSelector({ reportID: '1', + reportActions: undefined, actionName: CONST.IOU.ACTION.SUBMIT, reportActionID: '1', introSelected: undefined, From 1a493cca061f74098779f99fca8617e062ac4137 Mon Sep 17 00:00:00 2001 From: cretadn22 Date: Thu, 30 Jul 2026 02:10:38 +0700 Subject: [PATCH 2/3] Remove outdated comments --- src/libs/ReportUtils.ts | 1 - src/pages/inbox/report/actionContents/ChatActionableButtons.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index fc30cd81d30e..85b610619b5f 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -11703,7 +11703,6 @@ type CreateDraftTransactionParams = { reportID: string | undefined; actionName: IOUAction; reportActionID: string | undefined; - /** Report actions of the report identified by reportID, used to find the linked track-expense action */ reportActions: OnyxEntry; introSelected: OnyxEntry; draftTransactionIDs: string[] | undefined; diff --git a/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx b/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx index 9d3e69672f1a..fc6d5619a5f0 100644 --- a/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx +++ b/src/pages/inbox/report/actionContents/ChatActionableButtons.tsx @@ -59,7 +59,6 @@ function ChatActionableButtons({action, originalReportID, reportID, hasPendingFo const {translate} = useLocalize(); const lastWorkspaceNumber = useLastWorkspaceNumber(); const actionOwnerReportID = originalReportID ?? reportID; - // Used by createDraftTransactionAndNavigateToParticipantSelector to find the linked track-expense action const [actionOwnerReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${getNonEmptyStringOnyxID(actionOwnerReportID)}`); const [originalReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(originalReportID)}`); const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(reportID)}`); From 95119c1bbfc6659c43e3d5893dca52a6f8a2dfc0 Mon Sep 17 00:00:00 2001 From: cretadn22 Date: Thu, 30 Jul 2026 02:14:54 +0700 Subject: [PATCH 3/3] Add tests for linking report actions in createDraftTransactionAndNavigateToParticipantSelector --- .../actions/IOU/CreateDraftTransactionTest.ts | 146 +++++++++++++++++- 1 file changed, 145 insertions(+), 1 deletion(-) diff --git a/tests/actions/IOU/CreateDraftTransactionTest.ts b/tests/actions/IOU/CreateDraftTransactionTest.ts index b57692244c8c..f739c82b2896 100644 --- a/tests/actions/IOU/CreateDraftTransactionTest.ts +++ b/tests/actions/IOU/CreateDraftTransactionTest.ts @@ -10,7 +10,7 @@ import IntlStore from '@src/languages/IntlStore'; import OnyxUpdateManager from '@src/libs/actions/OnyxUpdateManager'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {Policy, Report} from '@src/types/onyx'; +import type {Policy, Report, ReportAction} from '@src/types/onyx'; import type Transaction from '@src/types/onyx/Transaction'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; @@ -19,6 +19,7 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import currencyList from '../../unit/currencyList.json'; +import createRandomReportAction from '../../utils/collections/reportActions'; import {createPolicyExpenseChat, createRandomReport, createSelfDM} from '../../utils/collections/reports'; import createRandomTransaction from '../../utils/collections/transaction'; import {getGlobalFetchMock, getOnyxData} from '../../utils/TestHelper'; @@ -193,6 +194,149 @@ describe('actions/IOU', () => { expect(updatedTransactionDrafts?.[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionToCategorize.transactionID}`]).toBeTruthy(); }); + it('should link the track-expense action found in the passed reportActions', async () => { + // Given a selfDM report with a tracked transaction and its money request action + const selfDMReport = createRandomReport(1, CONST.REPORT.CHAT_TYPE.SELF_DM); + const transaction: Transaction = {...createRandomTransaction(1), transactionID: 'tracked-transaction'}; + const trackedExpenseAction: ReportAction = { + ...createRandomReportAction(101), + actionName: CONST.REPORT.ACTIONS.TYPE.IOU, + originalMessage: { + IOUReportID: selfDMReport.reportID, + IOUTransactionID: transaction.transactionID, + amount: transaction.amount, + currency: transaction.currency, + type: CONST.IOU.REPORT_ACTION_TYPE.CREATE, + }, + }; + + await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, transaction); + await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${selfDMReport.reportID}`, selfDMReport); + + // When the draft is created with the report actions passed as a parameter + createDraftTransactionAndNavigateToParticipantSelector({ + reportID: selfDMReport.reportID, + reportActions: {[trackedExpenseAction.reportActionID]: trackedExpenseAction}, + actionName: CONST.IOU.ACTION.CATEGORIZE, + reportActionID: '1', + introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM}, + draftTransactionIDs: [], + activePolicy: undefined, + userBillingGracePeriodEnds: undefined, + amountOwed: 0, + transaction, + currentUserAccountID: RORY_ACCOUNT_ID, + currentUserEmail: RORY_EMAIL, + currentUserLocalCurrency: '', + filteredPoliciesCount: 0, + firstPolicyID: undefined, + }); + await waitForBatchedUpdates(); + + // Then the draft should be linked to the money request action found in the passed reportActions + let drafts: OnyxCollection; + await getOnyxData({ + key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, + callback: (val) => { + drafts = val; + }, + }); + const draft = drafts?.[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`]; + expect(draft?.linkedTrackedExpenseReportAction?.reportActionID).toBe(trackedExpenseAction.reportActionID); + expect(draft?.linkedTrackedExpenseReportID).toBe(selfDMReport.reportID); + }); + + it('should read the passed reportActions rather than the report actions stored in Onyx', async () => { + // Given a selfDM report with a tracked transaction, one matching action passed as a parameter and a different matching action stored in Onyx + const selfDMReport = createRandomReport(1, CONST.REPORT.CHAT_TYPE.SELF_DM); + const transaction: Transaction = {...createRandomTransaction(1), transactionID: 'tracked-transaction'}; + const originalMessage = { + IOUReportID: selfDMReport.reportID, + IOUTransactionID: transaction.transactionID, + amount: transaction.amount, + currency: transaction.currency, + type: CONST.IOU.REPORT_ACTION_TYPE.CREATE, + }; + const passedAction: ReportAction = {...createRandomReportAction(102), actionName: CONST.REPORT.ACTIONS.TYPE.IOU, originalMessage}; + const onyxOnlyAction: ReportAction = {...createRandomReportAction(103), actionName: CONST.REPORT.ACTIONS.TYPE.IOU, originalMessage}; + + await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, transaction); + await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${selfDMReport.reportID}`, selfDMReport); + await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${selfDMReport.reportID}`, {[onyxOnlyAction.reportActionID]: onyxOnlyAction}); + + // When the draft is created with only the passed action + createDraftTransactionAndNavigateToParticipantSelector({ + reportID: selfDMReport.reportID, + reportActions: {[passedAction.reportActionID]: passedAction}, + actionName: CONST.IOU.ACTION.CATEGORIZE, + reportActionID: '1', + introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM}, + draftTransactionIDs: [], + activePolicy: undefined, + userBillingGracePeriodEnds: undefined, + amountOwed: 0, + transaction, + currentUserAccountID: RORY_ACCOUNT_ID, + currentUserEmail: RORY_EMAIL, + currentUserLocalCurrency: '', + filteredPoliciesCount: 0, + firstPolicyID: undefined, + }); + await waitForBatchedUpdates(); + + // Then the draft should be linked to the passed action, proving the Onyx-stored actions are not read + let drafts: OnyxCollection; + await getOnyxData({ + key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, + callback: (val) => { + drafts = val; + }, + }); + const draft = drafts?.[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`]; + expect(draft?.linkedTrackedExpenseReportAction?.reportActionID).toBe(passedAction.reportActionID); + }); + + it('should not link any track-expense action when reportActions is undefined', async () => { + // Given a selfDM report with a tracked transaction and no reportActions passed + const selfDMReport = createRandomReport(1, CONST.REPORT.CHAT_TYPE.SELF_DM); + const transaction: Transaction = {...createRandomTransaction(1), transactionID: 'tracked-transaction'}; + + await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, transaction); + await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${selfDMReport.reportID}`, selfDMReport); + + // When the draft is created without reportActions + createDraftTransactionAndNavigateToParticipantSelector({ + reportID: selfDMReport.reportID, + reportActions: undefined, + actionName: CONST.IOU.ACTION.CATEGORIZE, + reportActionID: '1', + introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM}, + draftTransactionIDs: [], + activePolicy: undefined, + userBillingGracePeriodEnds: undefined, + amountOwed: 0, + transaction, + currentUserAccountID: RORY_ACCOUNT_ID, + currentUserEmail: RORY_EMAIL, + currentUserLocalCurrency: '', + filteredPoliciesCount: 0, + firstPolicyID: undefined, + }); + await waitForBatchedUpdates(); + + // Then the draft should still be created, with no linked track-expense action + let drafts: OnyxCollection; + await getOnyxData({ + key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, + callback: (val) => { + drafts = val; + }, + }); + const draft = drafts?.[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`]; + expect(draft).toBeTruthy(); + expect(draft?.linkedTrackedExpenseReportAction).toBeFalsy(); + }); + it('should create a draft transaction with correct data when categorizing', async () => { // Given a selfDM report and a transaction with specific data const selfDMReport = createRandomReport(1, CONST.REPORT.CHAT_TYPE.SELF_DM);