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