diff --git a/src/libs/actions/OnyxDerived/configs/reportAttributes.ts b/src/libs/actions/OnyxDerived/configs/reportAttributes.ts index 487613e879dc..2732f2ac7f57 100644 --- a/src/libs/actions/OnyxDerived/configs/reportAttributes.ts +++ b/src/libs/actions/OnyxDerived/configs/reportAttributes.ts @@ -86,30 +86,33 @@ export default createOnyxDerivedValueConfig({ if (isFullyComputed) { // if there are report-related updates, iterate over the updates - if (updates.length > 0) { - dataToIterate = prepareReportKeys(updates); - } else if (!!transactionsUpdates || !!transactionViolationsUpdates) { - let transactionReportIDs: string[] = []; - if (transactionsUpdates) { - transactionReportIDs = Object.values(transactionsUpdates).map((transaction) => `${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`); + if (updates.length > 0 || !!transactionsUpdates || !!transactionViolationsUpdates) { + if (updates.length > 0) { + dataToIterate = prepareReportKeys(updates); } - // Also handle transaction violations updates by extracting transaction IDs and finding their reports - if (transactionViolationsUpdates) { - const violationTransactionIDs = Object.keys(transactionViolationsUpdates).map((key) => key.replace(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, '')); - const violationReportIDs = violationTransactionIDs - .map((transactionID) => transactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]?.reportID) - .filter(Boolean) - .map((reportID) => `${ONYXKEYS.COLLECTION.REPORT}${reportID}`); - - // Also include chat reports for expense reports that have violations - const chatReportIDs = violationReportIDs - .map((reportKey) => reports?.[reportKey]?.chatReportID) - .filter(Boolean) - .map((chatReportID) => `${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`); - - transactionReportIDs = [...transactionReportIDs, ...violationReportIDs, ...chatReportIDs]; + if (!!transactionsUpdates || !!transactionViolationsUpdates) { + let transactionReportIDs: string[] = []; + if (transactionsUpdates) { + transactionReportIDs = Object.values(transactionsUpdates).map((transaction) => `${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`); + } + // Also handle transaction violations updates by extracting transaction IDs and finding their reports + if (transactionViolationsUpdates) { + const violationTransactionIDs = Object.keys(transactionViolationsUpdates).map((key) => key.replace(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, '')); + const violationReportIDs = violationTransactionIDs + .map((transactionID) => transactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]?.reportID) + .filter(Boolean) + .map((reportID) => `${ONYXKEYS.COLLECTION.REPORT}${reportID}`); + + // Also include chat reports for expense reports that have violations + const chatReportIDs = violationReportIDs + .map((reportKey) => reports?.[reportKey]?.chatReportID) + .filter(Boolean) + .map((chatReportID) => `${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`); + + transactionReportIDs = [...transactionReportIDs, ...violationReportIDs, ...chatReportIDs]; + } + dataToIterate.push(...prepareReportKeys(transactionReportIDs)); } - dataToIterate = prepareReportKeys(transactionReportIDs); } else { // No updates to process, return current value to prevent unnecessary computation return currentValue ?? {reports: {}, locale: null}; diff --git a/tests/unit/OnyxDerivedTest.ts b/tests/unit/OnyxDerivedTest.ts index 1adbb5b6635c..ecf1868025fd 100644 --- a/tests/unit/OnyxDerivedTest.ts +++ b/tests/unit/OnyxDerivedTest.ts @@ -1,11 +1,15 @@ /* eslint-disable @typescript-eslint/naming-convention */ import Onyx from 'react-native-onyx'; +import type {OnyxCollection} from 'react-native-onyx'; import OnyxUtils from 'react-native-onyx/dist/OnyxUtils'; +import reportAttributes from '@libs/actions/OnyxDerived/configs/reportAttributes'; import initOnyxDerivedValues from '@userActions/OnyxDerived'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import type {Report} from '@src/types/onyx'; import type {ReportActions} from '@src/types/onyx/ReportAction'; import {createRandomReport} from '../utils/collections/reports'; +import createRandomTransaction from '../utils/collections/transaction'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; describe('OnyxDerived', () => { @@ -72,6 +76,35 @@ describe('OnyxDerived', () => { }); }); + it('should contain both report attributes update when there are report and transaction updates', async () => { + await waitForBatchedUpdates(); + // Given 2 reports and 1 transaction + const reportID1 = '0'; + const reportID2 = '1'; + const reports: OnyxCollection = { + [`${ONYXKEYS.COLLECTION.REPORT}${reportID1}`]: createRandomReport(Number(reportID1)), + [`${ONYXKEYS.COLLECTION.REPORT}${reportID2}`]: createRandomReport(Number(reportID2)), + }; + const transaction = createRandomTransaction(1); + + // When the report attributes are recomputed with both report and transaction updates + reportAttributes.compute([reports, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined], {areAllConnectionsSet: true}); + const reportAttributesComputedValue = reportAttributes.compute([reports, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined], { + sourceValues: { + [ONYXKEYS.COLLECTION.REPORT]: { + [`${ONYXKEYS.COLLECTION.REPORT}${reportID1}`]: reports[`${ONYXKEYS.COLLECTION.REPORT}${reportID1}`], + }, + [ONYXKEYS.COLLECTION.TRANSACTION]: { + [`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`]: transaction, + }, + }, + areAllConnectionsSet: true, + }).reports; + + // Then the computed report attributes should contain both reports + expect(Object.keys(reportAttributesComputedValue)).toEqual([reportID1, reportID2]); + }); + describe('reportErrors', () => { it('returns empty errors when no errors exist', async () => { const report = createRandomReport(1);