1- import { act , render , screen } from '@testing-library/react-native' ;
1+ import { act , fireEvent , render , screen } from '@testing-library/react-native' ;
22
33import ComposeProviders from '@components/ComposeProviders' ;
44import { LocaleContextProvider } from '@components/LocaleContextProvider' ;
@@ -24,19 +24,47 @@ const FAKE_TRANSACTION_ID = '2';
2424const FAKE_EMAIL = 'fake@gmail.com' ;
2525const FAKE_ACCOUNT_ID = 1 ;
2626const FAKE_SECOND_ACCOUNT_ID = 2 ;
27+ const mockShowConfirmModal = jest . fn ( ) ;
28+
29+ jest . mock ( '@hooks/useConfirmModal' , ( ) => ( ) => ( {
30+ showConfirmModal : mockShowConfirmModal ,
31+ } ) ) ;
2732
2833/**
2934 * Helper function to render the IOURequestEditReportCommon component with required providers.
3035 * This encapsulates the component setup and makes tests more readable.
3136 */
32- const renderIOURequestEditReportCommon = ( { selectedReportID = '' , selectedPolicyID} : { selectedReportID : string ; selectedPolicyID ?: string } ) =>
37+ const renderIOURequestEditReportCommon = ( {
38+ selectedReportID = '' ,
39+ selectedPolicyID,
40+ transactionPolicyID,
41+ transactionIDs,
42+ isManualDistanceRequest = false ,
43+ isOdometerDistanceRequest = false ,
44+ selectReport = jest . fn ( ) ,
45+ createReport,
46+ } : {
47+ selectedReportID : string ;
48+ selectedPolicyID ?: string ;
49+ transactionPolicyID ?: string ;
50+ transactionIDs ?: string [ ] ;
51+ isManualDistanceRequest ?: boolean ;
52+ isOdometerDistanceRequest ?: boolean ;
53+ selectReport ?: jest . Mock ;
54+ createReport ?: jest . Mock ;
55+ } ) =>
3356 render (
3457 < NavigationContainer >
3558 < ComposeProviders components = { [ OnyxListItemProvider , LocaleContextProvider ] } >
3659 < IOURequestEditReportCommon
3760 selectedReportID = { selectedReportID }
3861 selectedPolicyID = { selectedPolicyID }
39- selectReport = { jest . fn ( ) }
62+ transactionPolicyID = { transactionPolicyID }
63+ transactionIDs = { transactionIDs }
64+ isManualDistanceRequest = { isManualDistanceRequest }
65+ isOdometerDistanceRequest = { isOdometerDistanceRequest }
66+ selectReport = { selectReport }
67+ createReport = { createReport }
4068 backTo = ""
4169 isPerDiemRequest = { false }
4270 />
@@ -110,6 +138,76 @@ describe('IOURequestEditReportCommon', () => {
110138 const dotIndicators = screen . queryAllByTestId ( CONST . DOT_INDICATOR_TEST_ID ) ;
111139 expect ( dotIndicators ) . toHaveLength ( 0 ) ;
112140 } ) ;
141+
142+ const setUpCommuterExclusionTest = async ( ) => {
143+ const currentReport : Report = {
144+ reportID : 'currentReport' ,
145+ reportName : 'Current Report' ,
146+ ownerAccountID : FAKE_ACCOUNT_ID ,
147+ policyID : 'currentPolicy' ,
148+ } ;
149+ await act ( async ( ) => {
150+ await Onyx . set ( `${ ONYXKEYS . COLLECTION . REPORT } ${ currentReport . reportID } ` , currentReport ) ;
151+ await Onyx . set ( `${ ONYXKEYS . COLLECTION . POLICY } ${ FAKE_POLICY_ID } ` , {
152+ ...createRandomPolicy ( Number ( FAKE_POLICY_ID ) , CONST . POLICY . TYPE . TEAM ) ,
153+ role : CONST . POLICY . ROLE . ADMIN ,
154+ pendingAction : undefined ,
155+ commuterExclusions : {
156+ method : CONST . POLICY . COMMUTER_EXCLUSION_METHOD . FIXED_DISTANCE ,
157+ fixedDistance : 1 ,
158+ fixedDistanceUnit : CONST . CUSTOM_UNITS . DISTANCE_UNIT_MILES ,
159+ } ,
160+ } ) ;
161+ } ) ;
162+ await waitForBatchedUpdatesWithAct ( ) ;
163+
164+ return currentReport ;
165+ } ;
166+
167+ it . each ( [
168+ [ 'a manual' , { isManualDistanceRequest : true } ] ,
169+ [ 'an odometer' , { isOdometerDistanceRequest : true } ] ,
170+ ] ) ( 'blocks moving %s distance expense to a report with commuter exclusions' , async ( _distanceType , requestTypeProps ) => {
171+ const currentReport = await setUpCommuterExclusionTest ( ) ;
172+ const selectReport = jest . fn ( ) ;
173+
174+ renderIOURequestEditReportCommon ( { selectedReportID : currentReport . reportID , transactionIDs : [ FAKE_TRANSACTION_ID ] , selectReport, ...requestTypeProps } ) ;
175+ await waitForBatchedUpdatesWithAct ( ) ;
176+ fireEvent . press ( screen . getByText ( 'Expense Report' ) ) ;
177+
178+ expect ( mockShowConfirmModal ) . toHaveBeenCalledTimes ( 1 ) ;
179+ expect ( selectReport ) . not . toHaveBeenCalled ( ) ;
180+ } ) ;
181+
182+ it ( 'allows moving a GPS distance expense to a report with commuter exclusions' , async ( ) => {
183+ const currentReport = await setUpCommuterExclusionTest ( ) ;
184+ const selectReport = jest . fn ( ) ;
185+
186+ renderIOURequestEditReportCommon ( { selectedReportID : currentReport . reportID , transactionIDs : [ FAKE_TRANSACTION_ID ] , selectReport} ) ;
187+ await waitForBatchedUpdatesWithAct ( ) ;
188+ fireEvent . press ( screen . getByText ( 'Expense Report' ) ) ;
189+
190+ expect ( mockShowConfirmModal ) . not . toHaveBeenCalled ( ) ;
191+ expect ( selectReport ) . toHaveBeenCalledTimes ( 1 ) ;
192+ } ) ;
193+
194+ it ( 'blocks creating a report for a manual distance expense with commuter exclusions' , async ( ) => {
195+ const currentReport = await setUpCommuterExclusionTest ( ) ;
196+ const createReport = jest . fn ( ) ;
197+
198+ renderIOURequestEditReportCommon ( {
199+ selectedReportID : currentReport . reportID ,
200+ transactionPolicyID : FAKE_POLICY_ID ,
201+ transactionIDs : [ FAKE_TRANSACTION_ID ] ,
202+ isManualDistanceRequest : true ,
203+ createReport,
204+ } ) ;
205+ await waitForBatchedUpdatesWithAct ( ) ;
206+ fireEvent . press ( screen . getByText ( 'Create report' ) , { } ) ;
207+
208+ expect ( createReport ) . not . toHaveBeenCalled ( ) ;
209+ expect ( mockShowConfirmModal ) . toHaveBeenCalledTimes ( 1 ) ;
210+ } ) ;
113211 } ) ;
114212
115213 describe ( 'NotFound' , ( ) => {
0 commit comments