Skip to content

Commit

Permalink
Merge pull request #30414 from OlimpiaZurek/feat/27641/reassure-lhn-r…
Browse files Browse the repository at this point in the history
…eport-screen

[NoQA] feat: add Reassure perf tests to ReportScreen
  • Loading branch information
mountiny authored Nov 1, 2023
2 parents a6b0b54 + accfab9 commit e04afc6
Show file tree
Hide file tree
Showing 5 changed files with 294 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,7 @@ function ComposerWithSuggestions({
setIsFullComposerAvailable={setIsFullComposerAvailable}
isComposerFullSize={isComposerFullSize}
value={value}
testID="composer"
numberOfLines={numberOfLines}
onNumberOfLinesChange={updateNumberOfLines}
shouldCalculateCaretPosition
Expand Down
2 changes: 1 addition & 1 deletion src/pages/home/report/ReportActionsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ function ReportActionsList({
<InvertedFlatList
accessibilityLabel={translate('sidebarScreen.listOfChatMessages')}
ref={reportScrollManager.ref}
testID="report-actions-list"
style={styles.overscrollBehaviorContain}
data={sortedReportActions}
renderItem={renderItem}
Expand All @@ -432,7 +433,6 @@ function ReportActionsList({
onLayout={onLayoutInner}
onScroll={trackVerticalScrolling}
extraData={extraData}
testID="report-actions-list"
/>
</Animated.View>
</>
Expand Down
52 changes: 6 additions & 46 deletions tests/perf-test/ReportActionsList.perf-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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
Expand All @@ -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 protected]',
},
],
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() {
Expand All @@ -125,11 +83,13 @@ function ReportActionsListWrapper() {
<ReactionListContext.Provider value={mockRef}>
<ActionListContext.Provider value={mockRef}>
<ReportActionsList
sortedReportActions={getMockedSortedReportActions(500)}
sortedReportActions={ReportTestUtils.getMockedSortedReportActions(500)}
report={LHNTestUtils.getFakeReport()}
onLayout={mockOnLayout}
onScroll={mockOnScroll}
loadMoreChats={mockLoadMoreChats}
loadMoreChats={mockLoadChats}
loadOlderChats={mockLoadChats}
loadNewerChats={mockLoadChats}
currentUserPersonalDetails={LHNTestUtils.fakePersonalDetails[currentUserAccountID]}
/>
</ActionListContext.Provider>
Expand Down
225 changes: 225 additions & 0 deletions tests/perf-test/ReportScreen.perf-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
import {fireEvent, screen} from '@testing-library/react-native';
import React from 'react';
import Onyx from 'react-native-onyx';
import {measurePerformance} from 'reassure';
import ComposeProviders from '../../src/components/ComposeProviders';
import DragAndDropProvider from '../../src/components/DragAndDrop/Provider';
import {LocaleContextProvider} from '../../src/components/LocaleContextProvider';
import OnyxProvider from '../../src/components/OnyxProvider';
import {CurrentReportIDContextProvider} from '../../src/components/withCurrentReportID';
import {KeyboardStateProvider} from '../../src/components/withKeyboardState';
import {WindowDimensionsProvider} from '../../src/components/withWindowDimensions';
import CONST from '../../src/CONST';
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 PusherHelper from '../utils/PusherHelper';
import * as ReportTestUtils from '../utils/ReportTestUtils';
import * as TestHelper from '../utils/TestHelper';
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatchedUpdates';

jest.setTimeout(60000);

jest.mock('react-native-reanimated', () => ({
...jest.requireActual('react-native-reanimated/mock'),
useSharedValue: jest.fn,
useAnimatedStyle: jest.fn,
useAnimatedRef: jest.fn,
}));

jest.mock('../../src/components/withNavigationFocus', () => (Component) => {
function WithNavigationFocus(props) {
return (
<Component
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
isFocused={false}
/>
);
}

WithNavigationFocus.displayName = 'WithNavigationFocus';

return WithNavigationFocus;
});

jest.mock('../../src/hooks/useEnvironment', () =>
jest.fn(() => ({
environment: 'development',
environmentURL: 'https://new.expensify.com',
isProduction: false,
isDevelopment: true,
})),
);

jest.mock('../../src/libs/Permissions', () => ({
canUseTasks: jest.fn(() => true),
canUseLinkPreviews: jest.fn(() => true),
}));

jest.mock('../../src/libs/Navigation/Navigation');

const mockedNavigate = jest.fn();
jest.mock('@react-navigation/native', () => {
const actualNav = jest.requireActual('@react-navigation/native');
return {
...actualNav,
useFocusEffect: jest.fn(),
useIsFocused: () => ({
navigate: mockedNavigate,
}),
useRoute: () => jest.fn(),
useNavigation: () => ({
navigate: jest.fn(),
addListener: () => jest.fn(),
}),
createNavigationContainerRef: jest.fn(),
};
});

// mock PortalStateContext
jest.mock('@gorhom/portal');

beforeAll(() =>
Onyx.init({
keys: ONYXKEYS,
safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
registerStorageEventListener: () => {},
}),
);

// Initialize the network key for OfflineWithFeedback
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();
});

function ReportScreenWrapper(args) {
return (
<ComposeProviders
components={[
OnyxProvider,
CurrentReportIDContextProvider,
KeyboardStateProvider,
WindowDimensionsProvider,
LocaleContextProvider,
DragAndDropProvider,
ReportAttachmentsProvider,
]}
>
<ReportScreen
// eslint-disable-next-line react/jsx-props-no-spreading
{...args}
/>
</ComposeProviders>
);
}

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
const header = await screen.findByLabelText(hintHeaderText);
expect(header).toBeDefined();
};

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(<ReportScreenWrapper route={mockRoute} />, {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',
};

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(<ReportScreenWrapper route={mockRoute} />, {scenario}));
});
61 changes: 61 additions & 0 deletions tests/utils/ReportTestUtils.js
Original file line number Diff line number Diff line change
@@ -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 protected]',
},
],
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};

0 comments on commit e04afc6

Please sign in to comment.