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

[No QA] Migrate 'OptionsListUtilsTest.js', 'DateUtilsTest.js', 'SidebarLinks.perf-test.js', 'markdown.js' and 'ReportUtilsTest.js' to Typescript #37206

Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
79d9495
refactor(typescript): migrate multiple tests and utils
pac-guerreiro Feb 26, 2024
1b2af89
Merge branch 'main' into pac-guerreiro/refactor/migrate-25309-25310-2…
pac-guerreiro Feb 26, 2024
0bd0ce5
Merge branch 'main' into pac-guerreiro/refactor/migrate-25309-25310-2…
pac-guerreiro Feb 28, 2024
c66339c
refactor(typescript): apply pull request suggestions
pac-guerreiro Feb 29, 2024
947c99f
Merge branch 'main' into pac-guerreiro/refactor/migrate-25309-25310-2…
pac-guerreiro Feb 29, 2024
2a76abb
refactor(typescript): resolve type error
pac-guerreiro Feb 29, 2024
76f4e2e
Merge branch 'main' into pac-guerreiro/refactor/migrate-25309-25310-2…
pac-guerreiro Mar 11, 2024
a5131ed
refactor(typescript): resolve type issues
pac-guerreiro Mar 12, 2024
d78e9d1
Merge branch 'main' into pac-guerreiro/refactor/migrate-25309-25310-2…
pac-guerreiro Mar 13, 2024
e5d3ef0
fix: wrong data type conversion
pac-guerreiro Mar 13, 2024
16854a9
Merge branch 'main' into pac-guerreiro/refactor/migrate-25309-25310-2…
pac-guerreiro Mar 14, 2024
c5b2ada
refactor(typescript): apply pull request suggestions
pac-guerreiro Mar 14, 2024
104f838
Merge branch 'main' into pac-guerreiro/refactor/migrate-25309-25310-2…
pac-guerreiro Mar 18, 2024
f051c2e
refactor(typescript): apply pull request suggestion
pac-guerreiro Mar 18, 2024
3e40a53
refactor(typescript): apply pull request feedback
pac-guerreiro Mar 20, 2024
5685095
Merge branch 'main' into pac-guerreiro/refactor/migrate-25309-25310-2…
pac-guerreiro Mar 22, 2024
ba09987
refactor(typescript): apply pull request suggestion
pac-guerreiro Mar 22, 2024
9ab0ea3
refactor(typescript): apply pull request feedback
pac-guerreiro Mar 22, 2024
dc6ede9
Merge branch 'main' into pac-guerreiro/refactor/migrate-25309-25310-2…
pac-guerreiro Mar 26, 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
2 changes: 1 addition & 1 deletion src/libs/DateUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ function formatToLongDateWithWeekday(datetime: string | Date): string {
*
* @returns Sunday
*/
function formatToDayOfWeek(datetime: Date): string {
function formatToDayOfWeek(datetime: string | Date): string {
pac-guerreiro marked this conversation as resolved.
Show resolved Hide resolved
return format(new Date(datetime), CONST.DATE.WEEKDAY_TIME_FORMAT);
pac-guerreiro marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down
2 changes: 1 addition & 1 deletion src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2042,4 +2042,4 @@ export {
getShareLogOptions,
};

export type {MemberForList, CategorySection, GetOptions};
export type {MemberForList, CategorySection, GetOptions, Tag};
2 changes: 1 addition & 1 deletion src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -930,7 +930,7 @@ function filterReportsByPolicyIDAndMemberAccountIDs(reports: Report[], policyMem
/**
* Given an array of reports, return them sorted by the last read timestamp.
*/
function sortReportsByLastRead(reports: Report[], reportMetadata: OnyxCollection<ReportMetadata>): Array<OnyxEntry<Report>> {
function sortReportsByLastRead(reports: Array<OnyxEntry<Report>>, reportMetadata: OnyxCollection<ReportMetadata>): Array<OnyxEntry<Report>> {
return reports
.filter((report) => !!report?.reportID && !!(reportMetadata?.[`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report.reportID}`]?.lastVisitTime ?? report?.lastReadTime))
.sort((a, b) => {
Expand Down
19 changes: 19 additions & 0 deletions src/types/utils/CollectionDataSet.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
import type {OnyxEntry} from 'react-native-onyx';
import type {OnyxCollectionKey, OnyxCollectionValuesMapping} from '@src/ONYXKEYS';

/** Helps with typing a collection item update inside Onyx.multiSet call */
type CollectionDataSet<TCollectionKey extends OnyxCollectionKey> = Record<`${TCollectionKey}${string}`, OnyxCollectionValuesMapping[TCollectionKey]>;

const toCollectionDataSet = <TCollectionKey extends OnyxCollectionKey>(
collectionKey: TCollectionKey,
collection: Array<OnyxEntry<OnyxCollectionValuesMapping[TCollectionKey]>>,
idSelector: (collectionValue: OnyxCollectionValuesMapping[TCollectionKey]) => string,
) => {
const collectionDataSet = collection.reduce<CollectionDataSet<TCollectionKey>>((result, collectionValue) => {
if (collectionValue) {
// eslint-disable-next-line no-param-reassign
result[`${collectionKey}${idSelector(collectionValue)}`] = collectionValue;
}
return result;
}, {} as CollectionDataSet<TCollectionKey>);

return collectionDataSet;
};

export default CollectionDataSet;

export {toCollectionDataSet};
Original file line number Diff line number Diff line change
@@ -1,35 +1,34 @@
// From: https://raw.githubusercontent.com/callstack/reassure/main/packages/reassure-compare/src/output/markdown.ts
import fs from 'node:fs/promises';
import path from 'path';
import _ from 'underscore';
import * as Logger from '../../utils/logger';
import type {AddedEntry, CompareEntry, CompareResult, PerformanceEntry, RemovedEntry} from '../types';
import * as format from './format';
import markdownTable from './markdownTable';

const tableHeader = ['Name', 'Duration'];

const collapsibleSection = (title, content) => `<details>\n<summary>${title}</summary>\n\n${content}\n</details>\n\n`;
const collapsibleSection = (title: string, content: string): string => `<details>\n<summary>${title}</summary>\n\n${content}\n</details>\n\n`;

const buildDurationDetails = (title, entry) => {
const buildDurationDetails = (title: string, entry: PerformanceEntry): string => {
const relativeStdev = entry.stdev / entry.mean;

return _.filter(
[
`**${title}**`,
`Mean: ${format.formatDuration(entry.mean)}`,
`Stdev: ${format.formatDuration(entry.stdev)} (${format.formatPercent(relativeStdev)})`,
entry.entries ? `Runs: ${entry.entries.join(' ')}` : '',
],
Boolean,
).join('<br/>');
return [
`**${title}**`,
`Mean: ${format.formatDuration(entry.mean)}`,
`Stdev: ${format.formatDuration(entry.stdev)} (${format.formatPercent(relativeStdev)})`,
entry.entries ? `Runs: ${entry.entries.join(' ')}` : '',
]
.filter(Boolean)
.join('<br/>');
};

const buildDurationDetailsEntry = (entry) =>
_.filter(['baseline' in entry ? buildDurationDetails('Baseline', entry.baseline) : '', 'current' in entry ? buildDurationDetails('Current', entry.current) : ''], Boolean).join(
'<br/><br/>',
);
const buildDurationDetailsEntry = (entry: CompareEntry | AddedEntry | RemovedEntry): string =>
['baseline' in entry ? buildDurationDetails('Baseline', entry.baseline) : '', 'current' in entry ? buildDurationDetails('Current', entry.current) : '']
.filter(Boolean)
.join('<br/><br/>');

const formatEntryDuration = (entry) => {
const formatEntryDuration = (entry: CompareEntry | AddedEntry | RemovedEntry): string => {
if ('baseline' in entry && 'current' in entry) {
return format.formatDurationDiffChange(entry);
}
Expand All @@ -42,39 +41,39 @@ const formatEntryDuration = (entry) => {
return '';
};

const buildDetailsTable = (entries) => {
const buildDetailsTable = (entries: Array<CompareEntry | AddedEntry | RemovedEntry>): string => {
if (!entries.length) {
return '';
}

const rows = _.map(entries, (entry) => [entry.name, buildDurationDetailsEntry(entry)]);
const rows = entries.map((entry) => [entry.name, buildDurationDetailsEntry(entry)]);
const content = markdownTable([tableHeader, ...rows]);

return collapsibleSection('Show details', content);
};

const buildSummaryTable = (entries, collapse = false) => {
const buildSummaryTable = (entries: Array<CompareEntry | AddedEntry | RemovedEntry>, collapse = false): string => {
if (!entries.length) {
return '_There are no entries_';
}

const rows = _.map(entries, (entry) => [entry.name, formatEntryDuration(entry)]);
const rows = entries.map((entry) => [entry.name, formatEntryDuration(entry)]);
const content = markdownTable([tableHeader, ...rows]);

return collapse ? collapsibleSection('Show entries', content) : content;
};

const buildMarkdown = (data) => {
const buildMarkdown = (data: CompareResult): string => {
let result = '## Performance Comparison Report 📊';

if (data.errors && data.errors.length) {
if (data.errors?.length) {
result += '\n\n### Errors\n';
data.errors.forEach((message) => {
result += ` 1. 🛑 ${message}\n`;
});
}

if (data.warnings && data.warnings.length) {
if (data.warnings?.length) {
result += '\n\n### Warnings\n';
data.warnings.forEach((message) => {
result += ` 1. 🟡 ${message}\n`;
Expand All @@ -92,7 +91,7 @@ const buildMarkdown = (data) => {
return result;
};

const writeToFile = (filePath, content) =>
const writeToFile = (filePath: string, content: string): Promise<void> =>
fs
.writeFile(filePath, content)
.then(() => {
Expand All @@ -106,7 +105,7 @@ const writeToFile = (filePath, content) =>
throw error;
});

const writeToMarkdown = (filePath, data) => {
const writeToMarkdown = (filePath: string, data: CompareResult): Promise<void> => {
const markdown = buildMarkdown(data);
return writeToFile(filePath, markdown).catch((error) => {
console.error(error);
Expand Down
57 changes: 57 additions & 0 deletions tests/e2e/compare/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
type Entries = number[];

/** Metadata information for performance results. */

/** Entry in the performance results file. */
type PerformanceEntry = {
/** Number of times the measurement test was run. */
runs: number;

/** Arithmetic average of measured render/execution durations for each run. */
mean: number;

/** Standard deviation of measured render/execution durations for each run. */
stdev: number;

/** Array of measured render/execution durations for each run. */
entries: Entries;
};

/**
* Compare entry for tests that have both baseline and current entry
*/
type CompareEntry = {
name: string;
current: PerformanceEntry;
baseline: PerformanceEntry;
durationDiff: number;
relativeDurationDiff: number;
};

/**
* Compare entry for tests that have only current entry
*/
type AddedEntry = {
name: string;
current: PerformanceEntry;
};

/**
* Compare entry for tests that have only baseline entry
*/
type RemovedEntry = {
name: string;
baseline: PerformanceEntry;
};

/** Output of compare function. */
type CompareResult = {
significance: CompareEntry[];
meaningless: CompareEntry[];
added: AddedEntry[];
removed: RemovedEntry[];
errors?: string[];
warnings?: string[];
};

export type {Entries, PerformanceEntry, CompareEntry, AddedEntry, RemovedEntry, CompareResult};
11 changes: 2 additions & 9 deletions tests/e2e/measure/math.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
type Entries = number[];

type Stats = {
mean: number;
stdev: number;
runs: number;
entries: Entries;
};
import type {Entries, PerformanceEntry} from '../compare/types';

const filterOutliersViaIQR = (data: Entries): Entries => {
let q1;
Expand Down Expand Up @@ -35,7 +28,7 @@ const std = (arr: Entries): number => {
return Math.sqrt(arr.map((i) => (i - avg) ** 2).reduce((a, b) => a + b) / arr.length);
};

const getStats = (entries: Entries): Stats => {
const getStats = (entries: Entries): PerformanceEntry => {
const cleanedEntries = filterOutliersViaIQR(entries);
const meanDuration = mean(cleanedEntries);
const stdevDuration = std(cleanedEntries);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
import {fireEvent, screen} from '@testing-library/react-native';
import Onyx from 'react-native-onyx';
import {measurePerformance} from 'reassure';
import _ from 'underscore';
import CONST from '../../src/CONST';
import ONYXKEYS from '../../src/ONYXKEYS';
import variables from '../../src/styles/variables';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import * as LHNTestUtils from '../utils/LHNTestUtils';
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatchedUpdates';

jest.mock('../../src/libs/Permissions');
jest.mock('../../src/hooks/usePermissions.ts');
jest.mock('../../src/libs/Navigation/Navigation');
jest.mock('../../src/components/Icon/Expensicons');
jest.mock('@libs/Permissions');
jest.mock('@hooks/usePermissions.ts');
jest.mock('@libs/Navigation/Navigation');
jest.mock('@components/Icon/Expensicons');

jest.mock('@react-navigation/native');

const getMockedReportsMap = (length = 100) => {
const mockReports = Array.from({length}, (__, i) => {
const reportID = i + 1;
const mockReports = Array.from({length}, (value, index) => {
const reportID = index + 1;
const participants = [1, 2];
const reportKey = `${ONYXKEYS.COLLECTION.REPORT}${reportID}`;
const report = LHNTestUtils.getFakeReport(participants, 1, true);

return {[reportKey]: report};
});

return _.assign({}, ...mockReports);
return {...mockReports};
};

const mockedResponseMap = getMockedReportsMap(500);
Expand All @@ -36,11 +35,9 @@ describe('SidebarLinks', () => {
Onyx.init({
keys: ONYXKEYS,
safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
registerStorageEventListener: () => {},
});

Onyx.multiSet({
[ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
[ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
[ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS],
[ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
Expand Down
Loading
Loading