diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index 33ecdb4d80635..8b7b75d36ecec 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -11835,6 +11835,7 @@ function completePaymentOnboarding( wasInvited: true, shouldSkipTestDriveModal: true, companySize: introSelected?.companySize as OnboardingCompanySize, + introSelected, }); } diff --git a/src/libs/actions/Report/index.ts b/src/libs/actions/Report/index.ts index 569edf4e1d3d4..eabb7950b78a6 100644 --- a/src/libs/actions/Report/index.ts +++ b/src/libs/actions/Report/index.ts @@ -1299,8 +1299,8 @@ function openReport( // Prepare guided setup data only when nvp_introSelected is set and onboarding is not completed // OldDot users will never have nvp_introSelected set, so they will not see guided setup messages - if (introSelected && !isOnboardingCompleted && !isInviteOnboardingComplete && !hasOpenReportWithGuidedSetupData) { - const {choice, inviteType} = introSelected; + if (deprecatedIntroSelected && !isOnboardingCompleted && !isInviteOnboardingComplete && !hasOpenReportWithGuidedSetupData) { + const {choice, inviteType} = deprecatedIntroSelected; const isInviteIOUorInvoice = inviteType === CONST.ONBOARDING_INVITE_TYPES.IOU || inviteType === CONST.ONBOARDING_INVITE_TYPES.INVOICE; const isInviteChoiceCorrect = choice === CONST.ONBOARDING_CHOICES.ADMIN || choice === CONST.ONBOARDING_CHOICES.SUBMIT || choice === CONST.ONBOARDING_CHOICES.CHAT_SPLIT; @@ -1312,10 +1312,10 @@ function openReport( } const onboardingData = prepareOnboardingOnyxData({ - introSelected, + introSelected: deprecatedIntroSelected, engagementChoice: choice, onboardingMessage, - companySize: introSelected?.companySize as OnboardingCompanySize, + companySize: deprecatedIntroSelected?.companySize as OnboardingCompanySize, }); if (onboardingData) { @@ -4537,6 +4537,7 @@ type CompleteOnboardingProps = { isInvitedAccountant?: boolean; onboardingPurposeSelected?: OnboardingPurpose; shouldWaitForRHPVariantInitialization?: boolean; + introSelected: OnyxEntry; }; async function completeOnboarding({ @@ -4555,9 +4556,10 @@ async function completeOnboarding({ isInvitedAccountant, onboardingPurposeSelected, shouldWaitForRHPVariantInitialization = false, + introSelected, }: CompleteOnboardingProps) { const onboardingData = prepareOnboardingOnyxData({ - introSelected: deprecatedIntroSelected, + introSelected, engagementChoice, onboardingMessage, adminsChatReportID, diff --git a/src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx b/src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx index 9251daf5d1360..1e478dd8d4fcb 100644 --- a/src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx +++ b/src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx @@ -219,6 +219,7 @@ function BaseOnboardingInterestedFeatures({shouldUseNativeStyles}: BaseOnboardin selectedInterestedFeatures: featuresMap.filter((feature) => feature.enabled).map((feature) => feature.id), shouldSkipTestDriveModal: !!policyID && !adminsChatReportID, shouldWaitForRHPVariantInitialization: isSidePanelReportSupported, + introSelected, }); // Avoid creating new WS because onboardingPolicyID is cleared before unmounting diff --git a/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx b/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx index 1b33506f6c3e8..4e2f3c350ab98 100644 --- a/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx +++ b/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx @@ -39,6 +39,7 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat const [onboardingPolicyID] = useOnyx(ONYXKEYS.ONBOARDING_POLICY_ID, {canBeMissing: true}); const [onboardingAdminsChatReportID] = useOnyx(ONYXKEYS.ONBOARDING_ADMINS_CHAT_REPORT_ID, {canBeMissing: true}); const [account] = useOnyx(ONYXKEYS.ACCOUNT, {canBeMissing: true}); + const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const archivedReportsIdSet = useArchivedReportsIdSet(); const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST, {canBeMissing: true}); const [onboardingValues] = useOnyx(ONYXKEYS.NVP_ONBOARDING, {canBeMissing: true}); @@ -80,6 +81,7 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat adminsChatReportID: onboardingAdminsChatReportID, onboardingPolicyID, shouldSkipTestDriveModal: !!onboardingPolicyID && !mergedAccountConciergeReportID, + introSelected, }); setOnboardingAdminsChatReportID(); @@ -105,6 +107,7 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat isSmallScreenWidth, mergedAccountConciergeReportID, conciergeChatReportID, + introSelected, ], ); diff --git a/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx b/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx index 18fcb3f9f670d..690cbc0d5f081 100644 --- a/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx +++ b/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx @@ -66,6 +66,7 @@ function BaseOnboardingPurpose({shouldUseNativeStyles, shouldEnableMaxHeight, ro const [onboardingAdminsChatReportID] = useOnyx(ONYXKEYS.ONBOARDING_ADMINS_CHAT_REPORT_ID, {canBeMissing: true}); const [personalDetailsForm] = useOnyx(ONYXKEYS.FORMS.ONBOARDING_PERSONAL_DETAILS_FORM, {canBeMissing: true}); const [onboardingCompanySize] = useOnyx(ONYXKEYS.ONBOARDING_COMPANY_SIZE, {canBeMissing: true}); + const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const paddingHorizontal = onboardingIsMediumOrLargerScreenWidth ? styles.ph8 : styles.ph5; const [customChoices = getEmptyArray()] = useOnyx(ONYXKEYS.ONBOARDING_CUSTOM_CHOICES, {canBeMissing: true}); @@ -105,6 +106,7 @@ function BaseOnboardingPurpose({shouldUseNativeStyles, shouldEnableMaxHeight, ro adminsChatReportID: onboardingAdminsChatReportID ?? undefined, onboardingPolicyID, companySize: onboardingCompanySize, + introSelected, }); // eslint-disable-next-line @typescript-eslint/no-deprecated diff --git a/src/pages/OnboardingWorkspaceInvite/BaseOnboardingWorkspaceInvite.tsx b/src/pages/OnboardingWorkspaceInvite/BaseOnboardingWorkspaceInvite.tsx index a58b2f10025cd..630860d987697 100644 --- a/src/pages/OnboardingWorkspaceInvite/BaseOnboardingWorkspaceInvite.tsx +++ b/src/pages/OnboardingWorkspaceInvite/BaseOnboardingWorkspaceInvite.tsx @@ -46,6 +46,7 @@ function BaseOnboardingWorkspaceInvite({shouldUseNativeStyles}: BaseOnboardingWo const [onboardingPolicyID] = useOnyx(ONYXKEYS.ONBOARDING_POLICY_ID, {canBeMissing: true}); const [onboardingAdminsChatReportID] = useOnyx(ONYXKEYS.ONBOARDING_ADMINS_CHAT_REPORT_ID, {canBeMissing: true}); const [onboardingPurposeSelected] = useOnyx(ONYXKEYS.ONBOARDING_PURPOSE_SELECTED, {canBeMissing: true}); + const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const policy = usePolicy(onboardingPolicyID); const {onboardingMessages} = useOnboardingMessages(); // We need to use isSmallScreenWidth, see navigateAfterOnboarding function comment @@ -130,6 +131,7 @@ function BaseOnboardingWorkspaceInvite({shouldUseNativeStyles}: BaseOnboardingWo shouldSkipTestDriveModal: !!onboardingPolicyID && !onboardingAdminsChatReportID, isInvitedAccountant, onboardingPurposeSelected, + introSelected, }); setOnboardingAdminsChatReportID(); diff --git a/src/pages/OnboardingWorkspaceOptional/BaseOnboardingWorkspaceOptional.tsx b/src/pages/OnboardingWorkspaceOptional/BaseOnboardingWorkspaceOptional.tsx index 56b0f8ce64626..708c918efe59e 100644 --- a/src/pages/OnboardingWorkspaceOptional/BaseOnboardingWorkspaceOptional.tsx +++ b/src/pages/OnboardingWorkspaceOptional/BaseOnboardingWorkspaceOptional.tsx @@ -42,6 +42,7 @@ function BaseOnboardingWorkspaceOptional({shouldUseNativeStyles}: BaseOnboarding const [conciergeChatReportID = ''] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID, {canBeMissing: true}); const archivedReportsIdSet = useArchivedReportsIdSet(); const {onboardingMessages} = useOnboardingMessages(); + const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const {isRestrictedPolicyCreation} = usePreferredPolicy(); // When we merge public email with work email, we now want to navigate to the // concierge chat report of the new work email and not the last accessed report. @@ -88,6 +89,7 @@ function BaseOnboardingWorkspaceOptional({shouldUseNativeStyles}: BaseOnboarding adminsChatReportID: onboardingAdminsChatReportID, onboardingPolicyID, shouldSkipTestDriveModal: !!onboardingPolicyID && !onboardingAdminsChatReportID, + introSelected, }); setOnboardingAdminsChatReportID(); @@ -113,6 +115,7 @@ function BaseOnboardingWorkspaceOptional({shouldUseNativeStyles}: BaseOnboarding isSmallScreenWidth, isBetaEnabled, mergedAccountConciergeReportID, + introSelected, conciergeChatReportID, ]); diff --git a/src/pages/OnboardingWorkspaces/BaseOnboardingWorkspaces.tsx b/src/pages/OnboardingWorkspaces/BaseOnboardingWorkspaces.tsx index 4edc17f88eea5..7aefa58fcf43d 100644 --- a/src/pages/OnboardingWorkspaces/BaseOnboardingWorkspaces.tsx +++ b/src/pages/OnboardingWorkspaces/BaseOnboardingWorkspaces.tsx @@ -50,6 +50,7 @@ function BaseOnboardingWorkspaces({route, shouldUseNativeStyles}: BaseOnboarding const [onboardingCompanySize] = useOnyx(ONYXKEYS.ONBOARDING_COMPANY_SIZE, {canBeMissing: true}); const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST, {canBeMissing: true}); const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: true}); + const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const archivedReportsIdSet = useArchivedReportsIdSet(); const isValidated = isCurrentUserValidated(loginList, session?.email); @@ -75,6 +76,7 @@ function BaseOnboardingWorkspaces({route, shouldUseNativeStyles}: BaseOnboarding lastName: onboardingPersonalDetails?.lastName ?? '', shouldSkipTestDriveModal: !!(policy.automaticJoiningEnabled ? policy.policyID : undefined), companySize: onboardingCompanySize, + introSelected, }); setOnboardingAdminsChatReportID(); setOnboardingPolicyID(policy.policyID); @@ -89,7 +91,16 @@ function BaseOnboardingWorkspaces({route, shouldUseNativeStyles}: BaseOnboarding false, ); }, - [onboardingMessages, onboardingPersonalDetails?.firstName, onboardingPersonalDetails?.lastName, isSmallScreenWidth, isBetaEnabled, onboardingCompanySize, archivedReportsIdSet], + [ + onboardingMessages, + onboardingPersonalDetails?.firstName, + onboardingPersonalDetails?.lastName, + isSmallScreenWidth, + isBetaEnabled, + onboardingCompanySize, + archivedReportsIdSet, + introSelected, + ], ); const policyIDItems = useMemo(() => { diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 55dfdaac81cf6..750a5446b635b 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -18,6 +18,7 @@ import { cancelPayment, canIOUBePaid, canUnapproveIOU, + completePaymentOnboarding, convertBulkTrackedExpensesToIOU, createDistanceRequest, deleteMoneyRequest, @@ -14955,4 +14956,142 @@ describe('actions/IOU', () => { }).not.toThrow(); }); }); + + describe('completePaymentOnboarding', () => { + let completeOnboardingSpy: jest.SpyInstance; + + beforeEach(async () => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + completeOnboardingSpy = jest.spyOn(require('@libs/actions/Report'), 'completeOnboarding').mockImplementation(jest.fn()); + await Onyx.set(ONYXKEYS.SESSION, {email: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}); + await Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, { + [CARLOS_ACCOUNT_ID]: { + accountID: CARLOS_ACCOUNT_ID, + firstName: 'Carlos', + lastName: 'Test', + }, + }); + await waitForBatchedUpdates(); + }); + + afterEach(() => { + completeOnboardingSpy.mockRestore(); + }); + + it('should not call completeOnboarding when introSelected is undefined', () => { + completePaymentOnboarding(CONST.PAYMENT_SELECTED.BBA, undefined); + expect(completeOnboardingSpy).not.toHaveBeenCalled(); + }); + + it('should not call completeOnboarding when isInviteOnboardingComplete is true', () => { + completePaymentOnboarding(CONST.PAYMENT_SELECTED.BBA, { + choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM, + inviteType: CONST.ONBOARDING_INVITE_TYPES.IOU, + isInviteOnboardingComplete: true, + }); + expect(completeOnboardingSpy).not.toHaveBeenCalled(); + }); + + it('should not call completeOnboarding when choice is missing', () => { + completePaymentOnboarding(CONST.PAYMENT_SELECTED.BBA, { + inviteType: CONST.ONBOARDING_INVITE_TYPES.IOU, + }); + expect(completeOnboardingSpy).not.toHaveBeenCalled(); + }); + + it('should not call completeOnboarding when inviteType is missing', () => { + completePaymentOnboarding(CONST.PAYMENT_SELECTED.BBA, { + choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM, + }); + expect(completeOnboardingSpy).not.toHaveBeenCalled(); + }); + + it('should override purpose to MANAGE_TEAM for IOU invite with BBA payment', () => { + const introSelected: IntroSelected = { + choice: CONST.ONBOARDING_CHOICES.SUBMIT, + inviteType: CONST.ONBOARDING_INVITE_TYPES.IOU, + companySize: CONST.ONBOARDING_COMPANY_SIZE.MICRO, + }; + completePaymentOnboarding(CONST.PAYMENT_SELECTED.BBA, introSelected); + + expect(completeOnboardingSpy).toHaveBeenCalledWith( + expect.objectContaining({ + engagementChoice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM, + paymentSelected: CONST.PAYMENT_SELECTED.BBA, + wasInvited: true, + shouldSkipTestDriveModal: true, + companySize: CONST.ONBOARDING_COMPANY_SIZE.MICRO, + introSelected, + }), + ); + }); + + it('should override purpose to CHAT_SPLIT for INVOICE invite with PBA payment', () => { + const introSelected: IntroSelected = { + choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM, + inviteType: CONST.ONBOARDING_INVITE_TYPES.INVOICE, + companySize: CONST.ONBOARDING_COMPANY_SIZE.SMALL, + }; + completePaymentOnboarding(CONST.PAYMENT_SELECTED.PBA, introSelected); + + expect(completeOnboardingSpy).toHaveBeenCalledWith( + expect.objectContaining({ + engagementChoice: CONST.ONBOARDING_CHOICES.CHAT_SPLIT, + paymentSelected: CONST.PAYMENT_SELECTED.PBA, + wasInvited: true, + shouldSkipTestDriveModal: true, + companySize: CONST.ONBOARDING_COMPANY_SIZE.SMALL, + introSelected, + }), + ); + }); + + it('should keep original purpose for INVOICE invite with BBA payment', () => { + const introSelected: IntroSelected = { + choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM, + inviteType: CONST.ONBOARDING_INVITE_TYPES.INVOICE, + }; + completePaymentOnboarding(CONST.PAYMENT_SELECTED.BBA, introSelected); + + expect(completeOnboardingSpy).toHaveBeenCalledWith( + expect.objectContaining({ + engagementChoice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM, + introSelected, + }), + ); + }); + + it('should keep original purpose for IOU invite with PBA payment', () => { + const introSelected: IntroSelected = { + choice: CONST.ONBOARDING_CHOICES.SUBMIT, + inviteType: CONST.ONBOARDING_INVITE_TYPES.IOU, + }; + completePaymentOnboarding(CONST.PAYMENT_SELECTED.PBA, introSelected); + + expect(completeOnboardingSpy).toHaveBeenCalledWith( + expect.objectContaining({ + engagementChoice: CONST.ONBOARDING_CHOICES.SUBMIT, + introSelected, + }), + ); + }); + + it('should pass introSelected and optional params through to completeOnboarding', () => { + const introSelected: IntroSelected = { + choice: CONST.ONBOARDING_CHOICES.CHAT_SPLIT, + inviteType: CONST.ONBOARDING_INVITE_TYPES.CHAT, + companySize: CONST.ONBOARDING_COMPANY_SIZE.MEDIUM, + }; + completePaymentOnboarding(CONST.PAYMENT_SELECTED.PBA, introSelected, 'adminsChatReport123', 'policyID456'); + + expect(completeOnboardingSpy).toHaveBeenCalledWith( + expect.objectContaining({ + engagementChoice: CONST.ONBOARDING_CHOICES.CHAT_SPLIT, + adminsChatReportID: 'adminsChatReport123', + onboardingPolicyID: 'policyID456', + introSelected, + }), + ); + }); + }); }); diff --git a/tests/actions/ReportTest.ts b/tests/actions/ReportTest.ts index b6aba6fd6981c..77491b2a70986 100644 --- a/tests/actions/ReportTest.ts +++ b/tests/actions/ReportTest.ts @@ -2337,6 +2337,7 @@ describe('actions/Report', () => { onboardingPolicyID, companySize: CONST.ONBOARDING_COMPANY_SIZE.MICRO, userReportedIntegration: null, + introSelected: {choice: engagementChoice}, }); await waitForBatchedUpdates(); @@ -3506,6 +3507,7 @@ describe('actions/Report', () => { onboardingPolicyID, companySize: CONST.ONBOARDING_COMPANY_SIZE.MICRO, userReportedIntegration: null, + introSelected: {choice: engagementChoice}, }); await waitForBatchedUpdates(); diff --git a/tests/ui/OnboardingPurpose.tsx b/tests/ui/OnboardingPurpose.tsx new file mode 100644 index 0000000000000..610713e635d4d --- /dev/null +++ b/tests/ui/OnboardingPurpose.tsx @@ -0,0 +1,185 @@ +import {PortalProvider} from '@gorhom/portal'; +import {NavigationContainer} from '@react-navigation/native'; +import {act, render, screen, userEvent, waitFor} from '@testing-library/react-native'; +import React from 'react'; +import Onyx from 'react-native-onyx'; +import ComposeProviders from '@components/ComposeProviders'; +import {LocaleContextProvider} from '@components/LocaleContextProvider'; +import OnyxListItemProvider from '@components/OnyxListItemProvider'; +import {CurrentReportIDContextProvider} from '@hooks/useCurrentReportID'; +import * as useResponsiveLayoutModule from '@hooks/useResponsiveLayout'; +import type ResponsiveLayoutResult from '@hooks/useResponsiveLayout/types'; +import Navigation from '@libs/Navigation/Navigation'; +import createPlatformStackNavigator from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigator'; +import type {OnboardingModalNavigatorParamList} from '@libs/Navigation/types'; +import OnboardingPurpose from '@pages/OnboardingPurpose'; +import {completeOnboarding} from '@userActions/Report'; +import CONST from '@src/CONST'; +import type {TranslationPaths} from '@src/languages/types'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import SCREENS from '@src/SCREENS'; +import * as TestHelper from '../utils/TestHelper'; +import waitForBatchedUpdatesWithAct from '../utils/waitForBatchedUpdatesWithAct'; + +const mockCompleteOnboarding = jest.mocked(completeOnboarding); + +jest.mock('@userActions/Report', () => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const actual = jest.requireActual('@userActions/Report'); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return { + ...actual, + completeOnboarding: jest.fn(), + }; +}); + +TestHelper.setupGlobalFetchMock(); + +// Helper to translate onboarding purpose keys that use dynamic CONST values +const translatePurpose = (choice: string) => TestHelper.translateLocal(`onboarding.purpose.${choice}` as TranslationPaths); + +const Stack = createPlatformStackNavigator(); + +const navigate = jest.spyOn(Navigation, 'navigate'); + +const renderOnboardingPurposePage = (initialRouteName: typeof SCREENS.ONBOARDING.PURPOSE, initialParams: OnboardingModalNavigatorParamList[typeof SCREENS.ONBOARDING.PURPOSE]) => { + return render( + + + + + + + + + , + ); +}; + +describe('OnboardingPurpose Page', () => { + beforeAll(() => { + Onyx.init({ + keys: ONYXKEYS, + }); + }); + + beforeEach(() => { + jest.spyOn(useResponsiveLayoutModule, 'default').mockReturnValue({ + isSmallScreenWidth: false, + shouldUseNarrowLayout: false, + } as ResponsiveLayoutResult); + }); + + afterEach(async () => { + await act(async () => { + await Onyx.clear(); + }); + jest.clearAllMocks(); + }); + + it('should navigate to personal details page when user selects a purpose and is from public domain', async () => { + await TestHelper.signInWithTestUser(); + + await act(async () => { + await Onyx.merge(ONYXKEYS.ACCOUNT, { + isFromPublicDomain: true, + hasAccessibleDomainPolicies: false, + }); + }); + + const {unmount} = renderOnboardingPurposePage(SCREENS.ONBOARDING.PURPOSE, {backTo: ''}); + + await waitForBatchedUpdatesWithAct(); + + const user = userEvent.setup(); + const chatSplitLabel = translatePurpose(CONST.ONBOARDING_CHOICES.CHAT_SPLIT); + const chatSplitOption = screen.getByLabelText(chatSplitLabel); + await user.press(chatSplitOption); + + await waitFor(() => { + expect(navigate).toHaveBeenCalledWith(ROUTES.ONBOARDING_PERSONAL_DETAILS.getRoute('')); + }); + + unmount(); + await waitForBatchedUpdatesWithAct(); + }); + + it('should navigate to employees page when user selects MANAGE_TEAM', async () => { + await TestHelper.signInWithTestUser(); + + await act(async () => { + await Onyx.merge(ONYXKEYS.ACCOUNT, { + isFromPublicDomain: false, + hasAccessibleDomainPolicies: true, + }); + }); + + const {unmount} = renderOnboardingPurposePage(SCREENS.ONBOARDING.PURPOSE, {backTo: ''}); + + await waitForBatchedUpdatesWithAct(); + + const user = userEvent.setup(); + const manageTeamLabel = translatePurpose(CONST.ONBOARDING_CHOICES.MANAGE_TEAM); + const manageTeamOption = screen.getByLabelText(manageTeamLabel); + await user.press(manageTeamOption); + + await waitFor(() => { + expect(navigate).toHaveBeenCalledWith(ROUTES.ONBOARDING_EMPLOYEES.getRoute('')); + }); + + unmount(); + await waitForBatchedUpdatesWithAct(); + }); + + it('should call completeOnboarding with introSelected when user is from private domain and selects a direct-complete choice', async () => { + await TestHelper.signInWithTestUser(); + + const introSelectedValue = { + choice: CONST.ONBOARDING_CHOICES.CHAT_SPLIT, + inviteType: CONST.ONBOARDING_INVITE_TYPES.CHAT, + companySize: CONST.ONBOARDING_COMPANY_SIZE.MICRO, + }; + + await act(async () => { + await Onyx.merge(ONYXKEYS.ACCOUNT, { + isFromPublicDomain: false, + hasAccessibleDomainPolicies: true, + }); + await Onyx.merge(ONYXKEYS.FORMS.ONBOARDING_PERSONAL_DETAILS_FORM, { + firstName: 'Test', + lastName: 'User', + }); + await Onyx.set(ONYXKEYS.NVP_INTRO_SELECTED, introSelectedValue); + }); + + const {unmount} = renderOnboardingPurposePage(SCREENS.ONBOARDING.PURPOSE, {backTo: ''}); + + await waitForBatchedUpdatesWithAct(); + + // Select CHAT_SPLIT which triggers completeOnboarding directly for private domain users + const user = userEvent.setup(); + const chatSplitLabel = translatePurpose(CONST.ONBOARDING_CHOICES.CHAT_SPLIT); + const chatSplitOption = screen.getByLabelText(chatSplitLabel); + await user.press(chatSplitOption); + + await waitFor(() => { + expect(mockCompleteOnboarding).toHaveBeenCalledWith( + expect.objectContaining({ + engagementChoice: CONST.ONBOARDING_CHOICES.CHAT_SPLIT, + firstName: 'Test', + lastName: 'User', + introSelected: introSelectedValue, + }), + ); + }); + + mockCompleteOnboarding.mockClear(); + unmount(); + await waitForBatchedUpdatesWithAct(); + }); +});