diff --git a/.github/libs/sanitizeStringForJSONParse.ts b/.github/libs/sanitizeStringForJSONParse.ts index 3fbdaa8661f8..ddb7549b0186 100644 --- a/.github/libs/sanitizeStringForJSONParse.ts +++ b/.github/libs/sanitizeStringForJSONParse.ts @@ -16,7 +16,7 @@ const replacer = (str: string): string => * Solution partly taken from SO user Gabriel Rodríguez Flores 🙇 * https://stackoverflow.com/questions/52789718/how-to-remove-special-characters-before-json-parse-while-file-reading */ -const sanitizeStringForJSONParse = (inputString: string): string => { +const sanitizeStringForJSONParse = (inputString: string | number | boolean | null | undefined): string => { if (typeof inputString !== 'string') { throw new TypeError('Input must me of type String'); } diff --git a/__mocks__/@react-navigation/native/index.ts b/__mocks__/@react-navigation/native/index.ts index 9a6680ba0b6e..0b7dda4621ad 100644 --- a/__mocks__/@react-navigation/native/index.ts +++ b/__mocks__/@react-navigation/native/index.ts @@ -3,9 +3,7 @@ import {useIsFocused as realUseIsFocused, useTheme as realUseTheme} from '@react // We only want these mocked for storybook, not jest const useIsFocused: typeof realUseIsFocused = process.env.NODE_ENV === 'test' ? realUseIsFocused : () => true; -// @ts-expect-error as we're mocking this function -const useTheme: typeof realUseTheme = process.env.NODE_ENV === 'test' ? realUseTheme : () => ({}); +const useTheme = process.env.NODE_ENV === 'test' ? realUseTheme : () => ({}); export * from '@react-navigation/core'; -export * from '@react-navigation/native'; export {useIsFocused, useTheme}; diff --git a/src/Expensify.tsx b/src/Expensify.tsx index e91a5223d7b6..6205afb9c03c 100644 --- a/src/Expensify.tsx +++ b/src/Expensify.tsx @@ -76,7 +76,9 @@ type ExpensifyOnyxProps = { type ExpensifyProps = ExpensifyOnyxProps; -const SplashScreenHiddenContext = React.createContext({}); +type SplashScreenHiddenContextType = {isSplashHidden?: boolean}; + +const SplashScreenHiddenContext = React.createContext({}); function Expensify({ isCheckingPublicRoom = true, diff --git a/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.tsx b/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.tsx index ee1c58999866..0c8af3dfc826 100644 --- a/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.tsx +++ b/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.tsx @@ -52,8 +52,7 @@ function BaseAnchorForAttachmentsOnly({style, source = '', displayName = '', dow }} onPressIn={onPressIn} onPressOut={onPressOut} - // @ts-expect-error TODO: Remove this once ShowContextMenuContext (https://github.com/Expensify/App/issues/24980) is migrated to TypeScript. - onLongPress={(event) => showContextMenuForReport(event, anchor, report.reportID, action, checkIfContextMenuActive, ReportUtils.isArchivedRoom(report))} + onLongPress={(event) => showContextMenuForReport(event, anchor, report?.reportID ?? '', action, checkIfContextMenuActive, ReportUtils.isArchivedRoom(report))} shouldUseHapticsOnLongPress accessibilityLabel={displayName} role={CONST.ROLE.BUTTON} diff --git a/src/components/PDFThumbnail/index.tsx b/src/components/PDFThumbnail/index.tsx index a5b911deb6ff..ce631f3b611f 100644 --- a/src/components/PDFThumbnail/index.tsx +++ b/src/components/PDFThumbnail/index.tsx @@ -1,4 +1,3 @@ -// @ts-expect-error - This line imports a module from 'pdfjs-dist' package which lacks TypeScript typings. import pdfWorkerSource from 'pdfjs-dist/legacy/build/pdf.worker'; import React, {useMemo} from 'react'; import {View} from 'react-native'; diff --git a/src/components/TabSelector/TabSelector.tsx b/src/components/TabSelector/TabSelector.tsx index 9fe1665f6b19..882d99f38e3d 100644 --- a/src/components/TabSelector/TabSelector.tsx +++ b/src/components/TabSelector/TabSelector.tsx @@ -68,7 +68,7 @@ function TabSelector({state, navigation, onTabPress = () => {}, position}: TabSe return position.interpolate({ inputRange, outputRange: inputRange.map((i) => (affectedTabs.includes(tabIndex) && i === tabIndex ? theme.border : theme.appBG)), - }); + }) as unknown as Animated.AnimatedInterpolation; } return theme.border; }, diff --git a/src/hooks/useAutoFocusInput.ts b/src/hooks/useAutoFocusInput.ts index e8e7c1187a63..c1f58901cee0 100644 --- a/src/hooks/useAutoFocusInput.ts +++ b/src/hooks/useAutoFocusInput.ts @@ -13,7 +13,6 @@ export default function useAutoFocusInput(): UseAutoFocusInput { const [isInputInitialized, setIsInputInitialized] = useState(false); const [isScreenTransitionEnded, setIsScreenTransitionEnded] = useState(false); - // @ts-expect-error TODO: Remove this when Expensify.js is migrated. const {isSplashHidden} = useContext(Expensify.SplashScreenHiddenContext); const inputRef = useRef(null); diff --git a/src/hooks/useTabNavigatorFocus/index.ts b/src/hooks/useTabNavigatorFocus/index.ts index 3fef0e53774f..f160f4670b26 100644 --- a/src/hooks/useTabNavigatorFocus/index.ts +++ b/src/hooks/useTabNavigatorFocus/index.ts @@ -64,7 +64,6 @@ function useTabNavigatorFocus({tabIndex}: UseTabNavigatorFocusParams): boolean { // We need to get the position animation value on component initialization to determine // if the tab is focused or not. Since it's an Animated.Value the only synchronous way // to retrieve the value is to use a private method. - // @ts-expect-error -- __getValue is a private method // eslint-disable-next-line no-underscore-dangle const initialTabPositionValue = tabPositionAnimation.__getValue(); diff --git a/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx index 6680ea302441..6e1d154ff350 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/BottomTabNavigator.tsx @@ -3,7 +3,7 @@ import type {StackNavigationOptions} from '@react-navigation/stack'; import React from 'react'; import createCustomBottomTabNavigator from '@libs/Navigation/AppNavigator/createCustomBottomTabNavigator'; import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRoute'; -import type {BottomTabNavigatorParamList} from '@libs/Navigation/types'; +import type {BottomTabNavigatorParamList, CentralPaneName, NavigationPartialRoute, RootStackParamList} from '@libs/Navigation/types'; import SidebarScreen from '@pages/home/sidebar/SidebarScreen'; import SearchPageBottomTab from '@pages/Search/SearchPageBottomTab'; import SCREENS from '@src/SCREENS'; @@ -19,7 +19,7 @@ const screenOptions: StackNavigationOptions = { }; function BottomTabNavigator() { - const activeRoute = useNavigationState(getTopmostCentralPaneRoute); + const activeRoute = useNavigationState | undefined>(getTopmostCentralPaneRoute); return ( diff --git a/src/libs/Navigation/AppNavigator/getPartialStateDiff.ts b/src/libs/Navigation/AppNavigator/getPartialStateDiff.ts index 4c18e161c9a9..5061c7500742 100644 --- a/src/libs/Navigation/AppNavigator/getPartialStateDiff.ts +++ b/src/libs/Navigation/AppNavigator/getPartialStateDiff.ts @@ -53,7 +53,7 @@ function getPartialStateDiff(state: State, templateState: St (stateTopmostCentralPane && templateStateTopmostCentralPane && stateTopmostCentralPane.name !== templateStateTopmostCentralPane.name && - !shallowCompare(stateTopmostCentralPane.params, templateStateTopmostCentralPane.params)) + !shallowCompare(stateTopmostCentralPane.params as Record | undefined, templateStateTopmostCentralPane.params as Record | undefined)) ) { // We need to wrap central pane routes in the central pane navigator. diff[NAVIGATORS.CENTRAL_PANE_NAVIGATOR] = templateStateTopmostCentralPane; @@ -73,7 +73,7 @@ function getPartialStateDiff(state: State, templateState: St (stateTopmostFullScreen && templateStateTopmostFullScreen && stateTopmostFullScreen.name !== templateStateTopmostFullScreen.name && - !shallowCompare(stateTopmostFullScreen.params, templateStateTopmostFullScreen.params)) + !shallowCompare(stateTopmostFullScreen.params as Record | undefined, templateStateTopmostFullScreen.params as Record | undefined)) ) { diff[NAVIGATORS.FULL_SCREEN_NAVIGATOR] = fullScreenDiff; } diff --git a/src/libs/Navigation/linkTo.ts b/src/libs/Navigation/linkTo.ts index 45a8609482ca..50050e4b8ff4 100644 --- a/src/libs/Navigation/linkTo.ts +++ b/src/libs/Navigation/linkTo.ts @@ -160,8 +160,8 @@ export default function linkTo(navigation: NavigationContainerRef value === undefined), - omitBy(action.payload.params?.params, (value) => value === undefined), + omitBy(topmostCentralPaneRoute?.params as Record | undefined, (value) => value === undefined), + omitBy(action.payload.params?.params as Record | undefined, (value) => value === undefined), ); // In case if type is 'FORCED_UP' we replace current screen with the provided. This means the current screen no longer exists in the stack if (type === CONST.NAVIGATION.TYPE.FORCED_UP) { diff --git a/src/libs/ObjectUtils.ts b/src/libs/ObjectUtils.ts index 9ffa461506c8..644fe1c7596e 100644 --- a/src/libs/ObjectUtils.ts +++ b/src/libs/ObjectUtils.ts @@ -1,11 +1,11 @@ -// eslint-disable-next-line @typescript-eslint/ban-types -const shallowCompare = (obj1?: object, obj2?: object) => { +const shallowCompare = (obj1?: Record, obj2?: Record): boolean => { if (!obj1 && !obj2) { return true; } if (obj1 && obj2) { - // @ts-expect-error we know that obj1 and obj2 are params of a route. - return Object.keys(obj1).length === Object.keys(obj2).length && Object.keys(obj1).every((key) => obj1[key] === obj2[key]); + const keys1 = Object.keys(obj1); + const keys2 = Object.keys(obj2); + return keys1.length === keys2.length && keys1.every((key) => obj1[key] === obj2[key]); } return false; }; diff --git a/src/libs/ReportActionComposeFocusManager.ts b/src/libs/ReportActionComposeFocusManager.ts index 11c1fd04329f..b25274ef2946 100644 --- a/src/libs/ReportActionComposeFocusManager.ts +++ b/src/libs/ReportActionComposeFocusManager.ts @@ -1,11 +1,12 @@ import React from 'react'; +import type {MutableRefObject} from 'react'; import type {TextInput} from 'react-native'; import ROUTES from '@src/ROUTES'; import Navigation from './Navigation/Navigation'; type FocusCallback = (shouldFocusForNonBlurInputOnTapOutside?: boolean) => void; -const composerRef = React.createRef(); +const composerRef: MutableRefObject = React.createRef(); const editComposerRef = React.createRef(); // There are two types of composer: general composer (edit composer) and main composer. // The general composer callback will take priority if it exists. diff --git a/src/libs/Url.ts b/src/libs/Url.ts index 80ca98c712cf..69894147a242 100644 --- a/src/libs/Url.ts +++ b/src/libs/Url.ts @@ -1,4 +1,5 @@ import 'react-native-url-polyfill/auto'; +import type {Route} from '@src/ROUTES'; /** * Add / to the end of any URL if not present @@ -48,12 +49,12 @@ function appendParam(url: string, paramName: string, paramValue: string) { // If parameter exists, replace it if (url.includes(`${paramName}=`)) { const regex = new RegExp(`${paramName}=([^&]*)`); - return url.replace(regex, `${paramName}=${paramValue}`); + return url.replace(regex, `${paramName}=${paramValue}`) as Route; } // If parameter doesn't exist, append it const separator = url.includes('?') ? '&' : '?'; - return `${url}${separator}${paramName}=${paramValue}`; + return `${url}${separator}${paramName}=${paramValue}` as Route; } function hasURL(text: string) { diff --git a/src/libs/migrations/NVPMigration.ts b/src/libs/migrations/NVPMigration.ts index 9ab774328f78..fc5bce22641f 100644 --- a/src/libs/migrations/NVPMigration.ts +++ b/src/libs/migrations/NVPMigration.ts @@ -1,6 +1,9 @@ import after from 'lodash/after'; import Onyx from 'react-native-onyx'; +import type {KeyValueMapping, OnyxEntry} from 'react-native-onyx'; +import type {Account} from 'src/types/onyx'; import ONYXKEYS from '@src/ONYXKEYS'; +import type {OnyxKey} from '@src/ONYXKEYS'; // These are the oldKeyName: newKeyName of the NVPs we can migrate without any processing const migrations = { @@ -27,35 +30,30 @@ export default function () { for (const [oldKey, newKey] of Object.entries(migrations)) { const connectionID = Onyx.connect({ - // @ts-expect-error oldKey is a variable - key: oldKey, + key: oldKey as OnyxKey, callback: (value) => { Onyx.disconnect(connectionID); if (value === null) { resolveWhenDone(); return; } - // @ts-expect-error These keys are variables, so we can't check the type Onyx.multiSet({ [newKey]: value, [oldKey]: null, - }).then(resolveWhenDone); + } as KeyValueMapping).then(resolveWhenDone); }, }); } const connectionIDAccount = Onyx.connect({ key: ONYXKEYS.ACCOUNT, - callback: (value) => { + callback: (value: OnyxEntry) => { Onyx.disconnect(connectionIDAccount); - // @ts-expect-error we are removing this property, so it is not in the type anymore if (!value?.activePolicyID) { resolveWhenDone(); return; } - // @ts-expect-error we are removing this property, so it is not in the type anymore const activePolicyID = value.activePolicyID; const newValue = {...value}; - // @ts-expect-error we are removing this property, so it is not in the type anymore delete newValue.activePolicyID; Onyx.multiSet({ [ONYXKEYS.NVP_ACTIVE_POLICY_ID]: activePolicyID, @@ -72,14 +70,12 @@ export default function () { resolveWhenDone(); return; } - const newValue = {}; + const newValue = {} as Record; for (const key of Object.keys(value)) { - // @ts-expect-error We have no fixed types here newValue[`nvp_${key}`] = value[key]; - // @ts-expect-error We have no fixed types here newValue[key] = null; } - Onyx.multiSet(newValue).then(resolveWhenDone); + Onyx.multiSet(newValue as KeyValueMapping).then(resolveWhenDone); }, }); }); diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.tsx b/src/pages/EnablePayments/AdditionalDetailsStep.tsx index 867bbadf9ea7..4756db4d43ec 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.tsx +++ b/src/pages/EnablePayments/AdditionalDetailsStep.tsx @@ -206,8 +206,7 @@ function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIO placeholder={translate('common.phoneNumberPlaceholder')} shouldSaveDraft /> - {/* @ts-expect-error TODO: Remove this once DatePicker (https://github.com/Expensify/App/issues/25148) is migrated to TypeScript. */} - + {translate('beneficialOwnerInfoStep.enterTheDateOfBirthOfTheOwner')} - {/* @ts-expect-error TODO: Remove this once DatePicker (https://github.com/Expensify/App/issues/25148) is migrated to TypeScript. */} - + {translate('businessInfoStep.selectYourCompanysIncorporationDate')} - {/* @ts-expect-error TODO: Remove this once DatePicker (https://github.com/Expensify/App/issues/25148) is migrated to TypeScript. */} - + {translate('personalInfoStep.enterYourDateOfBirth')} - {/* @ts-expect-error TODO: Remove this once DatePicker (https://github.com/Expensify/App/issues/25148) is migrated to TypeScript. */} - + { - // @ts-expect-error need to reassign this ref ReportActionComposeFocusManager.composerRef.current = el; textInputRef.current = el; if (typeof animatedRef === 'function') { @@ -649,7 +648,6 @@ function ComposerWithSuggestions( const unsubscribeNavigationFocus = navigation.addListener('focus', () => { KeyDownListener.addKeyDownPressListener(focusComposerOnKeyPress); // The report isn't unmounted and can be focused again after going back from another report so we should update the composerRef again - // @ts-expect-error need to reassign this ref ReportActionComposeFocusManager.composerRef.current = textInputRef.current; setUpComposeFocusManager(); }); diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index 90d8460a133e..adf358ab416d 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -49,7 +49,7 @@ import SendButton from './SendButton'; type ComposerRef = { blur: () => void; focus: (shouldDelay?: boolean) => void; - replaceSelectionWithText: (text: string, shouldAddTrailSpace: boolean) => void; + replaceSelectionWithText: EmojiPickerActions.OnEmojiSelected; prepareCommentAndResetComposer: () => string; isFocused: () => boolean; }; @@ -73,9 +73,9 @@ type ReportActionComposeOnyxProps = { type ReportActionComposeProps = ReportActionComposeOnyxProps & WithCurrentUserPersonalDetailsProps & - Pick & { + Pick & { /** A method to call when the form is submitted */ - onSubmit: (newComment: string | undefined) => void; + onSubmit: (newComment: string) => void; /** The report currently being looked at */ report: OnyxEntry; @@ -91,6 +91,9 @@ type ReportActionComposeProps = ReportActionComposeOnyxProps & /** A method to call when the input is blur */ onComposerBlur?: () => void; + + /** Should the input be disabled */ + disabled?: boolean; }; // We want consistent auto focus behavior on input between native and mWeb so we have some auto focus management code that will @@ -102,7 +105,7 @@ const willBlurTextInputOnTapOutside = willBlurTextInputOnTapOutsideFunc(); function ReportActionCompose({ blockedFromConcierge, currentUserPersonalDetails = {}, - disabled, + disabled = false, isComposerFullSize = false, onSubmit, pendingAction, @@ -482,7 +485,6 @@ function ReportActionCompose({ composerRef.current?.replaceSelectionWithText(...args)} emojiPickerID={report?.reportID} shiftVertical={emojiShiftVertical} diff --git a/src/pages/home/report/ReportActionItemMessageEdit.tsx b/src/pages/home/report/ReportActionItemMessageEdit.tsx index 7477c6c02eba..6cb03e8dae05 100644 --- a/src/pages/home/report/ReportActionItemMessageEdit.tsx +++ b/src/pages/home/report/ReportActionItemMessageEdit.tsx @@ -419,8 +419,8 @@ function ReportActionItemMessageEdit( }} onBlur={(event: NativeSyntheticEvent) => { setIsFocused(false); - // @ts-expect-error TODO: TextInputFocusEventData doesn't contain relatedTarget. const relatedTargetId = event.nativeEvent?.relatedTarget?.id; + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing if ((relatedTargetId && [messageEditInput, emojiButtonID].includes(relatedTargetId)) || EmojiPickerAction.isEmojiPickerVisible()) { return; } diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index 359d6ba93c15..b3bddb9ba499 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -161,7 +161,6 @@ function ReportFooter({ { const {isSmallScreenWidth} = useWindowDimensions(); const isFocused = useIsFocusedOriginal(); - const topmostCentralPane = useNavigationState(getTopmostCentralPaneRoute); + const topmostCentralPane = useNavigationState | undefined>(getTopmostCentralPaneRoute); return isFocused || (topmostCentralPane?.name === SCREENS.SEARCH.CENTRAL_PANE && isSmallScreenWidth); }; diff --git a/src/pages/iou/request/step/IOURequestStepScan/NavigationAwareCamera/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/NavigationAwareCamera/Camera.tsx similarity index 66% rename from src/pages/iou/request/step/IOURequestStepScan/NavigationAwareCamera/index.native.tsx rename to src/pages/iou/request/step/IOURequestStepScan/NavigationAwareCamera/Camera.tsx index beeb8938e917..e24901dcaa51 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/NavigationAwareCamera/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/NavigationAwareCamera/Camera.tsx @@ -1,15 +1,15 @@ import React from 'react'; import type {ForwardedRef} from 'react'; -import {Camera} from 'react-native-vision-camera'; +import {Camera as VisionCamera} from 'react-native-vision-camera'; import useTabNavigatorFocus from '@hooks/useTabNavigatorFocus'; import type {NavigationAwareCameraNativeProps} from './types'; // Wraps a camera that will only be active when the tab is focused or as soon as it starts to become focused. -function NavigationAwareCamera({cameraTabIndex, ...props}: NavigationAwareCameraNativeProps, ref: ForwardedRef) { +function Camera({cameraTabIndex, ...props}: NavigationAwareCameraNativeProps, ref: ForwardedRef) { const isCameraActive = useTabNavigatorFocus({tabIndex: cameraTabIndex}); return ( - ) { +function WebCamera({torchOn, onTorchAvailability, cameraTabIndex, ...props}: NavigationAwareCameraProps, ref: ForwardedRef) { const shouldShowCamera = useTabNavigatorFocus({ tabIndex: cameraTabIndex, }); @@ -26,6 +26,6 @@ function NavigationAwareCamera({torchOn, onTorchAvailability, cameraTabIndex, .. ); } -NavigationAwareCamera.displayName = 'NavigationAwareCamera'; +WebCamera.displayName = 'NavigationAwareCamera'; -export default React.forwardRef(NavigationAwareCamera); +export default React.forwardRef(WebCamera); diff --git a/src/pages/iou/request/step/IOURequestStepScan/NavigationAwareCamera/types.ts b/src/pages/iou/request/step/IOURequestStepScan/NavigationAwareCamera/types.ts index 0e6845792122..555cb7a92367 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/NavigationAwareCamera/types.ts +++ b/src/pages/iou/request/step/IOURequestStepScan/NavigationAwareCamera/types.ts @@ -12,7 +12,7 @@ type NavigationAwareCameraProps = WebcamProps & { cameraTabIndex: number; }; -type NavigationAwareCameraNativeProps = CameraProps & { +type NavigationAwareCameraNativeProps = Omit & { cameraTabIndex: number; }; diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index bafad583bd74..c022a079df65 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -36,7 +36,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Receipt} from '@src/types/onyx/Transaction'; import CameraPermission from './CameraPermission'; -import NavigationAwareCamera from './NavigationAwareCamera'; +import NavigationAwareCamera from './NavigationAwareCamera/Camera'; import type {IOURequestStepOnyxProps, IOURequestStepScanProps} from './types'; function IOURequestStepScan({ @@ -480,8 +480,7 @@ function IOURequestStepScan({ { setCameraPermissionState('granted'); @@ -110,7 +109,6 @@ function IOURequestStepScan({ let deviceId; for (const track of stream.getTracks()) { const setting = track.getSettings(); - // @ts-expect-error there is a type mismatch in typescipt types for MediaStreamTrack microsoft/TypeScript#39010 if (setting.zoom === 1) { deviceId = setting.deviceId; break; @@ -154,7 +152,6 @@ function IOURequestStepScan({ } navigator.permissions .query({ - // @ts-expect-error camera does exist in PermissionName name: 'camera', }) .then((permissionState) => { @@ -464,7 +461,6 @@ function IOURequestStepScan({ return; } trackRef.current.applyConstraints({ - // @ts-expect-error there is a type mismatch in typescipt types for MediaStreamTrack microsoft/TypeScript#39010 advanced: [{torch: false}], }); }, []); @@ -473,7 +469,6 @@ function IOURequestStepScan({ if (trackRef.current && isFlashLightOn) { trackRef.current .applyConstraints({ - // @ts-expect-error there is a type mismatch in typescipt types for MediaStreamTrack microsoft/TypeScript#39010 advanced: [{torch: true}], }) .then(() => { diff --git a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx index 32f72b015fa4..bf1bb8ad197e 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx @@ -91,13 +91,12 @@ function StateSelectionPage() { shouldShowBackButton onBackButtonPress={() => { const backTo = params?.backTo ?? ''; - let backToRoute = ''; + let backToRoute: Route | undefined; if (backTo) { backToRoute = appendParam(backTo, 'state', currentState ?? ''); } - // @ts-expect-error Navigation.goBack does take a param Navigation.goBack(backToRoute); }} /> diff --git a/src/setup/addUtilsToWindow.ts b/src/setup/addUtilsToWindow.ts index d2d11e138431..eb34d33364eb 100644 --- a/src/setup/addUtilsToWindow.ts +++ b/src/setup/addUtilsToWindow.ts @@ -2,6 +2,7 @@ import Onyx from 'react-native-onyx'; import * as Environment from '@libs/Environment/Environment'; import markAllPolicyReportsAsRead from '@libs/markAllPolicyReportsAsRead'; import * as Session from '@userActions/Session'; +import type {OnyxKey} from '@src/ONYXKEYS'; /** * This is used to inject development/debugging utilities into the window object on web and desktop. @@ -17,10 +18,9 @@ export default function addUtilsToWindow() { return; } - window.Onyx = Onyx; + window.Onyx = Onyx as typeof Onyx & {get: (key: OnyxKey) => Promise; log: (key: OnyxKey) => void}; // We intentionally do not offer an Onyx.get API because we believe it will lead to code patterns we don't want to use in this repo, but we can offer a workaround for the sake of debugging - // @ts-expect-error TS233 - injecting additional utility for use in runtime debugging, should not be used in any compiled code window.Onyx.get = function (key) { return new Promise((resolve) => { // eslint-disable-next-line rulesdir/prefer-onyx-connect-in-libs @@ -35,9 +35,7 @@ export default function addUtilsToWindow() { }); }; - // @ts-expect-error TS233 - injecting additional utility for use in runtime debugging, should not be used in any compiled code window.Onyx.log = function (key) { - // @ts-expect-error TS2339 - using additional utility injected above window.Onyx.get(key).then((value) => { /* eslint-disable-next-line no-console */ console.log(value); diff --git a/src/stories/Form.stories.tsx b/src/stories/Form.stories.tsx index 8a1c2ca0b8f0..f4e89f6766f0 100644 --- a/src/stories/Form.stories.tsx +++ b/src/stories/Form.stories.tsx @@ -1,5 +1,6 @@ import type {Meta, StoryFn} from '@storybook/react'; import React, {useState} from 'react'; +import type {ComponentType} from 'react'; import {View} from 'react-native'; import AddressSearch from '@components/AddressSearch'; import CheckboxWithLabel from '@components/CheckboxWithLabel'; @@ -36,29 +37,17 @@ type StorybookFormErrors = Partial>; const STORYBOOK_FORM_ID = 'TestForm' as keyof OnyxFormValuesMapping; -/** - * We use the Component Story Format for writing stories. Follow the docs here: - * - * https://storybook.js.org/docs/react/writing-stories/introduction#component-story-format - */ const story: Meta = { title: 'Components/Form', component: FormProvider, subcomponents: { - // @ts-expect-error Subcomponent passes props with unknown type causing a TS error - InputWrapper, - // @ts-expect-error Subcomponent passes props with unknown type causing a TS error - TextInput, - // @ts-expect-error Subcomponent passes props with unknown type causing a TS error - AddressSearch, - // @ts-expect-error Subcomponent passes props with unknown type causing a TS error - CheckboxWithLabel, - // @ts-expect-error Subcomponent passes props with unknown type causing a TS error - Picker, - // @ts-expect-error Subcomponent passes props with unknown type causing a TS error - StateSelector, - // @ts-expect-error Subcomponent passes props with unknown type causing a TS error - DatePicker, + InputWrapper: InputWrapper as ComponentType, + TextInput: TextInput as ComponentType, + AddressSearch: AddressSearch as ComponentType, + CheckboxWithLabel: CheckboxWithLabel as ComponentType, + Picker: Picker as ComponentType, + StateSelector: StateSelector as ComponentType, + DatePicker: DatePicker as ComponentType, }, }; diff --git a/src/types/modules/dom.d.ts b/src/types/modules/dom.d.ts index 60bd9c9ae983..029b4b3d6de5 100644 --- a/src/types/modules/dom.d.ts +++ b/src/types/modules/dom.d.ts @@ -19,6 +19,51 @@ declare global { AppleIDSignInOnSuccess: AppleIDSignInOnSuccessEvent; AppleIDSignInOnFailure: AppleIDSignInOnFailureEvent; } + + // eslint-disable-next-line @typescript-eslint/consistent-type-definitions + interface Permissions { + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Permissions/query) */ + query(permissionDesc: {name: 'geolocation' | 'notifications' | 'persistent-storage' | 'push' | 'screen-wake-lock' | 'xr-spatial-tracking' | 'camera'}): Promise; + } + + // eslint-disable-next-line @typescript-eslint/consistent-type-definitions + interface MediaTrackConstraintSet { + aspectRatio?: ConstrainDouble; + autoGainControl?: ConstrainBoolean; + channelCount?: ConstrainULong; + deviceId?: ConstrainDOMString; + displaySurface?: ConstrainDOMString; + echoCancellation?: ConstrainBoolean; + facingMode?: ConstrainDOMString; + frameRate?: ConstrainDouble; + groupId?: ConstrainDOMString; + height?: ConstrainULong; + noiseSuppression?: ConstrainBoolean; + sampleRate?: ConstrainULong; + sampleSize?: ConstrainULong; + width?: ConstrainULong; + zoom?: {ideal: number}; + torch?: boolean; + } + + // eslint-disable-next-line @typescript-eslint/consistent-type-definitions + interface MediaTrackSettings { + aspectRatio?: number; + autoGainControl?: boolean; + channelCount?: number; + deviceId?: string; + displaySurface?: string; + echoCancellation?: boolean; + facingMode?: string; + frameRate?: number; + groupId?: string; + height?: number; + noiseSuppression?: boolean; + sampleRate?: number; + sampleSize?: number; + width?: number; + zoom?: number; + } } export type {AppleIDSignInOnFailureEvent, AppleIDSignInOnSuccessEvent}; diff --git a/src/types/modules/pdf.worker.d.ts b/src/types/modules/pdf.worker.d.ts new file mode 100644 index 000000000000..307d0ff53a63 --- /dev/null +++ b/src/types/modules/pdf.worker.d.ts @@ -0,0 +1 @@ +declare module 'pdfjs-dist/legacy/build/pdf.worker'; diff --git a/src/types/modules/react-native-onyx.d.ts b/src/types/modules/react-native-onyx.d.ts index 8498b03ec933..453f707165e1 100644 --- a/src/types/modules/react-native-onyx.d.ts +++ b/src/types/modules/react-native-onyx.d.ts @@ -1,4 +1,5 @@ import type Onyx from 'react-native-onyx'; +import type {CollectionKeyBase} from 'react-native-onyx/dist/types'; import type {OnyxCollectionKey, OnyxFormDraftKey, OnyxFormKey, OnyxValueKey, OnyxValues} from '@src/ONYXKEYS'; declare module 'react-native-onyx' { @@ -9,11 +10,13 @@ declare module 'react-native-onyx' { values: OnyxValues; } } - declare global { // Global methods for Onyx key management for debugging purposes // eslint-disable-next-line @typescript-eslint/consistent-type-definitions interface Window { - Onyx: typeof Onyx; + Onyx: typeof Onyx & { + get: (key: CollectionKeyBase) => Promise; + log: (key: CollectionKeyBase) => void; + }; } } diff --git a/src/types/modules/react-native.d.ts b/src/types/modules/react-native.d.ts index effbdd9d28fa..a9ff35c97343 100644 --- a/src/types/modules/react-native.d.ts +++ b/src/types/modules/react-native.d.ts @@ -196,6 +196,14 @@ declare module 'react-native' { touchHistory: TouchHistory; }; + interface TextInputFocusEventData extends TargetedEvent { + text: string; + eventCount: number; + relatedTarget?: { + id?: string; + }; + } + // https://necolas.github.io/react-native-web/docs/interactions/#responderevent-props-api // Extracted from react-native-web, packages/react-native-web/src/modules/useResponderEvents/ResponderSystem.js interface ResponderProps { @@ -360,4 +368,11 @@ declare module 'react-native' { BootSplash: BootSplashModule; HybridAppModule: HybridAppModule; } + + namespace Animated { + interface AnimatedInterpolation extends AnimatedWithChildren { + interpolate(config: InterpolationConfigType): AnimatedInterpolation; + __getValue: () => OutputT; + } + } } diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 67525f2e2318..ac320729b2b7 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -24,6 +24,7 @@ import type {ReportActionBase} from '@src/types/onyx/ReportAction'; import {toCollectionDataSet} from '@src/types/utils/CollectionDataSet'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import PusherHelper from '../utils/PusherHelper'; +import type {MockFetch} from '../utils/TestHelper'; import * as TestHelper from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; import waitForNetworkPromises from '../utils/waitForNetworkPromises'; @@ -60,9 +61,10 @@ describe('actions/IOU', () => { }); }); + let mockFetch: MockFetch; beforeEach(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); + mockFetch = fetch as MockFetch; return Onyx.clear().then(waitForBatchedUpdates); }); @@ -77,179 +79,175 @@ describe('actions/IOU', () => { let transactionID: string | undefined; let transactionThread: OnyxEntry; let transactionThreadCreatedAction: OnyxEntry; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); IOU.requestMoney({reportID: ''}, amount, CONST.CURRENCY.USD, '', merchant, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment, {}); - return ( - waitForBatchedUpdates() - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT, - waitForCollectionCallback: true, - callback: (allReports) => { - Onyx.disconnect(connectionID); + return waitForBatchedUpdates() + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (allReports) => { + Onyx.disconnect(connectionID); - // A chat report, a transaction thread, and an iou report should be created - const chatReports = Object.values(allReports ?? {}).filter((report) => report?.type === CONST.REPORT.TYPE.CHAT); - const iouReports = Object.values(allReports ?? {}).filter((report) => report?.type === CONST.REPORT.TYPE.IOU); - expect(Object.keys(chatReports).length).toBe(2); - expect(Object.keys(iouReports).length).toBe(1); - const chatReport = chatReports[0]; - const transactionThreadReport = chatReports[1]; - const iouReport = iouReports[0]; - iouReportID = iouReport?.reportID; - transactionThread = transactionThreadReport; + // A chat report, a transaction thread, and an iou report should be created + const chatReports = Object.values(allReports ?? {}).filter((report) => report?.type === CONST.REPORT.TYPE.CHAT); + const iouReports = Object.values(allReports ?? {}).filter((report) => report?.type === CONST.REPORT.TYPE.IOU); + expect(Object.keys(chatReports).length).toBe(2); + expect(Object.keys(iouReports).length).toBe(1); + const chatReport = chatReports[0]; + const transactionThreadReport = chatReports[1]; + const iouReport = iouReports[0]; + iouReportID = iouReport?.reportID; + transactionThread = transactionThreadReport; - expect(iouReport?.notificationPreference).toBe(CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN); + expect(iouReport?.notificationPreference).toBe(CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN); - // They should be linked together - expect(chatReport?.participants).toEqual({[RORY_ACCOUNT_ID]: RORY_PARTICIPANT, [CARLOS_ACCOUNT_ID]: CARLOS_PARTICIPANT}); - expect(chatReport?.iouReportID).toBe(iouReport?.reportID); + // They should be linked together + expect(chatReport?.participants).toEqual({[RORY_ACCOUNT_ID]: RORY_PARTICIPANT, [CARLOS_ACCOUNT_ID]: CARLOS_PARTICIPANT}); + expect(chatReport?.iouReportID).toBe(iouReport?.reportID); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, - waitForCollectionCallback: false, - callback: (reportActionsForIOUReport) => { - Onyx.disconnect(connectionID); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, + waitForCollectionCallback: false, + callback: (reportActionsForIOUReport) => { + Onyx.disconnect(connectionID); - // The IOU report should have a CREATED action and IOU action - expect(Object.values(reportActionsForIOUReport ?? {}).length).toBe(2); - const createdActions = Object.values(reportActionsForIOUReport ?? {}).filter( - (reportAction) => reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED, - ); - const iouActions = Object.values(reportActionsForIOUReport ?? {}).filter( - (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.IOU, - ); - expect(Object.values(createdActions).length).toBe(1); - expect(Object.values(iouActions).length).toBe(1); - createdAction = createdActions?.[0] ?? null; - iouAction = iouActions?.[0] ?? null; + // The IOU report should have a CREATED action and IOU action + expect(Object.values(reportActionsForIOUReport ?? {}).length).toBe(2); + const createdActions = Object.values(reportActionsForIOUReport ?? {}).filter( + (reportAction) => reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED, + ); + const iouActions = Object.values(reportActionsForIOUReport ?? {}).filter( + (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.IOU, + ); + expect(Object.values(createdActions).length).toBe(1); + expect(Object.values(iouActions).length).toBe(1); + createdAction = createdActions?.[0] ?? null; + iouAction = iouActions?.[0] ?? null; - // The CREATED action should not be created after the IOU action - expect(Date.parse(createdAction?.created ?? '')).toBeLessThan(Date.parse(iouAction?.created ?? '')); + // The CREATED action should not be created after the IOU action + expect(Date.parse(createdAction?.created ?? '')).toBeLessThan(Date.parse(iouAction?.created ?? '')); - // The IOUReportID should be correct - expect(iouAction.originalMessage.IOUReportID).toBe(iouReportID); + // The IOUReportID should be correct + expect(iouAction.originalMessage.IOUReportID).toBe(iouReportID); - // The comment should be included in the IOU action - expect(iouAction.originalMessage.comment).toBe(comment); + // The comment should be included in the IOU action + expect(iouAction.originalMessage.comment).toBe(comment); - // The amount in the IOU action should be correct - expect(iouAction.originalMessage.amount).toBe(amount); + // The amount in the IOU action should be correct + expect(iouAction.originalMessage.amount).toBe(amount); - // The IOU type should be correct - expect(iouAction.originalMessage.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE); + // The IOU type should be correct + expect(iouAction.originalMessage.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE); - // Both actions should be pending - expect(createdAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - expect(iouAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + // Both actions should be pending + expect(createdAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + expect(iouAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread?.reportID}`, - waitForCollectionCallback: false, - callback: (reportActionsForTransactionThread) => { - Onyx.disconnect(connectionID); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread?.reportID}`, + waitForCollectionCallback: false, + callback: (reportActionsForTransactionThread) => { + Onyx.disconnect(connectionID); - // The transaction thread should have a CREATED action - expect(Object.values(reportActionsForTransactionThread ?? {}).length).toBe(1); - const createdActions = Object.values(reportActionsForTransactionThread ?? {}).filter( - (reportAction) => reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED, - ); - expect(Object.values(createdActions).length).toBe(1); - transactionThreadCreatedAction = createdActions[0]; + // The transaction thread should have a CREATED action + expect(Object.values(reportActionsForTransactionThread ?? {}).length).toBe(1); + const createdActions = Object.values(reportActionsForTransactionThread ?? {}).filter( + (reportAction) => reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED, + ); + expect(Object.values(createdActions).length).toBe(1); + transactionThreadCreatedAction = createdActions[0]; - expect(transactionThreadCreatedAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.TRANSACTION, - waitForCollectionCallback: true, - callback: (allTransactions) => { - Onyx.disconnect(connectionID); + expect(transactionThreadCreatedAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.TRANSACTION, + waitForCollectionCallback: true, + callback: (allTransactions) => { + Onyx.disconnect(connectionID); - // There should be one transaction - expect(Object.values(allTransactions ?? {}).length).toBe(1); - const transaction = Object.values(allTransactions ?? []).find((t) => !isEmptyObject(t)); - transactionID = transaction?.transactionID; + // There should be one transaction + expect(Object.values(allTransactions ?? {}).length).toBe(1); + const transaction = Object.values(allTransactions ?? []).find((t) => !isEmptyObject(t)); + transactionID = transaction?.transactionID; - // The transaction should be attached to the IOU report - expect(transaction?.reportID).toBe(iouReportID); + // The transaction should be attached to the IOU report + expect(transaction?.reportID).toBe(iouReportID); - // Its amount should match the amount of the expense - expect(transaction?.amount).toBe(amount); + // Its amount should match the amount of the expense + expect(transaction?.amount).toBe(amount); - // The comment should be correct - expect(transaction?.comment.comment).toBe(comment); + // The comment should be correct + expect(transaction?.comment.comment).toBe(comment); - // It should be pending - expect(transaction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + // It should be pending + expect(transaction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - // The transactionID on the iou action should match the one from the transactions collection - expect((iouAction?.originalMessage as IOUMessage)?.IOUTransactionID).toBe(transactionID); + // The transactionID on the iou action should match the one from the transactions collection + expect((iouAction?.originalMessage as IOUMessage)?.IOUTransactionID).toBe(transactionID); - expect(transaction?.merchant).toBe(merchant); + expect(transaction?.merchant).toBe(merchant); - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, - waitForCollectionCallback: false, - callback: (reportActionsForIOUReport) => { - Onyx.disconnect(connectionID); - expect(Object.values(reportActionsForIOUReport ?? {}).length).toBe(2); - Object.values(reportActionsForIOUReport ?? {}).forEach((reportAction) => expect(reportAction?.pendingAction).toBeFalsy()); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, - waitForCollectionCallback: false, - callback: (transaction) => { - Onyx.disconnect(connectionID); - expect(transaction?.pendingAction).toBeFalsy(); - resolve(); - }, - }); - }), - ) - ); + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, + waitForCollectionCallback: false, + callback: (reportActionsForIOUReport) => { + Onyx.disconnect(connectionID); + expect(Object.values(reportActionsForIOUReport ?? {}).length).toBe(2); + Object.values(reportActionsForIOUReport ?? {}).forEach((reportAction) => expect(reportAction?.pendingAction).toBeFalsy()); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, + waitForCollectionCallback: false, + callback: (transaction) => { + Onyx.disconnect(connectionID); + expect(transaction?.pendingAction).toBeFalsy(); + resolve(); + }, + }); + }), + ); }); it('updates existing chat report if there is one', () => { @@ -269,152 +267,147 @@ describe('actions/IOU', () => { let iouAction: OnyxEntry; let iouCreatedAction: OnyxEntry; let transactionID: string | undefined; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, chatReport) - .then(() => - Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport.reportID}`, { - [createdAction.reportActionID]: createdAction, - }), - ) - .then(() => { - IOU.requestMoney(chatReport, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment, {}); - return waitForBatchedUpdates(); - }) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT, - waitForCollectionCallback: true, - callback: (allReports) => { - Onyx.disconnect(connectionID); + mockFetch?.pause?.(); + return Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, chatReport) + .then(() => + Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport.reportID}`, { + [createdAction.reportActionID]: createdAction, + }), + ) + .then(() => { + IOU.requestMoney(chatReport, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment, {}); + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (allReports) => { + Onyx.disconnect(connectionID); - // The same chat report should be reused, a transaction thread and an IOU report should be created - expect(Object.values(allReports ?? {}).length).toBe(3); - expect(Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.CHAT)?.reportID).toBe(chatReport.reportID); - chatReport = Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.CHAT) ?? chatReport; - const iouReport = Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.IOU); - iouReportID = iouReport?.reportID; + // The same chat report should be reused, a transaction thread and an IOU report should be created + expect(Object.values(allReports ?? {}).length).toBe(3); + expect(Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.CHAT)?.reportID).toBe(chatReport.reportID); + chatReport = Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.CHAT) ?? chatReport; + const iouReport = Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.IOU); + iouReportID = iouReport?.reportID; - expect(iouReport?.notificationPreference).toBe(CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN); + expect(iouReport?.notificationPreference).toBe(CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN); - // They should be linked together - expect(chatReport.iouReportID).toBe(iouReportID); + // They should be linked together + expect(chatReport.iouReportID).toBe(iouReportID); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, - waitForCollectionCallback: false, - callback: (allIOUReportActions) => { - Onyx.disconnect(connectionID); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, + waitForCollectionCallback: false, + callback: (allIOUReportActions) => { + Onyx.disconnect(connectionID); - iouCreatedAction = - Object.values(allIOUReportActions ?? {}).find((reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED) ?? null; - iouAction = - Object.values(allIOUReportActions ?? {}).find( - (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU, - ) ?? null; + iouCreatedAction = Object.values(allIOUReportActions ?? {}).find((reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED) ?? null; + iouAction = + Object.values(allIOUReportActions ?? {}).find( + (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU, + ) ?? null; - // The CREATED action should not be created after the IOU action - expect(Date.parse(iouCreatedAction?.created ?? '')).toBeLessThan(Date.parse(iouAction?.created ?? '')); + // The CREATED action should not be created after the IOU action + expect(Date.parse(iouCreatedAction?.created ?? '')).toBeLessThan(Date.parse(iouAction?.created ?? '')); - // The IOUReportID should be correct - expect(iouAction?.originalMessage?.IOUReportID).toBe(iouReportID); + // The IOUReportID should be correct + expect(iouAction?.originalMessage?.IOUReportID).toBe(iouReportID); - // The comment should be included in the IOU action - expect(iouAction?.originalMessage?.comment).toBe(comment); + // The comment should be included in the IOU action + expect(iouAction?.originalMessage?.comment).toBe(comment); - // The amount in the IOU action should be correct - expect(iouAction?.originalMessage?.amount).toBe(amount); + // The amount in the IOU action should be correct + expect(iouAction?.originalMessage?.amount).toBe(amount); - // The IOU action type should be correct - expect(iouAction?.originalMessage?.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE); + // The IOU action type should be correct + expect(iouAction?.originalMessage?.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE); - // The IOU action should be pending - expect(iouAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + // The IOU action should be pending + expect(iouAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.TRANSACTION, - waitForCollectionCallback: true, - callback: (allTransactions) => { - Onyx.disconnect(connectionID); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.TRANSACTION, + waitForCollectionCallback: true, + callback: (allTransactions) => { + Onyx.disconnect(connectionID); - // There should be one transaction - expect(Object.values(allTransactions ?? {}).length).toBe(1); - const transaction = Object.values(allTransactions ?? {}).find((t) => !isEmptyObject(t)); - transactionID = transaction?.transactionID; + // There should be one transaction + expect(Object.values(allTransactions ?? {}).length).toBe(1); + const transaction = Object.values(allTransactions ?? {}).find((t) => !isEmptyObject(t)); + transactionID = transaction?.transactionID; - // The transaction should be attached to the IOU report - expect(transaction?.reportID).toBe(iouReportID); + // The transaction should be attached to the IOU report + expect(transaction?.reportID).toBe(iouReportID); - // Its amount should match the amount of the expense - expect(transaction?.amount).toBe(amount); + // Its amount should match the amount of the expense + expect(transaction?.amount).toBe(amount); - // The comment should be correct - expect(transaction?.comment.comment).toBe(comment); + // The comment should be correct + expect(transaction?.comment.comment).toBe(comment); - expect(transaction?.merchant).toBe(CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT); + expect(transaction?.merchant).toBe(CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT); - // It should be pending - expect(transaction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + // It should be pending + expect(transaction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - // The transactionID on the iou action should match the one from the transactions collection - expect((iouAction?.originalMessage as IOUMessage)?.IOUTransactionID).toBe(transactionID); + // The transactionID on the iou action should match the one from the transactions collection + expect((iouAction?.originalMessage as IOUMessage)?.IOUTransactionID).toBe(transactionID); - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, - waitForCollectionCallback: false, - callback: (reportActionsForIOUReport) => { - Onyx.disconnect(connectionID); - expect(Object.values(reportActionsForIOUReport ?? {}).length).toBe(2); - Object.values(reportActionsForIOUReport ?? {}).forEach((reportAction) => expect(reportAction?.pendingAction).toBeFalsy()); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, - callback: (transaction) => { - Onyx.disconnect(connectionID); - expect(transaction?.pendingAction).toBeFalsy(); - resolve(); - }, - }); - }), - ) - ); + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, + waitForCollectionCallback: false, + callback: (reportActionsForIOUReport) => { + Onyx.disconnect(connectionID); + expect(Object.values(reportActionsForIOUReport ?? {}).length).toBe(2); + Object.values(reportActionsForIOUReport ?? {}).forEach((reportAction) => expect(reportAction?.pendingAction).toBeFalsy()); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, + callback: (transaction) => { + Onyx.disconnect(connectionID); + expect(transaction?.pendingAction).toBeFalsy(); + resolve(); + }, + }); + }), + ); }); it('updates existing IOU report if there is one', () => { @@ -469,146 +462,142 @@ describe('actions/IOU', () => { }; let newIOUAction: OnyxEntry; let newTransaction: OnyxEntry; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`, chatReport) - .then(() => Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, iouReport)) - .then(() => - Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, { - [createdAction.reportActionID]: createdAction, - [iouAction.reportActionID]: iouAction, - }), - ) - .then(() => Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${existingTransaction.transactionID}`, existingTransaction)) - .then(() => { - if (chatReport) { - IOU.requestMoney(chatReport, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment, {}); - } - return waitForBatchedUpdates(); - }) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT, - waitForCollectionCallback: true, - callback: (allReports) => { - Onyx.disconnect(connectionID); + mockFetch?.pause?.(); + return Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`, chatReport) + .then(() => Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, iouReport)) + .then(() => + Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, { + [createdAction.reportActionID]: createdAction, + [iouAction.reportActionID]: iouAction, + }), + ) + .then(() => Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${existingTransaction.transactionID}`, existingTransaction)) + .then(() => { + if (chatReport) { + IOU.requestMoney(chatReport, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment, {}); + } + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (allReports) => { + Onyx.disconnect(connectionID); - // No new reports should be created - expect(Object.values(allReports ?? {}).length).toBe(3); - expect(Object.values(allReports ?? {}).find((report) => report?.reportID === chatReportID)).toBeTruthy(); - expect(Object.values(allReports ?? {}).find((report) => report?.reportID === iouReportID)).toBeTruthy(); + // No new reports should be created + expect(Object.values(allReports ?? {}).length).toBe(3); + expect(Object.values(allReports ?? {}).find((report) => report?.reportID === chatReportID)).toBeTruthy(); + expect(Object.values(allReports ?? {}).find((report) => report?.reportID === iouReportID)).toBeTruthy(); - chatReport = Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.CHAT) ?? null; - iouReport = Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.IOU) ?? null; + chatReport = Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.CHAT) ?? null; + iouReport = Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.IOU) ?? null; - // The total on the iou report should be updated - expect(iouReport?.total).toBe(11000); + // The total on the iou report should be updated + expect(iouReport?.total).toBe(11000); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, - waitForCollectionCallback: false, - callback: (reportActionsForIOUReport) => { - Onyx.disconnect(connectionID); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, + waitForCollectionCallback: false, + callback: (reportActionsForIOUReport) => { + Onyx.disconnect(connectionID); - expect(Object.values(reportActionsForIOUReport ?? {}).length).toBe(3); - newIOUAction = - Object.values(reportActionsForIOUReport ?? {}).find( - (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => - reportAction?.reportActionID !== createdAction.reportActionID && reportAction?.reportActionID !== iouAction?.reportActionID, - ) ?? null; + expect(Object.values(reportActionsForIOUReport ?? {}).length).toBe(3); + newIOUAction = + Object.values(reportActionsForIOUReport ?? {}).find( + (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => + reportAction?.reportActionID !== createdAction.reportActionID && reportAction?.reportActionID !== iouAction?.reportActionID, + ) ?? null; - // The IOUReportID should be correct - expect(iouAction.originalMessage.IOUReportID).toBe(iouReportID); + // The IOUReportID should be correct + expect(iouAction.originalMessage.IOUReportID).toBe(iouReportID); - // The comment should be included in the IOU action - expect(newIOUAction?.originalMessage.comment).toBe(comment); + // The comment should be included in the IOU action + expect(newIOUAction?.originalMessage.comment).toBe(comment); - // The amount in the IOU action should be correct - expect(newIOUAction?.originalMessage.amount).toBe(amount); + // The amount in the IOU action should be correct + expect(newIOUAction?.originalMessage.amount).toBe(amount); - // The type of the IOU action should be correct - expect(newIOUAction?.originalMessage.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE); + // The type of the IOU action should be correct + expect(newIOUAction?.originalMessage.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE); - // The IOU action should be pending - expect(newIOUAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + // The IOU action should be pending + expect(newIOUAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.TRANSACTION, - waitForCollectionCallback: true, - callback: (allTransactions) => { - Onyx.disconnect(connectionID); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.TRANSACTION, + waitForCollectionCallback: true, + callback: (allTransactions) => { + Onyx.disconnect(connectionID); - // There should be two transactions - expect(Object.values(allTransactions ?? {}).length).toBe(2); + // There should be two transactions + expect(Object.values(allTransactions ?? {}).length).toBe(2); - newTransaction = Object.values(allTransactions ?? {}).find((transaction) => transaction?.transactionID !== existingTransaction.transactionID) ?? null; + newTransaction = Object.values(allTransactions ?? {}).find((transaction) => transaction?.transactionID !== existingTransaction.transactionID) ?? null; - expect(newTransaction?.reportID).toBe(iouReportID); - expect(newTransaction?.amount).toBe(amount); - expect(newTransaction?.comment.comment).toBe(comment); - expect(newTransaction?.merchant).toBe(CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT); - expect(newTransaction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + expect(newTransaction?.reportID).toBe(iouReportID); + expect(newTransaction?.amount).toBe(amount); + expect(newTransaction?.comment.comment).toBe(comment); + expect(newTransaction?.merchant).toBe(CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT); + expect(newTransaction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - // The transactionID on the iou action should match the one from the transactions collection - expect((newIOUAction?.originalMessage as IOUMessage)?.IOUTransactionID).toBe(newTransaction?.transactionID); + // The transactionID on the iou action should match the one from the transactions collection + expect((newIOUAction?.originalMessage as IOUMessage)?.IOUTransactionID).toBe(newTransaction?.transactionID); - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForNetworkPromises) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, - waitForCollectionCallback: false, - callback: (reportActionsForIOUReport) => { - Onyx.disconnect(connectionID); - expect(Object.values(reportActionsForIOUReport ?? {}).length).toBe(3); - Object.values(reportActionsForIOUReport ?? {}).forEach((reportAction) => expect(reportAction?.pendingAction).toBeFalsy()); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.TRANSACTION, - waitForCollectionCallback: true, - callback: (allTransactions) => { - Onyx.disconnect(connectionID); - Object.values(allTransactions ?? {}).forEach((transaction) => expect(transaction?.pendingAction).toBeFalsy()); - resolve(); - }, - }); - }), - ) - ); + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForNetworkPromises) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, + waitForCollectionCallback: false, + callback: (reportActionsForIOUReport) => { + Onyx.disconnect(connectionID); + expect(Object.values(reportActionsForIOUReport ?? {}).length).toBe(3); + Object.values(reportActionsForIOUReport ?? {}).forEach((reportAction) => expect(reportAction?.pendingAction).toBeFalsy()); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.TRANSACTION, + waitForCollectionCallback: true, + callback: (allTransactions) => { + Onyx.disconnect(connectionID); + Object.values(allTransactions ?? {}).forEach((transaction) => expect(transaction?.pendingAction).toBeFalsy()); + resolve(); + }, + }); + }), + ); }); it('correctly implements RedBrickRoad error handling', () => { @@ -621,8 +610,7 @@ describe('actions/IOU', () => { let transactionID: string; let transactionThreadReport: OnyxEntry; let transactionThreadAction: OnyxEntry; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); IOU.requestMoney({reportID: ''}, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment, {}); return ( waitForBatchedUpdates() @@ -733,10 +721,8 @@ describe('actions/IOU', () => { }), ) .then((): Promise => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - return fetch.resume() as Promise; + mockFetch?.fail?.(); + return mockFetch?.resume?.() as Promise; }) .then( () => @@ -924,8 +910,7 @@ describe('actions/IOU', () => { ) // Cleanup - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.succeed) + .then(mockFetch?.succeed) ); }); }); @@ -1063,356 +1048,350 @@ describe('actions/IOU', () => { (item) => item[julesChatCreatedAction.reportActionID].reportID ?? '', ); - return ( - Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, { - ...reportCollectionDataSet, + return Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, { + ...reportCollectionDataSet, + }) + .then(() => + Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT_ACTIONS, { + ...carlosActionsCollectionDataSet, + ...julesCreatedActionsCollectionDataSet, + ...julesActionsCollectionDataSet, + }), + ) + .then(() => Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${julesExistingTransaction?.transactionID}`, julesExistingTransaction)) + .then(() => { + // When we split a bill offline + mockFetch?.pause?.(); + IOU.splitBill( + // TODO: Migrate after the backend accepts accountIDs + { + participants: [ + [CARLOS_EMAIL, String(CARLOS_ACCOUNT_ID)], + [JULES_EMAIL, String(JULES_ACCOUNT_ID)], + [VIT_EMAIL, String(VIT_ACCOUNT_ID)], + ].map(([email, accountID]) => ({login: email, accountID: Number(accountID)})), + currentUserLogin: RORY_EMAIL, + currentUserAccountID: RORY_ACCOUNT_ID, + amount, + comment, + currency: CONST.CURRENCY.USD, + merchant, + created: '', + tag: '', + existingSplitChatReportID: '', + }, + ); + return waitForBatchedUpdates(); }) - .then(() => - Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT_ACTIONS, { - ...carlosActionsCollectionDataSet, - ...julesCreatedActionsCollectionDataSet, - ...julesActionsCollectionDataSet, - }), - ) - .then(() => Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${julesExistingTransaction?.transactionID}`, julesExistingTransaction)) - .then(() => { - // When we split a bill offline - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - IOU.splitBill( - // TODO: Migrate after the backend accepts accountIDs - { - participants: [ - [CARLOS_EMAIL, String(CARLOS_ACCOUNT_ID)], - [JULES_EMAIL, String(JULES_ACCOUNT_ID)], - [VIT_EMAIL, String(VIT_ACCOUNT_ID)], - ].map(([email, accountID]) => ({login: email, accountID: Number(accountID)})), - currentUserLogin: RORY_EMAIL, - currentUserAccountID: RORY_ACCOUNT_ID, - amount, - comment, - currency: CONST.CURRENCY.USD, - merchant, - created: '', - tag: '', - existingSplitChatReportID: '', - }, - ); - return waitForBatchedUpdates(); - }) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT, - waitForCollectionCallback: true, - callback: (allReports) => { - Onyx.disconnect(connectionID); - - // There should now be 10 reports - expect(Object.values(allReports ?? {}).length).toBe(10); - - // 1. The chat report with Rory + Carlos - carlosChatReport = Object.values(allReports ?? {}).find((report) => report?.reportID === carlosChatReport?.reportID) ?? null; - expect(isEmptyObject(carlosChatReport)).toBe(false); - expect(carlosChatReport?.pendingFields).toBeFalsy(); - - // 2. The IOU report with Rory + Carlos (new) - carlosIOUReport = - Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.IOU && report.managerID === CARLOS_ACCOUNT_ID) ?? null; - expect(isEmptyObject(carlosIOUReport)).toBe(false); - expect(carlosIOUReport?.total).toBe(amount / 4); - - // 3. The chat report with Rory + Jules - julesChatReport = Object.values(allReports ?? {}).find((report) => report?.reportID === julesChatReport?.reportID) ?? null; - expect(isEmptyObject(julesChatReport)).toBe(false); - expect(julesChatReport?.pendingFields).toBeFalsy(); - - // 4. The IOU report with Rory + Jules - julesIOUReport = Object.values(allReports ?? {}).find((report) => report?.reportID === julesIOUReport?.reportID) ?? null; - expect(isEmptyObject(julesIOUReport)).toBe(false); - expect(julesChatReport?.pendingFields).toBeFalsy(); - expect(julesIOUReport?.total).toBe((julesExistingTransaction?.amount ?? 0) + amount / 4); - - // 5. The chat report with Rory + Vit (new) - vitChatReport = - Object.values(allReports ?? {}).find( - (report) => - report?.type === CONST.REPORT.TYPE.CHAT && - isEqual(report.participants, {[RORY_ACCOUNT_ID]: RORY_PARTICIPANT, [VIT_ACCOUNT_ID]: VIT_PARTICIPANT}), - ) ?? null; - expect(isEmptyObject(vitChatReport)).toBe(false); - expect(vitChatReport?.pendingFields).toStrictEqual({createChat: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD}); - - // 6. The IOU report with Rory + Vit (new) - vitIOUReport = - Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.IOU && report.managerID === VIT_ACCOUNT_ID) ?? null; - expect(isEmptyObject(vitIOUReport)).toBe(false); - expect(vitIOUReport?.total).toBe(amount / 4); - - // 7. The group chat with everyone - groupChat = - Object.values(allReports ?? {}).find( - (report) => - report?.type === CONST.REPORT.TYPE.CHAT && - isEqual(report.participants, { - [CARLOS_ACCOUNT_ID]: CARLOS_PARTICIPANT, - [JULES_ACCOUNT_ID]: JULES_PARTICIPANT, - [VIT_ACCOUNT_ID]: VIT_PARTICIPANT, - [RORY_ACCOUNT_ID]: RORY_PARTICIPANT, - }), - ) ?? null; - expect(isEmptyObject(groupChat)).toBe(false); - expect(groupChat?.pendingFields).toStrictEqual({createChat: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD}); - - // The 1:1 chat reports and the IOU reports should be linked together - expect(carlosChatReport?.iouReportID).toBe(carlosIOUReport?.reportID); - expect(carlosIOUReport?.chatReportID).toBe(carlosChatReport?.reportID); - expect(carlosIOUReport?.notificationPreference).toBe(CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN); - - expect(julesChatReport?.iouReportID).toBe(julesIOUReport?.reportID); - expect(julesIOUReport?.chatReportID).toBe(julesChatReport?.reportID); - - expect(vitChatReport?.iouReportID).toBe(vitIOUReport?.reportID); - expect(vitIOUReport?.chatReportID).toBe(vitChatReport?.reportID); - expect(carlosIOUReport?.notificationPreference).toBe(CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN); - - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, - waitForCollectionCallback: true, - callback: (allReportActions) => { - Onyx.disconnect(connectionID); - - // There should be reportActions on all 7 chat reports + 3 IOU reports in each 1:1 chat - expect(Object.values(allReportActions ?? {}).length).toBe(10); - - const carlosReportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${carlosChatReport?.iouReportID}`]; - const julesReportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${julesChatReport?.iouReportID}`]; - const vitReportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${vitChatReport?.iouReportID}`]; - const groupReportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${groupChat?.reportID}`]; - - // Carlos DM should have two reportActions – the existing CREATED action and a pending IOU action - expect(Object.values(carlosReportActions ?? {}).length).toBe(2); - carlosIOUCreatedAction = - Object.values(carlosReportActions ?? {}).find( - (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED, - ) ?? null; - carlosIOUAction = - Object.values(carlosReportActions ?? {}).find( - (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU, - ) ?? null; - expect(carlosIOUAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - expect(carlosIOUAction?.originalMessage.IOUReportID).toBe(carlosIOUReport?.reportID); - expect(carlosIOUAction?.originalMessage.amount).toBe(amount / 4); - expect(carlosIOUAction?.originalMessage.comment).toBe(comment); - expect(carlosIOUAction?.originalMessage.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE); - expect(Date.parse(carlosIOUCreatedAction?.created ?? '')).toBeLessThan(Date.parse(carlosIOUAction?.created ?? '')); - - // Jules DM should have three reportActions, the existing CREATED action, the existing IOU action, and a new pending IOU action - expect(Object.values(julesReportActions ?? {}).length).toBe(3); - expect(julesReportActions?.[julesCreatedAction.reportActionID]).toStrictEqual(julesCreatedAction); - julesIOUCreatedAction = - Object.values(julesReportActions ?? {}).find( - (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED, - ) ?? null; - julesIOUAction = - Object.values(julesReportActions ?? {}).find( - (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => - reportAction.reportActionID !== julesCreatedAction.reportActionID && - reportAction.reportActionID !== julesExistingIOUAction.reportActionID, - ) ?? null; - expect(julesIOUAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - expect(julesIOUAction?.originalMessage.IOUReportID).toBe(julesIOUReport?.reportID); - expect(julesIOUAction?.originalMessage.amount).toBe(amount / 4); - expect(julesIOUAction?.originalMessage.comment).toBe(comment); - expect(julesIOUAction?.originalMessage.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE); - expect(Date.parse(julesIOUCreatedAction?.created ?? '')).toBeLessThan(Date.parse(julesIOUAction?.created ?? '')); - - // Vit DM should have two reportActions – a pending CREATED action and a pending IOU action - expect(Object.values(vitReportActions ?? {}).length).toBe(2); - vitCreatedAction = - Object.values(vitReportActions ?? {}).find( - (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED, - ) ?? null; - vitIOUAction = - Object.values(vitReportActions ?? {}).find( - (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU, - ) ?? null; - expect(vitCreatedAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - expect(vitIOUAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - expect(vitIOUAction?.originalMessage.IOUReportID).toBe(vitIOUReport?.reportID); - expect(vitIOUAction?.originalMessage.amount).toBe(amount / 4); - expect(vitIOUAction?.originalMessage.comment).toBe(comment); - expect(vitIOUAction?.originalMessage.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE); - expect(Date.parse(vitCreatedAction?.created ?? '')).toBeLessThan(Date.parse(vitIOUAction?.created ?? '')); - - // Group chat should have two reportActions – a pending CREATED action and a pending IOU action w/ type SPLIT - expect(Object.values(groupReportActions ?? {}).length).toBe(2); - groupCreatedAction = - Object.values(groupReportActions ?? {}).find((reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED) ?? null; - groupIOUAction = - Object.values(groupReportActions ?? {}).find( - (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU, - ) ?? null; - expect(groupCreatedAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - expect(groupIOUAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - expect(groupIOUAction?.originalMessage).not.toHaveProperty('IOUReportID'); - expect(groupIOUAction?.originalMessage?.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.SPLIT); - expect(Date.parse(groupCreatedAction?.created ?? '')).toBeLessThanOrEqual(Date.parse(groupIOUAction?.created ?? '')); - - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.TRANSACTION, - waitForCollectionCallback: true, - callback: (allTransactions) => { - Onyx.disconnect(connectionID); + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (allReports) => { + Onyx.disconnect(connectionID); - /* There should be 5 transactions - * – one existing one with Jules - * - one for each of the three IOU reports - * - one on the group chat w/ deleted report - */ - expect(Object.values(allTransactions ?? {}).length).toBe(5); - expect(allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${julesExistingTransaction?.transactionID}`]).toBeTruthy(); - - carlosTransaction = - Object.values(allTransactions ?? {}).find( - (transaction) => transaction?.transactionID === (carlosIOUAction?.originalMessage as IOUMessage)?.IOUTransactionID, - ) ?? null; - julesTransaction = - Object.values(allTransactions ?? {}).find( - (transaction) => transaction?.transactionID === (julesIOUAction?.originalMessage as IOUMessage)?.IOUTransactionID, - ) ?? null; - vitTransaction = - Object.values(allTransactions ?? {}).find( - (transaction) => transaction?.transactionID === (vitIOUAction?.originalMessage as IOUMessage)?.IOUTransactionID, - ) ?? null; - groupTransaction = Object.values(allTransactions ?? {}).find((transaction) => transaction?.reportID === CONST.REPORT.SPLIT_REPORTID) ?? null; + // There should now be 10 reports + expect(Object.values(allReports ?? {}).length).toBe(10); + + // 1. The chat report with Rory + Carlos + carlosChatReport = Object.values(allReports ?? {}).find((report) => report?.reportID === carlosChatReport?.reportID) ?? null; + expect(isEmptyObject(carlosChatReport)).toBe(false); + expect(carlosChatReport?.pendingFields).toBeFalsy(); + + // 2. The IOU report with Rory + Carlos (new) + carlosIOUReport = + Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.IOU && report.managerID === CARLOS_ACCOUNT_ID) ?? null; + expect(isEmptyObject(carlosIOUReport)).toBe(false); + expect(carlosIOUReport?.total).toBe(amount / 4); + + // 3. The chat report with Rory + Jules + julesChatReport = Object.values(allReports ?? {}).find((report) => report?.reportID === julesChatReport?.reportID) ?? null; + expect(isEmptyObject(julesChatReport)).toBe(false); + expect(julesChatReport?.pendingFields).toBeFalsy(); + + // 4. The IOU report with Rory + Jules + julesIOUReport = Object.values(allReports ?? {}).find((report) => report?.reportID === julesIOUReport?.reportID) ?? null; + expect(isEmptyObject(julesIOUReport)).toBe(false); + expect(julesChatReport?.pendingFields).toBeFalsy(); + expect(julesIOUReport?.total).toBe((julesExistingTransaction?.amount ?? 0) + amount / 4); + + // 5. The chat report with Rory + Vit (new) + vitChatReport = + Object.values(allReports ?? {}).find( + (report) => + report?.type === CONST.REPORT.TYPE.CHAT && + isEqual(report.participants, {[RORY_ACCOUNT_ID]: RORY_PARTICIPANT, [VIT_ACCOUNT_ID]: VIT_PARTICIPANT}), + ) ?? null; + expect(isEmptyObject(vitChatReport)).toBe(false); + expect(vitChatReport?.pendingFields).toStrictEqual({createChat: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD}); + + // 6. The IOU report with Rory + Vit (new) + vitIOUReport = Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.IOU && report.managerID === VIT_ACCOUNT_ID) ?? null; + expect(isEmptyObject(vitIOUReport)).toBe(false); + expect(vitIOUReport?.total).toBe(amount / 4); + + // 7. The group chat with everyone + groupChat = + Object.values(allReports ?? {}).find( + (report) => + report?.type === CONST.REPORT.TYPE.CHAT && + isEqual(report.participants, { + [CARLOS_ACCOUNT_ID]: CARLOS_PARTICIPANT, + [JULES_ACCOUNT_ID]: JULES_PARTICIPANT, + [VIT_ACCOUNT_ID]: VIT_PARTICIPANT, + [RORY_ACCOUNT_ID]: RORY_PARTICIPANT, + }), + ) ?? null; + expect(isEmptyObject(groupChat)).toBe(false); + expect(groupChat?.pendingFields).toStrictEqual({createChat: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD}); - expect(carlosTransaction?.reportID).toBe(carlosIOUReport?.reportID); - expect(julesTransaction?.reportID).toBe(julesIOUReport?.reportID); - expect(vitTransaction?.reportID).toBe(vitIOUReport?.reportID); - expect(groupTransaction).toBeTruthy(); + // The 1:1 chat reports and the IOU reports should be linked together + expect(carlosChatReport?.iouReportID).toBe(carlosIOUReport?.reportID); + expect(carlosIOUReport?.chatReportID).toBe(carlosChatReport?.reportID); + expect(carlosIOUReport?.notificationPreference).toBe(CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN); - expect(carlosTransaction?.amount).toBe(amount / 4); - expect(julesTransaction?.amount).toBe(amount / 4); - expect(vitTransaction?.amount).toBe(amount / 4); - expect(groupTransaction?.amount).toBe(amount); + expect(julesChatReport?.iouReportID).toBe(julesIOUReport?.reportID); + expect(julesIOUReport?.chatReportID).toBe(julesChatReport?.reportID); - expect(carlosTransaction?.comment.comment).toBe(comment); - expect(julesTransaction?.comment.comment).toBe(comment); - expect(vitTransaction?.comment.comment).toBe(comment); - expect(groupTransaction?.comment.comment).toBe(comment); + expect(vitChatReport?.iouReportID).toBe(vitIOUReport?.reportID); + expect(vitIOUReport?.chatReportID).toBe(vitChatReport?.reportID); + expect(carlosIOUReport?.notificationPreference).toBe(CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN); - expect(carlosTransaction?.merchant).toBe(merchant); - expect(julesTransaction?.merchant).toBe(merchant); - expect(vitTransaction?.merchant).toBe(merchant); - expect(groupTransaction?.merchant).toBe(merchant); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, + waitForCollectionCallback: true, + callback: (allReportActions) => { + Onyx.disconnect(connectionID); - expect(carlosTransaction?.comment.source).toBe(CONST.IOU.TYPE.SPLIT); - expect(julesTransaction?.comment.source).toBe(CONST.IOU.TYPE.SPLIT); - expect(vitTransaction?.comment.source).toBe(CONST.IOU.TYPE.SPLIT); + // There should be reportActions on all 7 chat reports + 3 IOU reports in each 1:1 chat + expect(Object.values(allReportActions ?? {}).length).toBe(10); + + const carlosReportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${carlosChatReport?.iouReportID}`]; + const julesReportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${julesChatReport?.iouReportID}`]; + const vitReportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${vitChatReport?.iouReportID}`]; + const groupReportActions = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${groupChat?.reportID}`]; + + // Carlos DM should have two reportActions – the existing CREATED action and a pending IOU action + expect(Object.values(carlosReportActions ?? {}).length).toBe(2); + carlosIOUCreatedAction = + Object.values(carlosReportActions ?? {}).find( + (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED, + ) ?? null; + carlosIOUAction = + Object.values(carlosReportActions ?? {}).find( + (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU, + ) ?? null; + expect(carlosIOUAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + expect(carlosIOUAction?.originalMessage.IOUReportID).toBe(carlosIOUReport?.reportID); + expect(carlosIOUAction?.originalMessage.amount).toBe(amount / 4); + expect(carlosIOUAction?.originalMessage.comment).toBe(comment); + expect(carlosIOUAction?.originalMessage.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE); + expect(Date.parse(carlosIOUCreatedAction?.created ?? '')).toBeLessThan(Date.parse(carlosIOUAction?.created ?? '')); + + // Jules DM should have three reportActions, the existing CREATED action, the existing IOU action, and a new pending IOU action + expect(Object.values(julesReportActions ?? {}).length).toBe(3); + expect(julesReportActions?.[julesCreatedAction.reportActionID]).toStrictEqual(julesCreatedAction); + julesIOUCreatedAction = + Object.values(julesReportActions ?? {}).find( + (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED, + ) ?? null; + julesIOUAction = + Object.values(julesReportActions ?? {}).find( + (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => + reportAction.reportActionID !== julesCreatedAction.reportActionID && reportAction.reportActionID !== julesExistingIOUAction.reportActionID, + ) ?? null; + expect(julesIOUAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + expect(julesIOUAction?.originalMessage.IOUReportID).toBe(julesIOUReport?.reportID); + expect(julesIOUAction?.originalMessage.amount).toBe(amount / 4); + expect(julesIOUAction?.originalMessage.comment).toBe(comment); + expect(julesIOUAction?.originalMessage.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE); + expect(Date.parse(julesIOUCreatedAction?.created ?? '')).toBeLessThan(Date.parse(julesIOUAction?.created ?? '')); + + // Vit DM should have two reportActions – a pending CREATED action and a pending IOU action + expect(Object.values(vitReportActions ?? {}).length).toBe(2); + vitCreatedAction = + Object.values(vitReportActions ?? {}).find( + (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED, + ) ?? null; + vitIOUAction = + Object.values(vitReportActions ?? {}).find( + (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU, + ) ?? null; + expect(vitCreatedAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + expect(vitIOUAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + expect(vitIOUAction?.originalMessage.IOUReportID).toBe(vitIOUReport?.reportID); + expect(vitIOUAction?.originalMessage.amount).toBe(amount / 4); + expect(vitIOUAction?.originalMessage.comment).toBe(comment); + expect(vitIOUAction?.originalMessage.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE); + expect(Date.parse(vitCreatedAction?.created ?? '')).toBeLessThan(Date.parse(vitIOUAction?.created ?? '')); + + // Group chat should have two reportActions – a pending CREATED action and a pending IOU action w/ type SPLIT + expect(Object.values(groupReportActions ?? {}).length).toBe(2); + groupCreatedAction = + Object.values(groupReportActions ?? {}).find((reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED) ?? null; + groupIOUAction = + Object.values(groupReportActions ?? {}).find( + (reportAction): reportAction is ReportActionBase & OriginalMessageIOU => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU, + ) ?? null; + expect(groupCreatedAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + expect(groupIOUAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + expect(groupIOUAction?.originalMessage).not.toHaveProperty('IOUReportID'); + expect(groupIOUAction?.originalMessage?.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.SPLIT); + expect(Date.parse(groupCreatedAction?.created ?? '')).toBeLessThanOrEqual(Date.parse(groupIOUAction?.created ?? '')); - expect(carlosTransaction?.comment.originalTransactionID).toBe(groupTransaction?.transactionID); - expect(julesTransaction?.comment.originalTransactionID).toBe(groupTransaction?.transactionID); - expect(vitTransaction?.comment.originalTransactionID).toBe(groupTransaction?.transactionID); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.TRANSACTION, + waitForCollectionCallback: true, + callback: (allTransactions) => { + Onyx.disconnect(connectionID); - expect(carlosTransaction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - expect(julesTransaction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - expect(vitTransaction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - expect(groupTransaction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + /* There should be 5 transactions + * – one existing one with Jules + * - one for each of the three IOU reports + * - one on the group chat w/ deleted report + */ + expect(Object.values(allTransactions ?? {}).length).toBe(5); + expect(allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${julesExistingTransaction?.transactionID}`]).toBeTruthy(); + + carlosTransaction = + Object.values(allTransactions ?? {}).find( + (transaction) => transaction?.transactionID === (carlosIOUAction?.originalMessage as IOUMessage)?.IOUTransactionID, + ) ?? null; + julesTransaction = + Object.values(allTransactions ?? {}).find( + (transaction) => transaction?.transactionID === (julesIOUAction?.originalMessage as IOUMessage)?.IOUTransactionID, + ) ?? null; + vitTransaction = + Object.values(allTransactions ?? {}).find( + (transaction) => transaction?.transactionID === (vitIOUAction?.originalMessage as IOUMessage)?.IOUTransactionID, + ) ?? null; + groupTransaction = Object.values(allTransactions ?? {}).find((transaction) => transaction?.reportID === CONST.REPORT.SPLIT_REPORTID) ?? null; + + expect(carlosTransaction?.reportID).toBe(carlosIOUReport?.reportID); + expect(julesTransaction?.reportID).toBe(julesIOUReport?.reportID); + expect(vitTransaction?.reportID).toBe(vitIOUReport?.reportID); + expect(groupTransaction).toBeTruthy(); + + expect(carlosTransaction?.amount).toBe(amount / 4); + expect(julesTransaction?.amount).toBe(amount / 4); + expect(vitTransaction?.amount).toBe(amount / 4); + expect(groupTransaction?.amount).toBe(amount); + + expect(carlosTransaction?.comment.comment).toBe(comment); + expect(julesTransaction?.comment.comment).toBe(comment); + expect(vitTransaction?.comment.comment).toBe(comment); + expect(groupTransaction?.comment.comment).toBe(comment); + + expect(carlosTransaction?.merchant).toBe(merchant); + expect(julesTransaction?.merchant).toBe(merchant); + expect(vitTransaction?.merchant).toBe(merchant); + expect(groupTransaction?.merchant).toBe(merchant); + + expect(carlosTransaction?.comment.source).toBe(CONST.IOU.TYPE.SPLIT); + expect(julesTransaction?.comment.source).toBe(CONST.IOU.TYPE.SPLIT); + expect(vitTransaction?.comment.source).toBe(CONST.IOU.TYPE.SPLIT); + + expect(carlosTransaction?.comment.originalTransactionID).toBe(groupTransaction?.transactionID); + expect(julesTransaction?.comment.originalTransactionID).toBe(groupTransaction?.transactionID); + expect(vitTransaction?.comment.originalTransactionID).toBe(groupTransaction?.transactionID); + + expect(carlosTransaction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + expect(julesTransaction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + expect(vitTransaction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + expect(groupTransaction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - waitForCollectionCallback: false, - callback: (allPersonalDetails) => { - Onyx.disconnect(connectionID); - expect(allPersonalDetails).toMatchObject({ - [VIT_ACCOUNT_ID]: { - accountID: VIT_ACCOUNT_ID, - displayName: VIT_EMAIL, - login: VIT_EMAIL, - }, - }); - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForNetworkPromises) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT, - waitForCollectionCallback: true, - callback: (allReports) => { - Onyx.disconnect(connectionID); - Object.values(allReports ?? {}).forEach((report) => { - if (!report?.pendingFields) { - return; - } - Object.values(report?.pendingFields).forEach((pendingField) => expect(pendingField).toBeFalsy()); - }); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, - waitForCollectionCallback: true, - callback: (allReportActions) => { - Onyx.disconnect(connectionID); - Object.values(allReportActions ?? {}).forEach((reportAction) => expect(reportAction?.pendingAction).toBeFalsy()); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.TRANSACTION, - waitForCollectionCallback: true, - callback: (allTransactions) => { - Onyx.disconnect(connectionID); - Object.values(allTransactions ?? {}).forEach((transaction) => expect(transaction?.pendingAction).toBeFalsy()); - resolve(); - }, - }); - }), - ) - ); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + waitForCollectionCallback: false, + callback: (allPersonalDetails) => { + Onyx.disconnect(connectionID); + expect(allPersonalDetails).toMatchObject({ + [VIT_ACCOUNT_ID]: { + accountID: VIT_ACCOUNT_ID, + displayName: VIT_EMAIL, + login: VIT_EMAIL, + }, + }); + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForNetworkPromises) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (allReports) => { + Onyx.disconnect(connectionID); + Object.values(allReports ?? {}).forEach((report) => { + if (!report?.pendingFields) { + return; + } + Object.values(report?.pendingFields).forEach((pendingField) => expect(pendingField).toBeFalsy()); + }); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, + waitForCollectionCallback: true, + callback: (allReportActions) => { + Onyx.disconnect(connectionID); + Object.values(allReportActions ?? {}).forEach((reportAction) => expect(reportAction?.pendingAction).toBeFalsy()); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.TRANSACTION, + waitForCollectionCallback: true, + callback: (allTransactions) => { + Onyx.disconnect(connectionID); + Object.values(allTransactions ?? {}).forEach((transaction) => expect(transaction?.pendingAction).toBeFalsy()); + resolve(); + }, + }); + }), + ); }); }); @@ -1426,189 +1405,185 @@ describe('actions/IOU', () => { let payIOUAction: OnyxEntry; let transaction: OnyxEntry; IOU.requestMoney({reportID: ''}, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment, {}); - return ( - waitForBatchedUpdates() - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT, - waitForCollectionCallback: true, - callback: (allReports) => { - Onyx.disconnect(connectionID); + return waitForBatchedUpdates() + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (allReports) => { + Onyx.disconnect(connectionID); - expect(Object.values(allReports ?? {}).length).toBe(3); + expect(Object.values(allReports ?? {}).length).toBe(3); - const chatReports = Object.values(allReports ?? {}).filter((report) => report?.type === CONST.REPORT.TYPE.CHAT); - chatReport = chatReports[0]; - expect(chatReport).toBeTruthy(); - expect(chatReport).toHaveProperty('reportID'); - expect(chatReport).toHaveProperty('iouReportID'); + const chatReports = Object.values(allReports ?? {}).filter((report) => report?.type === CONST.REPORT.TYPE.CHAT); + chatReport = chatReports[0]; + expect(chatReport).toBeTruthy(); + expect(chatReport).toHaveProperty('reportID'); + expect(chatReport).toHaveProperty('iouReportID'); - iouReport = Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.IOU) ?? null; - expect(iouReport).toBeTruthy(); - expect(iouReport).toHaveProperty('reportID'); - expect(iouReport).toHaveProperty('chatReportID'); + iouReport = Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.IOU) ?? null; + expect(iouReport).toBeTruthy(); + expect(iouReport).toHaveProperty('reportID'); + expect(iouReport).toHaveProperty('chatReportID'); - expect(chatReport?.iouReportID).toBe(iouReport?.reportID); - expect(iouReport?.chatReportID).toBe(chatReport?.reportID); + expect(chatReport?.iouReportID).toBe(iouReport?.reportID); + expect(iouReport?.chatReportID).toBe(chatReport?.reportID); - expect(chatReport?.pendingFields).toBeFalsy(); - expect(iouReport?.pendingFields).toBeFalsy(); + expect(chatReport?.pendingFields).toBeFalsy(); + expect(iouReport?.pendingFields).toBeFalsy(); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, - waitForCollectionCallback: true, - callback: (allReportActions) => { - Onyx.disconnect(connectionID); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, + waitForCollectionCallback: true, + callback: (allReportActions) => { + Onyx.disconnect(connectionID); - const reportActionsForIOUReport = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport?.iouReportID}`]; + const reportActionsForIOUReport = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport?.iouReportID}`]; - createIOUAction = - Object.values(reportActionsForIOUReport ?? {}).find((reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU) ?? null; - expect(createIOUAction).toBeTruthy(); - expect((createIOUAction?.originalMessage as IOUMessage)?.IOUReportID).toBe(iouReport?.reportID); + createIOUAction = + Object.values(reportActionsForIOUReport ?? {}).find((reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU) ?? null; + expect(createIOUAction).toBeTruthy(); + expect((createIOUAction?.originalMessage as IOUMessage)?.IOUReportID).toBe(iouReport?.reportID); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.TRANSACTION, - waitForCollectionCallback: true, - callback: (allTransactions) => { - Onyx.disconnect(connectionID); - expect(Object.values(allTransactions ?? {}).length).toBe(1); - transaction = Object.values(allTransactions ?? {}).find((t) => t) ?? null; - expect(transaction).toBeTruthy(); - expect(transaction?.amount).toBe(amount); - expect(transaction?.reportID).toBe(iouReport?.reportID); - expect((createIOUAction?.originalMessage as IOUMessage)?.IOUTransactionID).toBe(transaction?.transactionID); - resolve(); - }, - }); - }), - ) - .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - if (chatReport && iouReport) { - IOU.payMoneyRequest(CONST.IOU.PAYMENT_TYPE.ELSEWHERE, chatReport, iouReport); - } - return waitForBatchedUpdates(); - }) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT, - waitForCollectionCallback: true, - callback: (allReports) => { - Onyx.disconnect(connectionID); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.TRANSACTION, + waitForCollectionCallback: true, + callback: (allTransactions) => { + Onyx.disconnect(connectionID); + expect(Object.values(allTransactions ?? {}).length).toBe(1); + transaction = Object.values(allTransactions ?? {}).find((t) => t) ?? null; + expect(transaction).toBeTruthy(); + expect(transaction?.amount).toBe(amount); + expect(transaction?.reportID).toBe(iouReport?.reportID); + expect((createIOUAction?.originalMessage as IOUMessage)?.IOUTransactionID).toBe(transaction?.transactionID); + resolve(); + }, + }); + }), + ) + .then(() => { + mockFetch?.pause?.(); + if (chatReport && iouReport) { + IOU.payMoneyRequest(CONST.IOU.PAYMENT_TYPE.ELSEWHERE, chatReport, iouReport); + } + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (allReports) => { + Onyx.disconnect(connectionID); - expect(Object.values(allReports ?? {}).length).toBe(3); + expect(Object.values(allReports ?? {}).length).toBe(3); - chatReport = Object.values(allReports ?? {}).find((r) => r?.type === CONST.REPORT.TYPE.CHAT) ?? null; - iouReport = Object.values(allReports ?? {}).find((r) => r?.type === CONST.REPORT.TYPE.IOU) ?? null; + chatReport = Object.values(allReports ?? {}).find((r) => r?.type === CONST.REPORT.TYPE.CHAT) ?? null; + iouReport = Object.values(allReports ?? {}).find((r) => r?.type === CONST.REPORT.TYPE.IOU) ?? null; - expect(chatReport?.iouReportID).toBeFalsy(); + expect(chatReport?.iouReportID).toBeFalsy(); - // expect(iouReport.status).toBe(CONST.REPORT.STATUS_NUM.REIMBURSED); - // expect(iouReport.stateNum).toBe(CONST.REPORT.STATE_NUM.APPROVED); + // expect(iouReport.status).toBe(CONST.REPORT.STATUS_NUM.REIMBURSED); + // expect(iouReport.stateNum).toBe(CONST.REPORT.STATE_NUM.APPROVED); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, - waitForCollectionCallback: true, - callback: (allReportActions) => { - Onyx.disconnect(connectionID); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, + waitForCollectionCallback: true, + callback: (allReportActions) => { + Onyx.disconnect(connectionID); - const reportActionsForIOUReport = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport?.reportID}`]; - expect(Object.values(reportActionsForIOUReport ?? {}).length).toBe(3); + const reportActionsForIOUReport = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport?.reportID}`]; + expect(Object.values(reportActionsForIOUReport ?? {}).length).toBe(3); - payIOUAction = - Object.values(reportActionsForIOUReport ?? {}).find( - (reportAction) => - reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && reportAction?.originalMessage?.type === CONST.IOU.REPORT_ACTION_TYPE.PAY, - ) ?? null; - expect(payIOUAction).toBeTruthy(); - expect(payIOUAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + payIOUAction = + Object.values(reportActionsForIOUReport ?? {}).find( + (reportAction) => + reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && reportAction?.originalMessage?.type === CONST.IOU.REPORT_ACTION_TYPE.PAY, + ) ?? null; + expect(payIOUAction).toBeTruthy(); + expect(payIOUAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT, - waitForCollectionCallback: true, - callback: (allReports) => { - Onyx.disconnect(connectionID); + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (allReports) => { + Onyx.disconnect(connectionID); - expect(Object.values(allReports ?? {}).length).toBe(3); + expect(Object.values(allReports ?? {}).length).toBe(3); - chatReport = Object.values(allReports ?? {}).find((r) => r?.type === CONST.REPORT.TYPE.CHAT) ?? null; - iouReport = Object.values(allReports ?? {}).find((r) => r?.type === CONST.REPORT.TYPE.IOU) ?? null; + chatReport = Object.values(allReports ?? {}).find((r) => r?.type === CONST.REPORT.TYPE.CHAT) ?? null; + iouReport = Object.values(allReports ?? {}).find((r) => r?.type === CONST.REPORT.TYPE.IOU) ?? null; - expect(chatReport?.iouReportID).toBeFalsy(); + expect(chatReport?.iouReportID).toBeFalsy(); - // expect(iouReport.status).toBe(CONST.REPORT.STATUS_NUM.REIMBURSED); - // expect(iouReport.stateNum).toBe(CONST.REPORT.STATE_NUM.APPROVED); + // expect(iouReport.status).toBe(CONST.REPORT.STATUS_NUM.REIMBURSED); + // expect(iouReport.stateNum).toBe(CONST.REPORT.STATE_NUM.APPROVED); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, - waitForCollectionCallback: true, - callback: (allReportActions) => { - Onyx.disconnect(connectionID); + resolve(); + }, + }); + }), + ) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, + waitForCollectionCallback: true, + callback: (allReportActions) => { + Onyx.disconnect(connectionID); - const reportActionsForIOUReport = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport?.reportID}`]; - expect(Object.values(reportActionsForIOUReport ?? {}).length).toBe(3); + const reportActionsForIOUReport = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport?.reportID}`]; + expect(Object.values(reportActionsForIOUReport ?? {}).length).toBe(3); - payIOUAction = - Object.values(reportActionsForIOUReport ?? {}).find( - (reportAction) => - reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && reportAction.originalMessage.type === CONST.IOU.REPORT_ACTION_TYPE.PAY, - ) ?? null; - expect(payIOUAction).toBeTruthy(); + payIOUAction = + Object.values(reportActionsForIOUReport ?? {}).find( + (reportAction) => + reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && reportAction.originalMessage.type === CONST.IOU.REPORT_ACTION_TYPE.PAY, + ) ?? null; + expect(payIOUAction).toBeTruthy(); - resolve(); - }, - }); - }), - ) - ); + resolve(); + }, + }); + }), + ); }); }); @@ -1618,8 +1593,7 @@ describe('actions/IOU', () => { const merchant = 'NASDAQ'; afterEach(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.resume(); + mockFetch?.resume?.(); }); it('updates the IOU request and IOU report when offline', () => { @@ -1628,8 +1602,7 @@ describe('actions/IOU', () => { let iouAction: OnyxEntry = null; let transaction: OnyxEntry = null; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); IOU.requestMoney({reportID: ''}, amount, CONST.CURRENCY.USD, '', merchant, RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment, {}); return waitForBatchedUpdates() .then(() => { @@ -1772,8 +1745,7 @@ describe('actions/IOU', () => { }), ) .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.resume(); + mockFetch?.resume?.(); }); }); @@ -1839,8 +1811,7 @@ describe('actions/IOU', () => { return waitForBatchedUpdates(); }) .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); + mockFetch?.fail?.(); if (transaction) { IOU.editMoneyRequest( @@ -1933,16 +1904,14 @@ describe('actions/IOU', () => { const merchant = 'NASDAQ'; afterEach(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.resume(); + mockFetch?.resume?.(); }); it('updates the expense request and expense report when paid while offline', () => { let expenseReport: OnyxEntry; let chatReport: OnyxEntry; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); Onyx.set(ONYXKEYS.SESSION, {email: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}); return waitForBatchedUpdates() .then(() => { @@ -2099,8 +2068,7 @@ describe('actions/IOU', () => { }), ) .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); + mockFetch?.fail?.(); if (chatReport && expenseReport) { IOU.payMoneyRequest('ACH', chatReport, expenseReport); } @@ -2250,8 +2218,7 @@ describe('actions/IOU', () => { it('delete an expense (IOU Action and transaction) successfully', async () => { // Given the fetch operations are paused and an expense is initiated - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); if (transaction && createIOUAction) { // When the expense is deleted @@ -2290,8 +2257,7 @@ describe('actions/IOU', () => { expect(t).toBeFalsy(); // Given fetch operations are resumed - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.resume(); + mockFetch?.resume?.(); await waitForBatchedUpdates(); // Then we recheck the IOU report action from the report actions collection @@ -2326,8 +2292,7 @@ describe('actions/IOU', () => { it('delete the IOU report when there are no visible comments left in the IOU report', async () => { // Given an IOU report and a paused fetch state - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); if (transaction && createIOUAction) { // When the IOU expense is deleted @@ -2350,8 +2315,7 @@ describe('actions/IOU', () => { expect(report).toBeTruthy(); // Given the resumed fetch state - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.resume(); + mockFetch?.resume?.(); await waitForBatchedUpdates(); report = await new Promise>((resolve) => { @@ -2403,8 +2367,7 @@ describe('actions/IOU', () => { expect(resultActionAfterUpdate?.pendingAction).toBeUndefined(); // When we attempt to delete an expense from the IOU report - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); if (transaction && createIOUAction) { IOU.deleteMoneyRequest(transaction?.transactionID, createIOUAction, false); } @@ -2430,8 +2393,7 @@ describe('actions/IOU', () => { expect(iouReport).toHaveProperty('chatReportID'); // Given the resumed fetch state - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.resume(); + mockFetch?.resume?.(); allReports = await new Promise>((resolve) => { const connectionID = Onyx.connect({ @@ -2495,8 +2457,7 @@ describe('actions/IOU', () => { await waitForBatchedUpdates(); // Given Fetch is paused and timers have advanced - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); jest.advanceTimersByTime(10); if (transaction && createIOUAction) { @@ -2518,8 +2479,7 @@ describe('actions/IOU', () => { }); expect(report).toBeFalsy(); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.resume(); + mockFetch?.resume?.(); // Then After resuming fetch, the report for the given thread ID still does not exist report = await new Promise>((resolve) => { @@ -2687,8 +2647,7 @@ describe('actions/IOU', () => { const resultActionAfter = reportActions?.[reportActionID]; expect(resultActionAfter?.pendingAction).toBeUndefined(); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); if (transaction && createIOUAction) { // When deleting expense @@ -2711,8 +2670,7 @@ describe('actions/IOU', () => { // When fetch resumes // Then the transaction thread report should still exist - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.resume(); + mockFetch?.resume?.(); await new Promise((resolve) => { const connectionID = Onyx.connect({ key: `${ONYXKEYS.COLLECTION.REPORT}${thread.reportID}`, @@ -2835,8 +2793,7 @@ describe('actions/IOU', () => { // Verify that our action is no longer in the loading state expect(resultActionAfterUpdate?.pendingAction).toBeUndefined(); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); if (transaction && createIOUAction) { // When we delete the expense IOU.deleteMoneyRequest(transaction.transactionID, createIOUAction, false); @@ -2859,8 +2816,7 @@ describe('actions/IOU', () => { }); // When we resume fetch - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.resume(); + mockFetch?.resume?.(); // Then we expect the moneyRequestPreview to show [Deleted expense] @@ -2909,8 +2865,7 @@ describe('actions/IOU', () => { expect(ioupreview?.message?.[0]?.text).toBe('rory@expensifail.com owes $300.00'); // When we delete the first expense - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); jest.advanceTimersByTime(10); if (transaction && createIOUAction) { IOU.deleteMoneyRequest(transaction.transactionID, createIOUAction, false); @@ -2925,8 +2880,7 @@ describe('actions/IOU', () => { expect(iouReport?.total).toBe(20000); // When we resume - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.resume(); + mockFetch?.resume?.(); // Then we expect the IOU report and reportPreview to update with new totals expect(iouReport).toBeTruthy(); @@ -3002,8 +2956,7 @@ describe('actions/IOU', () => { // When we delete the expense in SingleTransactionView and we should not delete the IOU report - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); if (transaction && createIOUAction) { IOU.deleteMoneyRequest(transaction.transactionID, createIOUAction, true); @@ -3028,8 +2981,7 @@ describe('actions/IOU', () => { expect(iouReport).toHaveProperty('reportID'); expect(iouReport).toHaveProperty('chatReportID'); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.resume(); + mockFetch?.resume?.(); allReports = await new Promise>((resolve) => { const connectionID = Onyx.connect({ @@ -3355,8 +3307,7 @@ describe('actions/IOU', () => { }), ) .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); + mockFetch?.fail?.(); if (expenseReport) { IOU.submitReport(expenseReport); } diff --git a/tests/actions/PolicyTagTest.ts b/tests/actions/PolicyTagTest.ts index ff4439c392fa..74ea13f3d139 100644 --- a/tests/actions/PolicyTagTest.ts +++ b/tests/actions/PolicyTagTest.ts @@ -7,6 +7,7 @@ import type {PolicyTags} from '@src/types/onyx'; import createRandomPolicy from '../utils/collections/policies'; import createRandomPolicyTags from '../utils/collections/policyTags'; import * as TestHelper from '../utils/TestHelper'; +import type {MockFetch} from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; OnyxUpdateManager(); @@ -17,9 +18,10 @@ describe('actions/Policy', () => { }); }); + let mockFetch: MockFetch; beforeEach(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); + mockFetch = fetch as MockFetch; return Onyx.clear().then(waitForBatchedUpdates); }); @@ -28,139 +30,127 @@ describe('actions/Policy', () => { const fakePolicy = createRandomPolicy(0); fakePolicy.requiresTag = false; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) - .then(() => { - Policy.setPolicyRequiresTag(fakePolicy.id, true); - return waitForBatchedUpdates(); - }) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - - // RequiresTag is enabled and pending - expect(policy?.requiresTag).toBeTruthy(); - expect(policy?.pendingFields?.requiresTag).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); - - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - expect(policy?.pendingFields?.requiresTag).toBeFalsy(); - resolve(); - }, - }); - }), - ) - ); + mockFetch?.pause?.(); + + return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) + .then(() => { + Policy.setPolicyRequiresTag(fakePolicy.id, true); + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + + // RequiresTag is enabled and pending + expect(policy?.requiresTag).toBeTruthy(); + expect(policy?.pendingFields?.requiresTag).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); + + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + expect(policy?.pendingFields?.requiresTag).toBeFalsy(); + resolve(); + }, + }); + }), + ); }); it('disable require tag', () => { const fakePolicy = createRandomPolicy(0); fakePolicy.requiresTag = true; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) - .then(() => { - Policy.setPolicyRequiresTag(fakePolicy.id, false); - return waitForBatchedUpdates(); - }) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - - // RequiresTag is disabled and pending - expect(policy?.requiresTag).toBeFalsy(); - expect(policy?.pendingFields?.requiresTag).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); - - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - expect(policy?.pendingFields?.requiresTag).toBeFalsy(); - resolve(); - }, - }); - }), - ) - ); + mockFetch?.pause?.(); + + return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) + .then(() => { + Policy.setPolicyRequiresTag(fakePolicy.id, false); + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + + // RequiresTag is disabled and pending + expect(policy?.requiresTag).toBeFalsy(); + expect(policy?.pendingFields?.requiresTag).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); + + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + expect(policy?.pendingFields?.requiresTag).toBeFalsy(); + resolve(); + }, + }); + }), + ); }); it('reset require tag when api returns an error', () => { const fakePolicy = createRandomPolicy(0); fakePolicy.requiresTag = true; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) - .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - Policy.setPolicyRequiresTag(fakePolicy.id, false); - return waitForBatchedUpdates(); - }) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - expect(policy?.pendingFields?.requiresTag).toBeFalsy(); - expect(policy?.errors).toBeTruthy(); - expect(policy?.requiresTag).toBeTruthy(); - resolve(); - }, - }); - }), - ) - ); + mockFetch?.pause?.(); + + return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) + .then(() => { + mockFetch?.fail?.(); + Policy.setPolicyRequiresTag(fakePolicy.id, false); + return waitForBatchedUpdates(); + }) + + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + expect(policy?.pendingFields?.requiresTag).toBeFalsy(); + expect(policy?.errors).toBeTruthy(); + expect(policy?.requiresTag).toBeTruthy(); + resolve(); + }, + }); + }), + ); }); }); @@ -173,65 +163,61 @@ describe('actions/Policy', () => { const newTagListName = 'New tag list name'; const fakePolicyTags = createRandomPolicyTags(oldTagListName); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) - .then(() => { - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); - }) - .then(() => { - Policy.renamePolicyTaglist( - fakePolicy.id, - { - oldName: oldTagListName, - newName: newTagListName, - }, - fakePolicyTags, - ); - return waitForBatchedUpdates(); - }) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - // Tag list name is updated and pending - expect(Object.keys(policyTags?.[oldTagListName] ?? {}).length).toBe(0); - expect(policyTags?.[newTagListName]?.name).toBe(newTagListName); - expect(policyTags?.[newTagListName]?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - expect(policyTags?.[newTagListName]?.pendingAction).toBeFalsy(); - expect(Object.keys(policyTags?.[oldTagListName] ?? {}).length).toBe(0); - - resolve(); - }, - }); - }), - ) - ); + mockFetch?.pause?.(); + + return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) + .then(() => { + Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); + }) + .then(() => { + Policy.renamePolicyTaglist( + fakePolicy.id, + { + oldName: oldTagListName, + newName: newTagListName, + }, + fakePolicyTags, + ); + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + // Tag list name is updated and pending + expect(Object.keys(policyTags?.[oldTagListName] ?? {}).length).toBe(0); + expect(policyTags?.[newTagListName]?.name).toBe(newTagListName); + expect(policyTags?.[newTagListName]?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + expect(policyTags?.[newTagListName]?.pendingAction).toBeFalsy(); + expect(Object.keys(policyTags?.[oldTagListName] ?? {}).length).toBe(0); + + resolve(); + }, + }); + }), + ); }); it('reset the policy tag list name when api returns error', () => { @@ -242,50 +228,45 @@ describe('actions/Policy', () => { const newTagListName = 'New tag list name'; const fakePolicyTags = createRandomPolicyTags(oldTagListName); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) - .then(() => { - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); - }) - .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - - Policy.renamePolicyTaglist( - fakePolicy.id, - { - oldName: oldTagListName, - newName: newTagListName, - }, - fakePolicyTags, - ); - return waitForBatchedUpdates(); - }) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - expect(policyTags?.[newTagListName]).toBeFalsy(); - expect(policyTags?.[oldTagListName]).toBeTruthy(); - expect(policyTags?.errors).toBeTruthy(); - - resolve(); - }, - }); - }), - ) - ); + mockFetch?.pause?.(); + + return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) + .then(() => { + Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); + }) + .then(() => { + mockFetch?.fail?.(); + + Policy.renamePolicyTaglist( + fakePolicy.id, + { + oldName: oldTagListName, + newName: newTagListName, + }, + fakePolicyTags, + ); + return waitForBatchedUpdates(); + }) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + expect(policyTags?.[newTagListName]).toBeFalsy(); + expect(policyTags?.[oldTagListName]).toBeTruthy(); + expect(policyTags?.errors).toBeTruthy(); + + resolve(); + }, + }); + }), + ); }); }); @@ -298,60 +279,56 @@ describe('actions/Policy', () => { const newTagName = 'new tag'; const fakePolicyTags = createRandomPolicyTags(tagListName); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) - .then(() => { - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); - }) - .then(() => { - Policy.createPolicyTag(fakePolicy.id, newTagName); - return waitForBatchedUpdates(); - }) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - const newTag = policyTags?.[tagListName]?.tags?.[newTagName]; - expect(newTag?.name).toBe(newTagName); - expect(newTag?.enabled).toBe(true); - expect(newTag?.errors).toBeFalsy(); - expect(newTag?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - const newTag = policyTags?.[tagListName]?.tags?.[newTagName]; - expect(newTag?.errors).toBeFalsy(); - expect(newTag?.pendingAction).toBeFalsy(); - - resolve(); - }, - }); - }), - ) - ); + mockFetch?.pause?.(); + + return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) + .then(() => { + Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); + }) + .then(() => { + Policy.createPolicyTag(fakePolicy.id, newTagName); + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + const newTag = policyTags?.[tagListName]?.tags?.[newTagName]; + expect(newTag?.name).toBe(newTagName); + expect(newTag?.enabled).toBe(true); + expect(newTag?.errors).toBeFalsy(); + expect(newTag?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + const newTag = policyTags?.[tagListName]?.tags?.[newTagName]; + expect(newTag?.errors).toBeFalsy(); + expect(newTag?.pendingAction).toBeFalsy(); + + resolve(); + }, + }); + }), + ); }); it('reset new policy tag when api returns error', () => { @@ -362,42 +339,37 @@ describe('actions/Policy', () => { const newTagName = 'new tag'; const fakePolicyTags = createRandomPolicyTags(tagListName); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) - .then(() => { - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); - }) - .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - - Policy.createPolicyTag(fakePolicy.id, newTagName); - return waitForBatchedUpdates(); - }) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - const newTag = policyTags?.[tagListName]?.tags?.[newTagName]; - expect(newTag?.errors).toBeTruthy(); - - resolve(); - }, - }); - }), - ) - ); + mockFetch?.pause?.(); + + return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) + .then(() => { + Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); + }) + .then(() => { + mockFetch?.fail?.(); + + Policy.createPolicyTag(fakePolicy.id, newTagName); + return waitForBatchedUpdates(); + }) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + const newTag = policyTags?.[tagListName]?.tags?.[newTagName]; + expect(newTag?.errors).toBeTruthy(); + + resolve(); + }, + }); + }), + ); }); }); @@ -416,65 +388,61 @@ describe('actions/Policy', () => { return acc; }, {}); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) - .then(() => { - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); - }) - .then(() => { - Policy.setWorkspaceTagEnabled(fakePolicy.id, tagsToUpdate); - return waitForBatchedUpdates(); - }) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - Object.keys(tagsToUpdate).forEach((key) => { - const updatedTag = policyTags?.[tagListName]?.tags[key]; - expect(updatedTag?.enabled).toBeFalsy(); - expect(updatedTag?.errors).toBeFalsy(); - expect(updatedTag?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); - expect(updatedTag?.pendingFields?.enabled).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); - }); - - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - Object.keys(tagsToUpdate).forEach((key) => { - const updatedTag = policyTags?.[tagListName]?.tags[key]; - expect(updatedTag?.errors).toBeFalsy(); - expect(updatedTag?.pendingAction).toBeFalsy(); - expect(updatedTag?.pendingFields?.enabled).toBeFalsy(); - }); - - resolve(); - }, - }); - }), - ) - ); + mockFetch?.pause?.(); + + return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) + .then(() => { + Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); + }) + .then(() => { + Policy.setWorkspaceTagEnabled(fakePolicy.id, tagsToUpdate); + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + Object.keys(tagsToUpdate).forEach((key) => { + const updatedTag = policyTags?.[tagListName]?.tags[key]; + expect(updatedTag?.enabled).toBeFalsy(); + expect(updatedTag?.errors).toBeFalsy(); + expect(updatedTag?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); + expect(updatedTag?.pendingFields?.enabled).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); + }); + + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + Object.keys(tagsToUpdate).forEach((key) => { + const updatedTag = policyTags?.[tagListName]?.tags[key]; + expect(updatedTag?.errors).toBeFalsy(); + expect(updatedTag?.pendingAction).toBeFalsy(); + expect(updatedTag?.pendingFields?.enabled).toBeFalsy(); + }); + + resolve(); + }, + }); + }), + ); }); it('reset policy tag enable when api returns error', () => { @@ -491,46 +459,41 @@ describe('actions/Policy', () => { return acc; }, {}); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) - .then(() => { - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); - }) - .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - - Policy.setWorkspaceTagEnabled(fakePolicy.id, tagsToUpdate); - return waitForBatchedUpdates(); - }) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - Object.keys(tagsToUpdate).forEach((key) => { - const updatedTag = policyTags?.[tagListName]?.tags[key]; - expect(updatedTag?.errors).toBeTruthy(); - expect(updatedTag?.pendingAction).toBeFalsy(); - expect(updatedTag?.pendingFields?.enabled).toBeFalsy(); - }); - - resolve(); - }, - }); - }), - ) - ); + mockFetch?.pause?.(); + + return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) + .then(() => { + Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); + }) + .then(() => { + mockFetch?.fail?.(); + + Policy.setWorkspaceTagEnabled(fakePolicy.id, tagsToUpdate); + return waitForBatchedUpdates(); + }) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + Object.keys(tagsToUpdate).forEach((key) => { + const updatedTag = policyTags?.[tagListName]?.tags[key]; + expect(updatedTag?.errors).toBeTruthy(); + expect(updatedTag?.pendingAction).toBeFalsy(); + expect(updatedTag?.pendingFields?.enabled).toBeFalsy(); + }); + + resolve(); + }, + }); + }), + ); }); }); @@ -544,63 +507,59 @@ describe('actions/Policy', () => { const oldTagName = Object.keys(fakePolicyTags?.[tagListName]?.tags)[0]; const newTagName = 'New tag'; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) - .then(() => { - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); - }) - .then(() => { - Policy.renamePolicyTag(fakePolicy.id, { - oldName: oldTagName, - newName: newTagName, - }); - return waitForBatchedUpdates(); - }) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - const tags = policyTags?.[tagListName]?.tags; - expect(tags?.[oldTagName]).toBeFalsy(); - expect(tags?.[newTagName]?.name).toBe(newTagName); - expect(tags?.[newTagName]?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); - expect(tags?.[newTagName]?.pendingFields?.name).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); - - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - const tags = policyTags?.[tagListName]?.tags; - expect(tags?.[newTagName]?.pendingAction).toBeFalsy(); - expect(tags?.[newTagName]?.pendingFields?.name).toBeFalsy(); - - resolve(); - }, - }); - }), - ) - ); + mockFetch?.pause?.(); + + return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) + .then(() => { + Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); + }) + .then(() => { + Policy.renamePolicyTag(fakePolicy.id, { + oldName: oldTagName, + newName: newTagName, + }); + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + const tags = policyTags?.[tagListName]?.tags; + expect(tags?.[oldTagName]).toBeFalsy(); + expect(tags?.[newTagName]?.name).toBe(newTagName); + expect(tags?.[newTagName]?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); + expect(tags?.[newTagName]?.pendingFields?.name).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); + + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + const tags = policyTags?.[tagListName]?.tags; + expect(tags?.[newTagName]?.pendingAction).toBeFalsy(); + expect(tags?.[newTagName]?.pendingFields?.name).toBeFalsy(); + + resolve(); + }, + }); + }), + ); }); it('reset policy tag name when api returns error', () => { @@ -612,46 +571,41 @@ describe('actions/Policy', () => { const oldTagName = Object.keys(fakePolicyTags?.[tagListName]?.tags)[0]; const newTagName = 'New tag'; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) - .then(() => { - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); - }) - .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - - Policy.renamePolicyTag(fakePolicy.id, { - oldName: oldTagName, - newName: newTagName, - }); - return waitForBatchedUpdates(); - }) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - const tags = policyTags?.[tagListName]?.tags; - expect(tags?.[newTagName]).toBeFalsy(); - expect(tags?.[oldTagName]?.errors).toBeTruthy(); - - resolve(); - }, - }); - }), - ) - ); + mockFetch?.pause?.(); + + return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) + .then(() => { + Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); + }) + .then(() => { + mockFetch?.fail?.(); + + Policy.renamePolicyTag(fakePolicy.id, { + oldName: oldTagName, + newName: newTagName, + }); + return waitForBatchedUpdates(); + }) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + const tags = policyTags?.[tagListName]?.tags; + expect(tags?.[newTagName]).toBeFalsy(); + expect(tags?.[oldTagName]?.errors).toBeTruthy(); + + resolve(); + }, + }); + }), + ); }); }); @@ -664,58 +618,54 @@ describe('actions/Policy', () => { const fakePolicyTags = createRandomPolicyTags(tagListName, 2); const tagsToDelete = Object.keys(fakePolicyTags?.[tagListName]?.tags ?? {}); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) - .then(() => { - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); - }) - .then(() => { - Policy.deletePolicyTags(fakePolicy.id, tagsToDelete); - return waitForBatchedUpdates(); - }) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - tagsToDelete.forEach((tagName) => { - expect(policyTags?.[tagListName]?.tags[tagName]?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); - }); - - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - tagsToDelete.forEach((tagName) => { - expect(policyTags?.[tagListName]?.tags[tagName]).toBeFalsy(); - }); - - resolve(); - }, - }); - }), - ) - ); + mockFetch?.pause?.(); + + return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) + .then(() => { + Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); + }) + .then(() => { + Policy.deletePolicyTags(fakePolicy.id, tagsToDelete); + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + tagsToDelete.forEach((tagName) => { + expect(policyTags?.[tagListName]?.tags[tagName]?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); + }); + + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + tagsToDelete.forEach((tagName) => { + expect(policyTags?.[tagListName]?.tags[tagName]).toBeFalsy(); + }); + + resolve(); + }, + }); + }), + ); }); it('reset the deleted policy tag when api returns error', () => { @@ -726,44 +676,39 @@ describe('actions/Policy', () => { const fakePolicyTags = createRandomPolicyTags(tagListName, 2); const tagsToDelete = Object.keys(fakePolicyTags?.[tagListName]?.tags ?? {}); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - - return ( - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) - .then(() => { - Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); - }) - .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - - Policy.deletePolicyTags(fakePolicy.id, tagsToDelete); - return waitForBatchedUpdates(); - }) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policyTags) => { - Onyx.disconnect(connectionID); - - tagsToDelete.forEach((tagName) => { - expect(policyTags?.[tagListName]?.tags[tagName].pendingAction).toBeFalsy(); - expect(policyTags?.[tagListName]?.tags[tagName].errors).toBeTruthy(); - }); - - resolve(); - }, - }); - }), - ) - ); + mockFetch?.pause?.(); + + return Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy) + .then(() => { + Onyx.set(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, fakePolicyTags); + }) + .then(() => { + mockFetch?.fail?.(); + + Policy.deletePolicyTags(fakePolicy.id, tagsToDelete); + return waitForBatchedUpdates(); + }) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policyTags) => { + Onyx.disconnect(connectionID); + + tagsToDelete.forEach((tagName) => { + expect(policyTags?.[tagListName]?.tags[tagName].pendingAction).toBeFalsy(); + expect(policyTags?.[tagListName]?.tags[tagName].errors).toBeTruthy(); + }); + + resolve(); + }, + }); + }), + ); }); }); }); diff --git a/tests/actions/PolicyTaxTest.ts b/tests/actions/PolicyTaxTest.ts index a17179d8f7af..b1c190f9e5ac 100644 --- a/tests/actions/PolicyTaxTest.ts +++ b/tests/actions/PolicyTaxTest.ts @@ -7,6 +7,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy as PolicyType, TaxRate} from '@src/types/onyx'; import createRandomPolicy from '../utils/collections/policies'; import * as TestHelper from '../utils/TestHelper'; +import type {MockFetch} from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; OnyxUpdateManager(); @@ -18,9 +19,10 @@ describe('actions/PolicyTax', () => { }); }); + let mockFetch: MockFetch; beforeEach(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); + mockFetch = fetch as MockFetch; return Onyx.clear() .then(() => Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy)) .then(waitForBatchedUpdates); @@ -29,53 +31,48 @@ describe('actions/PolicyTax', () => { describe('SetPolicyCustomTaxName', () => { it('Set policy`s custom tax name', () => { const customTaxName = 'Custom tag name'; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); Policy.setPolicyCustomTaxName(fakePolicy.id, customTaxName); - return ( - waitForBatchedUpdates() - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - expect(policy?.taxRates?.name).toBe(customTaxName); - expect(policy?.taxRates?.pendingFields?.name).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); - expect(policy?.taxRates?.errorFields).toBeFalsy(); - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - expect(policy?.taxRates?.pendingFields?.name).toBeFalsy(); - expect(policy?.taxRates?.errorFields).toBeFalsy(); - resolve(); - }, - }); - }), - ) - ); + return waitForBatchedUpdates() + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + expect(policy?.taxRates?.name).toBe(customTaxName); + expect(policy?.taxRates?.pendingFields?.name).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); + expect(policy?.taxRates?.errorFields).toBeFalsy(); + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + expect(policy?.taxRates?.pendingFields?.name).toBeFalsy(); + expect(policy?.taxRates?.errorFields).toBeFalsy(); + resolve(); + }, + }); + }), + ); }); it('Reset policy`s custom tax name when API returns an error', () => { const customTaxName = 'Custom tag name'; const originalCustomTaxName = fakePolicy?.taxRates?.name; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); Policy.setPolicyCustomTaxName(fakePolicy.id, customTaxName); return waitForBatchedUpdates() .then( @@ -95,10 +92,8 @@ describe('actions/PolicyTax', () => { }), ) .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - return fetch.resume() as Promise; + mockFetch?.fail?.(); + return mockFetch?.resume?.() as Promise; }) .then(waitForBatchedUpdates) .then( @@ -124,53 +119,48 @@ describe('actions/PolicyTax', () => { it('Set policy`s currency default tax', () => { const taxCode = 'id_TAX_RATE_1'; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); Policy.setWorkspaceCurrencyDefault(fakePolicy.id, taxCode); - return ( - waitForBatchedUpdates() - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - expect(policy?.taxRates?.defaultExternalID).toBe(taxCode); - expect(policy?.taxRates?.pendingFields?.defaultExternalID).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); - expect(policy?.taxRates?.errorFields).toBeFalsy(); - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - expect(policy?.taxRates?.pendingFields?.defaultExternalID).toBeFalsy(); - expect(policy?.taxRates?.errorFields).toBeFalsy(); - resolve(); - }, - }); - }), - ) - ); + return waitForBatchedUpdates() + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + expect(policy?.taxRates?.defaultExternalID).toBe(taxCode); + expect(policy?.taxRates?.pendingFields?.defaultExternalID).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); + expect(policy?.taxRates?.errorFields).toBeFalsy(); + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + expect(policy?.taxRates?.pendingFields?.defaultExternalID).toBeFalsy(); + expect(policy?.taxRates?.errorFields).toBeFalsy(); + resolve(); + }, + }); + }), + ); }); it('Reset policy`s currency default tax when API returns an error', () => { const taxCode = 'id_TAX_RATE_1'; const originalDefaultExternalID = fakePolicy?.taxRates?.defaultExternalID; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); Policy.setWorkspaceCurrencyDefault(fakePolicy.id, taxCode); return waitForBatchedUpdates() .then( @@ -190,10 +180,8 @@ describe('actions/PolicyTax', () => { }), ) .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - return fetch.resume() as Promise; + mockFetch?.fail?.(); + return mockFetch?.resume?.() as Promise; }) .then(waitForBatchedUpdates) .then( @@ -218,54 +206,49 @@ describe('actions/PolicyTax', () => { it('Set policy`s foreign currency default', () => { const taxCode = 'id_TAX_RATE_1'; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); Policy.setForeignCurrencyDefault(fakePolicy.id, taxCode); - return ( - waitForBatchedUpdates() - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - expect(policy?.taxRates?.foreignTaxDefault).toBe(taxCode); - expect(policy?.taxRates?.pendingFields?.foreignTaxDefault).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); - expect(policy?.taxRates?.errorFields).toBeFalsy(); - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - // Check if the policy pendingFields was cleared - expect(policy?.taxRates?.pendingFields?.foreignTaxDefault).toBeFalsy(); - expect(policy?.taxRates?.errorFields).toBeFalsy(); - resolve(); - }, - }); - }), - ) - ); + return waitForBatchedUpdates() + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + expect(policy?.taxRates?.foreignTaxDefault).toBe(taxCode); + expect(policy?.taxRates?.pendingFields?.foreignTaxDefault).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); + expect(policy?.taxRates?.errorFields).toBeFalsy(); + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + // Check if the policy pendingFields was cleared + expect(policy?.taxRates?.pendingFields?.foreignTaxDefault).toBeFalsy(); + expect(policy?.taxRates?.errorFields).toBeFalsy(); + resolve(); + }, + }); + }), + ); }); it('Reset policy`s foreign currency default when API returns an error', () => { const taxCode = 'id_TAX_RATE_1'; const originalDefaultForeignCurrencyID = fakePolicy?.taxRates?.foreignTaxDefault; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); Policy.setForeignCurrencyDefault(fakePolicy.id, taxCode); return waitForBatchedUpdates() .then( @@ -286,10 +269,8 @@ describe('actions/PolicyTax', () => { ) .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - return fetch.resume() as Promise; + mockFetch?.fail?.(); + return mockFetch?.resume?.() as Promise; }) .then(waitForBatchedUpdates) .then( @@ -319,49 +300,45 @@ describe('actions/PolicyTax', () => { code: 'id_TAX_RATE_2', }; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); createPolicyTax(fakePolicy.id, newTaxRate); - return ( - waitForBatchedUpdates() - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - const createdTax = policy?.taxRates?.taxes?.[newTaxRate.code ?? '']; - expect(createdTax?.code).toBe(newTaxRate.code); - expect(createdTax?.name).toBe(newTaxRate.name); - expect(createdTax?.value).toBe(newTaxRate.value); - expect(createdTax?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - const createdTax = policy?.taxRates?.taxes?.[newTaxRate.code ?? '']; - expect(createdTax?.errors).toBeFalsy(); - expect(createdTax?.pendingFields).toBeFalsy(); - resolve(); - }, - }); - }), - ) - ); + return waitForBatchedUpdates() + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + const createdTax = policy?.taxRates?.taxes?.[newTaxRate.code ?? '']; + expect(createdTax?.code).toBe(newTaxRate.code); + expect(createdTax?.name).toBe(newTaxRate.name); + expect(createdTax?.value).toBe(newTaxRate.value); + expect(createdTax?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD); + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + const createdTax = policy?.taxRates?.taxes?.[newTaxRate.code ?? '']; + expect(createdTax?.errors).toBeFalsy(); + expect(createdTax?.pendingFields).toBeFalsy(); + resolve(); + }, + }); + }), + ); }); it('Remove the optimistic tax if the API returns an error', () => { @@ -371,8 +348,7 @@ describe('actions/PolicyTax', () => { code: 'id_TAX_RATE_2', }; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); createPolicyTax(fakePolicy.id, newTaxRate); return waitForBatchedUpdates() .then( @@ -394,10 +370,8 @@ describe('actions/PolicyTax', () => { }), ) .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - return fetch.resume() as Promise; + mockFetch?.fail?.(); + return mockFetch?.resume?.() as Promise; }) .then(waitForBatchedUpdates) .then( @@ -420,55 +394,50 @@ describe('actions/PolicyTax', () => { describe('SetPolicyTaxesEnabled', () => { it('Disable policy`s taxes', () => { const disableTaxID = 'id_TAX_RATE_1'; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); setPolicyTaxesEnabled(fakePolicy.id, [disableTaxID], false); - return ( - waitForBatchedUpdates() - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - const disabledTax = policy?.taxRates?.taxes?.[disableTaxID]; - expect(disabledTax?.isDisabled).toBeTruthy(); - expect(disabledTax?.pendingFields?.isDisabled).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); - expect(disabledTax?.errorFields?.isDisabled).toBeFalsy(); + return waitForBatchedUpdates() + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + const disabledTax = policy?.taxRates?.taxes?.[disableTaxID]; + expect(disabledTax?.isDisabled).toBeTruthy(); + expect(disabledTax?.pendingFields?.isDisabled).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); + expect(disabledTax?.errorFields?.isDisabled).toBeFalsy(); - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - const disabledTax = policy?.taxRates?.taxes?.[disableTaxID]; - expect(disabledTax?.errorFields?.isDisabled).toBeFalsy(); - expect(disabledTax?.pendingFields?.isDisabled).toBeFalsy(); - resolve(); - }, - }); - }), - ) - ); + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + const disabledTax = policy?.taxRates?.taxes?.[disableTaxID]; + expect(disabledTax?.errorFields?.isDisabled).toBeFalsy(); + expect(disabledTax?.pendingFields?.isDisabled).toBeFalsy(); + resolve(); + }, + }); + }), + ); }); it('Disable policy`s taxes but API returns an error, then enable policy`s taxes again', () => { const disableTaxID = 'id_TAX_RATE_1'; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); setPolicyTaxesEnabled(fakePolicy.id, [disableTaxID], false); const originalTaxes = {...fakePolicy?.taxRates?.taxes}; return waitForBatchedUpdates() @@ -491,10 +460,8 @@ describe('actions/PolicyTax', () => { }), ) .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - return fetch.resume() as Promise; + mockFetch?.fail?.(); + return mockFetch?.resume?.() as Promise; }) .then(waitForBatchedUpdates) .then( @@ -521,57 +488,52 @@ describe('actions/PolicyTax', () => { it('Rename tax', () => { const taxID = 'id_TAX_RATE_1'; const newTaxName = 'Tax rate 1 updated'; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); renamePolicyTax(fakePolicy.id, taxID, newTaxName); - return ( - waitForBatchedUpdates() - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - const updatedTax = policy?.taxRates?.taxes?.[taxID]; - expect(updatedTax?.name).toBe(newTaxName); - expect(updatedTax?.pendingFields?.name).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); - expect(updatedTax?.errorFields?.name).toBeFalsy(); + return waitForBatchedUpdates() + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + const updatedTax = policy?.taxRates?.taxes?.[taxID]; + expect(updatedTax?.name).toBe(newTaxName); + expect(updatedTax?.pendingFields?.name).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); + expect(updatedTax?.errorFields?.name).toBeFalsy(); - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - const updatedTax = policy?.taxRates?.taxes?.[taxID]; - expect(updatedTax?.errorFields?.name).toBeFalsy(); - expect(updatedTax?.pendingFields?.name).toBeFalsy(); - resolve(); - }, - }); - }), - ) - ); + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + const updatedTax = policy?.taxRates?.taxes?.[taxID]; + expect(updatedTax?.errorFields?.name).toBeFalsy(); + expect(updatedTax?.pendingFields?.name).toBeFalsy(); + resolve(); + }, + }); + }), + ); }); it('Rename tax but API returns an error, then recover the original tax`s name', () => { const taxID = 'id_TAX_RATE_1'; const newTaxName = 'Tax rate 1 updated'; const originalTaxRate = {...fakePolicy?.taxRates?.taxes[taxID]}; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); renamePolicyTax(fakePolicy.id, taxID, newTaxName); return waitForBatchedUpdates() .then( @@ -593,10 +555,8 @@ describe('actions/PolicyTax', () => { }), ) .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - return fetch.resume() as Promise; + mockFetch?.fail?.(); + return mockFetch?.resume?.() as Promise; }) .then(waitForBatchedUpdates) .then( @@ -623,49 +583,45 @@ describe('actions/PolicyTax', () => { const taxID = 'id_TAX_RATE_1'; const newTaxValue = 10; const stringTaxValue = `${newTaxValue}%`; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); updatePolicyTaxValue(fakePolicy.id, taxID, newTaxValue); - return ( - waitForBatchedUpdates() - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - const updatedTax = policy?.taxRates?.taxes?.[taxID]; - expect(updatedTax?.value).toBe(stringTaxValue); - expect(updatedTax?.pendingFields?.value).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); - expect(updatedTax?.errorFields?.value).toBeFalsy(); + return waitForBatchedUpdates() + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + const updatedTax = policy?.taxRates?.taxes?.[taxID]; + expect(updatedTax?.value).toBe(stringTaxValue); + expect(updatedTax?.pendingFields?.value).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); + expect(updatedTax?.errorFields?.value).toBeFalsy(); - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - const updatedTax = policy?.taxRates?.taxes?.[taxID]; - expect(updatedTax?.errorFields?.value).toBeFalsy(); - expect(updatedTax?.pendingFields?.value).toBeFalsy(); - resolve(); - }, - }); - }), - ) - ); + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + const updatedTax = policy?.taxRates?.taxes?.[taxID]; + expect(updatedTax?.errorFields?.value).toBeFalsy(); + expect(updatedTax?.pendingFields?.value).toBeFalsy(); + resolve(); + }, + }); + }), + ); }); it('Update tax`s value but API returns an error, then recover the original tax`s value', () => { @@ -673,8 +629,7 @@ describe('actions/PolicyTax', () => { const newTaxValue = 10; const originalTaxRate = {...fakePolicy?.taxRates?.taxes[taxID]}; const stringTaxValue = `${newTaxValue}%`; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); updatePolicyTaxValue(fakePolicy.id, taxID, newTaxValue); return waitForBatchedUpdates() .then( @@ -696,10 +651,8 @@ describe('actions/PolicyTax', () => { }), ) .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - return fetch.resume() as Promise; + mockFetch?.fail?.(); + return mockFetch?.resume?.() as Promise; }) .then(waitForBatchedUpdates) .then( @@ -726,113 +679,104 @@ describe('actions/PolicyTax', () => { const foreignTaxDefault = fakePolicy?.taxRates?.foreignTaxDefault; const taxID = 'id_TAX_RATE_1'; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); deletePolicyTaxes(fakePolicy.id, [taxID]); - return ( - waitForBatchedUpdates() - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - const taxRates = policy?.taxRates; - const deletedTax = taxRates?.taxes?.[taxID]; - expect(taxRates?.pendingFields?.foreignTaxDefault).toBeFalsy(); - expect(taxRates?.foreignTaxDefault).toBe(foreignTaxDefault); - expect(deletedTax?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); - expect(deletedTax?.errors).toBeFalsy(); - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - const taxRates = policy?.taxRates; - const deletedTax = taxRates?.taxes?.[taxID]; - expect(taxRates?.pendingFields?.foreignTaxDefault).toBeFalsy(); - expect(deletedTax).toBeFalsy(); - resolve(); - }, - }); - }), - ) - ); + return waitForBatchedUpdates() + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + const taxRates = policy?.taxRates; + const deletedTax = taxRates?.taxes?.[taxID]; + expect(taxRates?.pendingFields?.foreignTaxDefault).toBeFalsy(); + expect(taxRates?.foreignTaxDefault).toBe(foreignTaxDefault); + expect(deletedTax?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); + expect(deletedTax?.errors).toBeFalsy(); + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + const taxRates = policy?.taxRates; + const deletedTax = taxRates?.taxes?.[taxID]; + expect(taxRates?.pendingFields?.foreignTaxDefault).toBeFalsy(); + expect(deletedTax).toBeFalsy(); + resolve(); + }, + }); + }), + ); }); it('Delete tax that is foreignTaxDefault', () => { const taxID = 'id_TAX_RATE_1'; const firstTaxID = 'id_TAX_EXEMPT'; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); - return ( - Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, {taxRates: {foreignTaxDefault: 'id_TAX_RATE_1'}}) - .then(() => { - deletePolicyTaxes(fakePolicy.id, [taxID]); - return waitForBatchedUpdates(); - }) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - const taxRates = policy?.taxRates; - const deletedTax = taxRates?.taxes?.[taxID]; - expect(taxRates?.pendingFields?.foreignTaxDefault).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); - expect(taxRates?.foreignTaxDefault).toBe(firstTaxID); - expect(deletedTax?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); - expect(deletedTax?.errors).toBeFalsy(); - resolve(); - }, - }); - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(fetch.resume) - .then(waitForBatchedUpdates) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, - waitForCollectionCallback: false, - callback: (policy) => { - Onyx.disconnect(connectionID); - const taxRates = policy?.taxRates; - const deletedTax = taxRates?.taxes?.[taxID]; - expect(taxRates?.pendingFields?.foreignTaxDefault).toBeFalsy(); - expect(deletedTax).toBeFalsy(); - resolve(); - }, - }); - }), - ) - ); + mockFetch?.pause?.(); + return Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, {taxRates: {foreignTaxDefault: 'id_TAX_RATE_1'}}) + .then(() => { + deletePolicyTaxes(fakePolicy.id, [taxID]); + return waitForBatchedUpdates(); + }) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + const taxRates = policy?.taxRates; + const deletedTax = taxRates?.taxes?.[taxID]; + expect(taxRates?.pendingFields?.foreignTaxDefault).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); + expect(taxRates?.foreignTaxDefault).toBe(firstTaxID); + expect(deletedTax?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); + expect(deletedTax?.errors).toBeFalsy(); + resolve(); + }, + }); + }), + ) + .then(mockFetch?.resume) + .then(waitForBatchedUpdates) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, + waitForCollectionCallback: false, + callback: (policy) => { + Onyx.disconnect(connectionID); + const taxRates = policy?.taxRates; + const deletedTax = taxRates?.taxes?.[taxID]; + expect(taxRates?.pendingFields?.foreignTaxDefault).toBeFalsy(); + expect(deletedTax).toBeFalsy(); + resolve(); + }, + }); + }), + ); }); it('Delete tax that is not foreignTaxDefault but API return an error, then recover the delated tax', () => { const foreignTaxDefault = fakePolicy?.taxRates?.foreignTaxDefault; const taxID = 'id_TAX_RATE_1'; - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + mockFetch?.pause?.(); deletePolicyTaxes(fakePolicy.id, [taxID]); return waitForBatchedUpdates() .then( @@ -855,10 +799,8 @@ describe('actions/PolicyTax', () => { }), ) .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.fail(); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - return fetch.resume() as Promise; + mockFetch?.fail?.(); + return mockFetch?.resume?.() as Promise; }) .then(waitForBatchedUpdates) .then( diff --git a/tests/actions/PolicyTest.ts b/tests/actions/PolicyTest.ts index 3e11f0a67938..6dae053afac7 100644 --- a/tests/actions/PolicyTest.ts +++ b/tests/actions/PolicyTest.ts @@ -7,6 +7,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy as PolicyType, Report, ReportAction, ReportActions} from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/Report'; import * as TestHelper from '../utils/TestHelper'; +import type {MockFetch} from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; const ESH_EMAIL = 'eshgupta1217@gmail.com'; @@ -23,15 +24,13 @@ describe('actions/Policy', () => { }); beforeEach(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); return Onyx.clear().then(waitForBatchedUpdates); }); describe('createWorkspace', () => { it('creates a new workspace', async () => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.pause(); + (fetch as MockFetch)?.pause?.(); Onyx.set(ONYXKEYS.SESSION, {email: ESH_EMAIL, accountID: ESH_ACCOUNT_ID}); await waitForBatchedUpdates(); @@ -124,8 +123,7 @@ describe('actions/Policy', () => { }); // Check for success data - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - fetch.resume(); + (fetch as MockFetch)?.resume?.(); await waitForBatchedUpdates(); policy = await new Promise((resolve) => { diff --git a/tests/actions/ReportTest.ts b/tests/actions/ReportTest.ts index 28aa84babfb5..4b49bdef5edd 100644 --- a/tests/actions/ReportTest.ts +++ b/tests/actions/ReportTest.ts @@ -52,7 +52,6 @@ describe('actions/Report', () => { afterEach(PusherHelper.teardown); it('should store a new report action in Onyx when onyxApiUpdate event is handled via Pusher', () => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); const TEST_USER_ACCOUNT_ID = 1; @@ -168,7 +167,6 @@ describe('actions/Report', () => { return TestHelper.signInWithTestUser(TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN) .then(() => TestHelper.setPersonalDetails(TEST_USER_LOGIN, TEST_USER_ACCOUNT_ID)) .then(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); // WHEN we add enough logs to send a packet @@ -195,7 +193,6 @@ describe('actions/Report', () => { it('should be updated correctly when new comments are added, deleted or marked as unread', () => { jest.useFakeTimers(); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); const REPORT_ID = '1'; let report: OnyxEntry; @@ -432,7 +429,6 @@ describe('actions/Report', () => { * already in the comment and the user deleted it on purpose. */ - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); // User edits comment to add link @@ -545,7 +541,6 @@ describe('actions/Report', () => { }); it('should properly toggle reactions on a message', () => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); const TEST_USER_ACCOUNT_ID = 1; @@ -666,7 +661,6 @@ describe('actions/Report', () => { }); it("shouldn't add the same reaction twice when changing preferred skin color and reaction doesn't support skin colors", () => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); const TEST_USER_ACCOUNT_ID = 1; diff --git a/tests/perf-test/ChatFinderPage.perf-test.tsx b/tests/perf-test/ChatFinderPage.perf-test.tsx index c31201c37b24..9c673d278905 100644 --- a/tests/perf-test/ChatFinderPage.perf-test.tsx +++ b/tests/perf-test/ChatFinderPage.perf-test.tsx @@ -1,5 +1,5 @@ import type * as NativeNavigation from '@react-navigation/native'; -import type {StackScreenProps} from '@react-navigation/stack'; +import type {StackNavigationProp, StackScreenProps} from '@react-navigation/stack'; import {fireEvent, screen} from '@testing-library/react-native'; import React, {useMemo} from 'react'; import type {ComponentType} from 'react'; @@ -112,7 +112,6 @@ beforeAll(() => // Initialize the network key for OfflineWithFeedback beforeEach(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); wrapOnyxWithWaitForBatchedUpdates(Onyx); Onyx.merge(ONYXKEYS.NETWORK, {isOffline: false}); @@ -124,9 +123,9 @@ afterEach(() => { }); type ChatFinderPageProps = StackScreenProps & { - betas: OnyxEntry; - reports: OnyxCollection; - isSearchingForReports: OnyxEntry; + betas?: OnyxEntry; + reports?: OnyxCollection; + isSearchingForReports?: OnyxEntry; }; function ChatFinderPageWrapper(args: ChatFinderPageProps) { @@ -164,21 +163,26 @@ test('[ChatFinderPage] should render list with cached options', async () => { await screen.findByTestId('ChatFinderPage'); }; - const navigation = {addListener}; - - return ( - waitForBatchedUpdates() - .then(() => - Onyx.multiSet({ - ...mockedReports, - [ONYXKEYS.PERSONAL_DETAILS_LIST]: mockedPersonalDetails, - [ONYXKEYS.BETAS]: mockedBetas, - [ONYXKEYS.IS_SEARCHING_FOR_REPORTS]: true, - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(() => measurePerformance(, {scenario})) - ); + const navigation = {addListener} as unknown as StackNavigationProp; + + return waitForBatchedUpdates() + .then(() => + Onyx.multiSet({ + ...mockedReports, + [ONYXKEYS.PERSONAL_DETAILS_LIST]: mockedPersonalDetails, + [ONYXKEYS.BETAS]: mockedBetas, + [ONYXKEYS.IS_SEARCHING_FOR_REPORTS]: true, + }), + ) + .then(() => + measurePerformance( + , + {scenario}, + ), + ); }); test('[ChatFinderPage] should interact when text input changes', async () => { @@ -193,19 +197,24 @@ test('[ChatFinderPage] should interact when text input changes', async () => { fireEvent.changeText(input, 'Email Five'); }; - const navigation = {addListener}; - - return ( - waitForBatchedUpdates() - .then(() => - Onyx.multiSet({ - ...mockedReports, - [ONYXKEYS.PERSONAL_DETAILS_LIST]: mockedPersonalDetails, - [ONYXKEYS.BETAS]: mockedBetas, - [ONYXKEYS.IS_SEARCHING_FOR_REPORTS]: true, - }), - ) - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. - .then(() => measurePerformance(, {scenario})) - ); + const navigation = {addListener} as unknown as StackNavigationProp; + + return waitForBatchedUpdates() + .then(() => + Onyx.multiSet({ + ...mockedReports, + [ONYXKEYS.PERSONAL_DETAILS_LIST]: mockedPersonalDetails, + [ONYXKEYS.BETAS]: mockedBetas, + [ONYXKEYS.IS_SEARCHING_FOR_REPORTS]: true, + }), + ) + .then(() => + measurePerformance( + , + {scenario}, + ), + ); }); diff --git a/tests/perf-test/ReportScreen.perf-test.tsx b/tests/perf-test/ReportScreen.perf-test.tsx index 29a17e9b0070..379dc34489e5 100644 --- a/tests/perf-test/ReportScreen.perf-test.tsx +++ b/tests/perf-test/ReportScreen.perf-test.tsx @@ -1,4 +1,4 @@ -import type {StackScreenProps} from '@react-navigation/stack'; +import type {StackNavigationProp, StackScreenProps} from '@react-navigation/stack'; import {screen, waitFor} from '@testing-library/react-native'; import type {ComponentType} from 'react'; import React from 'react'; @@ -114,7 +114,6 @@ beforeAll(() => // Initialize the network key for OfflineWithFeedback beforeEach(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); wrapOnyxWithWaitForBatchedUpdates(Onyx); Onyx.merge(ONYXKEYS.NETWORK, {isOffline: false}); @@ -163,7 +162,7 @@ function ReportScreenWrapper(props: ReportScreenWrapperProps) { const report = {...createRandomReport(1), policyID: '1'}; const reportActions = ReportTestUtils.getMockedReportActionsMap(1000); -const mockRoute = {params: {reportID: '1'}}; +const mockRoute = {params: {reportID: '1', reportActionID: ''}, key: 'Report', name: 'Report' as const}; test('[ReportScreen] should render ReportScreen', () => { const {triggerTransitionEnd, addListener} = TestHelper.createAddListenerMock(); @@ -185,7 +184,7 @@ test('[ReportScreen] should render ReportScreen', () => { await screen.findByTestId('report-actions-list'); }; - const navigation = {addListener}; + const navigation = {addListener} as unknown as StackNavigationProp; return waitForBatchedUpdates() .then(() => { @@ -210,9 +209,7 @@ test('[ReportScreen] should render ReportScreen', () => { .then(() => measurePerformance( , {scenario}, diff --git a/tests/ui/UnreadIndicatorsTest.tsx b/tests/ui/UnreadIndicatorsTest.tsx index 3e2c1b419070..e5c7e0359eed 100644 --- a/tests/ui/UnreadIndicatorsTest.tsx +++ b/tests/ui/UnreadIndicatorsTest.tsx @@ -119,7 +119,6 @@ beforeAll(() => { // fetch() never gets called so it does not need mocking) or we might have fetch throw an error to test error handling // behavior. But here we just want to treat all API requests as a generic "success" and in the cases where we need to // simulate data arriving we will just set it into Onyx directly with Onyx.merge() or Onyx.set() etc. - // @ts-expect-error -- TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated global.fetch = TestHelper.getGlobalFetchMock(); Linking.setInitialURL('https://new.expensify.com/'); diff --git a/tests/unit/APITest.ts b/tests/unit/APITest.ts index b9404973d418..07633b19802b 100644 --- a/tests/unit/APITest.ts +++ b/tests/unit/APITest.ts @@ -1,5 +1,6 @@ import MockedOnyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; +import type {ApiRequestCommandParameters, ReadCommand, WriteCommand} from '@libs/API/types'; import CONST from '@src/CONST'; import * as PersistedRequests from '@src/libs/actions/PersistedRequests'; import * as API from '@src/libs/API'; @@ -40,7 +41,6 @@ type XhrCalls = Array<{ const originalXHR = HttpUtils.xhr; beforeEach(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); HttpUtils.xhr = originalXHR; MainQueue.clear(); @@ -71,12 +71,9 @@ describe('APITests', () => { return Onyx.set(ONYXKEYS.NETWORK, {isOffline: true, isBackendReachable: false}) .then(() => { // When API Writes and Reads are called - // @ts-expect-error - mocking the parameter - API.write('mock command', {param1: 'value1'}); - // @ts-expect-error - mocking the parameter - API.read('mock command', {param2: 'value2'}); - // @ts-expect-error - mocking the parameter - API.write('mock command', {param3: 'value3'}); + API.write('mock command' as WriteCommand, {param1: 'value1'} as ApiRequestCommandParameters[WriteCommand]); + API.read('mock command' as ReadCommand, {param2: 'value2'} as unknown as ApiRequestCommandParameters[ReadCommand]); + API.write('mock command' as WriteCommand, {param3: 'value3'} as ApiRequestCommandParameters[WriteCommand]); return waitForBatchedUpdates(); }) .then(() => { @@ -110,10 +107,8 @@ describe('APITests', () => { }) .then(() => { // When API Write commands are made - // @ts-expect-error - mocking the parameter - API.write('mock command', {param1: 'value1'}); - // @ts-expect-error - mocking the parameter - API.write('mock command', {param2: 'value2'}); + API.write('mock command' as WriteCommand, {param1: 'value1'} as ApiRequestCommandParameters[WriteCommand]); + API.write('mock command' as WriteCommand, {param2: 'value2'} as ApiRequestCommandParameters[WriteCommand]); return waitForBatchedUpdates(); }) .then(() => { @@ -161,10 +156,8 @@ describe('APITests', () => { Onyx.set(ONYXKEYS.NETWORK, {isOffline: true, isBackendReachable: false}) .then(() => { // When API Write commands are made - // @ts-expect-error - mocking the parameter - API.write('mock command', {param1: 'value1'}); - // @ts-expect-error - mocking the parameter - API.write('mock command', {param2: 'value2'}); + API.write('mock command' as WriteCommand, {param1: 'value1'} as ApiRequestCommandParameters[WriteCommand]); + API.write('mock command' as WriteCommand, {param2: 'value2'} as ApiRequestCommandParameters[WriteCommand]); return waitForBatchedUpdates(); }) @@ -225,8 +218,7 @@ describe('APITests', () => { Onyx.set(ONYXKEYS.NETWORK, {isOffline: true, isBackendReachable: false}) .then(() => { // When API Write commands are made - // @ts-expect-error - mocking the parameter - API.write('mock command', {param1: 'value1'}); + API.write('mock command' as WriteCommand, {param1: 'value1'} as ApiRequestCommandParameters[WriteCommand]); return waitForNetworkPromises(); }) @@ -312,8 +304,7 @@ describe('APITests', () => { waitForBatchedUpdates() .then(() => Onyx.set(ONYXKEYS.NETWORK, {isOffline: true, isBackendReachable: false})) .then(() => { - // @ts-expect-error - mocking the parameter - API.write('Mock', {param1: 'value1'}); + API.write('Mock' as WriteCommand, {param1: 'value1'} as ApiRequestCommandParameters[WriteCommand]); return waitForBatchedUpdates(); }) @@ -346,20 +337,13 @@ describe('APITests', () => { }) .then(() => { // When we queue 6 persistable commands and one not persistable - // @ts-expect-error - mocking the parameter - API.write('MockCommand', {content: 'value1'}); - // @ts-expect-error - mocking the parameter - API.write('MockCommand', {content: 'value2'}); - // @ts-expect-error - mocking the parameter - API.write('MockCommand', {content: 'value3'}); - // @ts-expect-error - mocking the parameter - API.read('MockCommand', {content: 'not-persisted'}); - // @ts-expect-error - mocking the parameter - API.write('MockCommand', {content: 'value4'}); - // @ts-expect-error - mocking the parameter - API.write('MockCommand', {content: 'value5'}); - // @ts-expect-error - mocking the parameter - API.write('MockCommand', {content: 'value6'}); + API.write('MockCommand' as WriteCommand, {content: 'value1'} as ApiRequestCommandParameters[WriteCommand]); + API.write('MockCommand' as WriteCommand, {content: 'value2'} as ApiRequestCommandParameters[WriteCommand]); + API.write('MockCommand' as WriteCommand, {content: 'value3'} as ApiRequestCommandParameters[WriteCommand]); + API.read('MockCommand' as ReadCommand, {content: 'not-persisted'} as unknown as ApiRequestCommandParameters[ReadCommand]); + API.write('MockCommand' as WriteCommand, {content: 'value4'} as ApiRequestCommandParameters[WriteCommand]); + API.write('MockCommand' as WriteCommand, {content: 'value5'} as ApiRequestCommandParameters[WriteCommand]); + API.write('MockCommand' as WriteCommand, {content: 'value6'} as ApiRequestCommandParameters[WriteCommand]); return waitForBatchedUpdates(); }) @@ -390,18 +374,12 @@ describe('APITests', () => { }) .then(() => { // When we queue 6 persistable commands - // @ts-expect-error - mocking the parameter - API.write('MockCommand', {content: 'value1'}); - // @ts-expect-error - mocking the parameter - API.write('MockCommand', {content: 'value2'}); - // @ts-expect-error - mocking the parameter - API.write('MockCommand', {content: 'value3'}); - // @ts-expect-error - mocking the parameter - API.write('MockCommand', {content: 'value4'}); - // @ts-expect-error - mocking the parameter - API.write('MockCommand', {content: 'value5'}); - // @ts-expect-error - mocking the parameter - API.write('MockCommand', {content: 'value6'}); + API.write('MockCommand' as WriteCommand, {content: 'value1'} as ApiRequestCommandParameters[WriteCommand]); + API.write('MockCommand' as WriteCommand, {content: 'value2'} as ApiRequestCommandParameters[WriteCommand]); + API.write('MockCommand' as WriteCommand, {content: 'value3'} as ApiRequestCommandParameters[WriteCommand]); + API.write('MockCommand' as WriteCommand, {content: 'value4'} as ApiRequestCommandParameters[WriteCommand]); + API.write('MockCommand' as WriteCommand, {content: 'value5'} as ApiRequestCommandParameters[WriteCommand]); + API.write('MockCommand' as WriteCommand, {content: 'value6'} as ApiRequestCommandParameters[WriteCommand]); return waitForBatchedUpdates(); }) .then(() => Onyx.set(ONYXKEYS.NETWORK, {isOffline: false, isBackendReachable: true})) @@ -454,8 +432,7 @@ describe('APITests', () => { return waitForBatchedUpdates(); }) .then(() => { - // @ts-expect-error - mocking the parameter - API.write('MockCommand'); + API.write('MockCommand' as WriteCommand, {}); expect(PersistedRequests.getAll().length).toBe(1); expect(NetworkStore.isOffline()).toBe(true); expect(SequentialQueue.isRunning()).toBe(false); @@ -524,8 +501,7 @@ describe('APITests', () => { NetworkStore.resetHasReadRequiredDataFromStorage(); // And queue a Write request while offline - // @ts-expect-error - mocking the parameter - API.write('MockCommand', {content: 'value1'}); + API.write('MockCommand' as WriteCommand, {content: 'value1'} as ApiRequestCommandParameters[WriteCommand]); // Then we should expect the request to get persisted expect(PersistedRequests.getAll().length).toBe(1); @@ -561,12 +537,9 @@ describe('APITests', () => { expect(NetworkStore.isOffline()).toBe(false); // WHEN we make a request that should be retried, one that should not, and another that should - // @ts-expect-error - mocking the parameter - API.write('MockCommandOne'); - // @ts-expect-error - mocking the parameter - API.read('MockCommandTwo'); - // @ts-expect-error - mocking the parameter - API.write('MockCommandThree'); + API.write('MockCommandOne' as WriteCommand, {}); + API.read('MockCommandTwo' as ReadCommand, {}); + API.write('MockCommandThree' as WriteCommand, {}); // THEN the retryable requests should immediately be added to the persisted requests expect(PersistedRequests.getAll().length).toBe(2); diff --git a/tests/unit/EmojiTest.ts b/tests/unit/EmojiTest.ts index 24e56ec8de23..968e543363f2 100644 --- a/tests/unit/EmojiTest.ts +++ b/tests/unit/EmojiTest.ts @@ -202,7 +202,6 @@ describe('EmojiTest', () => { beforeAll(() => { Onyx.init({keys: ONYXKEYS}); - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); spy = jest.spyOn(User, 'updateFrequentlyUsedEmojis'); }); diff --git a/tests/unit/MiddlewareTest.ts b/tests/unit/MiddlewareTest.ts index 78a54461ae20..cc4bf7d0df6b 100644 --- a/tests/unit/MiddlewareTest.ts +++ b/tests/unit/MiddlewareTest.ts @@ -14,7 +14,6 @@ Onyx.init({ }); beforeAll(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); }); diff --git a/tests/unit/MigrationTest.ts b/tests/unit/MigrationTest.ts index 69e0e80e589a..9f0a3433932c 100644 --- a/tests/unit/MigrationTest.ts +++ b/tests/unit/MigrationTest.ts @@ -1,10 +1,12 @@ /* eslint-disable @typescript-eslint/naming-convention */ import Onyx from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; import CONST from '@src/CONST'; import Log from '@src/libs/Log'; import CheckForPreviousReportActionID from '@src/libs/migrations/CheckForPreviousReportActionID'; import KeyReportActionsDraftByReportActionID from '@src/libs/migrations/KeyReportActionsDraftByReportActionID'; import ONYXKEYS from '@src/ONYXKEYS'; +import type * as OnyxTypes from '@src/types/onyx'; import type {ReportActionsDraftCollectionDataSet} from '@src/types/onyx/ReportActionsDrafts'; import {toCollectionDataSet} from '@src/types/utils/CollectionDataSet'; import type CollectionDataSet from '@src/types/utils/CollectionDataSet'; @@ -260,13 +262,10 @@ describe('Migrations', () => { it('Should move individual draft to a draft collection of report', () => { const setQueries: ReportActionsDraftCollectionDataSet = {}; - // @ts-expect-error preset invalid value - setQueries[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}1_1`] = 'a'; - // @ts-expect-error preset invalid value - setQueries[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}1_2`] = 'b'; + setQueries[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}1_1`] = 'a' as unknown as OnyxEntry; + setQueries[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}1_2`] = 'b' as unknown as OnyxEntry; setQueries[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}2`] = {3: 'c'}; - // @ts-expect-error preset invalid value - setQueries[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}2_4`] = 'd'; + setQueries[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}2_4`] = 'd' as unknown as OnyxEntry; return Onyx.multiSet(setQueries) .then(KeyReportActionsDraftByReportActionID) @@ -321,8 +320,7 @@ describe('Migrations', () => { it("Shouldn't move empty individual draft to a draft collection of report", () => { const setQueries: ReportActionsDraftCollectionDataSet = {}; - // @ts-expect-error preset empty string value - setQueries[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}1_1`] = ''; + setQueries[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}1_1`] = '' as unknown as OnyxEntry; setQueries[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS}1`] = {}; return Onyx.multiSet(setQueries) diff --git a/tests/unit/NetworkTest.ts b/tests/unit/NetworkTest.ts index 3ea0f4da9468..9c48de96d1a2 100644 --- a/tests/unit/NetworkTest.ts +++ b/tests/unit/NetworkTest.ts @@ -28,7 +28,6 @@ OnyxUpdateManager(); const originalXHR = HttpUtils.xhr; beforeEach(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); HttpUtils.xhr = originalXHR; MainQueue.clear(); diff --git a/tests/unit/ReportActionsUtilsTest.ts b/tests/unit/ReportActionsUtilsTest.ts index 05fe50fe78b7..19b4a23e9028 100644 --- a/tests/unit/ReportActionsUtilsTest.ts +++ b/tests/unit/ReportActionsUtilsTest.ts @@ -1,4 +1,5 @@ import Onyx from 'react-native-onyx'; +import type {KeyValueMapping} from 'react-native-onyx'; import CONST from '../../src/CONST'; import * as ReportActionsUtils from '../../src/libs/ReportActionsUtils'; import ONYXKEYS from '../../src/ONYXKEYS'; @@ -1952,11 +1953,10 @@ describe('ReportActionsUtils', () => { waitForBatchedUpdates() // When Onyx is updated with the data and the sidebar re-renders .then(() => - // @ts-expect-error Preset necessary values Onyx.multiSet({ [`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`]: report, [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`]: {[action.reportActionID]: action, [action2.reportActionID]: action2}, - }), + } as unknown as KeyValueMapping), ) .then( () => diff --git a/tests/unit/RequestTest.ts b/tests/unit/RequestTest.ts index de05f9cab2fa..bb444717ad41 100644 --- a/tests/unit/RequestTest.ts +++ b/tests/unit/RequestTest.ts @@ -5,7 +5,6 @@ import * as TestHelper from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; beforeAll(() => { - // @ts-expect-error TODO: Remove this once TestHelper (https://github.com/Expensify/App/issues/25318) is migrated to TypeScript. global.fetch = TestHelper.getGlobalFetchMock(); }); diff --git a/tests/unit/awaitStagingDeploysTest.ts b/tests/unit/awaitStagingDeploysTest.ts index e4f7d6494b15..64d79c9faf94 100644 --- a/tests/unit/awaitStagingDeploysTest.ts +++ b/tests/unit/awaitStagingDeploysTest.ts @@ -68,16 +68,16 @@ beforeAll(() => { asMutable(core).getInput = mockGetInput; // Mock octokit module - const moctokit: InternalOctokit = { + const moctokit = { rest: { - // @ts-expect-error This error was removed because getting the rest of the data from internalOctokit makes the test to break actions: { + ...(GithubUtils.internalOctokit as unknown as typeof GithubUtils.octokit.actions), listWorkflowRuns: mockListWorkflowRuns as unknown as typeof GithubUtils.octokit.actions.listWorkflowRuns, }, }, }; - GithubUtils.internalOctokit = moctokit; + GithubUtils.internalOctokit = moctokit as InternalOctokit; }); beforeEach(() => { diff --git a/tests/unit/sanitizeStringForJSONParseTest.ts b/tests/unit/sanitizeStringForJSONParseTest.ts index 9d39685eb1f7..f9e647eb9a2a 100644 --- a/tests/unit/sanitizeStringForJSONParseTest.ts +++ b/tests/unit/sanitizeStringForJSONParseTest.ts @@ -30,7 +30,6 @@ const validJSONData: Array<[string, string]> = [ describe('santizeStringForJSONParse', () => { describe.each(badInputs)('willDetectBadInputs', (input) => { test('sanitizeStringForJSONParse', () => { - // @ts-expect-error TODO: Remove this once sanitizeStringForJSONParse (https://github.com/Expensify/App/issues/25360) is migrated to TypeScript. expect(() => sanitizeStringForJSONParse(input)).toThrow(); }); }); diff --git a/tests/utils/TestHelper.ts b/tests/utils/TestHelper.ts index 562176288565..bd107ba6ed56 100644 --- a/tests/utils/TestHelper.ts +++ b/tests/utils/TestHelper.ts @@ -190,7 +190,7 @@ function getGlobalFetchMock() { mockFetch.fail = () => (shouldFail = true); mockFetch.succeed = () => (shouldFail = false); - return mockFetch; + return mockFetch as typeof fetch; } function setPersonalDetails(login: string, accountID: number) { @@ -242,4 +242,5 @@ const createAddListenerMock = () => { return {triggerTransitionEnd, addListener}; }; +export type {MockFetch}; export {assertFormDataMatchesObject, buildPersonalDetails, buildTestReportComment, createAddListenerMock, getGlobalFetchMock, setPersonalDetails, signInWithTestUser, signOutTestUser};