@@ -2,12 +2,20 @@ import type {RouteProp} from '@react-navigation/native';
22import { fireEvent , render , screen } from '@testing-library/react-native' ;
33import React from 'react' ;
44import Navigation from '@libs/Navigation/Navigation' ;
5+ import { isReportActionVisible } from '@libs/ReportActionsUtils' ;
56import ParentNavigationSubtitle from '../../src/components/ParentNavigationSubtitle' ;
7+ import NAVIGATORS from '../../src/NAVIGATORS' ;
8+ import SCREENS from '../../src/SCREENS' ;
69
710jest . mock ( '@libs/Navigation/Navigation' ) ;
811
12+ jest . mock ( '@libs/ReportActionsUtils' , ( ) => ( {
13+ getReportAction : jest . fn ( ( ) => undefined ) ,
14+ isReportActionVisible : jest . fn ( ( ) => false ) ,
15+ } ) ) ;
16+
917const mockUseRootNavigationState = jest . fn ( ) ;
10- jest . mock ( '@src/ hooks/useRootNavigationState' , ( ) => ( {
18+ jest . mock ( '@hooks/useRootNavigationState' , ( ) => ( {
1119 // eslint-disable-next-line @typescript-eslint/naming-convention
1220 __esModule : true ,
1321 default : ( selector ?: ( state : unknown ) => unknown ) => mockUseRootNavigationState ( selector ) as unknown ,
@@ -24,11 +32,51 @@ jest.mock('@react-navigation/native', () => {
2432 } ;
2533} ) ;
2634
35+ /** Root state with TabNavigator → Reports split stack [parent DM, expense]; index on expense (matches issue #88499 stack). */
36+ function getMockRootStateWithReportsSplitStack ( parentReportID : string , expenseReportID : string ) {
37+ const parentRoute = {
38+ name : SCREENS . REPORT ,
39+ params : { reportID : parentReportID } ,
40+ key : 'route-parent-key' ,
41+ } ;
42+ const expenseRoute = {
43+ name : SCREENS . REPORT ,
44+ params : { reportID : expenseReportID } ,
45+ key : 'route-expense-key' ,
46+ } ;
47+ return {
48+ routes : [
49+ {
50+ name : NAVIGATORS . TAB_NAVIGATOR ,
51+ key : 'tab-root-key' ,
52+ state : {
53+ index : 0 ,
54+ routes : [
55+ {
56+ name : NAVIGATORS . REPORTS_SPLIT_NAVIGATOR ,
57+ key : 'reports-split-route-key' ,
58+ state : {
59+ key : 'reports-split-state-key' ,
60+ index : 1 ,
61+ routes : [ parentRoute , expenseRoute ] ,
62+ } ,
63+ } ,
64+ ] ,
65+ } ,
66+ } ,
67+ ] ,
68+ } ;
69+ }
70+
2771describe ( 'ParentNavigationSubtitle' , ( ) => {
2872 beforeEach ( ( ) => {
2973 jest . clearAllMocks ( ) ;
74+ jest . mocked ( isReportActionVisible ) . mockReturnValue ( false ) ;
3075 Navigation . getTopmostReportId = jest . fn ( ) ;
3176 Navigation . dismissModal = jest . fn ( ) ;
77+ Navigation . goBack = jest . fn ( ) ;
78+ Navigation . setParams = jest . fn ( ) ;
79+ Navigation . navigate = jest . fn ( ) ;
3280 } ) ;
3381
3482 it ( 'if the parent report is already displayed underneath RHP, simply dismiss the modal' , ( ) => {
@@ -130,4 +178,109 @@ describe('ParentNavigationSubtitle', () => {
130178 fireEvent ( clickableElement , 'press' , mockEvent ) ;
131179 expect ( Navigation . dismissModal ) . not . toHaveBeenCalled ( ) ;
132180 } ) ;
181+
182+ it ( 'goes back without navigating when parent report is already the previous route in Reports split stack under Tab navigator' , ( ) => {
183+ const parentReportID = 'parent-report' ;
184+ const expenseReportID = 'expense-report' ;
185+ const reportName = 'Parent chat' ;
186+ const workspaceName = 'Workspace' ;
187+
188+ mockUseRoute . mockReturnValue ( { name : SCREENS . REPORT } as AnyRoute ) ;
189+ mockUseRootNavigationState . mockImplementation ( ( selector ?: ( state : unknown ) => unknown ) => {
190+ const mockState = getMockRootStateWithReportsSplitStack ( parentReportID , expenseReportID ) ;
191+ if ( selector ) {
192+ return selector ( mockState ) ;
193+ }
194+ return undefined ;
195+ } ) ;
196+
197+ render (
198+ < ParentNavigationSubtitle
199+ parentNavigationSubtitleData = { { reportName, workspaceName} }
200+ parentReportID = { parentReportID }
201+ reportID = { expenseReportID }
202+ /> ,
203+ ) ;
204+
205+ fireEvent ( screen . getByTestId ( 'parent-navigation-subtitle-link' ) , 'press' , {
206+ preventDefault : jest . fn ( ) ,
207+ stopPropagation : jest . fn ( ) ,
208+ nativeEvent : { } ,
209+ } ) ;
210+
211+ expect ( Navigation . goBack ) . toHaveBeenCalled ( ) ;
212+ expect ( Navigation . navigate ) . not . toHaveBeenCalled ( ) ;
213+ expect ( Navigation . setParams ) . not . toHaveBeenCalled ( ) ;
214+ } ) ;
215+
216+ it ( 'sets reportActionID on the previous route then goes back when the parent action is visible' , ( ) => {
217+ const parentReportID = 'parent-report' ;
218+ const expenseReportID = 'expense-report' ;
219+ const parentReportActionID = 'action-999' ;
220+ const reportName = 'Parent chat' ;
221+ const workspaceName = 'Workspace' ;
222+
223+ jest . mocked ( isReportActionVisible ) . mockReturnValue ( true ) ;
224+
225+ mockUseRoute . mockReturnValue ( { name : SCREENS . REPORT } as AnyRoute ) ;
226+ mockUseRootNavigationState . mockImplementation ( ( selector ?: ( state : unknown ) => unknown ) => {
227+ const mockState = getMockRootStateWithReportsSplitStack ( parentReportID , expenseReportID ) ;
228+ if ( selector ) {
229+ return selector ( mockState ) ;
230+ }
231+ return undefined ;
232+ } ) ;
233+
234+ render (
235+ < ParentNavigationSubtitle
236+ parentNavigationSubtitleData = { { reportName, workspaceName} }
237+ parentReportID = { parentReportID }
238+ parentReportActionID = { parentReportActionID }
239+ reportID = { expenseReportID }
240+ /> ,
241+ ) ;
242+
243+ fireEvent ( screen . getByTestId ( 'parent-navigation-subtitle-link' ) , 'press' , {
244+ preventDefault : jest . fn ( ) ,
245+ stopPropagation : jest . fn ( ) ,
246+ nativeEvent : { } ,
247+ } ) ;
248+
249+ expect ( Navigation . setParams ) . toHaveBeenCalledWith ( { reportActionID : parentReportActionID } , 'route-parent-key' , 'reports-split-state-key' ) ;
250+ expect ( Navigation . goBack ) . toHaveBeenCalled ( ) ;
251+ expect ( Navigation . navigate ) . not . toHaveBeenCalled ( ) ;
252+ } ) ;
253+
254+ it ( 'navigates forward when the previous stack route is not the parent report' , ( ) => {
255+ const parentReportID = 'parent-report' ;
256+ const expenseReportID = 'expense-report' ;
257+ const reportName = 'Parent chat' ;
258+ const workspaceName = 'Workspace' ;
259+
260+ mockUseRoute . mockReturnValue ( { name : SCREENS . REPORT } as AnyRoute ) ;
261+ mockUseRootNavigationState . mockImplementation ( ( selector ?: ( state : unknown ) => unknown ) => {
262+ const mockState = getMockRootStateWithReportsSplitStack ( 'other-report' , expenseReportID ) ;
263+ if ( selector ) {
264+ return selector ( mockState ) ;
265+ }
266+ return undefined ;
267+ } ) ;
268+
269+ render (
270+ < ParentNavigationSubtitle
271+ parentNavigationSubtitleData = { { reportName, workspaceName} }
272+ parentReportID = { parentReportID }
273+ reportID = { expenseReportID }
274+ /> ,
275+ ) ;
276+
277+ fireEvent ( screen . getByTestId ( 'parent-navigation-subtitle-link' ) , 'press' , {
278+ preventDefault : jest . fn ( ) ,
279+ stopPropagation : jest . fn ( ) ,
280+ nativeEvent : { } ,
281+ } ) ;
282+
283+ expect ( Navigation . goBack ) . not . toHaveBeenCalled ( ) ;
284+ expect ( Navigation . navigate ) . toHaveBeenCalled ( ) ;
285+ } ) ;
133286} ) ;
0 commit comments