@@ -11,12 +11,14 @@ const mockGetReportOrDraftReport = jest.fn();
1111const mockDismissModal = jest . fn < ReturnType < DismissModal > , Parameters < DismissModal > > ( ) ;
1212const mockRevealRouteBeforeDismissingModal = jest . fn < ReturnType < RevealRouteBeforeDismissingModal > , Parameters < RevealRouteBeforeDismissingModal > > ( ) ;
1313const mockGetIsFullscreenPreInsertedUnderRHP = jest . fn < boolean , [ ] > ( ) ;
14+ const mockGetIsNarrowLayout = jest . fn < boolean , [ ] > ( ) ;
1415const mockReserveDeferredWriteChannel = jest . fn ( ) ;
1516const mockStartTracking = jest . fn ( ) ;
1617const mockSetFastPath = jest . fn ( ) ;
1718const mockSetPendingSubmitFollowUpAction = jest . fn ( ) ;
1819
1920jest . mock ( '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute' , ( ) => ( ) => mockIsSearchTopmostFullScreenRoute ( ) ) ;
21+ jest . mock ( '@libs/getIsNarrowLayout' , ( ) => ( ) => mockGetIsNarrowLayout ( ) ) ;
2022jest . mock ( '@libs/Navigation/Navigation' , ( ) => ( {
2123 dismissModal : mockDismissModal ,
2224 revealRouteBeforeDismissingModal : mockRevealRouteBeforeDismissingModal ,
@@ -52,6 +54,7 @@ describe('submitWithDismissFirst', () => {
5254 mockIsSearchTopmostFullScreenRoute . mockReturnValue ( false ) ;
5355 mockGetReportOrDraftReport . mockReturnValue ( undefined ) ;
5456 mockGetIsFullscreenPreInsertedUnderRHP . mockReturnValue ( false ) ;
57+ mockGetIsNarrowLayout . mockReturnValue ( false ) ;
5558 } ) ;
5659
5760 describe ( 'Search-topmost branch' , ( ) => {
@@ -201,10 +204,12 @@ describe('submitWithDismissFirst', () => {
201204 isSelfDMDestination : true ,
202205 } ;
203206
204- it ( 'hands navigation to the write instead of revealing the self-DM report' , ( ) => {
207+ it ( 'on wide layout hands navigation to the write instead of revealing the self-DM report' , ( ) => {
205208 // Without this branch the destination-report fast path reveals the self-DM and calls executeWrite with
206209 // shouldHandleNavigation: false, which makes cleanupAfterSkipConfirmSubmit drop the routing flags before
207- // navigateAfterExpenseCreate can route these users to Spend > Expenses.
210+ // navigateAfterExpenseCreate can route these users to Spend > Expenses. On wide layout navigateAfterExpenseCreate
211+ // reveals Search (which dismisses the modal itself), so no explicit dismiss happens here.
212+ mockGetIsNarrowLayout . mockReturnValue ( false ) ;
208213 mockGetReportOrDraftReport . mockReturnValue ( { reportID : 'selfDM1' } ) ;
209214 const executeWrite = jest . fn ( ) ;
210215
@@ -220,6 +225,34 @@ describe('submitWithDismissFirst', () => {
220225 expect ( mockDismissModal ) . not . toHaveBeenCalled ( ) ;
221226 } ) ;
222227
228+ it ( 'on narrow layout dismisses the modal first, then hands navigation to the write in afterTransition' , ( ) => {
229+ // Regression guard for https://github.com/Expensify/App/pull/97883: on narrow layout navigateAfterExpenseCreate
230+ // only switches the tab beneath the RHP, so the Create Expense modal must be dismissed here or the user is
231+ // stranded on an empty "Create Expense" page after a skip-confirmation (e.g. QAB scan) submit.
232+ mockGetIsNarrowLayout . mockReturnValue ( true ) ;
233+ mockGetReportOrDraftReport . mockReturnValue ( { reportID : 'selfDM1' } ) ;
234+ const executeWrite = jest . fn ( ) ;
235+
236+ submitWithDismissFirst ( {
237+ executeWrite,
238+ destinationReportID : 'selfDM1' ,
239+ telemetryContext : TELEMETRY_CONTEXT ,
240+ ...LOOKING_AROUND_SELF_DM ,
241+ } ) ;
242+
243+ expect ( mockDismissModal ) . toHaveBeenCalledTimes ( 1 ) ;
244+ expect ( mockRevealRouteBeforeDismissingModal ) . not . toHaveBeenCalled ( ) ;
245+ // The write is deferred until the modal transition completes.
246+ expect ( executeWrite ) . not . toHaveBeenCalled ( ) ;
247+
248+ const [ dismissOptions ] = mockDismissModal . mock . calls . at ( 0 ) ?? [ ] ;
249+ if ( ! dismissOptions ?. afterTransition ) {
250+ throw new Error ( 'Expected dismissModal afterTransition callback' ) ;
251+ }
252+ dismissOptions . afterTransition ( ) ;
253+ expect ( executeWrite ) . toHaveBeenCalledWith ( { shouldHandleNavigation : true } ) ;
254+ } ) ;
255+
223256 it ( 'still starts tracking so telemetry is not skipped' , ( ) => {
224257 mockGetReportOrDraftReport . mockReturnValue ( { reportID : 'selfDM1' } ) ;
225258
0 commit comments