diff --git a/src/libs/actions/Report/index.ts b/src/libs/actions/Report/index.ts index 0d160972372e..6039bd23dacc 100644 --- a/src/libs/actions/Report/index.ts +++ b/src/libs/actions/Report/index.ts @@ -2145,10 +2145,11 @@ function navigateToAndOpenChildReport( currentUserAccountID: number, introSelected: OnyxEntry, betas: OnyxEntry, + isSelfTourViewed: boolean | undefined, // TODO: personalDetails should be a required field in follow-up PRs https://github.com/Expensify/App/issues/73656 personalDetails?: OnyxEntry, ) { - const report = childReport ?? createChildReport(childReport, parentReportAction, parentReport, currentUserAccountID, introSelected, betas, personalDetails); + const report = childReport ?? createChildReport(childReport, parentReportAction, parentReport, currentUserAccountID, introSelected, betas, isSelfTourViewed, personalDetails); Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report.reportID, undefined, undefined, Navigation.getActiveRoute())); } @@ -2165,6 +2166,7 @@ function createChildReport( currentUserAccountID: number, introSelected: OnyxEntry, betas: OnyxEntry, + isSelfTourViewed: boolean | undefined, // TODO: personalDetails should be a required field in follow-up PRs https://github.com/Expensify/App/issues/73656 personalDetails?: OnyxEntry, ): Report { @@ -2210,6 +2212,7 @@ function createChildReport( parentReportActionID: parentReportAction.reportActionID, isNewThread: true, betas, + isSelfTourViewed, }); } else { Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${childReportID}`, newChat); @@ -2230,6 +2233,7 @@ function explain( currentUserAccountID: number, introSelected: OnyxEntry, betas: OnyxEntry, + isSelfTourViewed: boolean | undefined, delegateAccountID: number | undefined, timezone: Timezone = CONST.DEFAULT_TIME_ZONE, ) { @@ -2238,7 +2242,7 @@ function explain( } // Check if explanation thread report already exists - const report = childReport ?? createChildReport(childReport, reportAction, originalReport, currentUserAccountID, introSelected, betas); + const report = childReport ?? createChildReport(childReport, reportAction, originalReport, currentUserAccountID, introSelected, betas, isSelfTourViewed); Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(report.reportID, undefined, undefined, Navigation.getActiveRoute())); // Schedule adding the explanation comment on the next animation frame diff --git a/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx b/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx index 2629c98761fd..870f1f30ffd0 100644 --- a/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx @@ -445,16 +445,16 @@ const ContextMenuActions: ContextMenuAction[] = [ } return !shouldDisableThread(reportAction, isThreadReportParentAction, isArchivedRoom); }, - onPress: (closePopover, {reportAction, childReport, originalReport, currentUserAccountID, introSelected, betas}) => { + onPress: (closePopover, {reportAction, childReport, originalReport, currentUserAccountID, introSelected, isSelfTourViewed, betas}) => { if (closePopover) { hideContextMenu(false, () => { KeyboardUtils.dismiss().then(() => { - navigateToAndOpenChildReport(childReport, reportAction, originalReport, currentUserAccountID, introSelected, betas); + navigateToAndOpenChildReport(childReport, reportAction, originalReport, currentUserAccountID, introSelected, betas, isSelfTourViewed); }); }); return; } - navigateToAndOpenChildReport(childReport, reportAction, originalReport, currentUserAccountID, introSelected, betas); + navigateToAndOpenChildReport(childReport, reportAction, originalReport, currentUserAccountID, introSelected, betas, isSelfTourViewed); }, getDescription: () => {}, sentryLabel: CONST.SENTRY_LABEL.CONTEXT_MENU.REPLY_IN_THREAD, @@ -488,7 +488,7 @@ const ContextMenuActions: ContextMenuAction[] = [ return hasReasoning(reportAction); }, - onPress: (closePopover, {reportAction, childReport, originalReport, translate, currentUserPersonalDetails, introSelected, betas, delegateAccountID}) => { + onPress: (closePopover, {reportAction, childReport, originalReport, translate, currentUserPersonalDetails, introSelected, betas, isSelfTourViewed, delegateAccountID}) => { if (!originalReport?.reportID) { return; } @@ -504,6 +504,7 @@ const ContextMenuActions: ContextMenuAction[] = [ currentUserPersonalDetails.accountID, introSelected, betas, + isSelfTourViewed, delegateAccountID, currentUserPersonalDetails?.timezone, ); @@ -520,6 +521,7 @@ const ContextMenuActions: ContextMenuAction[] = [ currentUserPersonalDetails.accountID, introSelected, betas, + isSelfTourViewed, delegateAccountID, currentUserPersonalDetails?.timezone, ); diff --git a/src/pages/inbox/report/ReportActionItemMessageWithExplain.tsx b/src/pages/inbox/report/ReportActionItemMessageWithExplain.tsx index b849cc969aaa..99ad7411423b 100644 --- a/src/pages/inbox/report/ReportActionItemMessageWithExplain.tsx +++ b/src/pages/inbox/report/ReportActionItemMessageWithExplain.tsx @@ -1,3 +1,4 @@ +import {hasSeenTourSelector} from '@selectors/Onboarding'; import React from 'react'; import type {GestureResponderEvent} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; @@ -38,6 +39,7 @@ function ReportActionItemMessageWithExplain({message, action, childReport, origi const personalDetail = useCurrentUserPersonalDetails(); const {environmentURL} = useEnvironment(); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED); + const [isSelfTourViewed] = useOnyx(ONYXKEYS.NVP_ONBOARDING, {selector: hasSeenTourSelector}); const [betas] = useOnyx(ONYXKEYS.BETAS); const delegateAccountID = useDelegateAccountID(); @@ -47,7 +49,7 @@ function ReportActionItemMessageWithExplain({message, action, childReport, origi const handleLinkPress = (event: GestureResponderEvent | KeyboardEvent, href: string) => { // Handle the special "Explain" link if (href.endsWith(CONST.CONCIERGE_EXPLAIN_LINK_PATH)) { - explain(childReport, originalReport, action, translate, personalDetail.accountID, introSelected, betas, delegateAccountID, personalDetail?.timezone); + explain(childReport, originalReport, action, translate, personalDetail.accountID, introSelected, betas, isSelfTourViewed, delegateAccountID, personalDetail?.timezone); return; } diff --git a/src/pages/inbox/report/ReportActionItemThread.tsx b/src/pages/inbox/report/ReportActionItemThread.tsx index def30f62b538..81c54dd1da9c 100644 --- a/src/pages/inbox/report/ReportActionItemThread.tsx +++ b/src/pages/inbox/report/ReportActionItemThread.tsx @@ -1,3 +1,4 @@ +import {hasSeenTourSelector} from '@selectors/Onboarding'; import React from 'react'; import type {GestureResponderEvent} from 'react-native'; import {View} from 'react-native'; @@ -46,6 +47,7 @@ function ReportActionItemThread({numberOfReplies, accountIDs, mostRecentReply, r const {translate, datetimeToCalendarTime} = useLocalize(); const [childReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportAction.childReportID}`); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED); + const [isSelfTourViewed] = useOnyx(ONYXKEYS.NVP_ONBOARDING, {selector: hasSeenTourSelector}); const [betas] = useOnyx(ONYXKEYS.BETAS); const numberOfRepliesText = numberOfReplies > CONST.MAX_THREAD_REPLIES_PREVIEW ? `${CONST.MAX_THREAD_REPLIES_PREVIEW}+` : `${numberOfReplies}`; @@ -57,7 +59,7 @@ function ReportActionItemThread({numberOfReplies, accountIDs, mostRecentReply, r { - navigateToAndOpenChildReport(childReport, reportAction, report, currentUserAccountID, introSelected, betas); + navigateToAndOpenChildReport(childReport, reportAction, report, currentUserAccountID, introSelected, betas, isSelfTourViewed); }} role={CONST.ROLE.BUTTON} accessibilityLabel={`${numberOfReplies} ${replyText}`} diff --git a/tests/actions/ReportTest.ts b/tests/actions/ReportTest.ts index c6cf26b29e6f..4b183166215c 100644 --- a/tests/actions/ReportTest.ts +++ b/tests/actions/ReportTest.ts @@ -4829,7 +4829,7 @@ describe('actions/Report', () => { Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${PARENT_REPORT_ID}`, PARENT_REPORT); await waitForBatchedUpdates(); - Report.navigateToAndOpenChildReport(EXISTING_CHILD_REPORT, PARENT_REPORT_ACTION, PARENT_REPORT, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined); + Report.navigateToAndOpenChildReport(EXISTING_CHILD_REPORT, PARENT_REPORT_ACTION, PARENT_REPORT, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined, undefined); await waitForBatchedUpdates(); expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(EXISTING_CHILD_REPORT.reportID)); @@ -4848,7 +4848,7 @@ describe('actions/Report', () => { Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${PARENT_REPORT_ID}`, PARENT_REPORT); await waitForBatchedUpdates(); - Report.navigateToAndOpenChildReport(undefined, PARENT_REPORT_ACTION, PARENT_REPORT, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined); + Report.navigateToAndOpenChildReport(undefined, PARENT_REPORT_ACTION, PARENT_REPORT, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined, undefined); await waitForBatchedUpdates(); expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(MOCK_NEW_THREAD_REPORT_ID)); @@ -4863,7 +4863,7 @@ describe('actions/Report', () => { Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${PARENT_REPORT_ID}`, PARENT_REPORT); await waitForBatchedUpdates(); - Report.navigateToAndOpenChildReport(EXISTING_CHILD_REPORT, {} as OnyxTypes.ReportAction, PARENT_REPORT, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined); + Report.navigateToAndOpenChildReport(EXISTING_CHILD_REPORT, {} as OnyxTypes.ReportAction, PARENT_REPORT, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined, undefined); await waitForBatchedUpdates(); expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(EXISTING_CHILD_REPORT.reportID)); @@ -4882,7 +4882,7 @@ describe('actions/Report', () => { Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${PARENT_REPORT_ID}`, PARENT_REPORT); await waitForBatchedUpdates(); - Report.navigateToAndOpenChildReport(undefined, PARENT_REPORT_ACTION, PARENT_REPORT, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined); + Report.navigateToAndOpenChildReport(undefined, PARENT_REPORT_ACTION, PARENT_REPORT, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined, undefined); await waitForBatchedUpdates(); expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(MOCK_NEW_THREAD_REPORT_ID)); @@ -4901,7 +4901,7 @@ describe('actions/Report', () => { Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${PARENT_REPORT_ID}`, PARENT_REPORT); await waitForBatchedUpdates(); - Report.navigateToAndOpenChildReport(undefined, PARENT_REPORT_ACTION, PARENT_REPORT, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined); + Report.navigateToAndOpenChildReport(undefined, PARENT_REPORT_ACTION, PARENT_REPORT, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined, undefined); await waitForBatchedUpdates(); // Verify navigation happened with the new thread report @@ -4926,7 +4926,7 @@ describe('actions/Report', () => { Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${PARENT_REPORT_ID}`, PARENT_REPORT); await waitForBatchedUpdates(); - Report.navigateToAndOpenChildReport(EXISTING_CHILD_REPORT, PARENT_REPORT_ACTION, PARENT_REPORT, TEST_USER_ACCOUNT_ID, undefined, undefined); + Report.navigateToAndOpenChildReport(EXISTING_CHILD_REPORT, PARENT_REPORT_ACTION, PARENT_REPORT, TEST_USER_ACCOUNT_ID, undefined, undefined, undefined); await waitForBatchedUpdates(); expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(EXISTING_CHILD_REPORT.reportID)); @@ -4946,12 +4946,83 @@ describe('actions/Report', () => { Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${PARENT_REPORT_ID}`, PARENT_REPORT); await waitForBatchedUpdates(); - Report.navigateToAndOpenChildReport(undefined, PARENT_REPORT_ACTION, PARENT_REPORT, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, testBetas); + Report.navigateToAndOpenChildReport(undefined, PARENT_REPORT_ACTION, PARENT_REPORT, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, testBetas, undefined); await waitForBatchedUpdates(); TestHelper.expectAPICommandToHaveBeenCalled(WRITE_COMMANDS.OPEN_REPORT, 1); expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(MOCK_NEW_THREAD_REPORT_ID)); }); + + it.each<[boolean, 'defined' | 'undefined']>([ + [true, 'defined'], + [false, 'undefined'], + ])('should pass isSelfTourViewed=%s through to openReport so viewTour.completedTaskReportActionID is %s', async (isSelfTourViewed, expectation) => { + const CONCIERGE_REPORT_ID = '123456'; + const PARENT_REPORT = createRandomReport(1, undefined); + const PARENT_REPORT_ACTION: OnyxTypes.ReportAction = { + ...createRandomReportAction(REPORT_ACTION_ID), + reportActionID: '1', + actorAccountID: TEST_USER_ACCOUNT_ID, + }; + const introSelected: OnyxTypes.IntroSelected = {choice: CONST.ONBOARDING_CHOICES.SUBMIT, isInviteOnboardingComplete: false}; + + await TestHelper.signInWithTestUser(TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN); + await TestHelper.setPersonalDetails(TEST_USER_LOGIN, TEST_USER_ACCOUNT_ID); + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${CONCIERGE_REPORT_ID}`, { + reportID: CONCIERGE_REPORT_ID, + type: CONST.REPORT.TYPE.CHAT, + participants: { + [TEST_USER_ACCOUNT_ID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS}, + [CONST.ACCOUNT_ID.CONCIERGE]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS}, + }, + }); + await Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: false}); + Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${PARENT_REPORT_ID}`, PARENT_REPORT); + await waitForBatchedUpdates(); + + Report.navigateToAndOpenChildReport(undefined, PARENT_REPORT_ACTION, PARENT_REPORT, TEST_USER_ACCOUNT_ID, introSelected, undefined, isSelfTourViewed); + await waitForBatchedUpdates(); + + TestHelper.expectAPICommandToHaveBeenCalled(WRITE_COMMANDS.OPEN_REPORT, 1); + + const openReportCall = TestHelper.getFetchMockCalls(WRITE_COMMANDS.OPEN_REPORT).at(0); + const body = (openReportCall?.at(1) as RequestInit)?.body; + const guidedSetupDataParam = body instanceof FormData ? body.get('guidedSetupData') : null; + const guidedSetupData = JSON.parse(typeof guidedSetupDataParam === 'string' ? guidedSetupDataParam : '[]') as Array<{ + type: string; + task?: string; + completedTaskReportActionID?: string; + }>; + const viewTourTask = guidedSetupData.find((item) => item.type === 'task' && item.task === CONST.ONBOARDING_TASK_TYPE.VIEW_TOUR); + expect(viewTourTask).toBeDefined(); + if (expectation === 'defined') { + expect(viewTourTask?.completedTaskReportActionID).toBeDefined(); + } else { + expect(viewTourTask?.completedTaskReportActionID).toBeUndefined(); + } + + expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(MOCK_NEW_THREAD_REPORT_ID)); + }); + + it('should handle undefined isSelfTourViewed when navigating to existing child report', async () => { + const PARENT_REPORT = createRandomReport(1, undefined); + const EXISTING_CHILD_REPORT = createRandomReport(2, undefined); + const PARENT_REPORT_ACTION: OnyxTypes.ReportAction = { + ...createRandomReportAction(REPORT_ACTION_ID), + reportActionID: '1', + actorAccountID: TEST_USER_ACCOUNT_ID, + }; + + await TestHelper.signInWithTestUser(TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN); + Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${CHILD_REPORT_ID}`, EXISTING_CHILD_REPORT); + Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${PARENT_REPORT_ID}`, PARENT_REPORT); + await waitForBatchedUpdates(); + + Report.navigateToAndOpenChildReport(EXISTING_CHILD_REPORT, PARENT_REPORT_ACTION, PARENT_REPORT, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined, undefined); + await waitForBatchedUpdates(); + + expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(EXISTING_CHILD_REPORT.reportID)); + }); }); describe('explain', () => { @@ -4990,6 +5061,7 @@ describe('actions/Report', () => { INTRO_SELECTED, undefined, undefined, + undefined, CONST.DEFAULT_TIME_ZONE, ); @@ -4997,7 +5069,18 @@ describe('actions/Report', () => { }); it('should return early if reportAction is not provided', () => { - const result = Report.explain(undefined, undefined, undefined, TestHelper.translateLocal, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined, undefined, CONST.DEFAULT_TIME_ZONE); + const result = Report.explain( + undefined, + undefined, + undefined, + TestHelper.translateLocal, + TEST_USER_ACCOUNT_ID, + INTRO_SELECTED, + undefined, + undefined, + undefined, + CONST.DEFAULT_TIME_ZONE, + ); expect(result).toBeUndefined(); }); @@ -5025,6 +5108,7 @@ describe('actions/Report', () => { INTRO_SELECTED, undefined, undefined, + undefined, CONST.DEFAULT_TIME_ZONE, ); await waitForBatchedUpdates(); @@ -5045,7 +5129,18 @@ describe('actions/Report', () => { Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${PARENT_REPORT_ID}`, PARENT_REPORT); await waitForBatchedUpdates(); - Report.explain(undefined, PARENT_REPORT, REPORT_ACTION, TestHelper.translateLocal, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined, undefined, CONST.DEFAULT_TIME_ZONE); + Report.explain( + undefined, + PARENT_REPORT, + REPORT_ACTION, + TestHelper.translateLocal, + TEST_USER_ACCOUNT_ID, + INTRO_SELECTED, + undefined, + undefined, + undefined, + CONST.DEFAULT_TIME_ZONE, + ); await waitForBatchedUpdates(); expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(MOCK_NEW_THREAD_REPORT_ID)); @@ -5069,7 +5164,7 @@ describe('actions/Report', () => { Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${CHILD_REPORT_ID}`, EXISTING_CHILD_REPORT); await waitForBatchedUpdates(); - Report.explain(EXISTING_CHILD_REPORT, PARENT_REPORT, REPORT_ACTION, TestHelper.translateLocal, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined, undefined); + Report.explain(EXISTING_CHILD_REPORT, PARENT_REPORT, REPORT_ACTION, TestHelper.translateLocal, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, undefined, undefined, undefined); await waitForBatchedUpdates(); expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(EXISTING_CHILD_REPORT.reportID)); @@ -5089,7 +5184,18 @@ describe('actions/Report', () => { Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${CHILD_REPORT_ID}`, EXISTING_CHILD_REPORT); await waitForBatchedUpdates(); - Report.explain(EXISTING_CHILD_REPORT, PARENT_REPORT, REPORT_ACTION, TestHelper.translateLocal, TEST_USER_ACCOUNT_ID, undefined, undefined, undefined, CONST.DEFAULT_TIME_ZONE); + Report.explain( + EXISTING_CHILD_REPORT, + PARENT_REPORT, + REPORT_ACTION, + TestHelper.translateLocal, + TEST_USER_ACCOUNT_ID, + undefined, + undefined, + undefined, + undefined, + CONST.DEFAULT_TIME_ZONE, + ); await waitForBatchedUpdates(); expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(EXISTING_CHILD_REPORT.reportID)); @@ -5109,12 +5215,116 @@ describe('actions/Report', () => { Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${PARENT_REPORT_ID}`, PARENT_REPORT); await waitForBatchedUpdates(); - Report.explain(undefined, PARENT_REPORT, REPORT_ACTION, TestHelper.translateLocal, TEST_USER_ACCOUNT_ID, INTRO_SELECTED, testBetas, undefined, CONST.DEFAULT_TIME_ZONE); + Report.explain( + undefined, + PARENT_REPORT, + REPORT_ACTION, + TestHelper.translateLocal, + TEST_USER_ACCOUNT_ID, + INTRO_SELECTED, + testBetas, + undefined, + undefined, + CONST.DEFAULT_TIME_ZONE, + ); await waitForBatchedUpdates(); TestHelper.expectAPICommandToHaveBeenCalled(WRITE_COMMANDS.OPEN_REPORT, 1); expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(MOCK_NEW_THREAD_REPORT_ID)); }); + + it.each<[boolean, 'defined' | 'undefined']>([ + [true, 'defined'], + [false, 'undefined'], + ])('should pass isSelfTourViewed=%s through to createChildReport so viewTour.completedTaskReportActionID is %s', async (isSelfTourViewed, expectation) => { + const CONCIERGE_REPORT_ID = '123456'; + const introSelected: OnyxTypes.IntroSelected = {choice: CONST.ONBOARDING_CHOICES.SUBMIT, isInviteOnboardingComplete: false}; + const PARENT_REPORT = createRandomReport(1, undefined); + const REPORT_ACTION: OnyxTypes.ReportAction = { + ...createRandomReportAction(REPORT_ACTION_ID), + reportActionID: '1', + actorAccountID: TEST_USER_ACCOUNT_ID, + }; + + await TestHelper.signInWithTestUser(TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN); + await TestHelper.setPersonalDetails(TEST_USER_LOGIN, TEST_USER_ACCOUNT_ID); + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${CONCIERGE_REPORT_ID}`, { + reportID: CONCIERGE_REPORT_ID, + type: CONST.REPORT.TYPE.CHAT, + participants: { + [TEST_USER_ACCOUNT_ID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS}, + [CONST.ACCOUNT_ID.CONCIERGE]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS}, + }, + }); + await Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: false}); + Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${PARENT_REPORT_ID}`, PARENT_REPORT); + await waitForBatchedUpdates(); + + Report.explain( + undefined, + PARENT_REPORT, + REPORT_ACTION, + TestHelper.translateLocal, + TEST_USER_ACCOUNT_ID, + introSelected, + undefined, + isSelfTourViewed, + undefined, + CONST.DEFAULT_TIME_ZONE, + ); + await waitForBatchedUpdates(); + + TestHelper.expectAPICommandToHaveBeenCalled(WRITE_COMMANDS.OPEN_REPORT, 1); + + const openReportCall = TestHelper.getFetchMockCalls(WRITE_COMMANDS.OPEN_REPORT).at(0); + const body = (openReportCall?.at(1) as RequestInit)?.body; + const guidedSetupDataParam = body instanceof FormData ? body.get('guidedSetupData') : null; + const guidedSetupData = JSON.parse(typeof guidedSetupDataParam === 'string' ? guidedSetupDataParam : '[]') as Array<{ + type: string; + task?: string; + completedTaskReportActionID?: string; + }>; + const viewTourTask = guidedSetupData.find((item) => item.type === 'task' && item.task === CONST.ONBOARDING_TASK_TYPE.VIEW_TOUR); + expect(viewTourTask).toBeDefined(); + if (expectation === 'defined') { + expect(viewTourTask?.completedTaskReportActionID).toBeDefined(); + } else { + expect(viewTourTask?.completedTaskReportActionID).toBeUndefined(); + } + + expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(MOCK_NEW_THREAD_REPORT_ID)); + }); + + it('should handle undefined isSelfTourViewed when navigating to existing explain thread', async () => { + const PARENT_REPORT = createRandomReport(1, undefined); + const EXISTING_CHILD_REPORT = createRandomReport(2, undefined); + const REPORT_ACTION: OnyxTypes.ReportAction = { + ...createRandomReportAction(REPORT_ACTION_ID), + reportActionID: '1', + actorAccountID: TEST_USER_ACCOUNT_ID, + childReportID: CHILD_REPORT_ID, + }; + + await TestHelper.signInWithTestUser(TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN); + Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${CHILD_REPORT_ID}`, EXISTING_CHILD_REPORT); + await waitForBatchedUpdates(); + + Report.explain( + EXISTING_CHILD_REPORT, + PARENT_REPORT, + REPORT_ACTION, + TestHelper.translateLocal, + TEST_USER_ACCOUNT_ID, + INTRO_SELECTED, + undefined, + undefined, + undefined, + CONST.DEFAULT_TIME_ZONE, + ); + await waitForBatchedUpdates(); + + expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute(EXISTING_CHILD_REPORT.reportID)); + }); }); describe('toggleSubscribeToChildReport', () => {