@@ -1623,6 +1623,160 @@ describe('actions/IOU', () => {
16231623 . then ( mockFetch ?. succeed )
16241624 ) ;
16251625 } ) ;
1626+
1627+ it ( 'correctly implements RedBrickRoad error handling for ShareTrackedExpense when inviting new user to workspace' , async ( ) => {
1628+ const amount = 5000 ;
1629+ const comment = 'Shared tracked expense test' ;
1630+
1631+ // Setup test data - create a self DM report and policy expense chat
1632+ const selfDMReport : Report = {
1633+ reportID : '1' ,
1634+ type : CONST . REPORT . TYPE . CHAT ,
1635+ chatType : CONST . REPORT . CHAT_TYPE . SELF_DM ,
1636+ participants : { [ RORY_ACCOUNT_ID ] : RORY_PARTICIPANT } ,
1637+ } ;
1638+
1639+ const policy : Policy = {
1640+ id : 'policy123' ,
1641+ name : 'Test Policy' ,
1642+ role : CONST . POLICY . ROLE . ADMIN ,
1643+ type : CONST . POLICY . TYPE . TEAM ,
1644+ owner : RORY_EMAIL ,
1645+ outputCurrency : CONST . CURRENCY . USD ,
1646+ isPolicyExpenseChatEnabled : true ,
1647+ employeeList : {
1648+ [ CARLOS_EMAIL ] : {
1649+ role : CONST . POLICY . ROLE . ADMIN ,
1650+ } ,
1651+ } ,
1652+ } ;
1653+
1654+ const policyExpenseChat : Report = {
1655+ reportID : '2' ,
1656+ type : CONST . REPORT . TYPE . CHAT ,
1657+ chatType : CONST . REPORT . CHAT_TYPE . POLICY_EXPENSE_CHAT ,
1658+ policyID : policy . id ,
1659+ participants : {
1660+ [ RORY_ACCOUNT_ID ] : RORY_PARTICIPANT ,
1661+ [ CARLOS_ACCOUNT_ID ] : CARLOS_PARTICIPANT ,
1662+ } ,
1663+ } ;
1664+
1665+ // New accountant that is NOT in the workspace employee list (this will trigger the invitation)
1666+ const accountant = {
1667+ accountID : 999 ,
1668+ login : 'newaccountant@test.com' ,
1669+ email : 'newaccountant@test.com' ,
1670+ } ;
1671+
1672+ mockFetch ?. pause ?.( ) ;
1673+
1674+ // Setup initial data
1675+ await Promise . all ( [
1676+ Onyx . set ( `${ ONYXKEYS . COLLECTION . REPORT } ${ selfDMReport . reportID } ` , selfDMReport ) ,
1677+ Onyx . set ( `${ ONYXKEYS . COLLECTION . REPORT } ${ policyExpenseChat . reportID } ` , policyExpenseChat ) ,
1678+ Onyx . set ( `${ ONYXKEYS . COLLECTION . POLICY } ${ policy . id } ` , policy ) ,
1679+ Onyx . merge ( ONYXKEYS . PERSONAL_DETAILS_LIST , { [ accountant . accountID ] : accountant } ) ,
1680+ ] ) ;
1681+ await waitForBatchedUpdates ( ) ;
1682+
1683+ // First create a tracked expense in self DM
1684+ trackExpense ( {
1685+ report : selfDMReport ,
1686+ isDraftPolicy : true ,
1687+ action : CONST . IOU . ACTION . CREATE ,
1688+ participantParams : {
1689+ payeeEmail : RORY_EMAIL ,
1690+ payeeAccountID : RORY_ACCOUNT_ID ,
1691+ participant : { accountID : RORY_ACCOUNT_ID } ,
1692+ } ,
1693+ transactionParams : {
1694+ amount,
1695+ currency : CONST . CURRENCY . USD ,
1696+ created : format ( new Date ( ) , CONST . DATE . FNS_FORMAT_STRING ) ,
1697+ merchant : 'Test Merchant' ,
1698+ comment,
1699+ billable : false ,
1700+ } ,
1701+ } ) ;
1702+
1703+ mockFetch ?. resume ?.( ) ;
1704+ await waitForBatchedUpdates ( ) ;
1705+
1706+ // Capture the created tracked expense data
1707+ let selfDMReportID : string | undefined ;
1708+ await getOnyxData ( {
1709+ key : ONYXKEYS . COLLECTION . REPORT ,
1710+ waitForCollectionCallback : true ,
1711+ callback : ( reports ) => {
1712+ const selfDMReportOnyx = Object . values ( reports ?? { } ) . find ( ( report ) => report ?. reportID === selfDMReport . reportID ) ;
1713+ selfDMReportID = selfDMReportOnyx ?. reportID ;
1714+ } ,
1715+ } ) ;
1716+
1717+ const reportActions = await getOnyxValue ( `${ ONYXKEYS . COLLECTION . REPORT_ACTIONS } ${ selfDMReportID } ` ) ;
1718+ const actions = Object . values ( reportActions ?? { } ) ;
1719+ const linkedTrackedExpenseReportAction = actions . find ( ( action ) => action && isMoneyRequestAction ( action ) ) ;
1720+ const actionableWhisperReportActionID = actions . find ( ( action ) => action && isActionableTrackExpense ( action ) ) ?. reportActionID ;
1721+
1722+ let linkedTrackedExpenseReportID : string | undefined ;
1723+ await getOnyxData ( {
1724+ key : ONYXKEYS . COLLECTION . TRANSACTION ,
1725+ waitForCollectionCallback : true ,
1726+ callback : ( allTransactions ) => {
1727+ const transaction = Object . values ( allTransactions ?? { } ) . find ( ( t ) => ! isEmptyObject ( t ) ) ;
1728+ linkedTrackedExpenseReportID = transaction ?. reportID ;
1729+ } ,
1730+ } ) ;
1731+
1732+ // Now pause fetch and share the tracked expense with accountant
1733+ mockFetch ?. pause ?.( ) ;
1734+ trackExpense ( {
1735+ report : policyExpenseChat ,
1736+ isDraftPolicy : false ,
1737+ action : CONST . IOU . ACTION . SHARE ,
1738+ participantParams : {
1739+ payeeEmail : RORY_EMAIL ,
1740+ payeeAccountID : RORY_ACCOUNT_ID ,
1741+ participant : { reportID : policyExpenseChat . reportID , isPolicyExpenseChat : true } ,
1742+ } ,
1743+ policyParams : {
1744+ policy,
1745+ } ,
1746+ transactionParams : {
1747+ amount,
1748+ currency : CONST . CURRENCY . USD ,
1749+ created : format ( new Date ( ) , CONST . DATE . FNS_FORMAT_STRING ) ,
1750+ merchant : 'Test Merchant' ,
1751+ comment,
1752+ billable : false ,
1753+ actionableWhisperReportActionID,
1754+ linkedTrackedExpenseReportAction,
1755+ linkedTrackedExpenseReportID,
1756+ } ,
1757+ accountantParams : {
1758+ accountant,
1759+ } ,
1760+ } ) ;
1761+ await waitForBatchedUpdates ( ) ;
1762+
1763+ // Simulate network failure
1764+ mockFetch ?. fail ?.( ) ;
1765+ await ( mockFetch ?. resume ?.( ) as Promise < unknown > ) ;
1766+
1767+ // Verify error handling after failure - focus on workspace invitation error
1768+ const policyData = await getOnyxValue ( `${ ONYXKEYS . COLLECTION . POLICY } ${ policy . id } ` ) ;
1769+
1770+ // The new accountant should have been added to the employee list with error
1771+ const accountantEmployee = policyData ?. employeeList ?. [ accountant . email ] ;
1772+ expect ( accountantEmployee ) . toBeTruthy ( ) ;
1773+ expect ( accountantEmployee ?. errors ) . toBeTruthy ( ) ;
1774+ expect ( Object . values ( accountantEmployee ?. errors ?? { } ) . at ( 0 ) ) . toEqual ( translateLocal ( 'workspace.people.error.genericAdd' ) ) ;
1775+
1776+ // Cleanup
1777+ mockFetch ?. succeed ?.( ) ;
1778+ } ) ;
1779+
16261780 it ( 'does not trigger notifyNewAction when doing the money request in a money request report' , ( ) => {
16271781 requestMoney ( {
16281782 report : { reportID : '123' , type : CONST . REPORT . TYPE . EXPENSE } ,
0 commit comments