From da5ac472f94be4bd0ed974707b1ef619d445b823 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Sat, 20 Apr 2024 15:23:25 +0200 Subject: [PATCH 01/20] Check and remove unnecessary @ts-expect-error suppressions --- __mocks__/@react-navigation/native/index.ts | 3 +- src/Expensify.tsx | 2 +- .../BaseAnchorForAttachmentsOnly.tsx | 3 +- src/hooks/useAutoFocusInput.ts | 1 - src/libs/ObjectUtils.ts | 5 +- src/libs/migrations/NVPMigration.ts | 20 +- .../EnablePayments/AdditionalDetailsStep.tsx | 3 +- .../DateOfBirthUBO.tsx | 3 +- .../substeps/IncorporationDateBusiness.tsx | 3 +- .../PersonalInfo/substeps/DateOfBirth.tsx | 3 +- .../ReportActionCompose.tsx | 10 +- src/pages/home/report/ReportFooter.tsx | 7 +- .../PersonalDetails/StateSelectionPage.tsx | 5 +- tests/actions/IOUTest.ts | 1884 ++++++++--------- tests/actions/PolicyTest.ts | 8 +- tests/actions/ReportTest.ts | 6 - tests/perf-test/ReportScreen.perf-test.tsx | 9 +- tests/perf-test/SearchPage.perf-test.tsx | 11 +- tests/perf-test/SignInPage.perf-test.tsx | 2 +- tests/ui/UnreadIndicatorsTest.tsx | 1 - tests/unit/APITest.ts | 83 +- tests/unit/EmojiTest.ts | 1 - tests/unit/MiddlewareTest.ts | 1 - tests/unit/NetworkTest.ts | 1 - tests/unit/ReportActionsUtilsTest.ts | 4 +- tests/unit/RequestTest.ts | 1 - tests/unit/awaitStagingDeploysTest.ts | 1 - tests/utils/TestHelper.ts | 3 +- 28 files changed, 1001 insertions(+), 1083 deletions(-) diff --git a/__mocks__/@react-navigation/native/index.ts b/__mocks__/@react-navigation/native/index.ts index 9a6680ba0b6e..86772991ddac 100644 --- a/__mocks__/@react-navigation/native/index.ts +++ b/__mocks__/@react-navigation/native/index.ts @@ -3,8 +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'; diff --git a/src/Expensify.tsx b/src/Expensify.tsx index 6a57d6fdcc10..4920205d731d 100644 --- a/src/Expensify.tsx +++ b/src/Expensify.tsx @@ -74,7 +74,7 @@ type ExpensifyOnyxProps = { type ExpensifyProps = ExpensifyOnyxProps; -const SplashScreenHiddenContext = React.createContext({}); +const SplashScreenHiddenContext = React.createContext<{isSplashHidden?: boolean}>({}); function Expensify({ isCheckingPublicRoom = true, diff --git a/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.tsx b/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.tsx index da8e3694a7d2..3ce6ef4b36a9 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/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/libs/ObjectUtils.ts b/src/libs/ObjectUtils.ts index 9ffa461506c8..fd4c0956e877 100644 --- a/src/libs/ObjectUtils.ts +++ b/src/libs/ObjectUtils.ts @@ -4,8 +4,9 @@ const shallowCompare = (obj1?: object, obj2?: object) => { 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) as Array; + const keys2 = Object.keys(obj2) as Array; + return keys1.length === keys2.length && keys1.every((key) => obj1[key] === obj2[key]); } return false; }; 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 46e7191f222b..8dd15915df2e 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. */} - + void; focus: (shouldDelay?: boolean) => void; - replaceSelectionWithText: (text: string, shouldAddTrailSpace: boolean) => void; + replaceSelectionWithText: (text: string, shouldAddTrailSpace: Emoji) => void; prepareCommentAndResetComposer: () => string; isFocused: () => boolean; }; @@ -73,7 +73,7 @@ type ReportActionComposeOnyxProps = { type ReportActionComposeProps = ReportActionComposeOnyxProps & WithCurrentUserPersonalDetailsProps & - Pick & { + Pick & { /** A method to call when the form is submitted */ onSubmit: (newComment: string | undefined) => void; @@ -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, @@ -479,7 +482,6 @@ function ReportActionCompose({ composerRef.current?.replaceSelectionWithText(...args)} emojiPickerID={report?.reportID} shiftVertical={emojiShiftVertical} diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index 04fbd0308390..9f9b45c18b96 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -117,7 +117,11 @@ function ReportFooter({ ); const onSubmitComment = useCallback( - (text: string) => { + (text: string | undefined) => { + if (text === undefined) { + return; + } + const isTaskCreated = handleCreateTask(text); if (isTaskCreated) { return; @@ -146,7 +150,6 @@ function ReportFooter({ { const backTo = params?.backTo ?? ''; - let backToRoute = ''; + let backToRoute = '' as Route; if (backTo) { - backToRoute = appendParam(backTo, 'state', currentState ?? ''); + backToRoute = appendParam(backTo, 'state', currentState ?? '') as Route; } - // @ts-expect-error Navigation.goBack does take a param Navigation.goBack(backToRoute); }} /> diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index aa0af7e5f037..d2c108a4260a 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -24,6 +24,7 @@ import {toCollectionDataSet} from '@src/types/utils/CollectionDataSet'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import PusherHelper from '../utils/PusherHelper'; import * as TestHelper from '../utils/TestHelper'; +import type {MockFetch} from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; import waitForNetworkPromises from '../utils/waitForNetworkPromises'; @@ -51,9 +52,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); }); @@ -68,179 +70,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?.participantAccountIDs).toEqual([CARLOS_ACCOUNT_ID]); - expect(chatReport?.iouReportID).toBe(iouReport?.reportID); + // They should be linked together + expect(chatReport?.participantAccountIDs).toEqual([CARLOS_ACCOUNT_ID]); + 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', () => { @@ -260,152 +258,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', () => { @@ -460,146 +453,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', () => { @@ -612,8 +601,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() @@ -724,10 +712,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( () => @@ -915,8 +901,8 @@ 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) ); }); }); @@ -1054,349 +1040,344 @@ 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.participantAccountIDs, [VIT_ACCOUNT_ID]), - ) ?? 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.participantAccountIDs, [CARLOS_ACCOUNT_ID, JULES_ACCOUNT_ID, VIT_ACCOUNT_ID, RORY_ACCOUNT_ID]), - ) ?? 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); - - /* 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); + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (allReports) => { + Onyx.disconnect(connectionID); - expect(carlosTransaction?.comment.comment).toBe(comment); - expect(julesTransaction?.comment.comment).toBe(comment); - expect(vitTransaction?.comment.comment).toBe(comment); - expect(groupTransaction?.comment.comment).toBe(comment); + // 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.participantAccountIDs, [VIT_ACCOUNT_ID]), + ) ?? 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.participantAccountIDs, [CARLOS_ACCOUNT_ID, JULES_ACCOUNT_ID, VIT_ACCOUNT_ID, RORY_ACCOUNT_ID]), + ) ?? 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); - 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(); + }, + }); + }), + ); }); }); @@ -1410,189 +1391,186 @@ 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(); + }, + }); + }), + ) - expect(Object.values(allReports ?? {}).length).toBe(3); + .then(mockFetch.resume) + .then( + () => + new Promise((resolve) => { + const connectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (allReports) => { + Onyx.disconnect(connectionID); - 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(Object.values(allReports ?? {}).length).toBe(3); - expect(chatReport?.iouReportID).toBeFalsy(); + 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(iouReport.status).toBe(CONST.REPORT.STATUS_NUM.REIMBURSED); - // expect(iouReport.stateNum).toBe(CONST.REPORT.STATE_NUM.APPROVED); + expect(chatReport?.iouReportID).toBeFalsy(); - resolve(); - }, - }); - }), - ) - .then( - () => - new Promise((resolve) => { - const connectionID = Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, - waitForCollectionCallback: true, - callback: (allReportActions) => { - Onyx.disconnect(connectionID); + // 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); - 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(); + }, + }); + }), + ); }); }); @@ -1602,8 +1580,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', () => { @@ -1612,8 +1589,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(() => { @@ -1756,8 +1732,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?.(); }); }); @@ -1823,8 +1798,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( @@ -1917,16 +1891,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(() => { @@ -2083,8 +2055,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); } @@ -2233,9 +2204,9 @@ describe('actions/IOU', () => { afterEach(PusherHelper.teardown); 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(); + // Given the mockFetch operations are paused and an expense is initiated + + mockFetch.pause?.(); if (transaction && createIOUAction) { // When the expense is deleted @@ -2273,9 +2244,9 @@ 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(); + // Given mockFetch operations are resumed + + mockFetch.resume?.(); await waitForBatchedUpdates(); // Then we recheck the IOU report action from the report actions collection @@ -2309,9 +2280,9 @@ 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(); + // Given an IOU report and a paused mockFetch state + + mockFetch.pause?.(); if (transaction && createIOUAction) { // When the IOU expense is deleted @@ -2333,9 +2304,9 @@ describe('actions/IOU', () => { // Then the report should be truthy for offline support 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(); + // Given the resumed mockFetch state + + mockFetch.resume?.(); await waitForBatchedUpdates(); report = await new Promise>((resolve) => { @@ -2387,8 +2358,8 @@ 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); } @@ -2413,9 +2384,9 @@ describe('actions/IOU', () => { expect(iouReport).toHaveProperty('reportID'); 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(); + // Given the resumed mockFetch state + + mockFetch.resume?.(); allReports = await new Promise>((resolve) => { const connectionID = Onyx.connect({ @@ -2478,8 +2449,8 @@ 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) { @@ -2501,10 +2472,10 @@ 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(); - // Then After resuming fetch, the report for the given thread ID still does not exist + mockFetch.resume?.(); + + // Then After resuming mockFetch, the report for the given thread ID still does not exist report = await new Promise>((resolve) => { const connectionID = Onyx.connect({ key: `${ONYXKEYS.COLLECTION.REPORT}${thread.reportID}`, @@ -2668,8 +2639,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 @@ -2690,10 +2660,10 @@ describe('actions/IOU', () => { }); }); - // When fetch resumes + // When mockFetch 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}`, @@ -2815,8 +2785,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); @@ -2838,9 +2807,9 @@ 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(); + // When we resume mockFetch + + mockFetch.resume?.(); // Then we expect the moneyRequestPreview to show [Deleted expense] @@ -2889,8 +2858,8 @@ 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); @@ -2905,8 +2874,8 @@ 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(); @@ -2981,8 +2950,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); @@ -3007,8 +2975,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({ @@ -3334,8 +3301,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/PolicyTest.ts b/tests/actions/PolicyTest.ts index 44b69bcb86fe..0c6f035ca388 100644 --- a/tests/actions/PolicyTest.ts +++ b/tests/actions/PolicyTest.ts @@ -6,6 +6,7 @@ import * as Policy from '@src/libs/actions/Policy'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy as PolicyType, Report, ReportAction, ReportActions} from '@src/types/onyx'; import * as TestHelper from '../utils/TestHelper'; +import type {MockFetch} from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; const ESH_EMAIL = 'eshgupta1217@gmail.com'; @@ -21,15 +22,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(); @@ -122,8 +121,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 6f1ea2c5ee7f..8f6e66dd1fe8 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/ReportScreen.perf-test.tsx b/tests/perf-test/ReportScreen.perf-test.tsx index c89b7fe54b5f..9084d0141838 100644 --- a/tests/perf-test/ReportScreen.perf-test.tsx +++ b/tests/perf-test/ReportScreen.perf-test.tsx @@ -108,7 +108,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}); @@ -217,9 +216,9 @@ test('[ReportScreen] should render ReportScreen with composer interactions', () .then(() => measurePerformance( , {scenario}, @@ -276,9 +275,9 @@ test.skip('[ReportScreen] should press of the report item', () => { .then(() => measurePerformance( , {scenario}, diff --git a/tests/perf-test/SearchPage.perf-test.tsx b/tests/perf-test/SearchPage.perf-test.tsx index 6ccecf0f735b..d804cff1444b 100644 --- a/tests/perf-test/SearchPage.perf-test.tsx +++ b/tests/perf-test/SearchPage.perf-test.tsx @@ -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}); @@ -177,7 +176,7 @@ test('[Search Page] should render list with cached options', async () => { [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. + // @ts-expect-error Navigation prop is only used within this test .then(() => measurePerformance(, {scenario})) ); }); @@ -206,7 +205,7 @@ test('[Search Page] should interact when text input changes', async () => { [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. + // @ts-expect-error Navigation prop is only used within this test .then(() => measurePerformance(, {scenario})) ); }); @@ -235,7 +234,7 @@ test.skip('[Search Page] should render selection list', async () => { [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. + // @ts-expect-error Navigation prop is only used within this test .then(() => measurePerformance(, {scenario})) ); }); @@ -266,7 +265,7 @@ test('[Search Page] should search in selection list', async () => { [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. + // @ts-expect-error Navigation prop is only used within this test .then(() => measurePerformance(, {scenario})) ); }); @@ -297,7 +296,7 @@ test('[Search Page] should click on list item', async () => { [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. + // @ts-expect-error Navigation prop is only used within this test .then(() => measurePerformance(, {scenario})) ); }); diff --git a/tests/perf-test/SignInPage.perf-test.tsx b/tests/perf-test/SignInPage.perf-test.tsx index 67a8723192d2..a8b6a1475e94 100644 --- a/tests/perf-test/SignInPage.perf-test.tsx +++ b/tests/perf-test/SignInPage.perf-test.tsx @@ -74,7 +74,7 @@ describe('SignInPage', () => { // Initialize the network key for OfflineWithFeedback beforeEach(() => { - global.fetch = TestHelper.getGlobalFetchMock() as typeof fetch; + global.fetch = TestHelper.getGlobalFetchMock(); wrapOnyxWithWaitForBatchedUpdates(Onyx); Onyx.merge(ONYXKEYS.NETWORK, {isOffline: false}); }); diff --git a/tests/ui/UnreadIndicatorsTest.tsx b/tests/ui/UnreadIndicatorsTest.tsx index 2aeee2cc77bf..0917772e37c9 100644 --- a/tests/ui/UnreadIndicatorsTest.tsx +++ b/tests/ui/UnreadIndicatorsTest.tsx @@ -120,7 +120,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 359288b2a1ef..f0900cfbae3e 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}) .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.write('mock command' as WriteCommand, {param2: 'value2'} as ApiRequestCommandParameters[WriteCommand]); + 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}) .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}) .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})) .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})) @@ -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 954d561598e8..9d1b4b20cf31 100644 --- a/tests/unit/EmojiTest.ts +++ b/tests/unit/EmojiTest.ts @@ -194,7 +194,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/NetworkTest.ts b/tests/unit/NetworkTest.ts index 01689de89037..b6a705b33296 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 a926d0589e80..fc6c67b5c560 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..d65872b1593b 100644 --- a/tests/unit/awaitStagingDeploysTest.ts +++ b/tests/unit/awaitStagingDeploysTest.ts @@ -70,7 +70,6 @@ beforeAll(() => { // Mock octokit module const moctokit: InternalOctokit = { rest: { - // @ts-expect-error This error was removed because getting the rest of the data from internalOctokit makes the test to break actions: { listWorkflowRuns: mockListWorkflowRuns as unknown as typeof GithubUtils.octokit.actions.listWorkflowRuns, }, diff --git a/tests/utils/TestHelper.ts b/tests/utils/TestHelper.ts index 9f3b28973923..f89ed51e28d0 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}; From 5bed3792bb9a79e783dff795c9a0b5253d5672e1 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Sat, 20 Apr 2024 15:40:44 +0200 Subject: [PATCH 02/20] Fix ts and unit test issues --- tests/unit/APITest.ts | 2 +- tests/unit/awaitStagingDeploysTest.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unit/APITest.ts b/tests/unit/APITest.ts index f0900cfbae3e..9688b0890c34 100644 --- a/tests/unit/APITest.ts +++ b/tests/unit/APITest.ts @@ -72,7 +72,7 @@ describe('APITests', () => { .then(() => { // When API Writes and Reads are called API.write('mock command' as WriteCommand, {param1: 'value1'} as ApiRequestCommandParameters[WriteCommand]); - API.write('mock command' as WriteCommand, {param2: 'value2'} 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(); }) diff --git a/tests/unit/awaitStagingDeploysTest.ts b/tests/unit/awaitStagingDeploysTest.ts index d65872b1593b..e4f7d6494b15 100644 --- a/tests/unit/awaitStagingDeploysTest.ts +++ b/tests/unit/awaitStagingDeploysTest.ts @@ -70,6 +70,7 @@ beforeAll(() => { // Mock octokit module const moctokit: InternalOctokit = { rest: { + // @ts-expect-error This error was removed because getting the rest of the data from internalOctokit makes the test to break actions: { listWorkflowRuns: mockListWorkflowRuns as unknown as typeof GithubUtils.octokit.actions.listWorkflowRuns, }, From 9c45c2554dd82b8171007730b04def1a8747201a Mon Sep 17 00:00:00 2001 From: Yauheni Date: Mon, 22 Apr 2024 17:01:39 +0200 Subject: [PATCH 03/20] Check and remove unnecessary @ts-expect-error suppressions x2 --- src/Expensify.tsx | 4 +++- src/libs/Url.ts | 5 +++-- .../home/report/ReportActionCompose/ReportActionCompose.tsx | 2 +- .../settings/Profile/PersonalDetails/StateSelectionPage.tsx | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Expensify.tsx b/src/Expensify.tsx index 4920205d731d..a2293fa23f24 100644 --- a/src/Expensify.tsx +++ b/src/Expensify.tsx @@ -74,7 +74,9 @@ type ExpensifyOnyxProps = { type ExpensifyProps = ExpensifyOnyxProps; -const SplashScreenHiddenContext = React.createContext<{isSplashHidden?: boolean}>({}); +type SplashScreenHiddenContextType = {isSplashHidden?: boolean}; + +const SplashScreenHiddenContext = React.createContext({}); function Expensify({ isCheckingPublicRoom = true, diff --git a/src/libs/Url.ts b/src/libs/Url.ts index 4e3282e7bdb3..09d632f32653 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; } export {addTrailingForwardSlash, hasSameExpensifyOrigin, getPathFromURL, appendParam}; diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index 55c56910827f..6b398bc3cb5d 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: Emoji) => void; + replaceSelectionWithText: EmojiPickerActions.OnEmojiSelected; prepareCommentAndResetComposer: () => string; isFocused: () => boolean; }; diff --git a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx index 826e165acb08..bf1bb8ad197e 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx @@ -91,10 +91,10 @@ function StateSelectionPage() { shouldShowBackButton onBackButtonPress={() => { const backTo = params?.backTo ?? ''; - let backToRoute = '' as Route; + let backToRoute: Route | undefined; if (backTo) { - backToRoute = appendParam(backTo, 'state', currentState ?? '') as Route; + backToRoute = appendParam(backTo, 'state', currentState ?? ''); } Navigation.goBack(backToRoute); From 1c65f0098a92c4ba06660d61bd9bf5f060c9eec7 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Mon, 29 Apr 2024 14:56:03 +0200 Subject: [PATCH 04/20] Remove some ts-expect-error --- src/libs/ReportActionComposeFocusManager.ts | 3 ++- .../ComposerWithSuggestions.tsx | 2 -- src/pages/home/report/ReportActionItemMessageEdit.tsx | 1 - .../{index.native.tsx => Camera.tsx} | 10 +++++----- .../NavigationAwareCamera/{index.tsx => WebCamera.tsx} | 6 +++--- .../request/step/IOURequestStepScan/index.native.tsx | 6 +++--- .../iou/request/step/IOURequestStepScan/index.tsx | 2 +- src/types/modules/react-native.d.ts | 8 ++++++++ 8 files changed, 22 insertions(+), 16 deletions(-) rename src/pages/iou/request/step/IOURequestStepScan/NavigationAwareCamera/{index.native.tsx => Camera.tsx} (66%) rename src/pages/iou/request/step/IOURequestStepScan/NavigationAwareCamera/{index.tsx => WebCamera.tsx} (75%) 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/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index 8f42da5a1575..c8ccec909805 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -321,7 +321,6 @@ function ComposerWithSuggestions( */ const setTextInputRef = useCallback( (el: TextInput) => { - // @ts-expect-error need to reassign this ref ReportActionComposeFocusManager.composerRef.current = el; textInputRef.current = el; if (typeof animatedRef === 'function') { @@ -651,7 +650,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/ReportActionItemMessageEdit.tsx b/src/pages/home/report/ReportActionItemMessageEdit.tsx index fc3c92434fc4..f800beda5954 100644 --- a/src/pages/home/report/ReportActionItemMessageEdit.tsx +++ b/src/pages/home/report/ReportActionItemMessageEdit.tsx @@ -448,7 +448,6 @@ function ReportActionItemMessageEdit( }} onBlur={(event: NativeSyntheticEvent) => { setIsFocused(false); - // @ts-expect-error TODO: TextInputFocusEventData doesn't contain relatedTarget. const relatedTargetId = event.nativeEvent?.relatedTarget?.id; if (relatedTargetId && [messageEditInput, emojiButtonID].includes(relatedTargetId)) { return; 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/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index 5a95b78779e5..463243807dd7 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -35,7 +35,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({ @@ -415,8 +415,8 @@ function IOURequestStepScan({ Date: Mon, 29 Apr 2024 16:05:28 +0200 Subject: [PATCH 05/20] Update dom.d types --- .../request/step/IOURequestStepScan/index.tsx | 5 --- src/types/modules/dom.d.ts | 45 +++++++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index d3505c87b59d..b5e989442bac 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -98,7 +98,6 @@ function IOURequestStepScan({ const defaultConstraints = {facingMode: {exact: 'environment'}}; navigator.mediaDevices - // @ts-expect-error there is a type mismatch in typescipt types for MediaStreamTrack microsoft/TypeScript#39010 .getUserMedia({video: {facingMode: {exact: 'environment'}, zoom: {ideal: 1}}}) .then((stream) => { setCameraPermissionState('granted'); @@ -108,7 +107,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; @@ -152,7 +150,6 @@ function IOURequestStepScan({ } navigator.permissions .query({ - // @ts-expect-error camera does exist in PermissionName name: 'camera', }) .then((permissionState) => { @@ -398,7 +395,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}], }); }, []); @@ -407,7 +403,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/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}; From 07da9f91a2daab6c3e5082f34a546c3e2b368cfb Mon Sep 17 00:00:00 2001 From: Yauheni Date: Tue, 30 Apr 2024 14:54:14 +0200 Subject: [PATCH 06/20] Update react-native-onyx.d and react-navigation.d-Part-1 --- __mocks__/@react-navigation/native/index.ts | 1 - .../Navigators/BottomTabNavigator.tsx | 4 +- .../CustomRouter.ts | 3 -- .../FloatingActionButtonAndPopover.tsx | 3 +- src/setup/addUtilsToWindow.ts | 6 +-- src/types/modules/react-native-onyx.d.ts | 7 ++- src/types/modules/react-navigation.d.ts | 43 +++++++++++++++++++ 7 files changed, 54 insertions(+), 13 deletions(-) diff --git a/__mocks__/@react-navigation/native/index.ts b/__mocks__/@react-navigation/native/index.ts index 86772991ddac..0b7dda4621ad 100644 --- a/__mocks__/@react-navigation/native/index.ts +++ b/__mocks__/@react-navigation/native/index.ts @@ -6,5 +6,4 @@ const useIsFocused: typeof realUseIsFocused = process.env.NODE_ENV === 'test' ? 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/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/createCustomStackNavigator/CustomRouter.ts b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts index 504803026994..1e475b6b1ff9 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts @@ -17,15 +17,12 @@ function insertRootRoute(state: State, routeToInsert: Naviga // It's safe to modify this state before returning in getRehydratedState. - // @ts-expect-error Updating read only property // noinspection JSConstantReassignment state.routes = [...nonModalRoutes, routeToInsert, ...modalRoutes]; // eslint-disable-line - // @ts-expect-error Updating read only property // noinspection JSConstantReassignment state.index = state.routes.length - 1; // eslint-disable-line - // @ts-expect-error Updating read only property // noinspection JSConstantReassignment state.stale = true; // eslint-disable-line } diff --git a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx index d74ab3fbfb58..78f2da50d943 100644 --- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx +++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx @@ -19,6 +19,7 @@ import getIconForAction from '@libs/getIconForAction'; import interceptAnonymousUser from '@libs/interceptAnonymousUser'; import getTopmostCentralPaneRoute from '@libs/Navigation/getTopmostCentralPaneRoute'; import Navigation from '@libs/Navigation/Navigation'; +import type {CentralPaneName, NavigationPartialRoute, RootStackParamList} from '@libs/Navigation/types'; import * as ReportUtils from '@libs/ReportUtils'; import * as App from '@userActions/App'; import * as IOU from '@userActions/IOU'; @@ -39,7 +40,7 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject'; const useIsFocused = () => { 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/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/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-navigation.d.ts b/src/types/modules/react-navigation.d.ts index f6a47f3cdb9a..4e0efc975c89 100644 --- a/src/types/modules/react-navigation.d.ts +++ b/src/types/modules/react-navigation.d.ts @@ -1,3 +1,4 @@ +import type {ParamListBase, PartialRoute, Route} from '@react-navigation/native'; import type {RootStackParamList} from '@libs/Navigation/types'; declare global { @@ -6,3 +7,45 @@ declare global { interface RootParamList extends RootStackParamList {} } } + +declare module '@react-navigation/native' { + type PartialState = Partial> & { + stale?: true; + routes: Array>>; + }; + type NavigationRoute = Route, ParamList[RouteName]> & { + state?: NavigationState | PartialState; + }; + type NavigationState = { + /** + * Unique key for the navigation state. + */ + key: string; + /** + * Index of the currently focused route. + */ + index: number; + /** + * List of valid route names as defined in the screen components. + */ + routeNames: Array>; + /** + * Alternative entries for history. + */ + history?: unknown[]; + /** + * List of rendered routes. + */ + routes: Array>; + /** + * Custom type for the state, whether it's for tab, stack, drawer etc. + * During rehydration, the state will be discarded if type doesn't match with router type. + * It can also be used to detect the type of the navigator we're dealing with. + */ + type: string; + /** + * Whether the navigation state has been rehydrated. + */ + stale: false; + }; +} From 85ec0d677a5010edfc9574e02e15b609490e22f2 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Wed, 1 May 2024 11:31:40 +0200 Subject: [PATCH 07/20] Fix comments --- .../Navigation/AppNavigator/getPartialStateDiff.ts | 4 ++-- src/libs/Navigation/linkTo.ts | 5 ++++- src/libs/ObjectUtils.ts | 7 +++---- tests/unit/MigrationTest.ts | 14 ++++++-------- 4 files changed, 15 insertions(+), 15 deletions(-) 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 863cb102add4..55a561e22d65 100644 --- a/src/libs/Navigation/linkTo.ts +++ b/src/libs/Navigation/linkTo.ts @@ -153,7 +153,10 @@ export default function linkTo(navigation: NavigationContainerRef | undefined, + action.payload.params?.params as Record | 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 fd4c0956e877..644fe1c7596e 100644 --- a/src/libs/ObjectUtils.ts +++ b/src/libs/ObjectUtils.ts @@ -1,11 +1,10 @@ -// 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) { - const keys1 = Object.keys(obj1) as Array; - const keys2 = Object.keys(obj2) as Array; + 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/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) From 5f422b0906ece7f57373e35a93a2cd4127d844d8 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Wed, 1 May 2024 12:35:28 +0200 Subject: [PATCH 08/20] Fix issues related with react-native-animation and pdf.worker --- src/components/PDFThumbnail/index.tsx | 1 - src/hooks/useTabNavigatorFocus/index.ts | 1 - src/types/modules/pdf.worker.d.ts | 1 + src/types/modules/react-native.d.ts | 7 +++++++ 4 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 src/types/modules/pdf.worker.d.ts 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/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/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.d.ts b/src/types/modules/react-native.d.ts index e3db5db21e3b..a9ff35c97343 100644 --- a/src/types/modules/react-native.d.ts +++ b/src/types/modules/react-native.d.ts @@ -368,4 +368,11 @@ declare module 'react-native' { BootSplash: BootSplashModule; HybridAppModule: HybridAppModule; } + + namespace Animated { + interface AnimatedInterpolation extends AnimatedWithChildren { + interpolate(config: InterpolationConfigType): AnimatedInterpolation; + __getValue: () => OutputT; + } + } } From 6d01dd47bd4baa94b19ecdc8293be201222b32c5 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Wed, 1 May 2024 13:03:30 +0200 Subject: [PATCH 09/20] Fix ts-issue with this --- src/libs/Console/index.ts | 1 - tsconfig.json | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/Console/index.ts b/src/libs/Console/index.ts index f03d33674bde..8546c079098e 100644 --- a/src/libs/Console/index.ts +++ b/src/libs/Console/index.ts @@ -100,7 +100,6 @@ function sanitizeConsoleInput(text: string) { function createLog(text: string) { const time = new Date(); try { - // @ts-expect-error Any code inside `sanitizedInput` that gets evaluated by `eval()` will be executed in the context of the current this value. // eslint-disable-next-line no-eval, no-invalid-this const result = eval.call(this, text); diff --git a/tsconfig.json b/tsconfig.json index 7f7b7479f44b..591e847c3da8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -30,6 +30,7 @@ "strict": true, "moduleResolution": "node", "resolveJsonModule": true, + "noImplicitThis": false, "allowSyntheticDefaultImports": true, "skipLibCheck": true, "incremental": true, From 579668d01c72d3d40b5913d38f23d6fd3c8a7f76 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Wed, 1 May 2024 13:33:39 +0200 Subject: [PATCH 10/20] Fix spaces --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 591e847c3da8..67acd3cb18fe 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -30,7 +30,7 @@ "strict": true, "moduleResolution": "node", "resolveJsonModule": true, - "noImplicitThis": false, + "noImplicitThis": false, "allowSyntheticDefaultImports": true, "skipLibCheck": true, "incremental": true, From e2eb991325186542295bd27cd1de53c764c9bb75 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Mon, 6 May 2024 21:00:56 +0200 Subject: [PATCH 11/20] Remove some @ts-expect-errors --- .github/libs/sanitizeStringForJSONParse.ts | 2 +- src/stories/Form.stories.tsx | 27 +- tests/actions/PolicyTagTest.ts | 1147 +++++++++--------- tests/unit/sanitizeStringForJSONParseTest.ts | 1 - 4 files changed, 555 insertions(+), 622 deletions(-) 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/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/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/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(); }); }); From 0a8ecc7ca207e2df93442e98426dfdf88b07da5d Mon Sep 17 00:00:00 2001 From: Yauheni Date: Mon, 6 May 2024 22:52:40 +0200 Subject: [PATCH 12/20] Revert react-navigation changes --- src/libs/Console/index.ts | 1 + .../CustomRouter.ts | 3 ++ .../report/ReportActionItemMessageEdit.tsx | 1 + src/types/modules/react-navigation.d.ts | 43 ------------------- tsconfig.json | 1 - 5 files changed, 5 insertions(+), 44 deletions(-) diff --git a/src/libs/Console/index.ts b/src/libs/Console/index.ts index 8546c079098e..f03d33674bde 100644 --- a/src/libs/Console/index.ts +++ b/src/libs/Console/index.ts @@ -100,6 +100,7 @@ function sanitizeConsoleInput(text: string) { function createLog(text: string) { const time = new Date(); try { + // @ts-expect-error Any code inside `sanitizedInput` that gets evaluated by `eval()` will be executed in the context of the current this value. // eslint-disable-next-line no-eval, no-invalid-this const result = eval.call(this, text); diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts index 1e475b6b1ff9..504803026994 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/CustomRouter.ts @@ -17,12 +17,15 @@ function insertRootRoute(state: State, routeToInsert: Naviga // It's safe to modify this state before returning in getRehydratedState. + // @ts-expect-error Updating read only property // noinspection JSConstantReassignment state.routes = [...nonModalRoutes, routeToInsert, ...modalRoutes]; // eslint-disable-line + // @ts-expect-error Updating read only property // noinspection JSConstantReassignment state.index = state.routes.length - 1; // eslint-disable-line + // @ts-expect-error Updating read only property // noinspection JSConstantReassignment state.stale = true; // eslint-disable-line } diff --git a/src/pages/home/report/ReportActionItemMessageEdit.tsx b/src/pages/home/report/ReportActionItemMessageEdit.tsx index 8b629877e84d..d94807771566 100644 --- a/src/pages/home/report/ReportActionItemMessageEdit.tsx +++ b/src/pages/home/report/ReportActionItemMessageEdit.tsx @@ -449,6 +449,7 @@ function ReportActionItemMessageEdit( onBlur={(event: NativeSyntheticEvent) => { setIsFocused(false); 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/types/modules/react-navigation.d.ts b/src/types/modules/react-navigation.d.ts index 4e0efc975c89..f6a47f3cdb9a 100644 --- a/src/types/modules/react-navigation.d.ts +++ b/src/types/modules/react-navigation.d.ts @@ -1,4 +1,3 @@ -import type {ParamListBase, PartialRoute, Route} from '@react-navigation/native'; import type {RootStackParamList} from '@libs/Navigation/types'; declare global { @@ -7,45 +6,3 @@ declare global { interface RootParamList extends RootStackParamList {} } } - -declare module '@react-navigation/native' { - type PartialState = Partial> & { - stale?: true; - routes: Array>>; - }; - type NavigationRoute = Route, ParamList[RouteName]> & { - state?: NavigationState | PartialState; - }; - type NavigationState = { - /** - * Unique key for the navigation state. - */ - key: string; - /** - * Index of the currently focused route. - */ - index: number; - /** - * List of valid route names as defined in the screen components. - */ - routeNames: Array>; - /** - * Alternative entries for history. - */ - history?: unknown[]; - /** - * List of rendered routes. - */ - routes: Array>; - /** - * Custom type for the state, whether it's for tab, stack, drawer etc. - * During rehydration, the state will be discarded if type doesn't match with router type. - * It can also be used to detect the type of the navigator we're dealing with. - */ - type: string; - /** - * Whether the navigation state has been rehydrated. - */ - stale: false; - }; -} diff --git a/tsconfig.json b/tsconfig.json index 67acd3cb18fe..7f7b7479f44b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -30,7 +30,6 @@ "strict": true, "moduleResolution": "node", "resolveJsonModule": true, - "noImplicitThis": false, "allowSyntheticDefaultImports": true, "skipLibCheck": true, "incremental": true, From 90249acfe832e9de8d0f6ccd728ea7012dfda248 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Mon, 6 May 2024 23:04:30 +0200 Subject: [PATCH 13/20] Fix types for onSubmitComment inside ReportFooter --- .../home/report/ReportActionCompose/ReportActionCompose.tsx | 2 +- src/pages/home/report/ReportFooter.tsx | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index b356cbeb3a42..7226f04812b1 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -75,7 +75,7 @@ type ReportActionComposeProps = ReportActionComposeOnyxProps & WithCurrentUserPersonalDetailsProps & 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; diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index 01a985efdadb..4f890bafb6e4 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -128,11 +128,7 @@ function ReportFooter({ ); const onSubmitComment = useCallback( - (text: string | undefined) => { - if (text === undefined) { - return; - } - + (text: string) => { const isTaskCreated = handleCreateTask(text); if (isTaskCreated) { return; From a96ebf522b2a4f6b0e7bb989cf1c9f6528566787 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Mon, 6 May 2024 23:19:37 +0200 Subject: [PATCH 14/20] Fix types for TabSelector --- src/components/TabSelector/TabSelector.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/TabSelector/TabSelector.tsx b/src/components/TabSelector/TabSelector.tsx index 9fe1665f6b19..caddc201d1a6 100644 --- a/src/components/TabSelector/TabSelector.tsx +++ b/src/components/TabSelector/TabSelector.tsx @@ -38,7 +38,7 @@ function getIconAndTitle(route: string, translate: LocaleContextProps['translate } } -function getOpacity(position: Animated.AnimatedInterpolation, routesLength: number, tabIndex: number, active: boolean, affectedTabs: number[]) { +function getOpacity(position: Animated.AnimatedInterpolation, routesLength: number, tabIndex: number, active: boolean, affectedTabs: number[]) { const activeValue = active ? 1 : 0; const inactiveValue = active ? 0 : 1; @@ -118,9 +118,9 @@ function TabSelector({state, navigation, onTabPress = () => {}, position}: TabSe icon={icon} title={title} onPress={onPress} - activeOpacity={activeOpacity} - inactiveOpacity={inactiveOpacity} - backgroundColor={backgroundColor} + activeOpacity={activeOpacity as number} + inactiveOpacity={inactiveOpacity as number} + backgroundColor={backgroundColor as string} isActive={isActive} /> ); From 70e93db6d18e21de8d7780f25ab9b0876b737f05 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Wed, 8 May 2024 11:30:56 +0200 Subject: [PATCH 15/20] Fix comments --- src/components/TabSelector/TabSelector.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/TabSelector/TabSelector.tsx b/src/components/TabSelector/TabSelector.tsx index caddc201d1a6..882d99f38e3d 100644 --- a/src/components/TabSelector/TabSelector.tsx +++ b/src/components/TabSelector/TabSelector.tsx @@ -38,7 +38,7 @@ function getIconAndTitle(route: string, translate: LocaleContextProps['translate } } -function getOpacity(position: Animated.AnimatedInterpolation, routesLength: number, tabIndex: number, active: boolean, affectedTabs: number[]) { +function getOpacity(position: Animated.AnimatedInterpolation, routesLength: number, tabIndex: number, active: boolean, affectedTabs: number[]) { const activeValue = active ? 1 : 0; const inactiveValue = active ? 0 : 1; @@ -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; }, @@ -118,9 +118,9 @@ function TabSelector({state, navigation, onTabPress = () => {}, position}: TabSe icon={icon} title={title} onPress={onPress} - activeOpacity={activeOpacity as number} - inactiveOpacity={inactiveOpacity as number} - backgroundColor={backgroundColor as string} + activeOpacity={activeOpacity} + inactiveOpacity={inactiveOpacity} + backgroundColor={backgroundColor} isActive={isActive} /> ); From 2455f960b381905e88a817388fcc9359752296e0 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Wed, 8 May 2024 12:00:13 +0200 Subject: [PATCH 16/20] Fix PolicyTaxTests --- tests/actions/PolicyTaxTest.ts | 790 +++++++++++++++------------------ 1 file changed, 366 insertions(+), 424 deletions(-) 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( From e4e35312b3623c282240f529ffe78664a7fe01f6 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Wed, 8 May 2024 12:47:05 +0200 Subject: [PATCH 17/20] Fix types for perf-tests --- tests/perf-test/ChatFinderPage.perf-test.tsx | 78 +++++++++++--------- tests/perf-test/ReportScreen.perf-test.tsx | 8 +- 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/tests/perf-test/ChatFinderPage.perf-test.tsx b/tests/perf-test/ChatFinderPage.perf-test.tsx index fa1433c872b5..02103c4a5a65 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'; @@ -123,9 +123,9 @@ afterEach(() => { }); type ChatFinderPageProps = StackScreenProps & { - betas: OnyxEntry; - reports: OnyxCollection; - isSearchingForReports: OnyxEntry; + betas?: OnyxEntry; + reports?: OnyxCollection; + isSearchingForReports?: OnyxEntry; }; function ChatFinderPageWrapper(args: ChatFinderPageProps) { @@ -163,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 Navigation prop is only used within this test - .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 () => { @@ -192,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 Navigation prop is only used within this test - .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 8252266bae18..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'; @@ -162,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(); @@ -184,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(() => { @@ -209,9 +209,7 @@ test('[ReportScreen] should render ReportScreen', () => { .then(() => measurePerformance( , {scenario}, From f62529887969e9b2b89638d96e4039eceded386a Mon Sep 17 00:00:00 2001 From: Yauheni Date: Wed, 8 May 2024 13:10:32 +0200 Subject: [PATCH 18/20] Fix types for awaitStagingDeploys --- tests/unit/awaitStagingDeploysTest.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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(() => { From 530549ec4d9be81e83f79b03a13323c3930d73b1 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Fri, 10 May 2024 08:54:58 +0200 Subject: [PATCH 19/20] Update types for camera --- .../step/IOURequestStepScan/NavigationAwareCamera/types.ts | 2 +- src/pages/iou/request/step/IOURequestStepScan/index.native.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) 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 ba7492ad8416..c022a079df65 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -480,7 +480,6 @@ function IOURequestStepScan({ Date: Wed, 15 May 2024 11:40:43 +0200 Subject: [PATCH 20/20] Update IOUTest and remove @ts-expect-error --- tests/actions/IOUTest.ts | 1860 +++++++++++++++++++------------------- 1 file changed, 906 insertions(+), 954 deletions(-) diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 53753e79cbcc..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,8 +61,10 @@ describe('actions/IOU', () => { }); }); + let mockFetch: MockFetch; beforeEach(() => { global.fetch = TestHelper.getGlobalFetchMock(); + mockFetch = fetch as MockFetch; return Onyx.clear().then(waitForBatchedUpdates); }); @@ -76,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', () => { @@ -268,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', () => { @@ -468,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', () => { @@ -620,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() @@ -732,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( () => @@ -923,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) ); }); }); @@ -1062,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(); + }, + }); + }), + ); }); }); @@ -1425,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(); + }, + }); + }), + ); }); }); @@ -1617,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', () => { @@ -1627,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(() => { @@ -1771,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?.(); }); }); @@ -1838,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( @@ -1932,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(() => { @@ -2098,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); } @@ -2249,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 @@ -2289,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 @@ -2325,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 @@ -2349,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) => { @@ -2402,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); } @@ -2429,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({ @@ -2494,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) { @@ -2517,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) => { @@ -2686,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 @@ -2710,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}`, @@ -2834,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); @@ -2858,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] @@ -2908,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); @@ -2924,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(); @@ -3001,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); @@ -3027,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({ @@ -3354,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); }