From cecab118b83433f1f411e65df77c3b1eb1333032 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Fri, 3 Jan 2025 20:06:35 +0300 Subject: [PATCH 1/4] update lastVisibleActionCreated --- src/libs/actions/IOU.ts | 45 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index bdf2e49e6ddc..ee49b1c8e803 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -8393,6 +8393,7 @@ function putOnHold(transactionID: string, comment: string, reportID: string, sea const parentReportActionOptimistic = ReportUtils.getOptimisticDataForParentReportAction(reportID, createdReportActionComment.created, CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`]; + const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; const optimisticData: OnyxUpdate[] = [ { @@ -8418,6 +8419,13 @@ function putOnHold(transactionID: string, comment: string, reportID: string, sea key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`, value: updatedViolations, }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, + value: { + lastVisibleActionCreated: createdReportActionComment.created, + }, + }, ]; if (iouReport && iouReport.currency === transaction?.currency) { @@ -8463,6 +8471,21 @@ function putOnHold(transactionID: string, comment: string, reportID: string, sea errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericHoldExpenseFailureMessage'), }, }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [createdReportAction.reportActionID]: null, + [createdReportActionComment.reportActionID]: null, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, + value: { + lastVisibleActionCreated: report?.lastVisibleActionCreated, + }, + }, ]; // If we are holding from the search page, we optimistically update the snapshot data that search uses so that it is kept in sync @@ -8516,6 +8539,7 @@ function unholdRequest(transactionID: string, reportID: string, searchHash?: num const transactionViolations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`]; const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`]; + const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; const optimisticData: OnyxUpdate[] = [ { @@ -8540,6 +8564,13 @@ function unholdRequest(transactionID: string, reportID: string, searchHash?: num key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`, value: transactionViolations?.filter((violation) => violation.name !== CONST.VIOLATIONS.HOLD) ?? [], }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, + value: { + lastVisibleActionCreated: createdReportAction.created, + }, + }, ]; if (iouReport && iouReport.currency === transaction?.currency) { @@ -8570,6 +8601,13 @@ function unholdRequest(transactionID: string, reportID: string, searchHash?: num ]; const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [createdReportAction.reportActionID]: null, + }, + }, { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, @@ -8583,6 +8621,13 @@ function unholdRequest(transactionID: string, reportID: string, searchHash?: num key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`, value: transactionViolations ?? null, }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, + value: { + lastVisibleActionCreated: report?.lastVisibleActionCreated, + }, + }, ]; // If we are unholding from the search page, we optimistically update the snapshot data that search uses so that it is kept in sync From c0e4c4bad2b1e6a1a052d26150898d3369dc4ff5 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Fri, 3 Jan 2025 21:44:12 +0300 Subject: [PATCH 2/4] added tests --- tests/actions/IOUTest.ts | 94 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index f82290f91cfc..2a767a4ebff1 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -21,7 +21,7 @@ import * as ReportUtils from '@src/libs/ReportUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; -import type {Participant} from '@src/types/onyx/Report'; +import type {Participant, ReportCollectionDataSet} from '@src/types/onyx/Report'; import type {ReportActionsCollectionDataSet} from '@src/types/onyx/ReportAction'; import type {TransactionCollectionDataSet} from '@src/types/onyx/Transaction'; import {toCollectionDataSet} from '@src/types/utils/CollectionDataSet'; @@ -3683,6 +3683,98 @@ describe('actions/IOU', () => { }); }); + describe('putOnHold and unHoldRequest', () => { + test("putOnHold and unHoldRequest should properly update the transaction thread report's lastVisibleActionCreated to the optimistically added last report action created timestamp", () => { + const iouReport = ReportUtils.buildOptimisticIOUReport(1, 2, 100, '1', 'USD'); + const transaction = TransactionUtils.buildOptimisticTransaction({ + transactionParams: { + amount: 100, + currency: 'USD', + reportID: iouReport.reportID, + }, + }); + + const transactionCollectionDataSet: TransactionCollectionDataSet = { + [`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`]: transaction, + }; + const iouAction: OnyxTypes.ReportAction = ReportUtils.buildOptimisticIOUReportAction( + CONST.IOU.REPORT_ACTION_TYPE.CREATE, + transaction.amount, + transaction.currency, + '', + [], + transaction.transactionID, + ); + const transactionThread = ReportUtils.buildTransactionThread(iouAction, iouReport); + + const actions: OnyxInputValue = {[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouAction.reportActionID}`]: iouAction}; + const reportCollectionDataSet: ReportCollectionDataSet = { + [`${ONYXKEYS.COLLECTION.REPORT}${transactionThread.reportID}`]: transactionThread, + [`${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`]: iouReport, + }; + const actionCollectionDataSet: ReportActionsCollectionDataSet = {[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`]: actions}; + const comment = 'hold reason'; + + return waitForBatchedUpdates() + .then(() => Onyx.multiSet({...reportCollectionDataSet, ...transactionCollectionDataSet, ...actionCollectionDataSet})) + .then(() => { + // When an expense is put on hold + IOU.putOnHold(transaction.transactionID, comment, transactionThread.reportID); + return waitForBatchedUpdates(); + }) + .then(() => { + return new Promise((resolve) => { + const connection = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThread.reportID}`, + callback: (report) => { + Onyx.disconnect(connection); + const lastVisibleActionCreated = report?.lastVisibleActionCreated; + const connection2 = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread.reportID}`, + callback: (reportActions) => { + Onyx.disconnect(connection2); + resolve(); + const lastAction = ReportActionsUtils.getSortedReportActions(Object.values(reportActions ?? {}), true).at(0); + const message = ReportActionsUtils.getReportActionMessage(lastAction); + // Then the transaction thread report lastVisibleActionCreated should equal the hold comment action created timestamp. + expect(message?.text).toBe(comment); + expect(lastVisibleActionCreated).toBe(lastAction?.created); + }, + }); + }, + }); + }); + }) + .then(() => { + // When an expense is unhold + IOU.unholdRequest(transaction.transactionID, transactionThread.reportID); + return waitForBatchedUpdates(); + }) + .then(() => { + return new Promise((resolve) => { + const connection = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThread.reportID}`, + callback: (report) => { + Onyx.disconnect(connection); + const lastVisibleActionCreated = report?.lastVisibleActionCreated; + const connection2 = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread.reportID}`, + callback: (reportActions) => { + Onyx.disconnect(connection2); + resolve(); + const lastAction = ReportActionsUtils.getSortedReportActions(Object.values(reportActions ?? {}), true).at(0); + // Then the transaction thread report lastVisibleActionCreated should equal the unhold action created timestamp. + expect(lastAction?.actionName).toBe(CONST.REPORT.ACTIONS.TYPE.UNHOLD); + expect(lastVisibleActionCreated).toBe(lastAction?.created); + }, + }); + }, + }); + }); + }); + }); + }); + describe('sendInvoice', () => { it('creates a new invoice chat when one has been converted from individual to business', async () => { // Mock API.write for this test From 4ec59f87fa044ee2dcf82fbc347eded30f5c7dca Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Sat, 4 Jan 2025 22:43:01 +0300 Subject: [PATCH 3/4] separate tests --- tests/actions/IOUTest.ts | 45 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 2a767a4ebff1..55052f5ba41c 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -3683,8 +3683,8 @@ describe('actions/IOU', () => { }); }); - describe('putOnHold and unHoldRequest', () => { - test("putOnHold and unHoldRequest should properly update the transaction thread report's lastVisibleActionCreated to the optimistically added last report action created timestamp", () => { + describe('putOnHold', () => { + test("putOnHold should update the transaction thread report's lastVisibleActionCreated to the optimistically added hold comment report action created timestamp", () => { const iouReport = ReportUtils.buildOptimisticIOUReport(1, 2, 100, '1', 'USD'); const transaction = TransactionUtils.buildOptimisticTransaction({ transactionParams: { @@ -3744,6 +3744,47 @@ describe('actions/IOU', () => { }, }); }); + }); + }); + }); + + describe('unHoldRequest', () => { + test("unHoldRequest should update the transaction thread report's lastVisibleActionCreated to the optimistically added unhold report action created timestamp", () => { + const iouReport = ReportUtils.buildOptimisticIOUReport(1, 2, 100, '1', 'USD'); + const transaction = TransactionUtils.buildOptimisticTransaction({ + transactionParams: { + amount: 100, + currency: 'USD', + reportID: iouReport.reportID, + }, + }); + + const transactionCollectionDataSet: TransactionCollectionDataSet = { + [`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`]: transaction, + }; + const iouAction: OnyxTypes.ReportAction = ReportUtils.buildOptimisticIOUReportAction( + CONST.IOU.REPORT_ACTION_TYPE.CREATE, + transaction.amount, + transaction.currency, + '', + [], + transaction.transactionID, + ); + const transactionThread = ReportUtils.buildTransactionThread(iouAction, iouReport); + + const actions: OnyxInputValue = {[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouAction.reportActionID}`]: iouAction}; + const reportCollectionDataSet: ReportCollectionDataSet = { + [`${ONYXKEYS.COLLECTION.REPORT}${transactionThread.reportID}`]: transactionThread, + [`${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`]: iouReport, + }; + const actionCollectionDataSet: ReportActionsCollectionDataSet = {[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`]: actions}; + const comment = 'hold reason'; + + return waitForBatchedUpdates() + .then(() => Onyx.multiSet({...reportCollectionDataSet, ...transactionCollectionDataSet, ...actionCollectionDataSet})) + .then(() => { + IOU.putOnHold(transaction.transactionID, comment, transactionThread.reportID); + return waitForBatchedUpdates(); }) .then(() => { // When an expense is unhold From fb49ac27aceb81425b3d97b1c20bdc3438f9ba9d Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Sun, 5 Jan 2025 01:27:48 +0300 Subject: [PATCH 4/4] minor update --- tests/actions/IOUTest.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 55052f5ba41c..dc07c16c8d7f 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -3684,7 +3684,7 @@ describe('actions/IOU', () => { }); describe('putOnHold', () => { - test("putOnHold should update the transaction thread report's lastVisibleActionCreated to the optimistically added hold comment report action created timestamp", () => { + test("should update the transaction thread report's lastVisibleActionCreated to the optimistically added hold comment report action created timestamp", () => { const iouReport = ReportUtils.buildOptimisticIOUReport(1, 2, 100, '1', 'USD'); const transaction = TransactionUtils.buildOptimisticTransaction({ transactionParams: { @@ -3749,7 +3749,7 @@ describe('actions/IOU', () => { }); describe('unHoldRequest', () => { - test("unHoldRequest should update the transaction thread report's lastVisibleActionCreated to the optimistically added unhold report action created timestamp", () => { + test("should update the transaction thread report's lastVisibleActionCreated to the optimistically added unhold report action created timestamp", () => { const iouReport = ReportUtils.buildOptimisticIOUReport(1, 2, 100, '1', 'USD'); const transaction = TransactionUtils.buildOptimisticTransaction({ transactionParams: {