@@ -30,7 +30,7 @@ import * as API from '@src/libs/API';
3030import DateUtils from '@src/libs/DateUtils' ;
3131import ONYXKEYS from '@src/ONYXKEYS' ;
3232import ROUTES from '@src/ROUTES' ;
33- import type { Policy , Report , ReportNameValuePairs } from '@src/types/onyx' ;
33+ import type { Policy , Report , ReportNameValuePairs , ReportNextStepDeprecated } from '@src/types/onyx' ;
3434import type ReportAction from '@src/types/onyx/ReportAction' ;
3535import type { ReportActions } from '@src/types/onyx/ReportAction' ;
3636import type { OnyxData } from '@src/types/onyx/Request' ;
@@ -1381,6 +1381,100 @@ describe('actions/IOU/ReportWorkflow', () => {
13811381 const optimisticReportUpdate = onyxData . optimisticData ?. find ( ( update ) => update . key === `${ ONYXKEYS . COLLECTION . REPORT } ${ expenseReport . reportID } ` ) ;
13821382 expect ( ( optimisticReportUpdate ?. value as Report | undefined ) ?. managerID ) . toBe ( adminAccountID ) ;
13831383 } ) ;
1384+
1385+ it ( 'uses the rule approver in the optimistic next step when the existing report manager is stale' , async ( ) => {
1386+ // eslint-disable-next-line rulesdir/no-multiple-api-calls -- Inspecting API.write calls to verify submit payload and optimistic data.
1387+ const apiWriteSpy = jest . spyOn ( API , 'write' ) . mockImplementation ( ( ) => Promise . resolve ( ) ) ;
1388+ const policyID = '1' ;
1389+ const submitterAccountID = 100 ;
1390+ const defaultApproverAccountID = 101 ;
1391+ const ruleApproverAccountID = 102 ;
1392+ const submitterEmail = 'submitter@example.com' ;
1393+ const defaultApproverEmail = 'default-approver@example.com' ;
1394+ const ruleApproverEmail = 'rule-approver@example.com' ;
1395+
1396+ await Onyx . set ( ONYXKEYS . PERSONAL_DETAILS_LIST , {
1397+ [ submitterAccountID ] : { accountID : submitterAccountID , login : submitterEmail } ,
1398+ [ defaultApproverAccountID ] : { accountID : defaultApproverAccountID , login : defaultApproverEmail } ,
1399+ [ ruleApproverAccountID ] : { accountID : ruleApproverAccountID , login : ruleApproverEmail } ,
1400+ } ) ;
1401+
1402+ const policy : Policy = {
1403+ ...createRandomPolicy ( Number ( policyID ) ) ,
1404+ id : policyID ,
1405+ type : CONST . POLICY . TYPE . CORPORATE ,
1406+ approvalMode : CONST . POLICY . APPROVAL_MODE . ADVANCED ,
1407+ approver : defaultApproverEmail ,
1408+ owner : defaultApproverEmail ,
1409+ employeeList : {
1410+ [ submitterEmail ] : {
1411+ email : submitterEmail ,
1412+ submitsTo : defaultApproverEmail ,
1413+ } ,
1414+ } ,
1415+ rules : {
1416+ approvalRules : [
1417+ {
1418+ id : 'travel-rule' ,
1419+ applyWhen : [
1420+ {
1421+ field : CONST . POLICY . FIELDS . CATEGORY ,
1422+ condition : CONST . POLICY . RULE_CONDITIONS . MATCHES ,
1423+ value : 'Travel' ,
1424+ } ,
1425+ ] ,
1426+ approver : ruleApproverEmail ,
1427+ } ,
1428+ ] ,
1429+ } ,
1430+ } ;
1431+ const expenseReport : Report = {
1432+ ...createRandomReport ( Number ( policyID ) , undefined ) ,
1433+ reportID : '1' ,
1434+ policyID,
1435+ type : CONST . REPORT . TYPE . EXPENSE ,
1436+ ownerAccountID : submitterAccountID ,
1437+ managerID : defaultApproverAccountID ,
1438+ stateNum : CONST . REPORT . STATE_NUM . OPEN ,
1439+ statusNum : CONST . REPORT . STATUS_NUM . OPEN ,
1440+ total : 1000 ,
1441+ currency : CONST . CURRENCY . USD ,
1442+ } ;
1443+ const transaction : Transaction = {
1444+ ...createRandomTransaction ( 1 ) ,
1445+ reportID : expenseReport . reportID ,
1446+ category : 'Travel' ,
1447+ } ;
1448+
1449+ await Onyx . set ( `${ ONYXKEYS . COLLECTION . TRANSACTION } ${ transaction . transactionID } ` , transaction ) ;
1450+ await waitForBatchedUpdates ( ) ;
1451+
1452+ submitReport ( {
1453+ expenseReport,
1454+ policy,
1455+ currentUserAccountIDParam : submitterAccountID ,
1456+ currentUserEmailParam : submitterEmail ,
1457+ hasViolations : false ,
1458+ isASAPSubmitBetaEnabled : false ,
1459+ expenseReportCurrentNextStepDeprecated : undefined ,
1460+ userBillingGracePeriodEnds : undefined ,
1461+ amountOwed : 0 ,
1462+ ownerBillingGracePeriodEnd : undefined ,
1463+ delegateEmail : undefined ,
1464+ } ) ;
1465+
1466+ const [ , parameters , onyxData ] = apiWriteSpy . mock . calls . at ( - 1 ) as [ unknown , { managerAccountID ?: number } , OnyxData < typeof ONYXKEYS . COLLECTION . REPORT > ] ;
1467+ expect ( parameters . managerAccountID ) . toBe ( ruleApproverAccountID ) ;
1468+
1469+ const optimisticReportUpdate = onyxData . optimisticData ?. find ( ( update ) => update . key === `${ ONYXKEYS . COLLECTION . REPORT } ${ expenseReport . reportID } ` ) ;
1470+ expect ( ( optimisticReportUpdate ?. value as Report | undefined ) ?. managerID ) . toBe ( ruleApproverAccountID ) ;
1471+ expect ( ( optimisticReportUpdate ?. value as Report | undefined ) ?. nextStep ?. actorAccountID ) . toBe ( ruleApproverAccountID ) ;
1472+
1473+ const optimisticDeprecatedNextStepUpdate = onyxData . optimisticData ?. find ( ( update ) => update . key === `${ ONYXKEYS . COLLECTION . NEXT_STEP } ${ expenseReport . reportID } ` ) ;
1474+ const optimisticDeprecatedNextStep = optimisticDeprecatedNextStepUpdate ?. value as ReportNextStepDeprecated | undefined ;
1475+ expect ( optimisticDeprecatedNextStep ?. message ?. find ( ( message ) => message . type === 'strong' ) ?. text ) . toBe ( ruleApproverEmail ) ;
1476+ } ) ;
1477+
13841478 it ( 'keeps the workspace chat outstanding when an admin submits after approver changes' , async ( ) => {
13851479 // eslint-disable-next-line rulesdir/no-multiple-api-calls -- Inspecting optimistic parent chat data after submit from workspace chat.
13861480 const apiWriteSpy = jest . spyOn ( API , 'write' ) . mockImplementation ( ( ) => Promise . resolve ( ) ) ;
0 commit comments