Skip to content

Commit

Permalink
Revert "[No QA] Migrate 'OptionsListUtilsTest.js', 'DateUtilsTest.js'…
Browse files Browse the repository at this point in the history
…, 'SidebarLinks.perf-test.js', 'markdown.js' and 'ReportUtilsTest.js' to Typescript"
  • Loading branch information
marcaaron committed Mar 28, 2024
1 parent 054d129 commit 39aaa56
Show file tree
Hide file tree
Showing 9 changed files with 287 additions and 479 deletions.
2 changes: 1 addition & 1 deletion src/libs/DateUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ function formatToLongDateWithWeekday(datetime: string | Date): string {
* @returns Sunday
*/
function formatToDayOfWeek(datetime: Date): string {
return format(datetime, CONST.DATE.WEEKDAY_TIME_FORMAT);
return format(new Date(datetime), CONST.DATE.WEEKDAY_TIME_FORMAT);
}

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

export type {MemberForList, CategorySection, CategoryTreeSection, GetOptions, PayeePersonalDetails, Category, Tag};
export type {MemberForList, CategorySection, GetOptions, PayeePersonalDetails, Category};
6 changes: 1 addition & 5 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import type {
ReportMetadata,
Session,
Task,
TaxRate,
Transaction,
TransactionViolation,
UserWallet,
Expand Down Expand Up @@ -406,9 +405,6 @@ type OptionData = {
isDisabled?: boolean | null;
name?: string | null;
isSelfDM?: boolean | null;
reportID?: string;
enabled?: boolean;
data?: Partial<TaxRate>;
} & Report;

type OnyxDataTaskAssigneeChat = {
Expand Down Expand Up @@ -964,7 +960,7 @@ function filterReportsByPolicyIDAndMemberAccountIDs(reports: Report[], policyMem
/**
* Given an array of reports, return them sorted by the last read timestamp.
*/
function sortReportsByLastRead(reports: Array<OnyxEntry<Report>>, reportMetadata: OnyxCollection<ReportMetadata>): Array<OnyxEntry<Report>> {
function sortReportsByLastRead(reports: 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
4 changes: 1 addition & 3 deletions tests/e2e/compare/output/console.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ type Entry = {
type Data = {
significance: Entry[];
meaningless: Entry[];
errors: string[];
warnings: string[];
};

const printRegularLine = (entry: Entry) => {
Expand All @@ -38,4 +36,4 @@ export default (data: Data) => {
console.debug('');
};

export type {Data, Entry};
export type {Entry};
Original file line number Diff line number Diff line change
@@ -1,85 +1,80 @@
// 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 type {Stats} from 'tests/e2e/measure/math';
import _ from 'underscore';
import * as Logger from '../../utils/logger';
import type {Data, Entry} from './console';
import * as format from './format';
import markdownTable from './markdownTable';

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

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

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

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/>');
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/>');
};

const buildDurationDetailsEntry = (entry: Entry) =>
['baseline' in entry ? buildDurationDetails('Baseline', entry.baseline) : '', 'current' in entry ? buildDurationDetails('Current', entry.current) : '']
.filter(Boolean)
.join('<br/><br/>');

const formatEntryDuration = (entry: Entry): string => {
let formattedDuration = '';
const buildDurationDetailsEntry = (entry) =>
_.filter(['baseline' in entry ? buildDurationDetails('Baseline', entry.baseline) : '', 'current' in entry ? buildDurationDetails('Current', entry.current) : ''], Boolean).join(
'<br/><br/>',
);

const formatEntryDuration = (entry) => {
if ('baseline' in entry && 'current' in entry) {
formattedDuration = format.formatDurationDiffChange(entry);
return format.formatDurationDiffChange(entry);
}

if ('baseline' in entry) {
formattedDuration = format.formatDuration(entry.baseline.mean);
return format.formatDuration(entry.baseline.mean);
}

if ('current' in entry) {
formattedDuration = format.formatDuration(entry.current.mean);
return format.formatDuration(entry.current.mean);
}

return formattedDuration;
return '';
};

const buildDetailsTable = (entries: Entry[]) => {
const buildDetailsTable = (entries) => {
if (!entries.length) {
return '';
}

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

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

const buildSummaryTable = (entries: Entry[], collapse = false) => {
const buildSummaryTable = (entries, collapse = false) => {
if (!entries.length) {
return '_There are no entries_';
}

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

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

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

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

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

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

const writeToMarkdown = (filePath: string, data: Data) => {
const writeToMarkdown = (filePath, data) => {
const markdown = buildMarkdown(data);
return writeToFile(filePath, markdown).catch((error) => {
console.error(error);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
import {fireEvent, screen} from '@testing-library/react-native';
import Onyx from 'react-native-onyx';
import {measurePerformance} from 'reassure';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import _ from 'underscore';
import CONST from '../../src/CONST';
import ONYXKEYS from '../../src/ONYXKEYS';
import variables from '../../src/styles/variables';
import * as LHNTestUtils from '../utils/LHNTestUtils';
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatchedUpdates';

jest.mock('@libs/Permissions');
jest.mock('@hooks/usePermissions.ts');
jest.mock('@libs/Navigation/Navigation');
jest.mock('@components/Icon/Expensicons');
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('@react-navigation/native');

const getMockedReportsMap = (length = 100) => {
const mockReports = Object.fromEntries(
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 mockReports;
const mockReports = Array.from({length}, (__, i) => {
const reportID = i + 1;
const participants = [1, 2];
const reportKey = `${ONYXKEYS.COLLECTION.REPORT}${reportID}`;
const report = LHNTestUtils.getFakeReport(participants, 1, true);

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

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

const mockedResponseMap = getMockedReportsMap(500);
Expand All @@ -37,9 +36,11 @@ 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
57 changes: 24 additions & 33 deletions tests/unit/DateUtilsTest.ts → tests/unit/DateUtilsTest.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
/* eslint-disable @typescript-eslint/naming-convention */
import {addDays, addMinutes, format, setHours, setMinutes, subDays, subHours, subMinutes, subSeconds} from 'date-fns';
import {format as tzFormat, utcToZonedTime} from 'date-fns-tz';
import Onyx from 'react-native-onyx';
import DateUtils from '@libs/DateUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {SelectedTimezone} from '@src/types/onyx/PersonalDetails';
import CONST from '../../src/CONST';
import DateUtils from '../../src/libs/DateUtils';
import ONYXKEYS from '../../src/ONYXKEYS';
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';

const LOCALE = CONST.LOCALES.EN;
Expand All @@ -16,14 +14,13 @@ describe('DateUtils', () => {
keys: ONYXKEYS,
initialKeyStates: {
[ONYXKEYS.SESSION]: {accountID: 999},
[ONYXKEYS.PERSONAL_DETAILS_LIST]: {'999': {accountID: 999, timezone: {selected: 'Europe/London'}}},
[ONYXKEYS.PERSONAL_DETAILS_LIST]: {999: {timezone: {selected: UTC}}},
},
});
return waitForBatchedUpdates();
});

afterEach(() => {
jest.restoreAllMocks();
jest.useRealTimers();
Onyx.clear();
});
Expand All @@ -42,7 +39,7 @@ describe('DateUtils', () => {
});

it('formatToDayOfWeek should return a weekday', () => {
const weekDay = DateUtils.formatToDayOfWeek(new Date(datetime));
const weekDay = DateUtils.formatToDayOfWeek(datetime);
expect(weekDay).toBe('Monday');
});
it('formatToLocalTime should return a date in a local format', () => {
Expand All @@ -56,35 +53,32 @@ describe('DateUtils', () => {
});

it('should fallback to current date when getLocalDateFromDatetime is failing', () => {
const localDate = DateUtils.getLocalDateFromDatetime(LOCALE, undefined, 'InvalidTimezone' as SelectedTimezone);
const localDate = DateUtils.getLocalDateFromDatetime(LOCALE, undefined, 'InvalidTimezone');
expect(localDate.getTime()).not.toBeNaN();
});

it('should return the date in calendar time when calling datetimeToCalendarTime', () => {
const today = setMinutes(setHours(new Date(), 14), 32).toString();
const today = setMinutes(setHours(new Date(), 14), 32);
expect(DateUtils.datetimeToCalendarTime(LOCALE, today)).toBe('Today at 2:32 PM');

const tomorrow = addDays(setMinutes(setHours(new Date(), 14), 32), 1).toString();
const tomorrow = addDays(setMinutes(setHours(new Date(), 14), 32), 1);
expect(DateUtils.datetimeToCalendarTime(LOCALE, tomorrow)).toBe('Tomorrow at 2:32 PM');

const yesterday = setMinutes(setHours(subDays(new Date(), 1), 7), 43).toString();
const yesterday = setMinutes(setHours(subDays(new Date(), 1), 7), 43);
expect(DateUtils.datetimeToCalendarTime(LOCALE, yesterday)).toBe('Yesterday at 7:43 AM');

const date = setMinutes(setHours(new Date('2022-11-05'), 10), 17).toString();
const date = setMinutes(setHours(new Date('2022-11-05'), 10), 17);
expect(DateUtils.datetimeToCalendarTime(LOCALE, date)).toBe('Nov 5, 2022 at 10:17 AM');

const todayLowercaseDate = setMinutes(setHours(new Date(), 14), 32).toString();
const todayLowercaseDate = setMinutes(setHours(new Date(), 14), 32);
expect(DateUtils.datetimeToCalendarTime(LOCALE, todayLowercaseDate, false, undefined, true)).toBe('today at 2:32 PM');
});

it('should update timezone if automatic and selected timezone do not match', () => {
jest.spyOn(Intl, 'DateTimeFormat').mockImplementation(
() =>
({
resolvedOptions: () => ({timeZone: 'America/Chicago'}),
} as Intl.DateTimeFormat),
);
Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, {'999': {accountID: 999, timezone: {selected: 'Europe/London', automatic: true}}}).then(() => {
Intl.DateTimeFormat = jest.fn(() => ({
resolvedOptions: () => ({timeZone: 'America/Chicago'}),
}));
Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, {999: {timezone: {selected: UTC, automatic: true}}}).then(() => {
const result = DateUtils.getCurrentTimezone();
expect(result).toEqual({
selected: 'America/Chicago',
Expand All @@ -94,13 +88,10 @@ describe('DateUtils', () => {
});

it('should not update timezone if automatic and selected timezone match', () => {
jest.spyOn(Intl, 'DateTimeFormat').mockImplementation(
() =>
({
resolvedOptions: () => ({timeZone: UTC}),
} as Intl.DateTimeFormat),
);
Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, {'999': {accountID: 999, timezone: {selected: 'Europe/London', automatic: true}}}).then(() => {
Intl.DateTimeFormat = jest.fn(() => ({
resolvedOptions: () => ({timeZone: UTC}),
}));
Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, {999: {timezone: {selected: UTC, automatic: true}}}).then(() => {
const result = DateUtils.getCurrentTimezone();
expect(result).toEqual({
selected: UTC,
Expand All @@ -111,28 +102,28 @@ describe('DateUtils', () => {

it('canUpdateTimezone should return true when lastUpdatedTimezoneTime is more than 5 minutes ago', () => {
// Use fake timers to control the current time
jest.useFakeTimers();
jest.useFakeTimers('modern');
jest.setSystemTime(addMinutes(new Date(), 6));
const isUpdateTimezoneAllowed = DateUtils.canUpdateTimezone();
expect(isUpdateTimezoneAllowed).toBe(true);
});

it('canUpdateTimezone should return false when lastUpdatedTimezoneTime is less than 5 minutes ago', () => {
// Use fake timers to control the current time
jest.useFakeTimers();
jest.useFakeTimers('modern');
jest.setSystemTime(addMinutes(new Date(), 4));
const isUpdateTimezoneAllowed = DateUtils.canUpdateTimezone();
expect(isUpdateTimezoneAllowed).toBe(false);
});

it('should return the date in calendar time when calling datetimeToRelative', () => {
const aFewSecondsAgo = subSeconds(new Date(), 10).toString();
const aFewSecondsAgo = subSeconds(new Date(), 10);
expect(DateUtils.datetimeToRelative(LOCALE, aFewSecondsAgo)).toBe('less than a minute ago');

const aMinuteAgo = subMinutes(new Date(), 1).toString();
const aMinuteAgo = subMinutes(new Date(), 1);
expect(DateUtils.datetimeToRelative(LOCALE, aMinuteAgo)).toBe('1 minute ago');

const anHourAgo = subHours(new Date(), 1).toString();
const anHourAgo = subHours(new Date(), 1);
expect(DateUtils.datetimeToRelative(LOCALE, anHourAgo)).toBe('about 1 hour ago');
});

Expand Down
Loading

0 comments on commit 39aaa56

Please sign in to comment.