From 3edef23706eaa6ed4c94af39fe71d5c256788d0f Mon Sep 17 00:00:00 2001 From: LucasBeneston Date: Fri, 18 Oct 2024 19:04:09 +0200 Subject: [PATCH] (PC-32481) feat(culturalSurvey): use needsToFillCulturalSurvey in useStepperInfo --- src/features/auth/api/useSignIn.ts | 4 +- .../SSOButton/SSOButton.native.test.tsx | 9 +- .../auth/pages/login/Login.native.test.tsx | 45 ++++++--- .../AccountCreated.native.test.tsx | 27 ++++- .../signup/AccountCreated/AccountCreated.tsx | 4 +- .../AccountCreated.web.test.tsx | 5 +- .../signup/SetEmail/SetEmail.native.test.tsx | 2 + .../api/useCulturalSurveyQuestions.ts | 4 +- .../BeneficiaryAccountCreated.native.test.tsx | 34 ++++++- .../BeneficiaryAccountCreated.tsx | 4 +- .../BeneficiaryAccountCreated.web.test.tsx | 4 + .../BeneficiaryRequestSent.native.test.tsx | 31 +++++- .../confirmation/BeneficiaryRequestSent.tsx | 4 +- .../BeneficiaryRequestSent.web.test.tsx | 4 + .../useInitialScreenConfig.native.test.tsx | 31 +++--- .../RootNavigator/useInitialScreenConfig.tsx | 4 +- .../useInitialScreenConfig.web.test.tsx | 9 +- .../OfferPreviewModal.web.test.tsx | 1 + src/image.d.ts | 1 + ...useShouldShowCulturalSurvey.native.test.ts | 63 ------------ .../useShouldShowCulturalSurvey.ts | 25 ----- ...ralSurveyForBeneficiaryUser.native.test.ts | 98 +++++++++++++++++++ ...uldShowCulturalSurveyForBeneficiaryUser.ts | 39 ++++++++ 23 files changed, 308 insertions(+), 144 deletions(-) delete mode 100644 src/shared/culturalSurvey/useShouldShowCulturalSurvey.native.test.ts delete mode 100644 src/shared/culturalSurvey/useShouldShowCulturalSurvey.ts create mode 100644 src/shared/culturalSurvey/useShouldShowCulturalSurveyForBeneficiaryUser.native.test.ts create mode 100644 src/shared/culturalSurvey/useShouldShowCulturalSurveyForBeneficiaryUser.ts diff --git a/src/features/auth/api/useSignIn.ts b/src/features/auth/api/useSignIn.ts index e8307d3c7a5..cc093693a5e 100644 --- a/src/features/auth/api/useSignIn.ts +++ b/src/features/auth/api/useSignIn.ts @@ -18,7 +18,7 @@ import { useDeviceInfo } from 'features/trustedDevice/helpers/useDeviceInfo' import { analytics } from 'libs/analytics' import { LoginRoutineMethod, SSOType } from 'libs/analytics/logEventAnalytics' import { storage } from 'libs/storage' -import { useShouldShowCulturalSurvey } from 'shared/culturalSurvey/useShouldShowCulturalSurvey' +import { useShouldShowCulturalSurveyForBeneficiaryUser } from 'shared/culturalSurvey/useShouldShowCulturalSurveyForBeneficiaryUser' export const useSignIn = ({ params, @@ -73,7 +73,7 @@ const useHandleSigninSuccess = ( setErrorMessage?: (message: string) => void ) => { const { navigate } = useNavigation() - const shouldShowCulturalSurvey = useShouldShowCulturalSurvey() + const shouldShowCulturalSurvey = useShouldShowCulturalSurveyForBeneficiaryUser() const onAddFavoriteSuccess = useCallback((data?: FavoriteResponse) => { if (data?.offer?.id) { diff --git a/src/features/auth/components/SSOButton/SSOButton.native.test.tsx b/src/features/auth/components/SSOButton/SSOButton.native.test.tsx index b4e6092f439..05bee3c9583 100644 --- a/src/features/auth/components/SSOButton/SSOButton.native.test.tsx +++ b/src/features/auth/components/SSOButton/SSOButton.native.test.tsx @@ -16,6 +16,8 @@ import { mockServer } from 'tests/mswServer' import { reactQueryProviderHOC } from 'tests/reactQueryProviderHOC' import { act, fireEvent, render, screen } from 'tests/utils' +jest.spyOn(useFeatureFlagAPI, 'useFeatureFlag').mockReturnValue(true) + jest.mock('libs/monitoring') jest.mock('libs/react-native-device-info/getDeviceId') jest.mock('features/identityCheck/context/SubscriptionContextProvider', () => ({ @@ -24,7 +26,6 @@ jest.mock('features/identityCheck/context/SubscriptionContextProvider', () => ({ jest.mock('libs/network/NetInfoWrapper') -const useFeatureFlagSpy = jest.spyOn(useFeatureFlagAPI, 'useFeatureFlag').mockReturnValue(false) const apiPostGoogleAuthorize = jest.spyOn(API.api, 'postNativeV1OauthGoogleAuthorize') const getModelSpy = jest.spyOn(DeviceInfo, 'getModel') const getSystemNameSpy = jest.spyOn(DeviceInfo, 'getSystemName') @@ -56,7 +57,6 @@ describe('', () => { }) it('should sign in with device info when sso button is clicked', async () => { - useFeatureFlagSpy.mockReturnValueOnce(true) getModelSpy.mockReturnValueOnce('iPhone 13') getSystemNameSpy.mockReturnValueOnce('iOS') mockServer.postApi('/v1/oauth/google/authorize', { @@ -82,7 +82,6 @@ describe('', () => { }) it('should call onSignInFailure when signin fails', async () => { - useFeatureFlagSpy.mockReturnValueOnce(true) mockServer.postApi('/v1/oauth/google/authorize', { responseOptions: { statusCode: 500 }, }) @@ -97,7 +96,6 @@ describe('', () => { }) it('should log analytics when logging in with sso from signup', async () => { - useFeatureFlagSpy.mockReturnValueOnce(true) mockServer.postApi('/v1/oauth/google/authorize', { accessToken: 'accessToken', refreshToken: 'refreshToken', @@ -113,7 +111,6 @@ describe('', () => { }) it('should log analytics when logging in with sso from login', async () => { - useFeatureFlagSpy.mockReturnValueOnce(true) mockServer.postApi('/v1/oauth/google/authorize', { accessToken: 'accessToken', refreshToken: 'refreshToken', @@ -137,7 +134,6 @@ describe('', () => { }) it('should not log to Sentry on SSO login error', async () => { - useFeatureFlagSpy.mockReturnValueOnce(true) jest.spyOn(GoogleSignin, 'signIn').mockRejectedValueOnce('GoogleSignIn Error') renderSSOButton() @@ -160,7 +156,6 @@ describe('', () => { }) it('should log to Sentry on SSO login error', async () => { - useFeatureFlagSpy.mockReturnValueOnce(true) jest.spyOn(GoogleSignin, 'signIn').mockRejectedValueOnce('GoogleSignIn Error') renderSSOButton() diff --git a/src/features/auth/pages/login/Login.native.test.tsx b/src/features/auth/pages/login/Login.native.test.tsx index 7ce13f34ea4..076bdf4c469 100644 --- a/src/features/auth/pages/login/Login.native.test.tsx +++ b/src/features/auth/pages/login/Login.native.test.tsx @@ -22,10 +22,12 @@ import { navigateToHome } from 'features/navigation/helpers/navigateToHome' import { usePreviousRoute } from 'features/navigation/helpers/usePreviousRoute' import { StepperOrigin } from 'features/navigation/RootNavigator/types' import { FAKE_USER_ID } from 'fixtures/fakeUserId' +import { beneficiaryUser } from 'fixtures/user' import { analytics } from 'libs/analytics' // eslint-disable-next-line no-restricted-imports import { firebaseAnalytics } from 'libs/firebase/analytics' import * as useFeatureFlagAPI from 'libs/firebase/firestore/featureFlags/useFeatureFlag' +import { RemoteStoreFeatureFlags } from 'libs/firebase/firestore/types' import { captureMonitoringError } from 'libs/monitoring' import { NetworkErrorFixture, UnknownErrorFixture } from 'libs/recaptcha/fixtures' import { storage } from 'libs/storage' @@ -36,6 +38,10 @@ import { SUGGESTION_DELAY_IN_MS } from 'ui/components/inputs/EmailInputWithSpell import { SNACK_BAR_TIME_OUT_LONG } from 'ui/components/snackBar/SnackBarContext' import { Login } from './Login' + +const useFeatureFlagSpy = jest.spyOn(useFeatureFlagAPI, 'useFeatureFlag') +jest.mock('libs/firebase/remoteConfig/remoteConfig.services') + jest.mock('libs/network/NetInfoWrapper') jest.mock('libs/monitoring') @@ -68,7 +74,6 @@ const apiSignInSpy = jest.spyOn(API.api, 'postNativeV1Signin') const apiPostGoogleAuthorize = jest.spyOn(API.api, 'postNativeV1OauthGoogleAuthorize') const getModelSpy = jest.spyOn(DeviceInfo, 'getModel') const getSystemNameSpy = jest.spyOn(DeviceInfo, 'getSystemName') -const useFeatureFlagSpy = jest.spyOn(useFeatureFlagAPI, 'useFeatureFlag').mockReturnValue(false) jest.useFakeTimers() @@ -93,6 +98,7 @@ jest.mock('react-native/Libraries/Animated/createAnimatedComponent', () => { describe('', () => { beforeEach(() => { + activateFeatureFlags([RemoteStoreFeatureFlags.WIP_ENABLE_GOOGLE_SSO]) mockServer.postApi('/v1/me/favorites', favoriteResponseSnap) mockServer.getApi('/v1/oauth/state', { oauthStateToken: 'oauth_state_token', @@ -110,10 +116,6 @@ describe('', () => { }) it('should render correctly when feature flag is enabled', async () => { - // We use this hook twice but due to multiple rerender we have to mock the return value this way - // eslint-disable-next-line local-rules/independent-mocks - useFeatureFlagSpy.mockReturnValue(true) - renderLogin() await screen.findByText('Connecte-toi') @@ -145,9 +147,6 @@ describe('', () => { }) it('should sign in when SSO button is clicked with device info', async () => { - // We use this hook twice but due to multiple rerender we have to mock the return value this way - // eslint-disable-next-line local-rules/independent-mocks - useFeatureFlagSpy.mockReturnValue(true) getModelSpy.mockReturnValueOnce('iPhone 13') getSystemNameSpy.mockReturnValueOnce('iOS') mockServer.postApi('/v1/oauth/google/authorize', { @@ -256,6 +255,25 @@ describe('', () => { }) it('should redirect to NATIVE Cultural Survey WHEN signin is successful and user needs to fill cultural survey', async () => { + activateFeatureFlags([RemoteStoreFeatureFlags.WIP_ENABLE_GOOGLE_SSO]) + activateFeatureFlags() // disabled ENABLE_CULTURAL_SURVEY_MANDATORY feature flag + + mockMeApiCall({ + ...beneficiaryUser, + needsToFillCulturalSurvey: true, + showEligibleCard: false, + } as UserProfileResponse) + renderLogin() + + await fillInputs() + await act(() => fireEvent.press(screen.getByText('Se connecter'))) + + expect(navigate).toHaveBeenNthCalledWith(1, 'CulturalSurveyIntro') + }) + + it('should redirect to home WHEN signin is successful and ENABLE_CULTURAL_SURVEY_MANDATORY enabled', async () => { + activateFeatureFlags([RemoteStoreFeatureFlags.WIP_ENABLE_GOOGLE_SSO]) + activateFeatureFlags([RemoteStoreFeatureFlags.ENABLE_CULTURAL_SURVEY_MANDATORY]) mockMeApiCall({ needsToFillCulturalSurvey: true, showEligibleCard: false, @@ -265,8 +283,7 @@ describe('', () => { await fillInputs() await act(() => fireEvent.press(screen.getByText('Se connecter'))) - expect(navigate).toHaveBeenCalledTimes(1) - expect(navigate).toHaveBeenCalledWith('CulturalSurveyIntro') + expect(navigateToHome).toHaveBeenCalledTimes(1) }) it('should not redirect to EighteenBirthday WHEN signin is successful and user has already seen eligible card and needs to see it', async () => { @@ -482,8 +499,7 @@ describe('', () => { await screen.findByText('Connecte-toi') - expect(analytics.logStepperDisplayed).toHaveBeenCalledTimes(1) - expect(analytics.logStepperDisplayed).toHaveBeenCalledWith(StepperOrigin.PROFILE, 'Login') + expect(analytics.logStepperDisplayed).toHaveBeenNthCalledWith(1, StepperOrigin.PROFILE, 'Login') }) it('should log analytics when clicking on "Créer un compte" button', async () => { @@ -598,6 +614,7 @@ describe('', () => { it('should redirect to CulturalSurveyIntro instead of Offer when user needs to fill it', async () => { mockMeApiCall({ + ...beneficiaryUser, needsToFillCulturalSurvey: true, showEligibleCard: false, } as UserProfileResponse) @@ -886,3 +903,7 @@ function simulateSigninNetworkFailure() { function simulateAddToFavorites() { mockServer.postApi('/v1/me/favorites', favoriteResponseSnap) } + +const activateFeatureFlags = (activeFeatureFlags: RemoteStoreFeatureFlags[] = []) => { + useFeatureFlagSpy.mockImplementation((flag) => activeFeatureFlags.includes(flag)) +} diff --git a/src/features/auth/pages/signup/AccountCreated/AccountCreated.native.test.tsx b/src/features/auth/pages/signup/AccountCreated/AccountCreated.native.test.tsx index 362c832547a..622be9711fa 100644 --- a/src/features/auth/pages/signup/AccountCreated/AccountCreated.native.test.tsx +++ b/src/features/auth/pages/signup/AccountCreated/AccountCreated.native.test.tsx @@ -8,12 +8,16 @@ import { ShareAppWrapper } from 'features/share/context/ShareAppWrapper' import { ShareAppModalType } from 'features/share/types' import { beneficiaryUser } from 'fixtures/user' import { analytics } from 'libs/analytics' +import * as useFeatureFlagAPI from 'libs/firebase/firestore/featureFlags/useFeatureFlag' +import { RemoteStoreFeatureFlags } from 'libs/firebase/firestore/types' import { BatchUser } from 'libs/react-native-batch' import { mockAuthContextWithUser } from 'tests/AuthContextUtils' import { fireEvent, render, screen, waitFor } from 'tests/utils' import { AccountCreated } from './AccountCreated' +const useFeatureFlagSpy = jest.spyOn(useFeatureFlagAPI, 'useFeatureFlag') +jest.mock('libs/firebase/remoteConfig/remoteConfig.services') jest.mock('features/profile/api/useResetRecreditAmountToShow') jest.mock('features/navigation/helpers/navigateToHome') jest.mock('features/navigation/navigationRef') @@ -40,6 +44,10 @@ jest.mock('react-native/Libraries/Animated/createAnimatedComponent', () => { }) describe('', () => { + beforeEach(() => { + activateFeatureFlags() + }) + it('should render correctly', async () => { renderAccountCreated() @@ -55,8 +63,20 @@ describe('', () => { await waitFor(() => { expect(navigateFromRef).not.toHaveBeenCalled() - expect(navigate).toHaveBeenCalledTimes(1) - expect(navigate).toHaveBeenCalledWith('CulturalSurveyIntro', undefined) + expect(navigate).toHaveBeenNthCalledWith(1, 'CulturalSurveyIntro', undefined) + }) + }) + + it('should redirect to home page WHEN "On y va !" button is clicked BUT feature flag enableCulturalSurveyMandatory is enabled', async () => { + activateFeatureFlags([RemoteStoreFeatureFlags.ENABLE_CULTURAL_SURVEY_MANDATORY]) + renderAccountCreated() + fireEvent.press(await screen.findByLabelText('On y va\u00a0!')) + await waitFor(() => { + expect(navigateFromRef).toHaveBeenCalledWith( + navigateToHomeConfig.screen, + navigateToHomeConfig.params + ) + expect(navigate).not.toHaveBeenCalledWith('CulturalSurvey', undefined) }) }) @@ -105,3 +125,6 @@ const renderAccountCreated = () => render(, { wrapper: ShareAppWrapper, }) +const activateFeatureFlags = (activeFeatureFlags: RemoteStoreFeatureFlags[] = []) => { + useFeatureFlagSpy.mockImplementation((flag) => activeFeatureFlags.includes(flag)) +} diff --git a/src/features/auth/pages/signup/AccountCreated/AccountCreated.tsx b/src/features/auth/pages/signup/AccountCreated/AccountCreated.tsx index 8fd5e906b19..8244eb61ef7 100644 --- a/src/features/auth/pages/signup/AccountCreated/AccountCreated.tsx +++ b/src/features/auth/pages/signup/AccountCreated/AccountCreated.tsx @@ -7,7 +7,7 @@ import { useShareAppContext } from 'features/share/context/ShareAppWrapper' import { ShareAppModalType } from 'features/share/types' import { analytics } from 'libs/analytics' import { BatchEvent, BatchUser } from 'libs/react-native-batch' -import { useShouldShowCulturalSurvey } from 'shared/culturalSurvey/useShouldShowCulturalSurvey' +import { useShouldShowCulturalSurveyForBeneficiaryUser } from 'shared/culturalSurvey/useShouldShowCulturalSurveyForBeneficiaryUser' import IlluminatedSmileyAnimation from 'ui/animations/lottie_illuminated_smiley.json' import { ButtonPrimaryWhite } from 'ui/components/buttons/ButtonPrimaryWhite' import { InternalTouchableLink } from 'ui/components/touchableLink/InternalTouchableLink' @@ -17,7 +17,7 @@ import { Typo } from 'ui/theme' export function AccountCreated() { const { user } = useAuthContext() const { showShareAppModal } = useShareAppContext() - const shouldShowCulturalSurvey = useShouldShowCulturalSurvey() + const shouldShowCulturalSurvey = useShouldShowCulturalSurveyForBeneficiaryUser() const shouldNavigateToCulturalSurvey = shouldShowCulturalSurvey(user) diff --git a/src/features/auth/pages/signup/AccountCreated/AccountCreated.web.test.tsx b/src/features/auth/pages/signup/AccountCreated/AccountCreated.web.test.tsx index 915e23e03db..9b2143643bd 100644 --- a/src/features/auth/pages/signup/AccountCreated/AccountCreated.web.test.tsx +++ b/src/features/auth/pages/signup/AccountCreated/AccountCreated.web.test.tsx @@ -1,12 +1,15 @@ import React from 'react' +import * as useFeatureFlagAPI from 'libs/firebase/firestore/featureFlags/useFeatureFlag' import { checkAccessibilityFor, render, screen } from 'tests/utils/web' import { AccountCreated } from './AccountCreated' -jest.mock('libs/firebase/analytics/analytics') +jest.spyOn(useFeatureFlagAPI, 'useFeatureFlag').mockReturnValue(false) jest.mock('libs/firebase/remoteConfig/remoteConfig.services') +jest.mock('libs/firebase/analytics/analytics') + jest.mock('react-native-safe-area-context', () => ({ ...(jest.requireActual('react-native-safe-area-context') as Record), useSafeAreaInsets: () => ({ bottom: 16, right: 16, left: 16, top: 16 }), diff --git a/src/features/auth/pages/signup/SetEmail/SetEmail.native.test.tsx b/src/features/auth/pages/signup/SetEmail/SetEmail.native.test.tsx index 13880d5f33d..c2c2793974f 100644 --- a/src/features/auth/pages/signup/SetEmail/SetEmail.native.test.tsx +++ b/src/features/auth/pages/signup/SetEmail/SetEmail.native.test.tsx @@ -295,6 +295,7 @@ describe('', () => { useFeatureFlagSpy.mockReturnValueOnce(true) // first call in SetEmail useFeatureFlagSpy.mockReturnValueOnce(true) // second call in useOAuthState + useFeatureFlagSpy.mockReturnValueOnce(true) // third call in CulturalSurvey renderSetEmail() @@ -323,6 +324,7 @@ describe('', () => { useFeatureFlagSpy.mockReturnValueOnce(true) // first call in SetEmail useFeatureFlagSpy.mockReturnValueOnce(true) // second call in useOAuthState + useFeatureFlagSpy.mockReturnValueOnce(true) // third call in CulturalSurvey renderSetEmail() diff --git a/src/features/culturalSurvey/api/useCulturalSurveyQuestions.ts b/src/features/culturalSurvey/api/useCulturalSurveyQuestions.ts index d6a69879e1d..75dcebd0dab 100644 --- a/src/features/culturalSurvey/api/useCulturalSurveyQuestions.ts +++ b/src/features/culturalSurvey/api/useCulturalSurveyQuestions.ts @@ -5,14 +5,14 @@ import { CulturalSurveyQuestionsResponse } from 'api/gen' import { useAuthContext } from 'features/auth/context/AuthContext' import { useNetInfoContext } from 'libs/network/NetInfoWrapper' import { QueryKeys } from 'libs/queryKeys' -import { useShouldShowCulturalSurvey } from 'shared/culturalSurvey/useShouldShowCulturalSurvey' +import { useShouldShowCulturalSurveyForBeneficiaryUser } from 'shared/culturalSurvey/useShouldShowCulturalSurveyForBeneficiaryUser' const STALE_TIME_CULTURAL_SURVEY_QUESTIONS = 5 * 60 * 1000 export function useCulturalSurveyQuestions() { const { user, isLoggedIn } = useAuthContext() const netInfo = useNetInfoContext() - const shouldShowCulturalSurvey = useShouldShowCulturalSurvey() + const shouldShowCulturalSurvey = useShouldShowCulturalSurveyForBeneficiaryUser() const shouldRequestCulturalSurveyQuestions = shouldShowCulturalSurvey(user) return useQuery( diff --git a/src/features/identityCheck/pages/confirmation/BeneficiaryAccountCreated.native.test.tsx b/src/features/identityCheck/pages/confirmation/BeneficiaryAccountCreated.native.test.tsx index 1b7e15f708a..c86f889ee04 100644 --- a/src/features/identityCheck/pages/confirmation/BeneficiaryAccountCreated.native.test.tsx +++ b/src/features/identityCheck/pages/confirmation/BeneficiaryAccountCreated.native.test.tsx @@ -1,13 +1,18 @@ import React from 'react' +import { navigate } from '__mocks__/@react-navigation/native' import { BeneficiaryAccountCreated } from 'features/identityCheck/pages/confirmation/BeneficiaryAccountCreated' import * as ShareAppWrapperModule from 'features/share/context/ShareAppWrapper' import { ShareAppWrapper } from 'features/share/context/ShareAppWrapper' import { ShareAppModalType } from 'features/share/types' import { beneficiaryUser, underageBeneficiaryUser } from 'fixtures/user' +import * as useFeatureFlagAPI from 'libs/firebase/firestore/featureFlags/useFeatureFlag' +import { RemoteStoreFeatureFlags } from 'libs/firebase/firestore/types' import { BatchUser } from 'libs/react-native-batch' import { mockAuthContextWithUser } from 'tests/AuthContextUtils' -import { fireEvent, render, screen } from 'tests/utils' +import { fireEvent, render, screen, waitFor } from 'tests/utils' +const useFeatureFlagSpy = jest.spyOn(useFeatureFlagAPI, 'useFeatureFlag') +jest.mock('libs/firebase/remoteConfig/remoteConfig.services') jest.mock('features/auth/context/AuthContext') @@ -35,6 +40,7 @@ jest.mock('react-native/Libraries/Animated/createAnimatedComponent', () => { describe('', () => { beforeEach(() => { + activateFeatureFlags() mockAuthContextWithUser(underageBeneficiaryUser, { persist: true }) }) @@ -69,8 +75,8 @@ describe('', () => { { ...beneficiaryUser, needsToFillCulturalSurvey: false }, { persist: true } ) - renderBeneficiaryAccountCreated() + fireEvent.press(await screen.findByLabelText('C’est parti !')) expect(mockShowAppModal).toHaveBeenNthCalledWith(1, ShareAppModalType.BENEFICIARY) @@ -82,7 +88,31 @@ describe('', () => { expect(mockShowAppModal).not.toHaveBeenCalled() }) + + it('should redirect to native cultural survey page when "C’est parti !"button is clicked and user is supposed to see cultural survey', async () => { + renderBeneficiaryAccountCreated() + mockAuthContextWithUser( + { ...beneficiaryUser, needsToFillCulturalSurvey: true }, + { persist: true } + ) + fireEvent.press(await screen.findByLabelText('C’est parti !')) + await waitFor(() => { + expect(navigate).toHaveBeenNthCalledWith(1, 'CulturalSurveyIntro', undefined) + }) + }) + + it('should redirect to home page when "C’est parti !" button is clicked BUT feature flag enableCulturalSurveyMandatory is enabled', async () => { + activateFeatureFlags([RemoteStoreFeatureFlags.ENABLE_CULTURAL_SURVEY_MANDATORY]) + renderBeneficiaryAccountCreated() + fireEvent.press(await screen.findByLabelText('C’est parti !')) + await waitFor(() => { + expect(navigate).toHaveBeenNthCalledWith(1, 'TabNavigator', { screen: 'Home' }) + }) + }) }) const renderBeneficiaryAccountCreated = () => render(, { wrapper: ShareAppWrapper }) +const activateFeatureFlags = (activeFeatureFlags: RemoteStoreFeatureFlags[] = []) => { + useFeatureFlagSpy.mockImplementation((flag) => activeFeatureFlags.includes(flag)) +} diff --git a/src/features/identityCheck/pages/confirmation/BeneficiaryAccountCreated.tsx b/src/features/identityCheck/pages/confirmation/BeneficiaryAccountCreated.tsx index f9c0a8932b1..dd9f91a61dd 100644 --- a/src/features/identityCheck/pages/confirmation/BeneficiaryAccountCreated.tsx +++ b/src/features/identityCheck/pages/confirmation/BeneficiaryAccountCreated.tsx @@ -10,7 +10,7 @@ import { useShareAppContext } from 'features/share/context/ShareAppWrapper' import { ShareAppModalType } from 'features/share/types' import { formatPriceInEuroToDisplayPrice } from 'libs/parsers/getDisplayPrice' import { BatchEvent, BatchUser } from 'libs/react-native-batch' -import { useShouldShowCulturalSurvey } from 'shared/culturalSurvey/useShouldShowCulturalSurvey' +import { useShouldShowCulturalSurveyForBeneficiaryUser } from 'shared/culturalSurvey/useShouldShowCulturalSurveyForBeneficiaryUser' import TutorialPassLogo from 'ui/animations/tutorial_pass_logo.json' import { AnimatedProgressBar } from 'ui/components/bars/AnimatedProgressBar' import { ButtonPrimary } from 'ui/components/buttons/ButtonPrimary' @@ -26,7 +26,7 @@ export function BeneficiaryAccountCreated() { const { uniqueColors } = useTheme() const { user } = useAuthContext() const isUnderageBeneficiary = isUserUnderageBeneficiary(user) - const shouldShowCulturalSurvey = useShouldShowCulturalSurvey() + const shouldShowCulturalSurvey = useShouldShowCulturalSurveyForBeneficiaryUser() const shouldNavigateToCulturalSurvey = shouldShowCulturalSurvey(user) const { showShareAppModal } = useShareAppContext() const { actions } = useCreditStore() diff --git a/src/features/identityCheck/pages/confirmation/BeneficiaryAccountCreated.web.test.tsx b/src/features/identityCheck/pages/confirmation/BeneficiaryAccountCreated.web.test.tsx index 0c4e30c5bec..2e82e7b44e1 100644 --- a/src/features/identityCheck/pages/confirmation/BeneficiaryAccountCreated.web.test.tsx +++ b/src/features/identityCheck/pages/confirmation/BeneficiaryAccountCreated.web.test.tsx @@ -1,9 +1,13 @@ import React from 'react' +import * as useFeatureFlagAPI from 'libs/firebase/firestore/featureFlags/useFeatureFlag' import { render, checkAccessibilityFor, screen } from 'tests/utils/web' import { BeneficiaryAccountCreated } from './BeneficiaryAccountCreated' +jest.spyOn(useFeatureFlagAPI, 'useFeatureFlag').mockReturnValue(false) +jest.mock('libs/firebase/remoteConfig/remoteConfig.services') + jest.mock('features/auth/context/AuthContext') jest.mock('react-native-safe-area-context', () => ({ diff --git a/src/features/identityCheck/pages/confirmation/BeneficiaryRequestSent.native.test.tsx b/src/features/identityCheck/pages/confirmation/BeneficiaryRequestSent.native.test.tsx index b0d7c9ce220..aab00dbbaf5 100644 --- a/src/features/identityCheck/pages/confirmation/BeneficiaryRequestSent.native.test.tsx +++ b/src/features/identityCheck/pages/confirmation/BeneficiaryRequestSent.native.test.tsx @@ -5,10 +5,14 @@ import { navigate } from '__mocks__/@react-navigation/native' import { useAuthContext } from 'features/auth/context/AuthContext' import { navigateToHomeConfig } from 'features/navigation/helpers/navigateToHome' import { navigateFromRef } from 'features/navigation/navigationRef' +import * as useFeatureFlagAPI from 'libs/firebase/firestore/featureFlags/useFeatureFlag' +import { RemoteStoreFeatureFlags } from 'libs/firebase/firestore/types' import { render, fireEvent, screen } from 'tests/utils' import { BeneficiaryRequestSent } from './BeneficiaryRequestSent' +const useFeatureFlagSpy = jest.spyOn(useFeatureFlagAPI, 'useFeatureFlag') +jest.mock('libs/firebase/remoteConfig/remoteConfig.services') jest.mock('features/navigation/helpers/navigateToHome') jest.mock('features/navigation/navigationRef') @@ -27,6 +31,10 @@ jest.mock('react-native/Libraries/Animated/createAnimatedComponent', () => { }) describe('', () => { + beforeEach(() => { + activateFeatureFlags() + }) + it('should render correctly', async () => { render() @@ -41,8 +49,20 @@ describe('', () => { fireEvent.press(await screen.findByLabelText('On y va\u00a0!')) expect(navigateFromRef).not.toHaveBeenCalled() - expect(navigate).toHaveBeenCalledTimes(1) - expect(navigate).toHaveBeenCalledWith('CulturalSurveyIntro', undefined) + expect(navigate).toHaveBeenNthCalledWith(1, 'CulturalSurveyIntro', undefined) + }) + + it('should redirect to home page when "On y va !" button is clicked BUT feature flag enableCulturalSurveyMandatory is enabled', async () => { + activateFeatureFlags([RemoteStoreFeatureFlags.ENABLE_CULTURAL_SURVEY_MANDATORY]) + render() + + fireEvent.press(await screen.findByLabelText('On y va\u00a0!')) + + expect(navigateFromRef).toHaveBeenCalledWith( + navigateToHomeConfig.screen, + navigateToHomeConfig.params + ) + expect(navigate).not.toHaveBeenCalled() }) it('should redirect to home page WHEN "On y va !" button is clicked and user does not need to fill cultural survey', async () => { @@ -52,7 +72,6 @@ describe('', () => { mockedUseAuthContext.mockImplementationOnce(() => ({ user: { needsToFillCulturalSurvey: false }, })) // re-render because local storage value has been read and set - render() fireEvent.press(await screen.findByLabelText('On y va\u00a0!')) @@ -61,6 +80,10 @@ describe('', () => { navigateToHomeConfig.screen, navigateToHomeConfig.params ) - expect(navigate).not.toHaveBeenCalledWith('CulturalSurvey', undefined) + expect(navigate).not.toHaveBeenNthCalledWith(1, 'CulturalSurvey', undefined) }) }) + +const activateFeatureFlags = (activeFeatureFlags: RemoteStoreFeatureFlags[] = []) => { + useFeatureFlagSpy.mockImplementation((flag) => activeFeatureFlags.includes(flag)) +} diff --git a/src/features/identityCheck/pages/confirmation/BeneficiaryRequestSent.tsx b/src/features/identityCheck/pages/confirmation/BeneficiaryRequestSent.tsx index 3b2aa34d969..03a9ae847d9 100644 --- a/src/features/identityCheck/pages/confirmation/BeneficiaryRequestSent.tsx +++ b/src/features/identityCheck/pages/confirmation/BeneficiaryRequestSent.tsx @@ -3,7 +3,7 @@ import styled from 'styled-components/native' import { useAuthContext } from 'features/auth/context/AuthContext' import { navigateToHomeConfig } from 'features/navigation/helpers/navigateToHome' -import { useShouldShowCulturalSurvey } from 'shared/culturalSurvey/useShouldShowCulturalSurvey' +import { useShouldShowCulturalSurveyForBeneficiaryUser } from 'shared/culturalSurvey/useShouldShowCulturalSurveyForBeneficiaryUser' import { ButtonPrimaryWhite } from 'ui/components/buttons/ButtonPrimaryWhite' import { InternalTouchableLink } from 'ui/components/touchableLink/InternalTouchableLink' import { GenericInfoPage } from 'ui/pages/GenericInfoPage' @@ -12,7 +12,7 @@ import { Typo } from 'ui/theme' export function BeneficiaryRequestSent() { const { user } = useAuthContext() - const shouldShowCulturalSurvey = useShouldShowCulturalSurvey() + const shouldShowCulturalSurvey = useShouldShowCulturalSurveyForBeneficiaryUser() const shouldNavigateToCulturalSurvey = shouldShowCulturalSurvey(user) const body = 'Tu recevras un e-mail lorsque ta demande sera validée.' diff --git a/src/features/identityCheck/pages/confirmation/BeneficiaryRequestSent.web.test.tsx b/src/features/identityCheck/pages/confirmation/BeneficiaryRequestSent.web.test.tsx index 62e35bf0516..24c476f721d 100644 --- a/src/features/identityCheck/pages/confirmation/BeneficiaryRequestSent.web.test.tsx +++ b/src/features/identityCheck/pages/confirmation/BeneficiaryRequestSent.web.test.tsx @@ -1,9 +1,13 @@ import React from 'react' +import * as useFeatureFlagAPI from 'libs/firebase/firestore/featureFlags/useFeatureFlag' import { render, checkAccessibilityFor, screen } from 'tests/utils/web' import { BeneficiaryRequestSent } from './BeneficiaryRequestSent' +jest.spyOn(useFeatureFlagAPI, 'useFeatureFlag').mockReturnValue(false) +jest.mock('libs/firebase/remoteConfig/remoteConfig.services') + jest.mock('features/auth/context/AuthContext') jest.mock('react-native-safe-area-context', () => ({ diff --git a/src/features/navigation/RootNavigator/useInitialScreenConfig.native.test.tsx b/src/features/navigation/RootNavigator/useInitialScreenConfig.native.test.tsx index d19f29e8a55..737cf924260 100644 --- a/src/features/navigation/RootNavigator/useInitialScreenConfig.native.test.tsx +++ b/src/features/navigation/RootNavigator/useInitialScreenConfig.native.test.tsx @@ -2,6 +2,8 @@ import React from 'react' import { beneficiaryUser } from 'fixtures/user' import { analytics } from 'libs/analytics' +import * as useFeatureFlagAPI from 'libs/firebase/firestore/featureFlags/useFeatureFlag' +import { RemoteStoreFeatureFlags } from 'libs/firebase/firestore/types' import { SplashScreenProvider } from 'libs/splashscreen' import { storage } from 'libs/storage' import { mockAuthContextWithoutUser, mockAuthContextWithUser } from 'tests/AuthContextUtils' @@ -9,10 +11,17 @@ import { renderHook, waitFor } from 'tests/utils' import { useInitialScreen } from './useInitialScreenConfig' +const useFeatureFlagSpy = jest.spyOn(useFeatureFlagAPI, 'useFeatureFlag') +jest.mock('libs/firebase/remoteConfig/remoteConfig.services') + jest.mock('features/auth/context/AuthContext') jest.mock('libs/jwt/jwt') describe('useInitialScreen()', () => { + beforeEach(() => { + activateFeatureFlags() + }) + afterAll(async () => { await storage.clear('has_seen_tutorials') await storage.clear('has_seen_eligible_card') @@ -37,8 +46,7 @@ describe('useInitialScreen()', () => { expect(result.current).toEqual('TabNavigator') }) - expect(analytics.logScreenView).toHaveBeenCalledTimes(1) - expect(analytics.logScreenView).toHaveBeenCalledWith('Home') + expect(analytics.logScreenView).toHaveBeenNthCalledWith(1, 'Home') }) it('should return CulturalSurveyIntro when user should see cultural survey', async () => { @@ -60,8 +68,7 @@ describe('useInitialScreen()', () => { expect(result.current).toEqual('CulturalSurveyIntro') }) - expect(analytics.logScreenView).toHaveBeenCalledTimes(1) - expect(analytics.logScreenView).toHaveBeenCalledWith('CulturalSurveyIntro') + expect(analytics.logScreenView).toHaveBeenNthCalledWith(1, 'CulturalSurveyIntro') }) it('should return EighteenBirthday when user hasn’t seen eligible card', async () => { @@ -83,8 +90,7 @@ describe('useInitialScreen()', () => { expect(result.current).toEqual('EighteenBirthday') }) - expect(analytics.logScreenView).toHaveBeenCalledTimes(1) - expect(analytics.logScreenView).toHaveBeenCalledWith('EighteenBirthday') + expect(analytics.logScreenView).toHaveBeenNthCalledWith(1, 'EighteenBirthday') }) it('should return RecreditBirthdayNotification when user hasn’t seen eligible card and has credit to show', async () => { @@ -106,8 +112,7 @@ describe('useInitialScreen()', () => { expect(result.current).toEqual('RecreditBirthdayNotification') }) - expect(analytics.logScreenView).toHaveBeenCalledTimes(1) - expect(analytics.logScreenView).toHaveBeenCalledWith('RecreditBirthdayNotification') + expect(analytics.logScreenView).toHaveBeenNthCalledWith(1, 'RecreditBirthdayNotification') }) it('should return TabNavigator when user is not logged in and has seen tutorial', async () => { @@ -121,8 +126,7 @@ describe('useInitialScreen()', () => { expect(result.current).toEqual('TabNavigator') }) - expect(analytics.logScreenView).toHaveBeenCalledTimes(1) - expect(analytics.logScreenView).toHaveBeenCalledWith('Home') + expect(analytics.logScreenView).toHaveBeenNthCalledWith(1, 'Home') }) it('should return OnboardingWelcome when user is not logged in and hasn’t seen tutorial yet', async () => { @@ -136,8 +140,7 @@ describe('useInitialScreen()', () => { expect(result.current).toEqual('OnboardingWelcome') }) - expect(analytics.logScreenView).toHaveBeenCalledTimes(1) - expect(analytics.logScreenView).toHaveBeenCalledWith('OnboardingWelcome') + expect(analytics.logScreenView).toHaveBeenNthCalledWith(1, 'OnboardingWelcome') }) }) @@ -148,3 +151,7 @@ async function renderUseInitialScreen() { const { result } = renderHook(useInitialScreen, { wrapper }) return result } + +const activateFeatureFlags = (activeFeatureFlags: RemoteStoreFeatureFlags[] = []) => { + useFeatureFlagSpy.mockImplementation((flag) => activeFeatureFlags.includes(flag)) +} diff --git a/src/features/navigation/RootNavigator/useInitialScreenConfig.tsx b/src/features/navigation/RootNavigator/useInitialScreenConfig.tsx index f293c99b25b..84769373a39 100644 --- a/src/features/navigation/RootNavigator/useInitialScreenConfig.tsx +++ b/src/features/navigation/RootNavigator/useInitialScreenConfig.tsx @@ -6,7 +6,7 @@ import { useAuthContext } from 'features/auth/context/AuthContext' import { analytics } from 'libs/analytics/provider' import { useSafeState } from 'libs/hooks' import { storage } from 'libs/storage' -import { useShouldShowCulturalSurvey } from 'shared/culturalSurvey/useShouldShowCulturalSurvey' +import { useShouldShowCulturalSurveyForBeneficiaryUser } from 'shared/culturalSurvey/useShouldShowCulturalSurveyForBeneficiaryUser' import { homeNavConfig } from '../TabBar/helpers' @@ -14,7 +14,7 @@ import { RootScreenNames } from './types' export function useInitialScreen(): RootScreenNames | undefined { const { isLoggedIn, user } = useAuthContext() - const shouldShowCulturalSurvey = useShouldShowCulturalSurvey() + const shouldShowCulturalSurvey = useShouldShowCulturalSurveyForBeneficiaryUser() const [initialScreen, setInitialScreen] = useSafeState(undefined) diff --git a/src/features/navigation/RootNavigator/useInitialScreenConfig.web.test.tsx b/src/features/navigation/RootNavigator/useInitialScreenConfig.web.test.tsx index 11caa759f9e..3ee4adb1a20 100644 --- a/src/features/navigation/RootNavigator/useInitialScreenConfig.web.test.tsx +++ b/src/features/navigation/RootNavigator/useInitialScreenConfig.web.test.tsx @@ -3,13 +3,15 @@ import React from 'react' import { analytics } from 'libs/analytics' import { SplashScreenProvider } from 'libs/splashscreen' import { storage } from 'libs/storage' +import { reactQueryProviderHOC } from 'tests/reactQueryProviderHOC' import { renderHook, waitFor } from 'tests/utils/web' import { useInitialScreen } from './useInitialScreenConfig' -const wrapper = (props: { children: unknown }) => ( - {props.children as React.JSX.Element} -) +const wrapper = (props: { children: unknown }) => + reactQueryProviderHOC( + {props.children as React.JSX.Element} + ) jest.mock('libs/firebase/analytics/analytics') jest.mock('libs/firebase/remoteConfig/remoteConfig.services') @@ -22,7 +24,6 @@ describe('useInitialScreen()', () => { it('should redirect to Home if user has not seen tutorials', async () => { const { result } = renderHook(useInitialScreen, { wrapper }) - await waitFor(() => { expect(result.current).toEqual('TabNavigator') expect(analytics.logScreenView).toHaveBeenCalledTimes(1) diff --git a/src/features/offer/components/OfferPreviewModal/OfferPreviewModal.web.test.tsx b/src/features/offer/components/OfferPreviewModal/OfferPreviewModal.web.test.tsx index 5ffcf02ebf9..a1556ac64cf 100644 --- a/src/features/offer/components/OfferPreviewModal/OfferPreviewModal.web.test.tsx +++ b/src/features/offer/components/OfferPreviewModal/OfferPreviewModal.web.test.tsx @@ -10,6 +10,7 @@ jest.mock('react-native-safe-area-context', () => ({ useSafeAreaInsets: () => ({ bottom: 16, right: 16, left: 16, top: 16 }), })) +// eslint-disable-next-line jest/no-disabled-tests describe.skip('', () => { beforeEach(() => { jest.spyOn(console, 'warn').mockImplementation() diff --git a/src/image.d.ts b/src/image.d.ts index 46a069dac35..2e0c0366646 100644 --- a/src/image.d.ts +++ b/src/image.d.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ declare module '*.png' { const value: any export = value diff --git a/src/shared/culturalSurvey/useShouldShowCulturalSurvey.native.test.ts b/src/shared/culturalSurvey/useShouldShowCulturalSurvey.native.test.ts deleted file mode 100644 index 5d0089bff2c..00000000000 --- a/src/shared/culturalSurvey/useShouldShowCulturalSurvey.native.test.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { beneficiaryUser } from 'fixtures/user' -import { storage } from 'libs/storage' -import { renderHook, act } from 'tests/utils' - -import { useShouldShowCulturalSurvey } from './useShouldShowCulturalSurvey' - -const CULTURAL_SURVEY_DISPLAYS_STORAGE_KEY = 'times_cultural_survey_has_been_requested' - -describe('useShouldShowCulturalSurvey()', () => { - beforeEach(() => { - storage.clear(CULTURAL_SURVEY_DISPLAYS_STORAGE_KEY) - }) - - it('should return undefined while reading information', async () => { - const { result } = renderHook(useShouldShowCulturalSurvey) - - const shouldShowCulturalSurvey = result.current(beneficiaryUser) - await act(() => {}) - - expect(shouldShowCulturalSurvey).toBeUndefined() - }) - - it('should return true when user has never seen cultural survey', async () => { - const { result } = renderHook(useShouldShowCulturalSurvey) - - await act(() => {}) - const shouldShowCulturalSurvey = result.current(beneficiaryUser) - - expect(shouldShowCulturalSurvey).toBe(true) - }) - - it('should return false when user has already filled cultural survey', async () => { - const { result } = renderHook(useShouldShowCulturalSurvey) - - await act(() => {}) - const shouldShowCulturalSurvey = result.current({ - ...beneficiaryUser, - needsToFillCulturalSurvey: false, - }) - - expect(shouldShowCulturalSurvey).toBe(false) - }) - - it('should return true when user has seen cultural survey twice', async () => { - storage.saveObject(CULTURAL_SURVEY_DISPLAYS_STORAGE_KEY, 2) - const { result } = renderHook(useShouldShowCulturalSurvey) - - await act(() => {}) - const shouldShowCulturalSurvey = result.current(beneficiaryUser) - - expect(shouldShowCulturalSurvey).toBe(true) - }) - - it('should return false when user has seen cultural survey more than twice', async () => { - storage.saveObject(CULTURAL_SURVEY_DISPLAYS_STORAGE_KEY, 3) - const { result } = renderHook(useShouldShowCulturalSurvey) - - await act(() => {}) - const shouldShowCulturalSurvey = result.current(beneficiaryUser) - - expect(shouldShowCulturalSurvey).toBe(false) - }) -}) diff --git a/src/shared/culturalSurvey/useShouldShowCulturalSurvey.ts b/src/shared/culturalSurvey/useShouldShowCulturalSurvey.ts deleted file mode 100644 index aeeac50d1a5..00000000000 --- a/src/shared/culturalSurvey/useShouldShowCulturalSurvey.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { useCallback, useEffect, useState } from 'react' - -import { UserProfileResponse } from 'api/gen' -import { storage } from 'libs/storage' - -const MAX_NUMBER_OF_DISPLAYS = 3 - -export function useShouldShowCulturalSurvey() { - const [numberOfDisplays, setNumberOfDisplays] = useState() - - useEffect(() => { - storage.readObject('times_cultural_survey_has_been_requested').then((value) => { - setNumberOfDisplays(value || 0) - }) - }, []) - - return useCallback( - (user?: UserProfileResponse) => { - return numberOfDisplays === undefined - ? undefined - : !!user?.needsToFillCulturalSurvey && numberOfDisplays < MAX_NUMBER_OF_DISPLAYS - }, - [numberOfDisplays] - ) -} diff --git a/src/shared/culturalSurvey/useShouldShowCulturalSurveyForBeneficiaryUser.native.test.ts b/src/shared/culturalSurvey/useShouldShowCulturalSurveyForBeneficiaryUser.native.test.ts new file mode 100644 index 00000000000..68b344abe74 --- /dev/null +++ b/src/shared/culturalSurvey/useShouldShowCulturalSurveyForBeneficiaryUser.native.test.ts @@ -0,0 +1,98 @@ +import { beneficiaryUser, nonBeneficiaryUser } from 'fixtures/user' +import * as useFeatureFlagAPI from 'libs/firebase/firestore/featureFlags/useFeatureFlag' +import { RemoteStoreFeatureFlags } from 'libs/firebase/firestore/types' +import { storage } from 'libs/storage' +import { renderHook, act } from 'tests/utils' + +import { useShouldShowCulturalSurveyForBeneficiaryUser } from './useShouldShowCulturalSurveyForBeneficiaryUser' + +const useFeatureFlagSpy = jest.spyOn(useFeatureFlagAPI, 'useFeatureFlag') +jest.mock('libs/firebase/remoteConfig/remoteConfig.services') +const CULTURAL_SURVEY_DISPLAYS_STORAGE_KEY = 'times_cultural_survey_has_been_requested' + +const activateFeatureFlags = (activeFeatureFlags: RemoteStoreFeatureFlags[] = []) => { + useFeatureFlagSpy.mockImplementation((flag) => activeFeatureFlags.includes(flag)) +} + +describe('useShouldShowCulturalSurveyForBeneficiaryUser()', () => { + beforeEach(() => { + storage.clear(CULTURAL_SURVEY_DISPLAYS_STORAGE_KEY) + activateFeatureFlags() + }) + + it('should return true when feature flag is disabled and user has never seen cultural survey', async () => { + const { result } = renderHook(useShouldShowCulturalSurveyForBeneficiaryUser) + await act(() => {}) + const shouldShowCulturalSurvey = result.current(beneficiaryUser) + + expect(shouldShowCulturalSurvey).toBeTruthy() + }) + + it('should return false when cultural survey feature flag is enabled', async () => { + activateFeatureFlags([RemoteStoreFeatureFlags.ENABLE_CULTURAL_SURVEY_MANDATORY]) + const { result } = renderHook(useShouldShowCulturalSurveyForBeneficiaryUser) + await act(() => {}) + const shouldShowCulturalSurvey = result.current(beneficiaryUser) + + expect(shouldShowCulturalSurvey).toBeFalsy() + }) + + it('should return false while reading information', async () => { + const { result } = renderHook(useShouldShowCulturalSurveyForBeneficiaryUser) + + const shouldShowCulturalSurvey = result.current(beneficiaryUser) + await act(() => {}) + + expect(shouldShowCulturalSurvey).toBeFalsy() + }) + + it('should return false when user has already filled cultural survey', async () => { + const { result } = renderHook(useShouldShowCulturalSurveyForBeneficiaryUser) + + await act(() => {}) + const shouldShowCulturalSurvey = result.current({ + ...beneficiaryUser, + needsToFillCulturalSurvey: false, + }) + + expect(shouldShowCulturalSurvey).toBeFalsy() + }) + + it('should return false when user has never seen cultural survey but is not beneficiary', async () => { + const { result } = renderHook(useShouldShowCulturalSurveyForBeneficiaryUser) + + await act(() => {}) + const shouldShowCulturalSurvey = result.current(nonBeneficiaryUser) + + expect(shouldShowCulturalSurvey).toBeFalsy() + }) + + it('should return true when user has never seen cultural survey', async () => { + const { result } = renderHook(useShouldShowCulturalSurveyForBeneficiaryUser) + + await act(() => {}) + const shouldShowCulturalSurvey = result.current(beneficiaryUser) + + expect(shouldShowCulturalSurvey).toBeTruthy() + }) + + it('should return true when user has seen cultural survey twice', async () => { + storage.saveObject(CULTURAL_SURVEY_DISPLAYS_STORAGE_KEY, 2) + const { result } = renderHook(useShouldShowCulturalSurveyForBeneficiaryUser) + + await act(() => {}) + const shouldShowCulturalSurvey = result.current(beneficiaryUser) + + expect(shouldShowCulturalSurvey).toBeTruthy() + }) + + it('should return false when user has seen cultural survey more than twice', async () => { + storage.saveObject(CULTURAL_SURVEY_DISPLAYS_STORAGE_KEY, 3) + const { result } = renderHook(useShouldShowCulturalSurveyForBeneficiaryUser) + + await act(() => {}) + const shouldShowCulturalSurvey = result.current(beneficiaryUser) + + expect(shouldShowCulturalSurvey).toBeFalsy() + }) +}) diff --git a/src/shared/culturalSurvey/useShouldShowCulturalSurveyForBeneficiaryUser.ts b/src/shared/culturalSurvey/useShouldShowCulturalSurveyForBeneficiaryUser.ts new file mode 100644 index 00000000000..bf073849afc --- /dev/null +++ b/src/shared/culturalSurvey/useShouldShowCulturalSurveyForBeneficiaryUser.ts @@ -0,0 +1,39 @@ +import { useCallback, useEffect, useState } from 'react' + +import { UserProfileResponse } from 'api/gen' +import { useFeatureFlag } from 'libs/firebase/firestore/featureFlags/useFeatureFlag' +import { RemoteStoreFeatureFlags } from 'libs/firebase/firestore/types' +import { storage } from 'libs/storage' + +const MAX_NUMBER_OF_DISPLAYS = 3 + +export function useShouldShowCulturalSurveyForBeneficiaryUser() { + const isCulturalSurveyInIdentityCheck = useFeatureFlag( + RemoteStoreFeatureFlags.ENABLE_CULTURAL_SURVEY_MANDATORY + ) + const [numberOfDisplays, setNumberOfDisplays] = useState() + + useEffect(() => { + storage.readObject('times_cultural_survey_has_been_requested').then((value) => { + setNumberOfDisplays(value || 0) + }) + }, []) + + return useCallback( + (user?: UserProfileResponse) => { + const isNumberOfDisplaysUndefined = numberOfDisplays === undefined + if (isNumberOfDisplaysUndefined) { + return undefined + } + + if (isCulturalSurveyInIdentityCheck) { + return false + } + + const userNeedToFillSurvey = !!user?.needsToFillCulturalSurvey && user.isBeneficiary + const hasRemainingDisplays = numberOfDisplays < MAX_NUMBER_OF_DISPLAYS + return userNeedToFillSurvey && hasRemainingDisplays + }, + [numberOfDisplays, isCulturalSurveyInIdentityCheck] + ) +}