@@ -14,6 +14,14 @@ import {createRandomReport} from '../utils/collections/reports';
1414import { translateLocal } from '../utils/TestHelper' ;
1515import waitForBatchedUpdates from '../utils/waitForBatchedUpdates' ;
1616
17+ // Mock PolicyUtils so getPolicy and isPolicyAdmin are controllable in tests. ModifiedExpenseMessage
18+ // uses named imports from this module; spies alone do not affect those references, so we need a module mock.
19+ jest . mock ( '@libs/PolicyUtils' , ( ) => ( {
20+ ...jest . requireActual < typeof PolicyUtils > ( '@libs/PolicyUtils' ) ,
21+ getPolicy : jest . fn ( ) ,
22+ isPolicyAdmin : jest . fn ( ) ,
23+ } ) ) ;
24+
1725const MOVED_TO_REPORT_ID = '1' ;
1826const MOVED_FROM_REPORT_ID = '2' ;
1927
@@ -814,10 +822,22 @@ describe('ModifiedExpenseMessage', () => {
814822
815823 describe ( 'when policy rules modify an expense' , ( ) => {
816824 let environmentURL : string ;
825+ const policyRulesPolicyId = '1234' ;
826+
817827 beforeAll ( async ( ) => {
818828 environmentURL = await getEnvironmentURL ( ) ;
819829 } ) ;
820830
831+ beforeEach ( ( ) => {
832+ // Default: current user has policy rule access (admin + rules enabled), so link points to workspace rules
833+ // eslint-disable-next-line @typescript-eslint/no-deprecated
834+ ( PolicyUtils . getPolicy as jest . Mock ) . mockReturnValue ( {
835+ id : policyRulesPolicyId ,
836+ areRulesEnabled : true ,
837+ } as Policy ) ;
838+ ( PolicyUtils . isPolicyAdmin as jest . Mock ) . mockReturnValue ( true ) ;
839+ } ) ;
840+
821841 it ( 'returns the correct text message with multiple overrides' , ( ) => {
822842 const reportAction = {
823843 ...createRandomReportAction ( 1 ) ,
@@ -924,6 +944,28 @@ describe('ModifiedExpenseMessage', () => {
924944
925945 expect ( result ) . toEqual ( expectedResult ) ;
926946 } ) ;
947+
948+ it ( 'returns the correct text message with help link for non-admin' , ( ) => {
949+ ( PolicyUtils . isPolicyAdmin as jest . Mock ) . mockReturnValue ( false ) ;
950+
951+ const reportAction = {
952+ ...createRandomReportAction ( 1 ) ,
953+ actionName : CONST . REPORT . ACTIONS . TYPE . MODIFIED_EXPENSE ,
954+ originalMessage : {
955+ policyID : policyRulesPolicyId ,
956+ policyRulesModifiedFields : {
957+ category : 'Travel' ,
958+ merchant : "McDonald's" ,
959+ } ,
960+ } as OriginalMessageModifiedExpense ,
961+ } ;
962+
963+ const result = getForReportAction ( { reportAction, policyID : report . policyID } ) ;
964+
965+ expect ( result ) . toContain ( CONST . CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL ) ;
966+ expect ( result ) . toContain ( 'workspace rules</a>' ) ;
967+ expect ( result ) . toContain ( 'set the category to "Travel" and merchant to "McDonald\'s"' ) ;
968+ } ) ;
927969 } ) ;
928970
929971 describe ( 'when the category is changed without source (backward compatibility)' , ( ) => {
0 commit comments