diff --git a/src/components/ProductTrainingContext/TOOLTIPS.ts b/src/components/ProductTrainingContext/TOOLTIPS.ts index b0bed79b96e39..0256c7f679884 100644 --- a/src/components/ProductTrainingContext/TOOLTIPS.ts +++ b/src/components/ProductTrainingContext/TOOLTIPS.ts @@ -22,7 +22,7 @@ type ShouldShowConditionProps = { type TooltipData = { content: Array<{text: TranslationPaths; isBold: boolean}>; - onHideTooltip: () => void; + onHideTooltip: (isDismissedUsingCloseButton?: boolean) => void; name: ProductTrainingTooltipName; priority: number; shouldShow: (props: ShouldShowConditionProps) => boolean; @@ -35,7 +35,7 @@ const TOOLTIPS: Record = { {text: 'productTrainingTooltip.conciergeLHNGBR.part1', isBold: false}, {text: 'productTrainingTooltip.conciergeLHNGBR.part2', isBold: true}, ], - onHideTooltip: () => dismissProductTraining(CONCEIRGE_LHN_GBR), + onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(CONCEIRGE_LHN_GBR, isDismissedUsingCloseButton), name: CONCEIRGE_LHN_GBR, priority: 1300, // TODO: CONCEIRGE_LHN_GBR tooltip will be replaced by a tooltip in the #admins room @@ -47,7 +47,7 @@ const TOOLTIPS: Record = { {text: 'productTrainingTooltip.saveSearchTooltip.part1', isBold: true}, {text: 'productTrainingTooltip.saveSearchTooltip.part2', isBold: false}, ], - onHideTooltip: () => dismissProductTraining(RENAME_SAVED_SEARCH), + onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(RENAME_SAVED_SEARCH, isDismissedUsingCloseButton), name: RENAME_SAVED_SEARCH, priority: 1250, shouldShow: ({shouldUseNarrowLayout}) => !shouldUseNarrowLayout, @@ -58,7 +58,7 @@ const TOOLTIPS: Record = { {text: 'productTrainingTooltip.globalCreateTooltip.part2', isBold: false}, {text: 'productTrainingTooltip.globalCreateTooltip.part3', isBold: false}, ], - onHideTooltip: () => dismissProductTraining(GLOBAL_CREATE_TOOLTIP), + onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(GLOBAL_CREATE_TOOLTIP, isDismissedUsingCloseButton), name: GLOBAL_CREATE_TOOLTIP, priority: 1200, shouldShow: () => true, @@ -69,7 +69,7 @@ const TOOLTIPS: Record = { {text: 'productTrainingTooltip.bottomNavInboxTooltip.part2', isBold: false}, {text: 'productTrainingTooltip.bottomNavInboxTooltip.part3', isBold: false}, ], - onHideTooltip: () => dismissProductTraining(BOTTOM_NAV_INBOX_TOOLTIP), + onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(BOTTOM_NAV_INBOX_TOOLTIP, isDismissedUsingCloseButton), name: BOTTOM_NAV_INBOX_TOOLTIP, priority: 900, shouldShow: () => true, @@ -80,7 +80,7 @@ const TOOLTIPS: Record = { {text: 'productTrainingTooltip.workspaceChatTooltip.part2', isBold: false}, {text: 'productTrainingTooltip.workspaceChatTooltip.part3', isBold: false}, ], - onHideTooltip: () => dismissProductTraining(LHN_WORKSPACE_CHAT_TOOLTIP), + onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(LHN_WORKSPACE_CHAT_TOOLTIP, isDismissedUsingCloseButton), name: LHN_WORKSPACE_CHAT_TOOLTIP, priority: 800, shouldShow: () => true, @@ -102,7 +102,7 @@ const TOOLTIPS: Record = { {text: 'productTrainingTooltip.scanTestTooltip.part4', isBold: true}, {text: 'productTrainingTooltip.scanTestTooltip.part5', isBold: false}, ], - onHideTooltip: () => dismissProductTraining(SCAN_TEST_TOOLTIP_MANAGER), + onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(SCAN_TEST_TOOLTIP_MANAGER, isDismissedUsingCloseButton), name: SCAN_TEST_TOOLTIP_MANAGER, priority: 1000, shouldShow: () => true, @@ -113,7 +113,7 @@ const TOOLTIPS: Record = { {text: 'productTrainingTooltip.scanTestTooltip.part7', isBold: true}, {text: 'productTrainingTooltip.scanTestTooltip.part8', isBold: false}, ], - onHideTooltip: () => dismissProductTraining(SCAN_TEST_CONFIRMATION), + onHideTooltip: (isDismissedUsingCloseButton = false) => dismissProductTraining(SCAN_TEST_CONFIRMATION, isDismissedUsingCloseButton), name: SCAN_TEST_CONFIRMATION, priority: 1100, shouldShow: () => true, diff --git a/src/components/ProductTrainingContext/index.tsx b/src/components/ProductTrainingContext/index.tsx index c877e1d45fbce..9b44460a2a4fb 100644 --- a/src/components/ProductTrainingContext/index.tsx +++ b/src/components/ProductTrainingContext/index.tsx @@ -4,6 +4,7 @@ import {useOnyx} from 'react-native-onyx'; import Button from '@components/Button'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; +import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; @@ -11,7 +12,10 @@ import useSidePanel from '@hooks/useSidePanel'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {parseFSAttributes} from '@libs/Fullstory'; +import getPlatform from '@libs/getPlatform'; import {hasCompletedGuidedSetupFlowSelector} from '@libs/onboardingSelectors'; +import isProductTrainingElementDismissed from '@libs/TooltipUtils'; +import variables from '@styles/variables'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; @@ -98,7 +102,7 @@ function ProductTrainingContextProvider({children}: ChildrenProps) { return false; } - const isDismissed = !!dismissedProductTraining?.[tooltipName]; + const isDismissed = isProductTrainingElementDismissed(tooltipName, dismissedProductTraining); if (isDismissed) { return false; @@ -203,6 +207,22 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou */ useLayoutEffect(parseFSAttributes, []); + const shouldShowProductTrainingTooltip = useMemo(() => { + return shouldShow && shouldRenderTooltip(tooltipName) && !shouldHideToolTip; + }, [shouldRenderTooltip, tooltipName, shouldShow, shouldHideToolTip]); + + const hideTooltip = useCallback( + (isDismissedUsingCloseButton = false) => { + if (!shouldShowProductTrainingTooltip) { + return; + } + const tooltip = TOOLTIPS[tooltipName]; + tooltip.onHideTooltip(isDismissedUsingCloseButton); + unregisterTooltip(tooltipName); + }, + [tooltipName, shouldShowProductTrainingTooltip, unregisterTooltip], + ); + const renderProductTrainingTooltip = useCallback(() => { const tooltip = TOOLTIPS[tooltipName]; return ( @@ -218,7 +238,8 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou styles.flexWrap, styles.textAlignCenter, styles.gap3, - styles.p2, + styles.pv2, + styles.ph1, ]} > + {!tooltip?.shouldRenderActionButtons && ( + { + hideTooltip(true); + } + : undefined + } + // For other platforms, we stick with `onPress`. + onPress={ + getPlatform() !== CONST.PLATFORM.ANDROID + ? () => { + hideTooltip(true); + } + : undefined + } + shouldUseAutoHitSlop + accessibilityLabel={translate('productTrainingTooltip.scanTestTooltip.noThanks')} + role={CONST.ROLE.BUTTON} + > + + + )} {!!tooltip?.shouldRenderActionButtons && ( @@ -258,42 +310,35 @@ const useProductTrainingContext = (tooltipName: ProductTrainingTooltipName, shou ); }, [ - config.onConfirm, - config.onDismiss, + tooltipName, styles.alignItemsCenter, - styles.flex1, styles.flexRow, + styles.justifyContentStart, + styles.justifyContentCenter, styles.flexWrap, + styles.textAlignCenter, styles.gap3, - styles.justifyContentBetween, - styles.justifyContentCenter, - styles.mw100, - styles.p2, - styles.productTrainingTooltipText, styles.pv2, - styles.textAlignCenter, - styles.textBold, + styles.ph1, + styles.productTrainingTooltipText, styles.textWrap, - styles.gap2, - styles.justifyContentStart, + styles.mw100, + styles.flex1, + styles.justifyContentBetween, styles.ph2, + styles.gap2, + styles.textBold, theme.tooltipHighlightText, - tooltipName, + theme.icon, translate, + config.onConfirm, + config.onDismiss, + hideTooltip, ]); - const shouldShowProductTrainingTooltip = useMemo(() => { - return shouldShow && shouldRenderTooltip(tooltipName) && !shouldHideToolTip; - }, [shouldRenderTooltip, tooltipName, shouldShow, shouldHideToolTip]); - const hideProductTrainingTooltip = useCallback(() => { - if (!shouldShowProductTrainingTooltip) { - return; - } - const tooltip = TOOLTIPS[tooltipName]; - tooltip.onHideTooltip(); - unregisterTooltip(tooltipName); - }, [tooltipName, shouldShowProductTrainingTooltip, unregisterTooltip]); + hideTooltip(false); + }, [hideTooltip]); return { renderProductTrainingTooltip, diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts index 0aaa8ddad9d0a..811a1dae4d2e4 100644 --- a/src/hooks/useOnboardingFlow.ts +++ b/src/hooks/useOnboardingFlow.ts @@ -6,6 +6,7 @@ import {startOnboardingFlow} from '@libs/actions/Welcome/OnboardingFlow'; import Navigation from '@libs/Navigation/Navigation'; import {hasCompletedGuidedSetupFlowSelector, tryNewDotOnyxSelector} from '@libs/onboardingSelectors'; import {buildCannedSearchQuery} from '@libs/SearchQueryUtils'; +import isProductTrainingElementDismissed from '@libs/TooltipUtils'; import CONFIG from '@src/CONFIG'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -45,8 +46,7 @@ function useOnboardingFlowRouter() { if (CONFIG.IS_HYBRID_APP && isLoadingOnyxValue(isSingleNewDotEntryMetadata)) { return; } - - if (hasBeenAddedToNudgeMigration && !dismissedProductTraining?.migratedUserWelcomeModal) { + if (hasBeenAddedToNudgeMigration && !isProductTrainingElementDismissed('migratedUserWelcomeModal', dismissedProductTraining)) { const defaultCannedQuery = buildCannedSearchQuery(); const query = defaultCannedQuery; Navigation.navigate(ROUTES.SEARCH_ROOT.getRoute({query})); diff --git a/src/libs/API/parameters/DismissProductTraining.ts b/src/libs/API/parameters/DismissProductTraining.ts index 6a82ad995294d..f3c066a5f9488 100644 --- a/src/libs/API/parameters/DismissProductTraining.ts +++ b/src/libs/API/parameters/DismissProductTraining.ts @@ -1,5 +1,6 @@ type DismissProductTrainingParams = { name: string; + dismissedMethod: 'x' | 'click'; }; export default DismissProductTrainingParams; diff --git a/src/libs/TooltipUtils.ts b/src/libs/TooltipUtils.ts new file mode 100644 index 0000000000000..aa2040ce035f5 --- /dev/null +++ b/src/libs/TooltipUtils.ts @@ -0,0 +1,8 @@ +import type {OnyxEntry} from 'react-native-onyx'; +import type {DismissedProductTraining} from '@src/types/onyx'; + +function isProductTrainingElementDismissed(elementName: keyof DismissedProductTraining, dismissedProductTraining: OnyxEntry) { + return typeof dismissedProductTraining?.[elementName] === 'string' ? !!dismissedProductTraining?.[elementName] : !!dismissedProductTraining?.[elementName]?.timestamp; +} + +export default isProductTrainingElementDismissed; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 39cae82f3e5ad..c47eab35e5cf3 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -4846,11 +4846,14 @@ function dismissChangePolicyModal() { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, value: { - [CONST.CHANGE_POLICY_TRAINING_MODAL]: DateUtils.getDBTime(date.valueOf()), + [CONST.CHANGE_POLICY_TRAINING_MODAL]: { + timestamp: DateUtils.getDBTime(date.valueOf()), + dismissedMethod: 'click', + }, }, }, ]; - API.write(WRITE_COMMANDS.DISMISS_PRODUCT_TRAINING, {name: CONST.CHANGE_POLICY_TRAINING_MODAL}, {optimisticData}); + API.write(WRITE_COMMANDS.DISMISS_PRODUCT_TRAINING, {name: CONST.CHANGE_POLICY_TRAINING_MODAL, dismissedMethod: 'click'}, {optimisticData}); } /** diff --git a/src/libs/actions/Welcome/index.ts b/src/libs/actions/Welcome/index.ts index a98b600e5baf1..e959d84c9c139 100644 --- a/src/libs/actions/Welcome/index.ts +++ b/src/libs/actions/Welcome/index.ts @@ -207,18 +207,22 @@ function setSelfTourViewed(shouldUpdateOnyxDataOnlyLocally = false) { API.write(WRITE_COMMANDS.SELF_TOUR_VIEWED, null, {optimisticData}); } -function dismissProductTraining(elementName: string) { +function dismissProductTraining(elementName: string, isDismissedUsingCloseButton = false) { const date = new Date(); + const dismissedMethod = isDismissedUsingCloseButton ? 'x' : 'click'; const optimisticData = [ { onyxMethod: Onyx.METHOD.MERGE, key: ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, value: { - [elementName]: DateUtils.getDBTime(date.valueOf()), + [elementName]: { + timestamp: DateUtils.getDBTime(date.valueOf()), + dismissedMethod, + }, }, }, ]; - API.write(WRITE_COMMANDS.DISMISS_PRODUCT_TRAINING, {name: elementName}, {optimisticData}); + API.write(WRITE_COMMANDS.DISMISS_PRODUCT_TRAINING, {name: elementName, dismissedMethod}, {optimisticData}); } export { diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index 60d34f6d08671..c4de07bca24b3 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -536,7 +536,7 @@ function IOURequestStepScan({ { onConfirm: setTestReceiptAndNavigate, onDismiss: () => { - dismissProductTraining(CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP); + dismissProductTraining(CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP, true); }, }, ); diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index 47363fd5f81dc..1e6193e980980 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -590,7 +590,7 @@ function IOURequestStepScan({ { onConfirm: setTestReceiptAndNavigate, onDismiss: () => { - dismissProductTraining(CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP); + dismissProductTraining(CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP, true); }, }, ); diff --git a/src/types/onyx/DismissedProductTraining.ts b/src/types/onyx/DismissedProductTraining.ts index d0bcdaebdc3e6..0c224fae8547e 100644 --- a/src/types/onyx/DismissedProductTraining.ts +++ b/src/types/onyx/DismissedProductTraining.ts @@ -10,6 +10,17 @@ const { SCAN_TEST_TOOLTIP_MANAGER, SCAN_TEST_CONFIRMATION, } = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES; + +/** + * This type is used to store the timestamp of when the user dismisses a product training ui elements. + */ +type DismissedProductTrainingElement = { + /** The timestamp of when the user dismissed the product training element. */ + timestamp: string; + + /** The method of how the user dismissed the product training element, click or x. */ + dismissedMethod: 'click' | 'x'; +}; /** * This type is used to store the timestamp of when the user dismisses a product training ui elements. */ @@ -17,54 +28,54 @@ type DismissedProductTraining = { /** * When user dismisses the nudgeMigration Welcome Modal, we store the timestamp here. */ - [CONST.MIGRATED_USER_WELCOME_MODAL]: string; + [CONST.MIGRATED_USER_WELCOME_MODAL]: DismissedProductTrainingElement; // TODO: CONCEIRGE_LHN_GBR tooltip will be replaced by a tooltip in the #admins room // https://github.com/Expensify/App/issues/57045#issuecomment-2701455668 /** * When user dismisses the conciergeLHNGBR product training tooltip, we store the timestamp here. */ - [CONCEIRGE_LHN_GBR]: string; + [CONCEIRGE_LHN_GBR]: DismissedProductTrainingElement; /** * When user dismisses the renameSavedSearch product training tooltip, we store the timestamp here. */ - [RENAME_SAVED_SEARCH]: string; + [RENAME_SAVED_SEARCH]: DismissedProductTrainingElement; /** * When user dismisses the bottomNavInboxTooltip product training tooltip, we store the timestamp here. */ - [BOTTOM_NAV_INBOX_TOOLTIP]: string; + [BOTTOM_NAV_INBOX_TOOLTIP]: DismissedProductTrainingElement; /** * When user dismisses the lhnWorkspaceChatTooltip product training tooltip, we store the timestamp here. */ - [LHN_WORKSPACE_CHAT_TOOLTIP]: string; + [LHN_WORKSPACE_CHAT_TOOLTIP]: DismissedProductTrainingElement; /** * When user dismisses the globalCreateTooltip product training tooltip, we store the timestamp here. */ - [GLOBAL_CREATE_TOOLTIP]: string; + [GLOBAL_CREATE_TOOLTIP]: DismissedProductTrainingElement; /** * When user dismisses the globalCreateTooltip product training tooltip, we store the timestamp here. */ - [SCAN_TEST_TOOLTIP]: string; + [SCAN_TEST_TOOLTIP]: DismissedProductTrainingElement; /** * When user dismisses the test manager tooltip product training tooltip, we store the timestamp here. */ - [SCAN_TEST_TOOLTIP_MANAGER]: string; + [SCAN_TEST_TOOLTIP_MANAGER]: DismissedProductTrainingElement; /** * When user dismisses the test manager on confirmantion page product training tooltip, we store the timestamp here. */ - [SCAN_TEST_CONFIRMATION]: string; + [SCAN_TEST_CONFIRMATION]: DismissedProductTrainingElement; /** * When user dismisses the ChangeReportPolicy feature training modal, we store the timestamp here. */ - [CONST.CHANGE_POLICY_TRAINING_MODAL]: string; + [CONST.CHANGE_POLICY_TRAINING_MODAL]: DismissedProductTrainingElement; }; export default DismissedProductTraining; diff --git a/tests/ui/components/ProductTrainingContextProvider.tsx b/tests/ui/components/ProductTrainingContextProvider.tsx index 66595066bc080..e7a67957f09aa 100644 --- a/tests/ui/components/ProductTrainingContextProvider.tsx +++ b/tests/ui/components/ProductTrainingContextProvider.tsx @@ -190,7 +190,9 @@ describe('ProductTrainingContextProvider', () => { Onyx.merge(ONYXKEYS.NVP_TRYNEWDOT, {nudgeMigration: {timestamp: new Date()}}); const date = new Date(); Onyx.set(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, { - migratedUserWelcomeModal: DateUtils.getDBTime(date.valueOf()), + migratedUserWelcomeModal: { + timestamp: DateUtils.getDBTime(date.valueOf()), + }, }); await waitForBatchedUpdatesWithAct(); @@ -209,8 +211,12 @@ describe('ProductTrainingContextProvider', () => { Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true}); const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP; Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, { - migratedUserWelcomeModal: DateUtils.getDBTime(date.valueOf()), - [testTooltip]: DateUtils.getDBTime(date.valueOf()), + migratedUserWelcomeModal: { + timestamp: DateUtils.getDBTime(date.valueOf()), + }, + [testTooltip]: { + timestamp: DateUtils.getDBTime(date.valueOf()), + }, }); await waitForBatchedUpdatesWithAct(); @@ -225,7 +231,9 @@ describe('ProductTrainingContextProvider', () => { Onyx.merge(ONYXKEYS.NVP_TRYNEWDOT, {nudgeMigration: {timestamp: new Date()}}); const date = new Date(); Onyx.set(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, { - migratedUserWelcomeModal: DateUtils.getDBTime(date.valueOf()), + migratedUserWelcomeModal: { + timestamp: DateUtils.getDBTime(date.valueOf()), + }, }); await waitForBatchedUpdatesWithAct(); const testTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.GLOBAL_CREATE_TOOLTIP; @@ -300,7 +308,9 @@ describe('ProductTrainingContextProvider', () => { Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true}); const date = new Date(); Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, { - migratedUserWelcomeModal: DateUtils.getDBTime(date.valueOf()), + migratedUserWelcomeModal: { + timestamp: DateUtils.getDBTime(date.valueOf()), + }, }); await waitForBatchedUpdatesWithAct(); @@ -329,8 +339,12 @@ describe('ProductTrainingContextProvider', () => { const lowPriorityTooltip = CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.LHN_WORKSPACE_CHAT_TOOLTIP; Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, { - migratedUserWelcomeModal: DateUtils.getDBTime(date.valueOf()), - [highPriorityTooltip]: DateUtils.getDBTime(date.valueOf()), + migratedUserWelcomeModal: { + timestamp: DateUtils.getDBTime(date.valueOf()), + }, + [highPriorityTooltip]: { + timestamp: DateUtils.getDBTime(date.valueOf()), + }, }); await waitForBatchedUpdatesWithAct(); @@ -353,7 +367,9 @@ describe('ProductTrainingContextProvider', () => { Onyx.merge(ONYXKEYS.NVP_ONBOARDING, {hasCompletedGuidedSetupFlow: true}); const date = new Date(); Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, { - migratedUserWelcomeModal: DateUtils.getDBTime(date.valueOf()), + migratedUserWelcomeModal: { + timestamp: DateUtils.getDBTime(date.valueOf()), + }, }); await waitForBatchedUpdatesWithAct(); @@ -374,7 +390,9 @@ describe('ProductTrainingContextProvider', () => { // When dismissing higher priority tooltip Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, { - [highPriorityTooltip]: DateUtils.getDBTime(date.valueOf()), + [highPriorityTooltip]: { + timestamp: DateUtils.getDBTime(date.valueOf()), + }, }); await waitForBatchedUpdatesWithAct(); diff --git a/tests/unit/OptionsListUtilsTest.ts b/tests/unit/OptionsListUtilsTest.ts index 0b9fb72a8a214..b7c5082426c46 100644 --- a/tests/unit/OptionsListUtilsTest.ts +++ b/tests/unit/OptionsListUtilsTest.ts @@ -685,7 +685,13 @@ describe('OptionsListUtils', () => { expect(options.personalDetails).toEqual(expect.arrayContaining([expect.objectContaining({login: CONST.EMAIL.MANAGER_MCTEST})])); return waitForBatchedUpdates() - .then(() => Onyx.set(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {[CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP]: new Date() as unknown as string})) + .then(() => + Onyx.set(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, { + [CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.SCAN_TEST_TOOLTIP]: { + timestamp: DateUtils.getDBTime(new Date().valueOf()), + }, + }), + ) .then(() => { // Manager McTest shouldn't be included to recipients when the user has already submitted an expense const optionsWhenUserAlreadySubmittedExpense = getValidOptions(