@@ -2,9 +2,10 @@ import type {KeyValueMapping} from 'react-native-onyx';
22import Onyx from 'react-native-onyx' ;
33import { isExpenseReport } from '@libs/ReportUtils' ;
44import { actionR14932 as mockIOUAction , originalMessageR14932 as mockOriginalMessage } from '../../__mocks__/reportData/actions' ;
5+ import { iouReportR14932 as mockIOUReport } from '../../__mocks__/reportData/reports' ;
56import CONST from '../../src/CONST' ;
67import * as ReportActionsUtils from '../../src/libs/ReportActionsUtils' ;
7- import { isIOUActionMatchingTransactionList } from '../../src/libs/ReportActionsUtils' ;
8+ import { getOneTransactionThreadReportID , getOriginalMessage , isIOUActionMatchingTransactionList } from '../../src/libs/ReportActionsUtils' ;
89import ONYXKEYS from '../../src/ONYXKEYS' ;
910import type { Report , ReportAction } from '../../src/types/onyx' ;
1011import createRandomReport from '../utils/collections/reports' ;
@@ -353,6 +354,75 @@ describe('ReportActionsUtils', () => {
353354 } ) ;
354355 } ) ;
355356
357+ describe ( 'getOneTransactionThreadReportID' , ( ) => {
358+ const IOUReportID = 'REPORT_IOU' ;
359+ const IOUExpenseReportID = 'REPORT_EXPENSE' ;
360+ const IOUTransactionID = 'TRANSACTION_IOU' ;
361+ const IOUExpenseTransactionID = 'TRANSACTION_EXPENSE' ;
362+
363+ const mockedReports : Record < `${typeof ONYXKEYS . COLLECTION . REPORT } ${string } `, Report > = {
364+ [ `${ ONYXKEYS . COLLECTION . REPORT } ${ IOUReportID } ` ] : { ...mockIOUReport , reportID : IOUReportID } ,
365+ [ `${ ONYXKEYS . COLLECTION . REPORT } ${ IOUExpenseReportID } ` ] : { ...mockIOUReport , type : CONST . REPORT . TYPE . EXPENSE , reportID : IOUExpenseReportID } ,
366+ } ;
367+
368+ const linkedCreateAction = {
369+ ...mockIOUAction ,
370+ originalMessage : { ...getOriginalMessage ( mockIOUAction ) , IOUTransactionID} ,
371+ } ;
372+
373+ const unlinkedCreateAction = {
374+ ...mockIOUAction ,
375+ originalMessage : { ...getOriginalMessage ( mockIOUAction ) , IOUTransactionID : IOUExpenseTransactionID } ,
376+ } ;
377+
378+ const linkedDeleteAction = {
379+ ...mockIOUAction ,
380+ originalMessage : {
381+ ...getOriginalMessage ( mockIOUAction ) ,
382+ IOUTransactionID,
383+ type : CONST . IOU . REPORT_ACTION_TYPE . DELETE ,
384+ } ,
385+ } ;
386+
387+ const linkedPayAction = {
388+ ...mockIOUAction ,
389+ originalMessage : {
390+ ...getOriginalMessage ( mockIOUAction ) ,
391+ IOUTransactionID,
392+ type : CONST . IOU . REPORT_ACTION_TYPE . PAY ,
393+ } ,
394+ } ;
395+
396+ beforeEach ( async ( ) => {
397+ await Onyx . mergeCollection ( ONYXKEYS . COLLECTION . REPORT , mockedReports ) ;
398+ } ) ;
399+
400+ it ( 'should return the childReportID for a valid single IOU action' , ( ) => {
401+ const result = getOneTransactionThreadReportID ( IOUReportID , [ linkedCreateAction ] , false , [ IOUTransactionID ] ) ;
402+ expect ( result ) . toEqual ( linkedCreateAction . childReportID ) ;
403+ } ) ;
404+
405+ it ( 'should return undefined for action with a transaction that is not linked to it' , ( ) => {
406+ const result = getOneTransactionThreadReportID ( IOUReportID , [ unlinkedCreateAction ] , false , [ IOUTransactionID ] ) ;
407+ expect ( result ) . toBeUndefined ( ) ;
408+ } ) ;
409+
410+ it ( 'should return undefined if multiple IOU actions are present' , ( ) => {
411+ const result = getOneTransactionThreadReportID ( IOUReportID , [ linkedCreateAction , linkedCreateAction ] , false , [ IOUTransactionID ] ) ;
412+ expect ( result ) . toBeUndefined ( ) ;
413+ } ) ;
414+
415+ it ( 'should skip actions where original message type is PAY' , ( ) => {
416+ const result = getOneTransactionThreadReportID ( IOUReportID , [ linkedPayAction , linkedCreateAction ] , false , [ IOUTransactionID ] ) ;
417+ expect ( result ) . toEqual ( linkedCreateAction . childReportID ) ;
418+ } ) ;
419+
420+ it ( 'should return undefined if no valid IOU actions are present' , ( ) => {
421+ const result = getOneTransactionThreadReportID ( IOUReportID , [ unlinkedCreateAction , linkedDeleteAction , linkedPayAction ] , false , [ IOUTransactionID ] ) ;
422+ expect ( result ) . toBeUndefined ( ) ;
423+ } ) ;
424+ } ) ;
425+
356426 describe ( 'getSortedReportActionsForDisplay' , ( ) => {
357427 it ( 'should filter out non-whitelisted actions' , ( ) => {
358428 const input : ReportAction [ ] = [
@@ -786,6 +856,8 @@ describe('ReportActionsUtils', () => {
786856 } ) ;
787857 } ) ;
788858
859+ describe ( 'getOneTransactionThreadReportID' , ( ) => { } ) ;
860+
789861 describe ( 'shouldShowAddMissingDetails' , ( ) => {
790862 it ( 'should return true if personal detail is not completed' , async ( ) => {
791863 const card = {
0 commit comments