diff --git a/tests/perf-test/ReportActionCompose.perf-test.tsx b/tests/perf-test/ReportActionCompose.perf-test.tsx index 28987e6b58ed..9c6cfdae5a5c 100644 --- a/tests/perf-test/ReportActionCompose.perf-test.tsx +++ b/tests/perf-test/ReportActionCompose.perf-test.tsx @@ -101,26 +101,44 @@ function ReportActionComposeWrapper() { } const mockEvent = {preventDefault: jest.fn()}; -test.skip('[ReportActionCompose] should render Composer with text input interactions', async () => { +test('[ReportActionCompose] should render Composer with text input interactions', async () => { const scenario = async () => { // Query for the composer const composer = await screen.findByTestId('composer'); fireEvent.changeText(composer, '@test'); + }; - // Query for the suggestions - await screen.findByTestId('suggestions'); + await waitForBatchedUpdates(); + await measurePerformance(, {scenario}); +}); + +test('[ReportActionCompose] should scroll to hide suggestions', async () => { + const scenario = async () => { + // Query for the composer + const composer = await screen.findByTestId('composer'); // scroll to hide suggestions fireEvent.scroll(composer); + }; + + await waitForBatchedUpdates(); + await measurePerformance(, {scenario}); +}); + +test('[ReportActionCompose] should press to block suggestions', async () => { + const scenario = async () => { + // Query for the composer + const composer = await screen.findByTestId('composer'); // press to block suggestions fireEvent.press(composer); }; - return waitForBatchedUpdates().then(() => measurePerformance(, {scenario})); + await waitForBatchedUpdates(); + await measurePerformance(, {scenario}); }); -test.skip('[ReportActionCompose] should press add attachemnt button', async () => { +test('[ReportActionCompose] should press add attachemnt button', async () => { const scenario = async () => { // Query for the attachment button const hintAttachmentButtonText = Localize.translateLocal('common.create'); @@ -129,10 +147,11 @@ test.skip('[ReportActionCompose] should press add attachemnt button', async () = fireEvent.press(attachmentButton, mockEvent); }; - return waitForBatchedUpdates().then(() => measurePerformance(, {scenario})); + await waitForBatchedUpdates(); + await measurePerformance(, {scenario}); }); -test.skip('[ReportActionCompose] should press add emoji button', async () => { +test('[ReportActionCompose] should press add emoji button', async () => { const scenario = async () => { // Query for the emoji button const hintEmojiButtonText = Localize.translateLocal('reportActionCompose.emoji'); @@ -141,10 +160,11 @@ test.skip('[ReportActionCompose] should press add emoji button', async () => { fireEvent.press(emojiButton); }; - return waitForBatchedUpdates().then(() => measurePerformance(, {scenario})); + await waitForBatchedUpdates(); + await measurePerformance(, {scenario}); }); -test.skip('[ReportActionCompose] should press send message button', async () => { +test('[ReportActionCompose] should press send message button', async () => { const scenario = async () => { // Query for the send button const hintSendButtonText = Localize.translateLocal('common.send'); @@ -153,25 +173,40 @@ test.skip('[ReportActionCompose] should press send message button', async () => fireEvent.press(sendButton); }; - return waitForBatchedUpdates().then(() => measurePerformance(, {scenario})); + await waitForBatchedUpdates(); + await measurePerformance(, {scenario}); }); -test.skip('[ReportActionCompose] render composer with attachement modal interactions', async () => { +test('[ReportActionCompose] press add attachment button', async () => { const scenario = async () => { const hintAddAttachmentButtonText = Localize.translateLocal('reportActionCompose.addAttachment'); - const hintAssignTaskButtonText = Localize.translateLocal('newTaskPage.assignTask'); - const hintSplitBillButtonText = Localize.translateLocal('iou.splitExpense'); - // Query for the attachment modal items const addAttachmentButton = await screen.findByLabelText(hintAddAttachmentButtonText); fireEvent.press(addAttachmentButton, mockEvent); + }; + await waitForBatchedUpdates(); + await measurePerformance(, {scenario}); +}); + +test('[ReportActionCompose] should press split bill button', async () => { + const scenario = async () => { + const hintSplitBillButtonText = Localize.translateLocal('iou.splitExpense'); const splitBillButton = await screen.findByLabelText(hintSplitBillButtonText); fireEvent.press(splitBillButton, mockEvent); + }; + + await waitForBatchedUpdates(); + await measurePerformance(, {scenario}); +}); +test('[ReportActionCompose] should press assign task button', async () => { + const scenario = async () => { + const hintAssignTaskButtonText = Localize.translateLocal('newTaskPage.assignTask'); const assignTaskButton = await screen.findByLabelText(hintAssignTaskButtonText); fireEvent.press(assignTaskButton, mockEvent); }; - return waitForBatchedUpdates().then(() => measurePerformance(, {scenario})); + await waitForBatchedUpdates(); + await measurePerformance(, {scenario}); }); diff --git a/tests/perf-test/ReportActionsList.perf-test.tsx b/tests/perf-test/ReportActionsList.perf-test.tsx index 0fd2501910c8..96ef3759be23 100644 --- a/tests/perf-test/ReportActionsList.perf-test.tsx +++ b/tests/perf-test/ReportActionsList.perf-test.tsx @@ -16,7 +16,6 @@ import {ActionListContext, ReactionListContext} from '@src/pages/home/ReportScre import variables from '@src/styles/variables'; import createRandomReportAction from '../utils/collections/reportActions'; import * as LHNTestUtilsModule from '../utils/LHNTestUtils'; -import PusherHelper from '../utils/PusherHelper'; import * as ReportTestUtils from '../utils/ReportTestUtils'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatchedUpdates'; @@ -66,26 +65,16 @@ beforeAll(() => }), ); -afterAll(() => { - jest.clearAllMocks(); -}); - const mockOnLayout = jest.fn(); const mockOnScroll = jest.fn(); const mockLoadChats = jest.fn(); const mockRef = {current: null, flatListRef: null, scrollPosition: null, setScrollPosition: () => {}}; -// Initialize the network key for OfflineWithFeedback beforeEach(() => { - PusherHelper.setup(); + // Initialize the network key for OfflineWithFeedback + Onyx.merge(ONYXKEYS.NETWORK, {isOffline: false}); wrapOnyxWithWaitForBatchedUpdates(Onyx); - return Onyx.merge(ONYXKEYS.NETWORK, {isOffline: false}); -}); - -// Clear out Onyx after each test so that each test starts with a clean slate -afterEach(() => { - Onyx.clear(); - PusherHelper.teardown(); + Onyx.clear().then(waitForBatchedUpdates); }); function ReportActionsListWrapper() { @@ -113,24 +102,35 @@ function ReportActionsListWrapper() { ); } -test.skip('[ReportActionsList] should render ReportActionsList with 500 reportActions stored', () => { +test('[ReportActionsList] should render ReportActionsList with 500 reportActions stored', async () => { const scenario = async () => { await screen.findByTestId('report-actions-list'); + }; + await waitForBatchedUpdates(); + + Onyx.multiSet({ + [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtilsModule.fakePersonalDetails, + }); + + await measurePerformance(, {scenario}); +}); + +test('[ReportActionsList] should render list items', async () => { + const scenario = async () => { const hintText = Localize.translateLocal('accessibilityHints.chatMessage'); - // Ensure that the list of items is rendered await screen.findAllByLabelText(hintText); }; - return waitForBatchedUpdates() - .then(() => - Onyx.multiSet({ - [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtilsModule.fakePersonalDetails, - }), - ) - .then(() => measurePerformance(, {scenario})); + await waitForBatchedUpdates(); + + Onyx.multiSet({ + [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtilsModule.fakePersonalDetails, + }); + + await measurePerformance(, {scenario}); }); -test.skip('[ReportActionsList] should scroll and click some of the reports', () => { +test('[ReportActionsList] should scroll through list of items', async () => { const eventData = { nativeEvent: { contentOffset: { @@ -152,18 +152,12 @@ test.skip('[ReportActionsList] should scroll and click some of the reports', () const scenario = async () => { const reportActionsList = await screen.findByTestId('report-actions-list'); fireEvent.scroll(reportActionsList, eventData); - - const hintText = Localize.translateLocal('accessibilityHints.chatMessage'); - const reportItems = await screen.findAllByLabelText(hintText); - - fireEvent.press(reportItems[0], 'onLongPress'); }; + await waitForBatchedUpdates(); + + Onyx.multiSet({ + [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtilsModule.fakePersonalDetails, + }); - return waitForBatchedUpdates() - .then(() => - Onyx.multiSet({ - [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtilsModule.fakePersonalDetails, - }), - ) - .then(() => measurePerformance(, {scenario})); + await measurePerformance(, {scenario}); }); diff --git a/tests/perf-test/ReportScreen.perf-test.tsx b/tests/perf-test/ReportScreen.perf-test.tsx index d452e9412655..129fcdcd38d7 100644 --- a/tests/perf-test/ReportScreen.perf-test.tsx +++ b/tests/perf-test/ReportScreen.perf-test.tsx @@ -1,7 +1,8 @@ import type {StackNavigationProp, StackScreenProps} from '@react-navigation/stack'; -import {screen, waitFor} from '@testing-library/react-native'; +import {screen} from '@testing-library/react-native'; import type {ComponentType} from 'react'; import React from 'react'; +import {Dimensions, InteractionManager} from 'react-native'; import Onyx from 'react-native-onyx'; import type Animated from 'react-native-reanimated'; import {measurePerformance} from 'reassure'; @@ -27,7 +28,6 @@ import createCollection from '../utils/collections/createCollection'; import createPersonalDetails from '../utils/collections/personalDetails'; import createRandomPolicy from '../utils/collections/policies'; import createRandomReport from '../utils/collections/reports'; -import PusherHelper from '../utils/PusherHelper'; import * as ReportTestUtils from '../utils/ReportTestUtils'; import * as TestHelper from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; @@ -41,6 +41,26 @@ jest.mock('@src/libs/API', () => ({ read: jest.fn(), })); +jest.mock('react-native/Libraries/Interaction/InteractionManager', () => ({ + runAfterInteractions: () => ({ + cancel: jest.fn(), + }), + createInteractionHandle: jest.fn(), + clearInteractionHandle: jest.fn(), +})); + +jest.mock('react-native', () => { + const actualReactNative = jest.requireActual('react-native'); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return { + ...actualReactNative, + Dimensions: { + ...actualReactNative.Dimensions, + addEventListener: jest.fn(), + }, + }; +}); + jest.mock('react-native-reanimated', () => { const actualNav = jest.requireActual('react-native-reanimated/mock'); return { @@ -115,17 +135,41 @@ beforeAll(() => }), ); -// Initialize the network key for OfflineWithFeedback +type MockListener = { + remove: jest.Mock; + callback?: () => void; +}; + +const mockListener: MockListener = {remove: jest.fn()}; +let mockCancel: jest.Mock; +let mockRunAfterInteractions: jest.Mock; + beforeEach(() => { global.fetch = TestHelper.getGlobalFetchMock(); wrapOnyxWithWaitForBatchedUpdates(Onyx); - Onyx.merge(ONYXKEYS.NETWORK, {isOffline: false}); -}); -// Clear out Onyx after each test so that each test starts with a clean state -afterEach(() => { - Onyx.clear(); - PusherHelper.teardown(); + // Reset mocks before each test + (Dimensions.addEventListener as jest.Mock).mockClear(); + mockListener.remove.mockClear(); + + // Mock the implementation of addEventListener to return the mockListener + (Dimensions.addEventListener as jest.Mock).mockImplementation((event, callback) => { + if (event === 'change') { + mockListener.callback = callback; + return mockListener; + } + return {remove: jest.fn()}; + }); + + // Mock the implementation of InteractionManager.runAfterInteractions + mockCancel = jest.fn(); + mockRunAfterInteractions = jest.fn().mockReturnValue({cancel: mockCancel}); + + jest.spyOn(InteractionManager, 'runAfterInteractions').mockImplementation(mockRunAfterInteractions); + + // Initialize the network key for OfflineWithFeedback + Onyx.merge(ONYXKEYS.NETWORK, {isOffline: false}); + Onyx.clear().then(waitForBatchedUpdates); }); const policies = createCollection( @@ -164,58 +208,110 @@ function ReportScreenWrapper(props: ReportScreenWrapperProps) { } const report = {...createRandomReport(1), policyID: '1'}; -const reportActions = ReportTestUtils.getMockedReportActionsMap(1000); +const reportActions = ReportTestUtils.getMockedReportActionsMap(10); const mockRoute = {params: {reportID: '1', reportActionID: ''}, key: 'Report', name: 'Report' as const}; -test.skip('[ReportScreen] should render ReportScreen', () => { - const {triggerTransitionEnd, addListener} = TestHelper.createAddListenerMock(); +test('[ReportScreen] should render ReportScreen', async () => { + const {addListener} = TestHelper.createAddListenerMock(); const scenario = async () => { - /** - * First make sure ReportScreen is mounted, so that we can trigger - * the transitionEnd event manually. - * - * If we don't do that, then the transitionEnd event will be triggered - * before the ReportScreen is mounted, and the test will fail. - */ await screen.findByTestId('ReportScreen'); - await waitFor(triggerTransitionEnd); + }; + + const navigation = {addListener} as unknown as StackNavigationProp; + + await waitForBatchedUpdates(); + const reportCollectionDataSet: ReportCollectionDataSet = { + [`${ONYXKEYS.COLLECTION.REPORT}${mockRoute.params.reportID}`]: report, + }; + const reportActionsCollectionDataSet: ReportActionsCollectionDataSet = { + [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${mockRoute.params.reportID}`]: reportActions, + }; - // Query for the composer + Onyx.multiSet({ + [ONYXKEYS.IS_SIDEBAR_LOADED]: true, + [ONYXKEYS.PERSONAL_DETAILS_LIST]: personalDetails, + [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS], + [`${ONYXKEYS.COLLECTION.POLICY}`]: policies, + [ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT]: true, + ...reportCollectionDataSet, + ...reportActionsCollectionDataSet, + }); + await measurePerformance( + , + {scenario}, + ); +}); + +test('[ReportScreen] should render composer', async () => { + const {addListener} = TestHelper.createAddListenerMock(); + const scenario = async () => { await screen.findByTestId('composer'); + }; + + const navigation = {addListener} as unknown as StackNavigationProp; + + await waitForBatchedUpdates(); + + const reportCollectionDataSet: ReportCollectionDataSet = { + [`${ONYXKEYS.COLLECTION.REPORT}${mockRoute.params.reportID}`]: report, + }; + + const reportActionsCollectionDataSet: ReportActionsCollectionDataSet = { + [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${mockRoute.params.reportID}`]: reportActions, + }; + Onyx.multiSet({ + [ONYXKEYS.IS_SIDEBAR_LOADED]: true, + [ONYXKEYS.PERSONAL_DETAILS_LIST]: personalDetails, + [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS], + [`${ONYXKEYS.COLLECTION.POLICY}`]: policies, + [ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT]: true, + ...reportCollectionDataSet, + ...reportActionsCollectionDataSet, + }); + await measurePerformance( + , + {scenario}, + ); +}); - // Query for the report list +test('[ReportScreen] should render report list', async () => { + const {addListener} = TestHelper.createAddListenerMock(); + const scenario = async () => { await screen.findByTestId('report-actions-list'); }; const navigation = {addListener} as unknown as StackNavigationProp; - return waitForBatchedUpdates() - .then(() => { - const reportCollectionDataSet: ReportCollectionDataSet = { - [`${ONYXKEYS.COLLECTION.REPORT}${mockRoute.params.reportID}`]: report, - }; - - const reportActionsCollectionDataSet: ReportActionsCollectionDataSet = { - [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${mockRoute.params.reportID}`]: reportActions, - }; - - return Onyx.multiSet({ - [ONYXKEYS.IS_SIDEBAR_LOADED]: true, - [ONYXKEYS.PERSONAL_DETAILS_LIST]: personalDetails, - [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS], - [`${ONYXKEYS.COLLECTION.POLICY}`]: policies, - [ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT]: true, - ...reportCollectionDataSet, - ...reportActionsCollectionDataSet, - }); - }) - .then(() => - measurePerformance( - , - {scenario}, - ), - ); + await waitForBatchedUpdates(); + + const reportCollectionDataSet: ReportCollectionDataSet = { + [`${ONYXKEYS.COLLECTION.REPORT}${mockRoute.params.reportID}`]: report, + }; + + const reportActionsCollectionDataSet: ReportActionsCollectionDataSet = { + [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${mockRoute.params.reportID}`]: reportActions, + }; + + Onyx.multiSet({ + [ONYXKEYS.IS_SIDEBAR_LOADED]: true, + [ONYXKEYS.PERSONAL_DETAILS_LIST]: personalDetails, + [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS], + [`${ONYXKEYS.COLLECTION.POLICY}`]: policies, + [ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT]: true, + ...reportCollectionDataSet, + ...reportActionsCollectionDataSet, + }); + await measurePerformance( + , + {scenario}, + ); }); diff --git a/tests/perf-test/SidebarLinks.perf-test.tsx b/tests/perf-test/SidebarLinks.perf-test.tsx index 1945f0372a10..4caa22d062d4 100644 --- a/tests/perf-test/SidebarLinks.perf-test.tsx +++ b/tests/perf-test/SidebarLinks.perf-test.tsx @@ -5,6 +5,7 @@ import variables from '@styles/variables'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import * as LHNTestUtils from '../utils/LHNTestUtils'; +import * as TestHelper from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatchedUpdates'; @@ -38,14 +39,32 @@ const getMockedReportsMap = (length = 100) => { return mockReports; }; -const mockedResponseMap = getMockedReportsMap(500); +const mockedResponseMap = getMockedReportsMap(5); -describe.skip('SidebarLinks', () => { +describe('SidebarLinks', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], }); + }); + + beforeEach(() => { + global.fetch = TestHelper.getGlobalFetchMock(); + wrapOnyxWithWaitForBatchedUpdates(Onyx); + + // Initialize the network key for OfflineWithFeedback + Onyx.merge(ONYXKEYS.NETWORK, {isOffline: false}); + Onyx.clear().then(waitForBatchedUpdates); + }); + + test('[SidebarLinks] should render Sidebar with 500 reports stored', async () => { + const scenario = async () => { + // Query for the sidebar + await screen.findByTestId('lhn-options-list'); + }; + + await waitForBatchedUpdates(); Onyx.multiSet({ [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails, @@ -54,22 +73,12 @@ describe.skip('SidebarLinks', () => { [ONYXKEYS.IS_LOADING_REPORT_DATA]: false, ...mockedResponseMap, }); - }); - // Initialize the network key for OfflineWithFeedback - beforeEach(() => { - wrapOnyxWithWaitForBatchedUpdates(Onyx); - return Onyx.merge(ONYXKEYS.NETWORK, {isOffline: false}); + await measurePerformance(, {scenario, runs: 1}); }); - afterAll(() => { - Onyx.clear(); - }); - - test('[SidebarLinks] should render Sidebar with 500 reports stored', async () => { + test('[SidebarLinks] should render list itmes', async () => { const scenario = async () => { - // Query for the sidebar - await screen.findByTestId('lhn-options-list'); /** * Query for display names of participants [1, 2]. * This will ensure that the sidebar renders a list of items. @@ -78,10 +87,19 @@ describe.skip('SidebarLinks', () => { }; await waitForBatchedUpdates(); + + Onyx.multiSet({ + [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails, + [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS], + [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD, + [ONYXKEYS.IS_LOADING_REPORT_DATA]: false, + ...mockedResponseMap, + }); + await measurePerformance(, {scenario}); }); - test('[SidebarLinks] should scroll and click some of the items', async () => { + test('[SidebarLinks] should scroll through the list of items ', async () => { const scenario = async () => { const eventData = { nativeEvent: { @@ -104,15 +122,37 @@ describe.skip('SidebarLinks', () => { const lhnOptionsList = await screen.findByTestId('lhn-options-list'); fireEvent.scroll(lhnOptionsList, eventData); - // find elements that are currently visible in the viewport - const button1 = await screen.findByTestId('7'); - const button2 = await screen.findByTestId('8'); - fireEvent.press(button1); - fireEvent.press(button2); }; await waitForBatchedUpdates(); + Onyx.multiSet({ + [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails, + [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS], + [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD, + [ONYXKEYS.IS_LOADING_REPORT_DATA]: false, + ...mockedResponseMap, + }); + + await measurePerformance(, {scenario}); + }); + + test('[SidebarLinks] should click on list item', async () => { + const scenario = async () => { + const button = await screen.findByTestId('1'); + fireEvent.press(button); + }; + + await waitForBatchedUpdates(); + + Onyx.multiSet({ + [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails, + [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS], + [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD, + [ONYXKEYS.IS_LOADING_REPORT_DATA]: false, + ...mockedResponseMap, + }); + await measurePerformance(, {scenario}); }); });