Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Reassure] Add measureFunction test for formatSectionsFromSearchTerm #38551

Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
9b6d7bf
add temp diff
brandonhenry Mar 19, 2024
2a0259f
Initial OptionsListUtils additions
brandonhenry Mar 21, 2024
521433c
finished writing tets
brandonhenry Mar 23, 2024
0e05d45
Update OptionsListUtils.ts
brandonhenry Mar 23, 2024
7484497
Finishing touches for formatSectionsFromSearchTerm reassure
brandonhenry Mar 23, 2024
7a5ee30
Update tests/perf-test/OptionsListUtils.perf-test.ts
brandonhenry Mar 28, 2024
8365041
minor adjustments based on code review
brandonhenry Mar 28, 2024
5793e41
added more robust tests
brandonhenry Mar 30, 2024
f66ad13
Merge remote-tracking branch 'upstream/main' into 38166-reassure-add-…
brandonhenry Mar 30, 2024
1677188
small touchups
brandonhenry Apr 1, 2024
f07b5c0
only test worst case
brandonhenry Apr 2, 2024
70963c3
updated to search_value
brandonhenry Apr 2, 2024
d39a71c
Using variables over hardcode
brandonhenry Apr 2, 2024
28c784a
added test for empty search term. also added new getmockpersonaldetai…
brandonhenry Apr 3, 2024
f5b4657
Setting `shouldGetOptionDetails` to true for true worst case
brandonhenry Apr 3, 2024
746c2da
Also set no search term getoptions to true
brandonhenry Apr 3, 2024
102778a
Merge remote-tracking branch 'upstream/main' into 38166-reassure-add-…
brandonhenry Apr 4, 2024
54c747a
ran prettier
brandonhenry Apr 4, 2024
4d6e185
Update tests/utils/collections/optionData.ts
brandonhenry Apr 5, 2024
ec58fa5
Merge remote-tracking branch 'upstream/main' into 38166-reassure-add-…
brandonhenry Apr 5, 2024
a830536
hasDraft was removed from optionData
brandonhenry Apr 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions tests/perf-test/OptionsListUtils.perf-test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import {rand} from '@ngneat/falso';
import type * as NativeNavigation from '@react-navigation/native';
import Onyx from 'react-native-onyx';
import {measureFunction} from 'reassure';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import type {OptionData} from '@libs/ReportUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {PersonalDetails} from '@src/types/onyx';
import type Report from '@src/types/onyx/Report';
import {formatSectionsFromSearchTerm} from '../../src/libs/OptionsListUtils';
import createCollection from '../utils/collections/createCollection';
import createRandomOptionData from '../utils/collections/optionData';
import createPersonalDetails from '../utils/collections/personalDetails';
import {getRandomDate} from '../utils/collections/reportActions';
import createRandomReport from '../utils/collections/reports';
Expand All @@ -16,6 +20,10 @@ const REPORTS_COUNT = 5000;
const PERSONAL_DETAILS_LIST_COUNT = 1000;
const SEARCH_VALUE = 'TestingValue';

const PERSONAL_DETAILS_COUNT = 1000;
const SELECTED_OPTIONS_COUNT = 1000;
const RECENT_REPORTS_COUNT = 100;

