From 997c47a048c44f87755bedd832859be18a7d741e Mon Sep 17 00:00:00 2001 From: "Marc Glasser (via MelvinBot)" Date: Thu, 12 Mar 2026 22:55:34 +0000 Subject: [PATCH 1/6] Fix react-native-permissions mock: define RESULTS inline and return Promises The mock imported RESULTS from react-native-permissions/dist/commonjs/permissions, but that module only exports PERMISSIONS. RESULTS lives in a separate module (dist/commonjs/results), so it was always undefined at runtime. Additionally, the mock check() and request() functions returned plain strings instead of Promises, which doesn't match the real API contract and caused getLocationPermission().then() to fail. This fixes the flaky IOURequestStepConfirmationPageTest failure that has been affecting multiple unrelated PRs on main. Co-authored-by: Marc Glasser --- __mocks__/react-native-permissions.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/__mocks__/react-native-permissions.ts b/__mocks__/react-native-permissions.ts index 9ee11ea473f55..4bf9f434f9efb 100644 --- a/__mocks__/react-native-permissions.ts +++ b/__mocks__/react-native-permissions.ts @@ -1,6 +1,14 @@ -import {PERMISSIONS, RESULTS} from 'react-native-permissions/dist/commonjs/permissions'; +import {PERMISSIONS} from 'react-native-permissions/dist/commonjs/permissions'; import type {ValueOf} from 'type-fest'; +const RESULTS = { + UNAVAILABLE: 'unavailable', + BLOCKED: 'blocked', + DENIED: 'denied', + GRANTED: 'granted', + LIMITED: 'limited', +} as const; + type Results = ValueOf; type ResultsCollection = Record; type NotificationSettings = Record; @@ -8,8 +16,8 @@ type Notification = {status: Results; settings: NotificationSettings}; const openLimitedPhotoLibraryPicker: jest.Mock = jest.fn(() => {}); const openSettings: jest.Mock = jest.fn(() => {}); -const check = jest.fn(() => RESULTS.GRANTED as string); -const request = jest.fn(() => RESULTS.GRANTED as string); +const check = jest.fn(() => Promise.resolve(RESULTS.GRANTED as string)); +const request = jest.fn(() => Promise.resolve(RESULTS.GRANTED as string)); const checkLocationAccuracy: jest.Mock = jest.fn(() => 'full'); const requestLocationAccuracy: jest.Mock = jest.fn(() => 'full'); From 1f8e746b469be7e728acc1633dbb5b8d2ebf49ca Mon Sep 17 00:00:00 2001 From: "Marc Glasser (via MelvinBot)" Date: Thu, 12 Mar 2026 23:29:44 +0000 Subject: [PATCH 2/6] Fix Navigation mock and test timing for unreported distance expense test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add setNavigationActionToMicrotaskQueue to the Navigation mock (consistent with all other test files) and await batched updates after the button press so the async createTransaction → requestMoney call chain completes before the assertion runs. Co-authored-by: Marc Glasser --- tests/ui/components/IOURequestStepConfirmationPageTest.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ui/components/IOURequestStepConfirmationPageTest.tsx b/tests/ui/components/IOURequestStepConfirmationPageTest.tsx index 8103ed3f50f37..e6c3c14731431 100644 --- a/tests/ui/components/IOURequestStepConfirmationPageTest.tsx +++ b/tests/ui/components/IOURequestStepConfirmationPageTest.tsx @@ -98,6 +98,7 @@ jest.mock('@libs/Navigation/Navigation', () => { navigate: jest.fn(), goBack: jest.fn(), dismissModalWithReport: jest.fn(), + setNavigationActionToMicrotaskQueue: jest.fn((callback: () => void) => callback()), navigationRef: mockRef, }; }); @@ -1263,6 +1264,7 @@ describe('IOURequestStepConfirmationPageTest', () => { await waitForBatchedUpdatesWithAct(); fireEvent.press(await screen.findByText(/^Create .*expense/i)); + await waitForBatchedUpdatesWithAct(); // Unreported distance requests should skip createDistanceRequest and use requestMoney expect(IOU.createDistanceRequest).not.toHaveBeenCalled(); From efd10c8875ac5bc592aa1613054a1344bc8fadb9 Mon Sep 17 00:00:00 2001 From: "Monil Bhavsar (via MelvinBot)" Date: Fri, 13 Mar 2026 11:30:03 +0000 Subject: [PATCH 3/6] Import RESULTS from react-native-permissions/dist/commonjs/results instead of defining inline Co-authored-by: Monil Bhavsar --- __mocks__/react-native-permissions.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/__mocks__/react-native-permissions.ts b/__mocks__/react-native-permissions.ts index 4bf9f434f9efb..d84dcf2298773 100644 --- a/__mocks__/react-native-permissions.ts +++ b/__mocks__/react-native-permissions.ts @@ -1,14 +1,7 @@ import {PERMISSIONS} from 'react-native-permissions/dist/commonjs/permissions'; +import {RESULTS} from 'react-native-permissions/dist/commonjs/results'; import type {ValueOf} from 'type-fest'; -const RESULTS = { - UNAVAILABLE: 'unavailable', - BLOCKED: 'blocked', - DENIED: 'denied', - GRANTED: 'granted', - LIMITED: 'limited', -} as const; - type Results = ValueOf; type ResultsCollection = Record; type NotificationSettings = Record; From 56fb0a0ebe853403d7ee287725a24ee01d04db4e Mon Sep 17 00:00:00 2001 From: "Monil Bhavsar (via MelvinBot)" Date: Fri, 13 Mar 2026 11:38:13 +0000 Subject: [PATCH 4/6] Fix: define RESULTS inline to resolve typecheck failure The import from 'react-native-permissions/dist/commonjs/results' has no type declaration file, causing TS7016. Define the RESULTS object inline with 'as const' instead, which matches the runtime values and provides proper type safety. Co-authored-by: Monil Bhavsar --- __mocks__/react-native-permissions.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/__mocks__/react-native-permissions.ts b/__mocks__/react-native-permissions.ts index d84dcf2298773..4bf9f434f9efb 100644 --- a/__mocks__/react-native-permissions.ts +++ b/__mocks__/react-native-permissions.ts @@ -1,7 +1,14 @@ import {PERMISSIONS} from 'react-native-permissions/dist/commonjs/permissions'; -import {RESULTS} from 'react-native-permissions/dist/commonjs/results'; import type {ValueOf} from 'type-fest'; +const RESULTS = { + UNAVAILABLE: 'unavailable', + BLOCKED: 'blocked', + DENIED: 'denied', + GRANTED: 'granted', + LIMITED: 'limited', +} as const; + type Results = ValueOf; type ResultsCollection = Record; type NotificationSettings = Record; From 4f689c6732fc5277245c72585134064aaf1b7b06 Mon Sep 17 00:00:00 2001 From: Monil Bhavsar Date: Fri, 13 Mar 2026 18:54:07 +0530 Subject: [PATCH 5/6] Wait for render before asserting --- tests/ui/SessionTest.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/SessionTest.tsx b/tests/ui/SessionTest.tsx index 6f3b64b28b4a5..229c9263a6086 100644 --- a/tests/ui/SessionTest.tsx +++ b/tests/ui/SessionTest.tsx @@ -117,7 +117,7 @@ describe('Deep linking', () => { Linking.setInitialURL(url); const {unmount} = render(); - await waitForBatchedUpdates(); + await waitForBatchedUpdatesWithAct(); expect(lastVisitedPath).toBe(`/${ROUTES.REPORT}/${report.reportID}`); From 3e18337f83cde63bc865356a425f9a853f9745bd Mon Sep 17 00:00:00 2001 From: "Monil Bhavsar (via MelvinBot)" Date: Fri, 13 Mar 2026 13:27:50 +0000 Subject: [PATCH 6/6] Fix: remove unused waitForBatchedUpdates import in SessionTest Co-authored-by: Monil Bhavsar --- tests/ui/SessionTest.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ui/SessionTest.tsx b/tests/ui/SessionTest.tsx index 229c9263a6086..f74ec76992b6c 100644 --- a/tests/ui/SessionTest.tsx +++ b/tests/ui/SessionTest.tsx @@ -15,7 +15,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import {createRandomReport} from '../utils/collections/reports'; import * as TestHelper from '../utils/TestHelper'; -import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; import waitForBatchedUpdatesWithAct from '../utils/waitForBatchedUpdatesWithAct'; import waitForNetworkPromises from '../utils/waitForNetworkPromises';