diff --git a/src/pages/home/report/ReportActionsList.js b/src/pages/home/report/ReportActionsList.js index af5b2e0a09c3..2bd969364e31 100644 --- a/src/pages/home/report/ReportActionsList.js +++ b/src/pages/home/report/ReportActionsList.js @@ -433,7 +433,6 @@ function ReportActionsList({ onLayout={onLayoutInner} onScroll={trackVerticalScrolling} extraData={extraData} - testID="report-actions-list" /> diff --git a/tests/perf-test/ReportActionsList.perf-test.js b/tests/perf-test/ReportActionsList.perf-test.js index f4dcd969923f..991ca82da1b6 100644 --- a/tests/perf-test/ReportActionsList.perf-test.js +++ b/tests/perf-test/ReportActionsList.perf-test.js @@ -13,6 +13,7 @@ import {ActionListContext, ReactionListContext} from '../../src/pages/home/Repor import variables from '../../src/styles/variables'; import * as LHNTestUtils from '../utils/LHNTestUtils'; import PusherHelper from '../utils/PusherHelper'; +import * as ReportTestUtils from '../utils/ReportTestUtils'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatchedUpdates'; @@ -58,7 +59,7 @@ afterAll(() => { const mockOnLayout = jest.fn(); const mockOnScroll = jest.fn(); -const mockLoadMoreChats = jest.fn(); +const mockLoadChats = jest.fn(); const mockRef = {current: null}; // Initialize the network key for OfflineWithFeedback @@ -74,49 +75,6 @@ afterEach(() => { PusherHelper.teardown(); }); -const getFakeReportAction = (index) => ({ - actionName: 'ADDCOMMENT', - actorAccountID: index, - automatic: false, - avatar: '', - created: '2023-09-12 16:27:35.124', - isAttachment: true, - isFirstItem: false, - lastModified: '2021-07-14T15:00:00Z', - message: [ - { - html: 'hey', - isDelatedParentAction: false, - isEdited: false, - reactions: [], - text: 'test', - type: 'TEXT', - whisperedTo: [], - }, - ], - originalMessage: { - html: 'hey', - lastModified: '2021-07-14T15:00:00Z', - }, - pendingAction: null, - person: [ - { - type: 'TEXT', - style: 'strong', - text: 'email@test.com', - }, - ], - previousReportActionID: '1', - reportActionID: index.toString(), - reportActionTimestamp: 1696243169753, - sequenceNumber: 2, - shouldShow: true, - timestamp: 1696243169, - whisperedToAccountIDs: [], -}); - -const getMockedSortedReportActions = (length = 100) => Array.from({length}, (__, i) => getFakeReportAction(i)); - const currentUserAccountID = 5; function ReportActionsListWrapper() { @@ -125,11 +83,13 @@ function ReportActionsListWrapper() { diff --git a/tests/perf-test/ReportScreen.perf-test.js b/tests/perf-test/ReportScreen.perf-test.js index 6d2d2dc28b00..9172caba913b 100644 --- a/tests/perf-test/ReportScreen.perf-test.js +++ b/tests/perf-test/ReportScreen.perf-test.js @@ -1,73 +1,50 @@ import Onyx from 'react-native-onyx'; import {measurePerformance} from 'reassure'; import React from 'react'; -import {screen} from '@testing-library/react-native'; +import {fireEvent, screen} from '@testing-library/react-native'; import ReportScreen from '../../src/pages/home/ReportScreen'; +import ComposeProviders from '../../src/components/ComposeProviders'; +import OnyxProvider from '../../src/components/OnyxProvider'; +import {KeyboardStateProvider} from '../../src/components/withKeyboardState'; +import {WindowDimensionsProvider} from '../../src/components/withWindowDimensions'; +import {LocaleContextProvider} from '../../src/components/LocaleContextProvider'; +import {CurrentReportIDContextProvider} from '../../src/components/withCurrentReportID'; +import DragAndDropProvider from '../../src/components/DragAndDrop/Provider'; +import {ReportAttachmentsProvider} from '../../src/pages/home/report/ReportAttachmentsContext'; +import * as LHNTestUtils from '../utils/LHNTestUtils'; +import CONST from '../../src/CONST'; +import ONYXKEYS from '../../src/ONYXKEYS'; +import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; +import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatchedUpdates'; +import PusherHelper from '../utils/PusherHelper'; +import * as TestHelper from '../utils/TestHelper'; +import * as ReportTestUtils from '../utils/ReportTestUtils'; +import * as Localize from '../../src/libs/Localize'; + +jest.setTimeout(60000); + +jest.mock('react-native-reanimated', () => ({ + ...jest.requireActual('react-native-reanimated/mock'), + useSharedValue: jest.fn, + useAnimatedStyle: jest.fn, + useAnimatedRef: jest.fn, +})); -const ONYXKEYS = { - PERSONAL_DETAILS: 'personalDetails', - NVP_PRIORITY_MODE: 'nvp_priorityMode', - SESSION: 'session', - BETAS: 'betas', - COLLECTION: { - REPORT: 'report_', - REPORT_ACTIONS: 'reportActions_', - }, - NETWORK: 'network', -}; - -jest.mock('../../src/hooks/useLocalize', () => - jest.fn(() => ({ - translate: (text) => text, - })), -); -jest.mock('../../src/hooks/useNetwork', () => - jest.fn(() => ({ - isOffline: false, - })), -); - -jest.mock('../../src/hooks/useKeyboardState', () => - jest.fn(() => ({ - isKeyboardShown: false, - })), -); +jest.mock('../../src/components/withNavigationFocus', () => (Component) => { + function WithNavigationFocus(props) { + return ( + + ); + } -jest.mock('../../src/hooks/useWindowDimensions', () => - jest.fn(() => ({ - windowHeight: 1000, - isSmallScreenWidth: false, - isMediumScreenWidth: false, - isLargeScreenWidth: false, - })), -); + WithNavigationFocus.displayName = 'WithNavigationFocus'; -jest.mock('../../src/components/withLocalize', () => (Component) => (props) => ( - text} - /> -)); - -jest.mock('../../src/components/withWindowDimensions', () => (Component) => (props) => ( - -)); - -jest.mock('../../src/components/withKeyboardState', () => (Component) => (props) => ( - -)); + return WithNavigationFocus; +}); jest.mock('../../src/hooks/useEnvironment', () => jest.fn(() => ({ @@ -80,10 +57,10 @@ jest.mock('../../src/hooks/useEnvironment', () => jest.mock('../../src/libs/Permissions', () => ({ canUseTasks: jest.fn(() => true), + canUseLinkPreviews: jest.fn(() => true), })); jest.mock('../../src/libs/Navigation/Navigation'); -jest.mock('../../src/components/Icon/Expensicons'); const mockedNavigate = jest.fn(); jest.mock('@react-navigation/native', () => { @@ -94,9 +71,10 @@ jest.mock('@react-navigation/native', () => { useIsFocused: () => ({ navigate: mockedNavigate, }), + useRoute: () => jest.fn(), useNavigation: () => ({ navigate: jest.fn(), - addListener: jest.fn(), + addListener: () => jest.fn(), }), createNavigationContainerRef: jest.fn(), }; @@ -109,23 +87,138 @@ beforeAll(() => Onyx.init({ keys: ONYXKEYS, safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], - registerStorageEventListener: () => { - }, + registerStorageEventListener: () => {}, }), ); // Initialize the network key for OfflineWithFeedback -beforeEach(() => Onyx.merge(ONYXKEYS.NETWORK, {isOffline: false})); +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 slate +// Clear out Onyx after each test so that each test starts with a clean state afterEach(() => { Onyx.clear(); + PusherHelper.teardown(); }); -test('should render report screen', () => { +function ReportScreenWrapper(args) { + return ( + + + + ); +} + +test('should render ReportScreen with composer interactions', () => { const scenario = async () => { + // Query for the report list await screen.findByTestId('report-actions-list'); + + // Query for the composer + const composer = await screen.findByTestId('composer'); + expect(composer).toBeDefined(); + + // Type in the composer + fireEvent.changeText(composer, 'Test message'); + + const hintSendButtonText = Localize.translateLocal('common.send'); + + // Query for the send button + const sendButton = await screen.findByLabelText(hintSendButtonText); + expect(sendButton).toBeDefined(); + + // Click on the send button + fireEvent.press(sendButton); + + const hintHeaderText = Localize.translateLocal('common.back'); + + // Query for the header + await screen.findByLabelText(hintHeaderText); + }; + + const policy = { + policyID: 1, + name: 'Testing Policy', + }; + + const report = LHNTestUtils.getFakeReport(); + const reportActions = ReportTestUtils.getMockedReportsMap(1000); + const mockRoute = {params: {reportID: '1'}}; + + return waitForBatchedUpdates() + .then(() => + Onyx.multiSet({ + [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.BETAS]: [CONST.BETAS.DEFAULT_ROOMS, CONST.BETAS.POLICY_ROOMS], + [`${ONYXKEYS.COLLECTION.POLICY}${policy.policyID}`]: policy, + [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${mockRoute.params.reportID}`]: { + isLoadingReportActions: false, + }, + }), + ) + .then(() => measurePerformance(, {scenario})); +}); + +test('should press of the report item', () => { + const scenario = async () => { + // 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); + + expect(reportPreviewButtons.length).toBeDefined(); + + // click on the report preview button + fireEvent.press(reportPreviewButtons[0]); + }; + + const policy = { + policyID: 123, + name: 'Testing Policy', }; - measurePerformance(, {scenario}); + + const report = LHNTestUtils.getFakeReport(); + const reportActions = ReportTestUtils.getMockedReportsMap(1000); + const mockRoute = {params: {reportID: '2'}}; + + return waitForBatchedUpdates() + .then(() => + Onyx.multiSet({ + [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.BETAS]: [CONST.BETAS.DEFAULT_ROOMS, CONST.BETAS.POLICY_ROOMS], + [`${ONYXKEYS.COLLECTION.POLICY}${policy.policyID}`]: policy, + [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${mockRoute.params.reportID}`]: { + isLoadingReportActions: false, + }, + }), + ) + .then(() => measurePerformance(, {scenario})); }); diff --git a/tests/utils/ReportTestUtils.js b/tests/utils/ReportTestUtils.js new file mode 100644 index 000000000000..48e5ebfaa56d --- /dev/null +++ b/tests/utils/ReportTestUtils.js @@ -0,0 +1,61 @@ +import _ from 'underscore'; + +const actionNames = ['ADDCOMMENT', 'IOU', 'REPORTPREVIEW']; + +const getFakeReportAction = (index, actionName) => ({ + actionName, + actorAccountID: index, + automatic: false, + avatar: '', + created: '2023-09-12 16:27:35.124', + isAttachment: true, + isFirstItem: false, + lastModified: '2021-07-14T15:00:00Z', + message: [ + { + html: 'hey', + isDelatedParentAction: false, + isEdited: false, + reactions: [], + text: 'test', + type: 'TEXT', + whisperedTo: [], + }, + ], + originalMessage: { + html: 'hey', + lastModified: '2021-07-14T15:00:00Z', + // IOUReportID: index, + linkedReportID: index.toString(), + }, + pendingAction: null, + person: [ + { + type: 'TEXT', + style: 'strong', + text: 'email@test.com', + }, + ], + previousReportActionID: '1', + reportActionID: index.toString(), + reportActionTimestamp: 1696243169753, + sequenceNumber: 0, + shouldShow: true, + timestamp: 1696243169, + whisperedToAccountIDs: [], +}); + +const getMockedSortedReportActions = (length = 100) => Array.from({length}, (__, i) => getFakeReportAction(i)); + +const getMockedReportsMap = (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); + + return {[reportID]: reportAction}; + }); + return _.assign({}, ...mockReports); +}; + +export {getFakeReportAction, getMockedSortedReportActions, getMockedReportsMap};