const reports = createCollection<Report>(
(item) => `${ONYXKEYS.COLLECTION.REPORT}${item.reportID}`,
(index) => ({
Expand All @@ -32,6 +40,27 @@ const personalDetails = createCollection<PersonalDetails>(
PERSONAL_DETAILS_LIST_COUNT,
);

const getMockedReports = (length = 500) =>
createCollection<Report>(
(item) => `${ONYXKEYS.COLLECTION.REPORT}${item.reportID}`,
(index) => ({
...createRandomReport(index),
type: rand(Object.values(CONST.REPORT.TYPE)),
lastVisibleActionCreated: getRandomDate(),
}),
length,
);

const getMockedPersonalDetails = (length = 500) =>
createCollection<PersonalDetails>(
(item) => item.accountID,
(index) => createPersonalDetails(index),
length,
);

const mockedReportsMap = getMockedReports(REPORTS_COUNT) as Record<`${typeof ONYXKEYS.COLLECTION.REPORT}`, Report>;
const mockedPersonalDetailsMap = getMockedPersonalDetails(PERSONAL_DETAILS_LIST_COUNT);

const mockedBetas = Object.values(CONST.BETAS);

jest.mock('@react-navigation/native', () => {
Expand All @@ -48,6 +77,21 @@ const options = OptionsListUtils.createOptionList(personalDetails, reports);

/* GetOption is the private function and is never called directly, we are testing the functions which call getOption with different params */
describe('OptionsListUtils', () => {
beforeAll(() => {
Onyx.init({
keys: ONYXKEYS,
});

Onyx.multiSet({
...mockedReportsMap,
...mockedPersonalDetailsMap,
});
});

afterAll(() => {
Onyx.clear();
});

/* Testing getSearchOptions */
test('[OptionsListUtils] getSearchOptions with search value', async () => {
await waitForBatchedUpdates();
Expand Down Expand Up @@ -77,4 +121,62 @@ describe('OptionsListUtils', () => {
await waitForBatchedUpdates();
await measureFunction(() => OptionsListUtils.getMemberInviteOptions(options.personalDetails, mockedBetas, SEARCH_VALUE));
});

test('[OptionsListUtils] worst case scenario with a search term that matches a subset of selectedOptions, filteredRecentReports, and filteredPersonalDetails', async () => {
const SELECTED_OPTION_TEXT = 'Selected Option';
const RECENT_REPORT_TEXT = 'Recent Report';
const PERSONAL_DETAIL_TEXT = 'Personal Detail';

const SELECTED_OPTIONS_MATCH_FREQUENCY = 2;
const RECENT_REPORTS_MATCH_FREQUENCY = 3;
const PERSONAL_DETAILS_MATCH_FREQUENCY = 5;

const selectedOptions = createCollection<OptionData>(
(item) => item.reportID,
(index) => ({
...createRandomOptionData(index),
searchText: index % SELECTED_OPTIONS_MATCH_FREQUENCY === 0 ? SEARCH_VALUE : `${SELECTED_OPTION_TEXT} ${index}`,
}),
SELECTED_OPTIONS_COUNT,
);
const filteredRecentReports = createCollection<OptionData>(
(item) => item.reportID,
(index) => ({
...createRandomOptionData(index + SELECTED_OPTIONS_COUNT),
searchText: index % RECENT_REPORTS_MATCH_FREQUENCY === 0 ? SEARCH_VALUE : `${RECENT_REPORT_TEXT} ${index}`,
}),
RECENT_REPORTS_COUNT,
);
const filteredPersonalDetails = createCollection<OptionData>(
(item) => item.reportID,
(index) => ({
...createRandomOptionData(index + SELECTED_OPTIONS_COUNT + RECENT_REPORTS_COUNT),
searchText: index % PERSONAL_DETAILS_MATCH_FREQUENCY === 0 ? SEARCH_VALUE : `${PERSONAL_DETAIL_TEXT} ${index}`,
}),
PERSONAL_DETAILS_COUNT,
);

const mockedPersonalDetails = getMockedPersonalDetails(PERSONAL_DETAILS_COUNT);

await measureFunction(() =>
formatSectionsFromSearchTerm(
SEARCH_VALUE,
Object.values(selectedOptions),
Object.values(filteredRecentReports),
Object.values(filteredPersonalDetails),
false,
mockedPersonalDetails,
true,
),
);
});

test('[OptionsListUtils] empty search term with selected options and mocked personal details', async () => {
const selectedOptions = createCollection<OptionData>((item) => item.reportID, createRandomOptionData, SELECTED_OPTIONS_COUNT);

const mockedPersonalDetails = getMockedPersonalDetails(PERSONAL_DETAILS_COUNT);

await waitForBatchedUpdates();
await measureFunction(() => formatSectionsFromSearchTerm('', Object.values(selectedOptions), [], [], true, mockedPersonalDetails, true));
});
});
59 changes: 59 additions & 0 deletions tests/utils/collections/optionData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// tests/utils/collections/optionData.ts
import {rand, randBoolean, randEmail, randNumber, randPhoneNumber, randWord} from '@ngneat/falso';
import type {OptionData} from '@libs/ReportUtils';
import CONST from '@src/CONST';

export default function createRandomOptionData(index: number): OptionData {
return {
login: randEmail(),
searchText: randWord(),
reportID: `report_${index}`,
text: randWord(),
alternateText: randWord(),
tooltipText: randWord(),
keyForList: `option_${index}`,
descriptiveText: randWord(),
isUnread: randBoolean(),
isPinned: randBoolean(),
isSelected: randBoolean(),
phoneNumber: randPhoneNumber(),
policyName: randWord(),
policyID: `policy_${index}`,
accountID: randNumber(),
isArchivedRoom: randBoolean(),
isPolicyExpenseChat: randBoolean(),
chatType: rand(Object.values(CONST.REPORT.CHAT_TYPE)),
hasOutstandingChildRequest: randBoolean(),
isOwnPolicyExpenseChat: randBoolean(),
lastMessageText: randWord(),
lastMessageTimestamp: Date.now(),
lastVisibleActionCreated: new Date().toISOString(),
lastReadCreated: new Date().toISOString(),
lastReadTime: new Date().toISOString(),
lastReadSequenceNumber: randNumber(),
lastMentionedTime: randBoolean() ? new Date().toISOString() : null,
notificationPreference: rand(Object.values(CONST.REPORT.NOTIFICATION_PREFERENCE)),
oldPolicyName: randWord(),
hasParentAccess: randBoolean(),
description: randWord(),
isDeletedParentAction: randBoolean(),
reportName: randWord(),
reportActionID: `reportAction_${index}`,
chatReportID: `chatReport_${index}`,
stateNum: rand(Object.values(CONST.REPORT.STATE_NUM)),
statusNum: rand(Object.values(CONST.REPORT.STATUS_NUM)),
type: rand(Object.values(CONST.REPORT.TYPE)),
visibility: rand(Object.values(CONST.REPORT.VISIBILITY)),
isLastMessageDeletedParentAction: randBoolean(),
isCancelledIOU: randBoolean(),
iouReportID: `iou_${index}`,
iouReportAmount: randNumber({min: 0, max: 1000}),
currency: randWord(),
isWaitingOnBankAccount: randBoolean(),
hasDraft: randBoolean(),
lastVisibleActionLastModified: new Date().toISOString(),
lastActorAccountID: randNumber(),
ownerAccountID: randNumber(),
ownerEmail: randEmail(),
};
}
Loading