From 4eece91f8e302822a0ad3aa1162ce1a5b10847f0 Mon Sep 17 00:00:00 2001 From: Github Date: Fri, 2 Feb 2024 16:24:38 +0100 Subject: [PATCH] ReportSceen perf test refactor --- tests/perf-test/ReportScreen.perf-test.js | 109 +++++++--------------- tests/utils/ReportTestUtils.js | 9 +- tests/utils/TestHelper.js | 2 + tests/utils/collections/reportActions.ts | 18 +++- 4 files changed, 59 insertions(+), 79 deletions(-) diff --git a/tests/perf-test/ReportScreen.perf-test.js b/tests/perf-test/ReportScreen.perf-test.js index 5a144e715f5b..e86d0bf4fa09 100644 --- a/tests/perf-test/ReportScreen.perf-test.js +++ b/tests/perf-test/ReportScreen.perf-test.js @@ -1,8 +1,7 @@ -import {act, fireEvent, screen} from '@testing-library/react-native'; +import {fireEvent, screen, waitFor} from '@testing-library/react-native'; import React from 'react'; import Onyx from 'react-native-onyx'; import {measurePerformance} from 'reassure'; -import _ from 'underscore'; import ComposeProviders from '../../src/components/ComposeProviders'; import DragAndDropProvider from '../../src/components/DragAndDrop/Provider'; import {LocaleContextProvider} from '../../src/components/LocaleContextProvider'; @@ -15,7 +14,10 @@ import * as Localize from '../../src/libs/Localize'; import ONYXKEYS from '../../src/ONYXKEYS'; import {ReportAttachmentsProvider} from '../../src/pages/home/report/ReportAttachmentsContext'; import ReportScreen from '../../src/pages/home/ReportScreen'; -import * as LHNTestUtils from '../utils/LHNTestUtils'; +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'; @@ -56,6 +58,7 @@ jest.mock('../../src/hooks/useEnvironment', () => jest.mock('../../src/libs/Permissions', () => ({ canUseLinkPreviews: jest.fn(() => true), + canUseDefaultRooms: jest.fn(() => true), })); jest.mock('../../src/hooks/usePermissions.ts'); @@ -103,32 +106,17 @@ afterEach(() => { PusherHelper.teardown(); }); -/** - * This is a helper function to create a mock for the addListener function of the react-navigation library. - * The reason we need this is because we need to trigger the transitionEnd event in our tests to simulate - * the transitionEnd event that is triggered when the screen transition animation is completed. - * - * P.S: This can't be moved to a utils file because Jest wants any external function to stay in the scope. - * - * @returns {Object} An object with two functions: triggerTransitionEnd and addListener - */ -const createAddListenerMock = () => { - const transitionEndListeners = []; - const triggerTransitionEnd = () => { - transitionEndListeners.forEach((transitionEndListener) => transitionEndListener()); - }; - - const addListener = jest.fn().mockImplementation((listener, callback) => { - if (listener === 'transitionEnd') { - transitionEndListeners.push(callback); - } - return () => { - _.filter(transitionEndListeners, (cb) => cb !== callback); - }; - }); +const policies = createCollection( + (item) => `${ONYXKEYS.COLLECTION.POLICY}${item.id}`, + (index) => createRandomPolicy(index), + 10, +); - return {triggerTransitionEnd, addListener}; -}; +const personalDetails = createCollection( + (item) => item.accountID, + (index) => createPersonalDetails(index), + 20, +); function ReportScreenWrapper(args) { return ( @@ -152,8 +140,12 @@ function ReportScreenWrapper(args) { ); } -test.skip('[ReportScreen] should render ReportScreen with composer interactions', () => { - const {triggerTransitionEnd, addListener} = createAddListenerMock(); +const report = {...createRandomReport(1), policyID: '1'}; +const reportActions = ReportTestUtils.getMockedReportActionsMap(500); +const mockRoute = {params: {reportID: '1'}}; + +test('[ReportScreen] should render ReportScreen with composer interactions', () => { + const {triggerTransitionEnd, addListener} = TestHelper.createAddListenerMock(); const scenario = async () => { /** * First make sure ReportScreen is mounted, so that we can trigger @@ -163,11 +155,7 @@ test.skip('[ReportScreen] should render ReportScreen with composer interactions' * before the ReportScreen is mounted, and the test will fail. */ await screen.findByTestId('ReportScreen'); - - await act(triggerTransitionEnd); - - // Query for the report list - await screen.findByTestId('report-actions-list'); + await waitFor(triggerTransitionEnd); // Query for the composer const composer = await screen.findByTestId('composer'); @@ -189,15 +177,6 @@ test.skip('[ReportScreen] should render ReportScreen with composer interactions' await screen.findByLabelText(hintHeaderText); }; - const policy = { - policyID: 1, - name: 'Testing Policy', - }; - - const report = LHNTestUtils.getFakeReport(); - const reportActions = ReportTestUtils.getMockedReportActionsMap(1000); - const mockRoute = {params: {reportID: '1'}}; - const navigation = {addListener}; return waitForBatchedUpdates() @@ -206,12 +185,10 @@ test.skip('[ReportScreen] should render ReportScreen with composer interactions' [ONYXKEYS.IS_SIDEBAR_LOADED]: true, [`${ONYXKEYS.COLLECTION.REPORT}${mockRoute.params.reportID}`]: report, [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${mockRoute.params.reportID}`]: reportActions, - [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails, + [ONYXKEYS.PERSONAL_DETAILS_LIST]: personalDetails, [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS], - [`${ONYXKEYS.COLLECTION.POLICY}${policy.policyID}`]: policy, - [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${mockRoute.params.reportID}`]: { - isLoadingReportActions: false, - }, + [`${ONYXKEYS.COLLECTION.POLICY}`]: policies, + [ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT]: true, }), ) .then(() => @@ -225,8 +202,8 @@ test.skip('[ReportScreen] should render ReportScreen with composer interactions' ); }); -test.skip('[ReportScreen] should press of the report item', () => { - const {triggerTransitionEnd, addListener} = createAddListenerMock(); +test('[ReportScreen] should press of the report item', () => { + const {triggerTransitionEnd, addListener} = TestHelper.createAddListenerMock(); const scenario = async () => { /** * First make sure ReportScreen is mounted, so that we can trigger @@ -237,32 +214,19 @@ test.skip('[ReportScreen] should press of the report item', () => { */ await screen.findByTestId('ReportScreen'); - await act(triggerTransitionEnd); + await waitFor(triggerTransitionEnd); // Query for the report list await screen.findByTestId('report-actions-list'); - // Query for the composer - await screen.findByTestId('composer'); - - const hintReportPreviewText = Localize.translateLocal('iou.viewDetails'); - - // Query for report preview buttons - const reportPreviewButtons = await screen.findAllByLabelText(hintReportPreviewText); + const hintText = Localize.translateLocal('accessibilityHints.chatMessage'); - // click on the report preview button - fireEvent.press(reportPreviewButtons[0]); - }; + // Query for the list of items + const reportItems = await screen.findAllByLabelText(hintText); - const policy = { - policyID: 123, - name: 'Testing Policy', + fireEvent.press(reportItems[0], 'onLongPress'); }; - const report = LHNTestUtils.getFakeReport(); - const reportActions = ReportTestUtils.getMockedReportActionsMap(1000); - const mockRoute = {params: {reportID: '2'}}; - const navigation = {addListener}; return waitForBatchedUpdates() @@ -271,12 +235,9 @@ test.skip('[ReportScreen] should press of the report item', () => { [ONYXKEYS.IS_SIDEBAR_LOADED]: true, [`${ONYXKEYS.COLLECTION.REPORT}${mockRoute.params.reportID}`]: report, [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${mockRoute.params.reportID}`]: reportActions, - [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails, + [ONYXKEYS.PERSONAL_DETAILS_LIST]: personalDetails, [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS], - [`${ONYXKEYS.COLLECTION.POLICY}${policy.policyID}`]: policy, - [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${mockRoute.params.reportID}`]: { - isLoadingReportActions: false, - }, + [`${ONYXKEYS.COLLECTION.POLICY}`]: policies, }), ) .then(() => diff --git a/tests/utils/ReportTestUtils.js b/tests/utils/ReportTestUtils.js index 910f2200876b..86899e4045f6 100644 --- a/tests/utils/ReportTestUtils.js +++ b/tests/utils/ReportTestUtils.js @@ -1,4 +1,5 @@ import _ from 'underscore'; +import createRandomReportAction from './collections/reportActions'; const actionNames = ['ADDCOMMENT', 'IOU', 'REPORTPREVIEW', 'CLOSED']; @@ -51,7 +52,13 @@ const getMockedReportActionsMap = (length = 100) => { const mockReports = Array.from({length}, (__, i) => { const reportID = i + 1; const actionName = i === 0 ? 'CREATED' : actionNames[i % actionNames.length]; - const reportAction = getFakeReportAction(reportID, actionName); + const reportAction = { + ...createRandomReportAction(reportID), + actionName, + originalMessage: { + linkedReportID: reportID.toString(), + }, + }; return {[reportID]: reportAction}; }); diff --git a/tests/utils/TestHelper.js b/tests/utils/TestHelper.js index dd95ab4efb67..9059041afd19 100644 --- a/tests/utils/TestHelper.js +++ b/tests/utils/TestHelper.js @@ -218,6 +218,8 @@ function assertFormDataMatchesObject(formData, obj) { /** * This is a helper function to create a mock for the addListener function of the react-navigation library. + * The reason we need this is because we need to trigger the transitionEnd event in our tests to simulate + * the transitionEnd event that is triggered when the screen transition animation is completed. * * @returns {Object} An object with two functions: triggerTransitionEnd and addListener */ diff --git a/tests/utils/collections/reportActions.ts b/tests/utils/collections/reportActions.ts index cc258e89c041..bb14a2c7a41b 100644 --- a/tests/utils/collections/reportActions.ts +++ b/tests/utils/collections/reportActions.ts @@ -1,4 +1,5 @@ -import {rand, randAggregation, randBoolean, randPastDate, randWord} from '@ngneat/falso'; +import {rand, randAggregation, randBoolean, randWord} from '@ngneat/falso'; +import {format} from 'date-fns'; import CONST from '@src/CONST'; import type {ReportAction} from '@src/types/onyx'; @@ -17,6 +18,15 @@ const flattenActionNamesValues = (actionNames: any) => { return result; }; +const getRandomDate = (): string => { + const randomTimestamp = Math.random() * new Date().getTime(); + const randomDate = new Date(randomTimestamp); + + const formattedDate = format(randomDate, CONST.DATE.FNS_DB_FORMAT_STRING); + + return formattedDate; +}; + export default function createRandomReportAction(index: number): ReportAction { return { // we need to add any here because of the way we are generating random values @@ -32,7 +42,7 @@ export default function createRandomReportAction(index: number): ReportAction { text: randWord(), }, ], - created: randPastDate().toISOString(), + created: getRandomDate(), message: [ { type: randWord(), @@ -57,13 +67,13 @@ export default function createRandomReportAction(index: number): ReportAction { ], originalMessage: { html: randWord(), - type: rand(Object.values(CONST.IOU.REPORT_ACTION_TYPE)), + lastModified: getRandomDate(), }, whisperedToAccountIDs: randAggregation(), avatar: randWord(), automatic: randBoolean(), shouldShow: randBoolean(), - lastModified: randPastDate().toISOString(), + lastModified: getRandomDate(), pendingAction: rand(Object.values(CONST.RED_BRICK_ROAD_PENDING_ACTION)), delegateAccountID: index, errors: {},