@@ -21,6 +21,7 @@ const TRANSACTION_ID = 'transaction1';
2121const CONFIRMATION_TEST_ID = 'EmbeddedConfirmation' ;
2222const LOADER_TEST_ID = 'manualTabPendingReset' ;
2323const AMOUNT_TEST_ID = 'EmbeddedAmount' ;
24+ const CURRENT_USER_EMAIL = 'invoice.sender@example.com' ;
2425
2526jest . mock ( '@userActions/Tab' ) ;
2627jest . mock ( '@rnmapbox/maps' , ( ) => ( {
@@ -87,10 +88,21 @@ describe('IOURequestStartPage manual tab content', () => {
8788 } ) ;
8889 } ) ;
8990
91+ type RenderStartPageOptions = {
92+ /** The request type the shared draft still carries when the page mounts. */
93+ iouRequestType : IOURequestType ;
94+
95+ /** The flow the page is started for - this is what decides whether tabs are rendered. */
96+ iouType ?: IOUType ;
97+
98+ /** Whether the new manual expense flow beta is on. */
99+ isNewManualExpenseFlowEnabled ?: boolean ;
100+ } ;
101+
90102 /**
91103 * Seeds the beta, the manual tab selection and a draft transaction of the given request type, then renders the page.
92104 */
93- async function renderStartPageWithDraftType ( iouRequestType : IOURequestType , iouType : IOUType = CONST . IOU . TYPE . SUBMIT , isNewManualExpenseFlowEnabled = true ) {
105+ async function renderStartPage ( { iouRequestType, iouType = CONST . IOU . TYPE . SUBMIT , isNewManualExpenseFlowEnabled = true } : RenderStartPageOptions ) {
94106 await act ( async ( ) => {
95107 await Onyx . set ( ONYXKEYS . BETAS , isNewManualExpenseFlowEnabled ? [ CONST . BETAS . NEW_MANUAL_EXPENSE_FLOW ] : [ ] ) ;
96108 await Onyx . set ( `${ ONYXKEYS . COLLECTION . SELECTED_TAB } ${ CONST . TAB . IOU_REQUEST_TYPE } ` , CONST . TAB_REQUEST . MANUAL ) ;
@@ -130,7 +142,7 @@ describe('IOURequestStartPage manual tab content', () => {
130142
131143 it ( 'shows a loader instead of the embedded confirmation while a per diem draft is still pending its reset to manual' , async ( ) => {
132144 // Given the new manual expense flow beta and a draft that is still a per diem request
133- await renderStartPageWithDraftType ( CONST . IOU . REQUEST_TYPE . PER_DIEM ) ;
145+ await renderStartPage ( { iouRequestType : CONST . IOU . REQUEST_TYPE . PER_DIEM } ) ;
134146
135147 // Then the manual tab waits for the reset instead of mounting the confirmation against the per diem draft
136148 expect ( screen . getByTestId ( LOADER_TEST_ID ) ) . toBeOnTheScreen ( ) ;
@@ -139,7 +151,7 @@ describe('IOURequestStartPage manual tab content', () => {
139151
140152 it ( 'shows a loader instead of the embedded confirmation while a scan draft is still pending its reset to manual' , async ( ) => {
141153 // Given the new manual expense flow beta and a draft that is still a scan request
142- await renderStartPageWithDraftType ( CONST . IOU . REQUEST_TYPE . SCAN ) ;
154+ await renderStartPage ( { iouRequestType : CONST . IOU . REQUEST_TYPE . SCAN } ) ;
143155
144156 // Then the manual tab waits for the reset instead of mounting the confirmation against the scan draft
145157 expect ( screen . getByTestId ( LOADER_TEST_ID ) ) . toBeOnTheScreen ( ) ;
@@ -148,7 +160,7 @@ describe('IOURequestStartPage manual tab content', () => {
148160
149161 it ( 'shows the embedded confirmation once the draft is a manual request' , async ( ) => {
150162 // Given the new manual expense flow beta and a draft that has been reset to a manual request
151- await renderStartPageWithDraftType ( CONST . IOU . REQUEST_TYPE . MANUAL ) ;
163+ await renderStartPage ( { iouRequestType : CONST . IOU . REQUEST_TYPE . MANUAL } ) ;
152164
153165 // Then the confirmation is mounted and the pending-reset loader is gone
154166 expect ( screen . getByTestId ( CONFIRMATION_TEST_ID ) ) . toBeOnTheScreen ( ) ;
@@ -157,16 +169,45 @@ describe('IOURequestStartPage manual tab content', () => {
157169
158170 it ( 'lands the tab-less pay flow directly on the embedded confirmation instead of the amount page' , async ( ) => {
159171 // Given the new manual expense flow beta and a pay flow, which renders no tabs
160- await renderStartPageWithDraftType ( CONST . IOU . REQUEST_TYPE . MANUAL , CONST . IOU . TYPE . PAY ) ;
172+ await renderStartPage ( { iouRequestType : CONST . IOU . REQUEST_TYPE . MANUAL , iouType : CONST . IOU . TYPE . PAY } ) ;
161173
162174 // Then the details page is the landing page, so the amount page is never shown first
163175 expect ( screen . getByTestId ( CONFIRMATION_TEST_ID ) ) . toBeOnTheScreen ( ) ;
164176 expect ( screen . queryByTestId ( AMOUNT_TEST_ID ) ) . not . toBeOnTheScreen ( ) ;
165177 } ) ;
166178
179+ it ( 'does not strand the tab-less pay flow on the pending-reset loader when the draft is still a scan request' , async ( ) => {
180+ // Given a pay flow that mounts against a leftover scan draft from an earlier expense in the same chat
181+ await renderStartPage ( { iouRequestType : CONST . IOU . REQUEST_TYPE . SCAN , iouType : CONST . IOU . TYPE . PAY } ) ;
182+
183+ // Then the confirmation mounts anyway - the pay flow renders no tabs, so the reset the loader waits on never runs
184+ expect ( screen . getByTestId ( CONFIRMATION_TEST_ID ) ) . toBeOnTheScreen ( ) ;
185+ expect ( screen . queryByTestId ( LOADER_TEST_ID ) ) . not . toBeOnTheScreen ( ) ;
186+ } ) ;
187+
188+ it ( 'keeps the amount page as the landing page for the invoice flow' , async ( ) => {
189+ // Given an invoice flow, which is the one type left off the embedded confirmation
190+ await act ( async ( ) => {
191+ // AccessOrNotFoundWrapper gates the invoice flow behind an admin workspace that can send invoices.
192+ await Onyx . set ( ONYXKEYS . SESSION , { email : CURRENT_USER_EMAIL , accountID : 1 } ) ;
193+ await Onyx . set ( `${ ONYXKEYS . COLLECTION . POLICY } policy1` , {
194+ id : 'policy1' ,
195+ name : 'Invoice workspace' ,
196+ type : CONST . POLICY . TYPE . TEAM ,
197+ role : CONST . POLICY . ROLE . ADMIN ,
198+ areInvoicesEnabled : true ,
199+ } ) ;
200+ } ) ;
201+ await renderStartPage ( { iouRequestType : CONST . IOU . REQUEST_TYPE . MANUAL , iouType : CONST . IOU . TYPE . INVOICE } ) ;
202+
203+ // Then it still lands on the amount page first
204+ expect ( screen . getByTestId ( AMOUNT_TEST_ID ) ) . toBeOnTheScreen ( ) ;
205+ expect ( screen . queryByTestId ( CONFIRMATION_TEST_ID ) ) . not . toBeOnTheScreen ( ) ;
206+ } ) ;
207+
167208 it ( 'keeps the amount page as the landing page for the pay flow when the beta is off' , async ( ) => {
168209 // Given a pay flow started without the new manual expense flow beta
169- await renderStartPageWithDraftType ( CONST . IOU . REQUEST_TYPE . MANUAL , CONST . IOU . TYPE . PAY , false ) ;
210+ await renderStartPage ( { iouRequestType : CONST . IOU . REQUEST_TYPE . MANUAL , iouType : CONST . IOU . TYPE . PAY , isNewManualExpenseFlowEnabled : false } ) ;
170211
171212 // Then the legacy amount-first flow is preserved
172213 expect ( screen . getByTestId ( AMOUNT_TEST_ID ) ) . toBeOnTheScreen ( ) ;
0 commit comments