From 39aaa567d352e8a43538886ea614c745d1b8c03a Mon Sep 17 00:00:00 2001 From: Marc Glasser Date: Wed, 27 Mar 2024 15:51:39 -1000 Subject: [PATCH] Revert "[No QA] Migrate 'OptionsListUtilsTest.js', 'DateUtilsTest.js', 'SidebarLinks.perf-test.js', 'markdown.js' and 'ReportUtilsTest.js' to Typescript" --- src/libs/DateUtils.ts | 2 +- src/libs/OptionsListUtils.ts | 2 +- src/libs/ReportUtils.ts | 6 +- tests/e2e/compare/output/console.ts | 4 +- .../output/{markdown.ts => markdown.js} | 65 ++- ...erf-test.tsx => SidebarLinks.perf-test.js} | 39 +- .../{DateUtilsTest.ts => DateUtilsTest.js} | 57 ++- ...stUtilsTest.ts => OptionsListUtilsTest.js} | 389 ++++++------------ ...{ReportUtilsTest.ts => ReportUtilsTest.js} | 202 ++++----- 9 files changed, 287 insertions(+), 479 deletions(-) rename tests/e2e/compare/output/{markdown.ts => markdown.js} (57%) rename tests/perf-test/{SidebarLinks.perf-test.tsx => SidebarLinks.perf-test.js} (79%) rename tests/unit/{DateUtilsTest.ts => DateUtilsTest.js} (85%) rename tests/unit/{OptionsListUtilsTest.ts => OptionsListUtilsTest.js} (85%) rename tests/unit/{ReportUtilsTest.ts => ReportUtilsTest.js} (84%) diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index 44c7682b47f2..4d4f8d425681 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -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); } /** diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 81dd669f03b5..bb52686c4bd4 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -2110,4 +2110,4 @@ export { getTaxRatesSection, }; -export type {MemberForList, CategorySection, CategoryTreeSection, GetOptions, PayeePersonalDetails, Category, Tag}; +export type {MemberForList, CategorySection, GetOptions, PayeePersonalDetails, Category}; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 37aea210e784..ce4264b32141 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -28,7 +28,6 @@ import type { ReportMetadata, Session, Task, - TaxRate, Transaction, TransactionViolation, UserWallet, @@ -406,9 +405,6 @@ type OptionData = { isDisabled?: boolean | null; name?: string | null; isSelfDM?: boolean | null; - reportID?: string; - enabled?: boolean; - data?: Partial; } & Report; type OnyxDataTaskAssigneeChat = { @@ -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>, reportMetadata: OnyxCollection): Array> { +function sortReportsByLastRead(reports: Report[], reportMetadata: OnyxCollection): Array> { return reports .filter((report) => !!report?.reportID && !!(reportMetadata?.[`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report.reportID}`]?.lastVisitTime ?? report?.lastReadTime)) .sort((a, b) => { diff --git a/tests/e2e/compare/output/console.ts b/tests/e2e/compare/output/console.ts index 3da0100b603f..de8e5d913893 100644 --- a/tests/e2e/compare/output/console.ts +++ b/tests/e2e/compare/output/console.ts @@ -13,8 +13,6 @@ type Entry = { type Data = { significance: Entry[]; meaningless: Entry[]; - errors: string[]; - warnings: string[]; }; const printRegularLine = (entry: Entry) => { @@ -38,4 +36,4 @@ export default (data: Data) => { console.debug(''); }; -export type {Data, Entry}; +export type {Entry}; diff --git a/tests/e2e/compare/output/markdown.ts b/tests/e2e/compare/output/markdown.js similarity index 57% rename from tests/e2e/compare/output/markdown.ts rename to tests/e2e/compare/output/markdown.js index 34bc3251c422..119830a5bb2c 100644 --- a/tests/e2e/compare/output/markdown.ts +++ b/tests/e2e/compare/output/markdown.js @@ -1,85 +1,80 @@ // From: https://github.com/raw/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) => `
\n${title}\n\n${content}\n
\n\n`; +const collapsibleSection = (title, content) => `
\n${title}\n\n${content}\n
\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('
'); + return _.filter( + [ + `**${title}**`, + `Mean: ${format.formatDuration(entry.mean)}`, + `Stdev: ${format.formatDuration(entry.stdev)} (${format.formatPercent(relativeStdev)})`, + entry.entries ? `Runs: ${entry.entries.join(' ')}` : '', + ], + Boolean, + ).join('
'); }; -const buildDurationDetailsEntry = (entry: Entry) => - ['baseline' in entry ? buildDurationDetails('Baseline', entry.baseline) : '', 'current' in entry ? buildDurationDetails('Current', entry.current) : ''] - .filter(Boolean) - .join('

'); - -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( + '

', + ); +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`; @@ -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(() => { @@ -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); diff --git a/tests/perf-test/SidebarLinks.perf-test.tsx b/tests/perf-test/SidebarLinks.perf-test.js similarity index 79% rename from tests/perf-test/SidebarLinks.perf-test.tsx rename to tests/perf-test/SidebarLinks.perf-test.js index 2848015d5c63..0b10718fd0c4 100644 --- a/tests/perf-test/SidebarLinks.perf-test.tsx +++ b/tests/perf-test/SidebarLinks.perf-test.js @@ -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); @@ -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, diff --git a/tests/unit/DateUtilsTest.ts b/tests/unit/DateUtilsTest.js similarity index 85% rename from tests/unit/DateUtilsTest.ts rename to tests/unit/DateUtilsTest.js index a7f43ea84045..a752eea1a990 100644 --- a/tests/unit/DateUtilsTest.ts +++ b/tests/unit/DateUtilsTest.js @@ -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; @@ -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(); }); @@ -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', () => { @@ -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', @@ -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, @@ -111,7 +102,7 @@ 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); @@ -119,20 +110,20 @@ describe('DateUtils', () => { 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'); }); diff --git a/tests/unit/OptionsListUtilsTest.ts b/tests/unit/OptionsListUtilsTest.js similarity index 85% rename from tests/unit/OptionsListUtilsTest.ts rename to tests/unit/OptionsListUtilsTest.js index 1d5632f0efd9..7244b7830a29 100644 --- a/tests/unit/OptionsListUtilsTest.ts +++ b/tests/unit/OptionsListUtilsTest.js @@ -1,35 +1,30 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; -import CONST from '@src/CONST'; -import type {Tag} from '@src/libs/OptionsListUtils'; -import * as OptionsListUtils from '@src/libs/OptionsListUtils'; -import * as ReportUtils from '@src/libs/ReportUtils'; -import ONYXKEYS from '@src/ONYXKEYS'; -import type {PersonalDetails, Policy, PolicyCategories, Report, TaxRatesWithDefault} from '@src/types/onyx'; +import _ from 'underscore'; +import CONST from '../../src/CONST'; +import * as OptionsListUtils from '../../src/libs/OptionsListUtils'; +import * as ReportUtils from '../../src/libs/ReportUtils'; +import ONYXKEYS from '../../src/ONYXKEYS'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; -type PersonalDetailsList = Record; - describe('OptionsListUtils', () => { // Given a set of reports with both single participants and multiple participants some pinned and some not - const REPORTS: OnyxCollection = { - '1': { + const REPORTS = { + 1: { lastReadTime: '2021-01-14 11:25:39.295', lastVisibleActionCreated: '2022-11-22 03:26:02.015', isPinned: false, - reportID: '1', + reportID: 1, participantAccountIDs: [2, 1], visibleChatMemberAccountIDs: [2, 1], reportName: 'Iron Man, Mister Fantastic', hasDraft: true, type: CONST.REPORT.TYPE.CHAT, }, - '2': { + 2: { lastReadTime: '2021-01-14 11:25:39.296', lastVisibleActionCreated: '2022-11-22 03:26:02.016', isPinned: false, - reportID: '2', + reportID: 2, participantAccountIDs: [3], visibleChatMemberAccountIDs: [3], reportName: 'Spider-Man', @@ -37,41 +32,41 @@ describe('OptionsListUtils', () => { }, // This is the only report we are pinning in this test - '3': { + 3: { lastReadTime: '2021-01-14 11:25:39.297', lastVisibleActionCreated: '2022-11-22 03:26:02.170', isPinned: true, - reportID: '3', + reportID: 3, participantAccountIDs: [1], visibleChatMemberAccountIDs: [1], reportName: 'Mister Fantastic', type: CONST.REPORT.TYPE.CHAT, }, - '4': { + 4: { lastReadTime: '2021-01-14 11:25:39.298', lastVisibleActionCreated: '2022-11-22 03:26:02.180', isPinned: false, - reportID: '4', + reportID: 4, participantAccountIDs: [4], visibleChatMemberAccountIDs: [4], reportName: 'Black Panther', type: CONST.REPORT.TYPE.CHAT, }, - '5': { + 5: { lastReadTime: '2021-01-14 11:25:39.299', lastVisibleActionCreated: '2022-11-22 03:26:02.019', isPinned: false, - reportID: '5', + reportID: 5, participantAccountIDs: [5], visibleChatMemberAccountIDs: [5], reportName: 'Invisible Woman', type: CONST.REPORT.TYPE.CHAT, }, - '6': { + 6: { lastReadTime: '2021-01-14 11:25:39.300', lastVisibleActionCreated: '2022-11-22 03:26:02.020', isPinned: false, - reportID: '6', + reportID: 6, participantAccountIDs: [6], visibleChatMemberAccountIDs: [6], reportName: 'Thor', @@ -79,11 +74,11 @@ describe('OptionsListUtils', () => { }, // Note: This report has the largest lastVisibleActionCreated - '7': { + 7: { lastReadTime: '2021-01-14 11:25:39.301', lastVisibleActionCreated: '2022-11-22 03:26:03.999', isPinned: false, - reportID: '7', + reportID: 7, participantAccountIDs: [7], visibleChatMemberAccountIDs: [7], reportName: 'Captain America', @@ -91,11 +86,11 @@ describe('OptionsListUtils', () => { }, // Note: This report has no lastVisibleActionCreated - '8': { + 8: { lastReadTime: '2021-01-14 11:25:39.301', lastVisibleActionCreated: '2022-11-22 03:26:02.000', isPinned: false, - reportID: '8', + reportID: 8, participantAccountIDs: [12], visibleChatMemberAccountIDs: [12], reportName: 'Silver Surfer', @@ -103,23 +98,23 @@ describe('OptionsListUtils', () => { }, // Note: This report has an IOU - '9': { + 9: { lastReadTime: '2021-01-14 11:25:39.302', lastVisibleActionCreated: '2022-11-22 03:26:02.998', isPinned: false, - reportID: '9', + reportID: 9, participantAccountIDs: [8], visibleChatMemberAccountIDs: [8], reportName: 'Mister Sinister', - iouReportID: '100', + iouReportID: 100, type: CONST.REPORT.TYPE.CHAT, }, // This report is an archived room – it does not have a name and instead falls back on oldPolicyName - '10': { + 10: { lastReadTime: '2021-01-14 11:25:39.200', lastVisibleActionCreated: '2022-11-22 03:26:02.001', - reportID: '10', + reportID: 10, isPinned: false, participantAccountIDs: [2, 7], visibleChatMemberAccountIDs: [2, 7], @@ -136,81 +131,71 @@ describe('OptionsListUtils', () => { }; // And a set of personalDetails some with existing reports and some without - const PERSONAL_DETAILS: PersonalDetailsList = { + const PERSONAL_DETAILS = { // These exist in our reports - '1': { + 1: { accountID: 1, displayName: 'Mister Fantastic', login: 'reedrichards@expensify.com', isSelected: true, - reportID: '1', }, - '2': { + 2: { accountID: 2, displayName: 'Iron Man', login: 'tonystark@expensify.com', - reportID: '1', }, - '3': { + 3: { accountID: 3, displayName: 'Spider-Man', login: 'peterparker@expensify.com', - reportID: '1', }, - '4': { + 4: { accountID: 4, displayName: 'Black Panther', login: 'tchalla@expensify.com', - reportID: '1', }, - '5': { + 5: { accountID: 5, displayName: 'Invisible Woman', login: 'suestorm@expensify.com', - reportID: '1', }, - '6': { + 6: { accountID: 6, displayName: 'Thor', login: 'thor@expensify.com', - reportID: '1', }, - '7': { + 7: { accountID: 7, displayName: 'Captain America', login: 'steverogers@expensify.com', - reportID: '1', }, - '8': { + 8: { accountID: 8, displayName: 'Mr Sinister', login: 'mistersinister@marauders.com', - reportID: '1', }, // These do not exist in reports at all - '9': { + 9: { accountID: 9, displayName: 'Black Widow', login: 'natasharomanoff@expensify.com', - reportID: '', }, - '10': { + 10: { accountID: 10, displayName: 'The Incredible Hulk', login: 'brucebanner@expensify.com', - reportID: '', }, }; - const REPORTS_WITH_CONCIERGE: OnyxCollection = { + const REPORTS_WITH_CONCIERGE = { ...REPORTS, - '11': { + 11: { lastReadTime: '2021-01-14 11:25:39.302', lastVisibleActionCreated: '2022-11-22 03:26:02.022', isPinned: false, - reportID: '11', + reportID: 11, participantAccountIDs: [999], visibleChatMemberAccountIDs: [999], reportName: 'Concierge', @@ -218,13 +203,13 @@ describe('OptionsListUtils', () => { }, }; - const REPORTS_WITH_CHRONOS: OnyxCollection = { + const REPORTS_WITH_CHRONOS = { ...REPORTS, - '12': { + 12: { lastReadTime: '2021-01-14 11:25:39.302', lastVisibleActionCreated: '2022-11-22 03:26:02.022', isPinned: false, - reportID: '12', + reportID: 12, participantAccountIDs: [1000], visibleChatMemberAccountIDs: [1000], reportName: 'Chronos', @@ -232,13 +217,13 @@ describe('OptionsListUtils', () => { }, }; - const REPORTS_WITH_RECEIPTS: OnyxCollection = { + const REPORTS_WITH_RECEIPTS = { ...REPORTS, - '13': { + 13: { lastReadTime: '2021-01-14 11:25:39.302', lastVisibleActionCreated: '2022-11-22 03:26:02.022', isPinned: false, - reportID: '13', + reportID: 13, participantAccountIDs: [1001], visibleChatMemberAccountIDs: [1001], reportName: 'Receipts', @@ -246,77 +231,67 @@ describe('OptionsListUtils', () => { }, }; - const REPORTS_WITH_WORKSPACE_ROOMS: OnyxCollection = { + const REPORTS_WITH_WORKSPACE_ROOMS = { ...REPORTS, - '14': { + 14: { lastReadTime: '2021-01-14 11:25:39.302', lastVisibleActionCreated: '2022-11-22 03:26:02.022', isPinned: false, - reportID: '14', + reportID: 14, participantAccountIDs: [1, 10, 3], visibleChatMemberAccountIDs: [1, 10, 3], reportName: '', oldPolicyName: 'Avengers Room', + isArchivedRoom: false, chatType: CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, isOwnPolicyExpenseChat: true, type: CONST.REPORT.TYPE.CHAT, }, }; - const PERSONAL_DETAILS_WITH_CONCIERGE: PersonalDetailsList = { + const PERSONAL_DETAILS_WITH_CONCIERGE = { ...PERSONAL_DETAILS, - '999': { + 999: { accountID: 999, displayName: 'Concierge', login: 'concierge@expensify.com', - reportID: '', }, }; - const PERSONAL_DETAILS_WITH_CHRONOS: PersonalDetailsList = { + const PERSONAL_DETAILS_WITH_CHRONOS = { ...PERSONAL_DETAILS, - '1000': { + 1000: { accountID: 1000, displayName: 'Chronos', login: 'chronos@expensify.com', - reportID: '', }, }; - const PERSONAL_DETAILS_WITH_RECEIPTS: PersonalDetailsList = { + const PERSONAL_DETAILS_WITH_RECEIPTS = { ...PERSONAL_DETAILS, - '1001': { + 1001: { accountID: 1001, displayName: 'Receipts', login: 'receipts@expensify.com', - reportID: '', }, }; - const PERSONAL_DETAILS_WITH_PERIODS: PersonalDetailsList = { + const PERSONAL_DETAILS_WITH_PERIODS = { ...PERSONAL_DETAILS, - '1002': { + 1002: { accountID: 1002, displayName: 'The Flash', login: 'barry.allen@expensify.com', - reportID: '', }, }; - const policyID = 'ABC123'; - - const POLICY: Policy = { - id: policyID, + const POLICY = { + policyID: 'ABC123', name: 'Hero Policy', - role: 'user', - type: 'free', - owner: '', - outputCurrency: '', - isPolicyExpenseChatEnabled: false, }; // Set the currently logged in user, report data, and personal details @@ -325,12 +300,11 @@ describe('OptionsListUtils', () => { keys: ONYXKEYS, initialKeyStates: { [ONYXKEYS.SESSION]: {accountID: 2, email: 'tonystark@expensify.com'}, - [`${ONYXKEYS.COLLECTION.REPORT}100` as const]: { - reportID: '', + [`${ONYXKEYS.COLLECTION.REPORT}100`]: { ownerAccountID: 8, - total: 1000, + total: '1000', }, - [`${ONYXKEYS.COLLECTION.POLICY}${policyID}` as const]: POLICY, + [`${ONYXKEYS.COLLECTION.POLICY}${POLICY.policyID}`]: POLICY, }, }); Onyx.registerLogger(() => {}); @@ -345,7 +319,7 @@ describe('OptionsListUtils', () => { expect(results.personalDetails.length).toBe(2); // Then all of the reports should be shown including the archived rooms. - expect(results.recentReports.length).toBe(Object.values(REPORTS).length); + expect(results.recentReports.length).toBe(_.size(REPORTS)); // When we filter again but provide a searchValue results = OptionsListUtils.getSearchOptions(REPORTS, PERSONAL_DETAILS, 'spider'); @@ -386,7 +360,7 @@ describe('OptionsListUtils', () => { // We should expect all personalDetails to be returned, // minus the currently logged in user and recent reports count - expect(results.personalDetails.length).toBe(Object.values(PERSONAL_DETAILS).length - 1 - MAX_RECENT_REPORTS); + expect(results.personalDetails.length).toBe(_.size(PERSONAL_DETAILS) - 1 - MAX_RECENT_REPORTS); // We should expect personal details sorted alphabetically expect(results.personalDetails[0].text).toBe('Black Widow'); @@ -395,11 +369,11 @@ describe('OptionsListUtils', () => { expect(results.personalDetails[3].text).toBe('The Incredible Hulk'); // Then the result which has an existing report should also have the reportID attached - const personalDetailWithExistingReport = results.personalDetails.find((personalDetail) => personalDetail.login === 'peterparker@expensify.com'); - expect(personalDetailWithExistingReport?.reportID).toBe('2'); + const personalDetailWithExistingReport = _.find(results.personalDetails, (personalDetail) => personalDetail.login === 'peterparker@expensify.com'); + expect(personalDetailWithExistingReport.reportID).toBe(2); // When we only pass personal details - results = OptionsListUtils.getFilteredOptions({}, PERSONAL_DETAILS, [], ''); + results = OptionsListUtils.getFilteredOptions([], PERSONAL_DETAILS, [], ''); // We should expect personal details sorted alphabetically expect(results.personalDetails[0].text).toBe('Black Panther'); @@ -440,28 +414,28 @@ describe('OptionsListUtils', () => { // Concierge is included in the results by default. We should expect all the personalDetails to show // (minus the 5 that are already showing and the currently logged in user) - expect(results.personalDetails.length).toBe(Object.values(PERSONAL_DETAILS_WITH_CONCIERGE).length - 1 - MAX_RECENT_REPORTS); + expect(results.personalDetails.length).toBe(_.size(PERSONAL_DETAILS_WITH_CONCIERGE) - 1 - MAX_RECENT_REPORTS); expect(results.recentReports).toEqual(expect.arrayContaining([expect.objectContaining({login: 'concierge@expensify.com'})])); // Test by excluding Concierge from the results results = OptionsListUtils.getFilteredOptions(REPORTS_WITH_CONCIERGE, PERSONAL_DETAILS_WITH_CONCIERGE, [], '', [], [CONST.EMAIL.CONCIERGE]); // All the personalDetails should be returned minus the currently logged in user and Concierge - expect(results.personalDetails.length).toBe(Object.values(PERSONAL_DETAILS_WITH_CONCIERGE).length - 2 - MAX_RECENT_REPORTS); + expect(results.personalDetails.length).toBe(_.size(PERSONAL_DETAILS_WITH_CONCIERGE) - 2 - MAX_RECENT_REPORTS); expect(results.personalDetails).not.toEqual(expect.arrayContaining([expect.objectContaining({login: 'concierge@expensify.com'})])); // Test by excluding Chronos from the results results = OptionsListUtils.getFilteredOptions(REPORTS_WITH_CHRONOS, PERSONAL_DETAILS_WITH_CHRONOS, [], '', [], [CONST.EMAIL.CHRONOS]); // All the personalDetails should be returned minus the currently logged in user and Concierge - expect(results.personalDetails.length).toBe(Object.values(PERSONAL_DETAILS_WITH_CHRONOS).length - 2 - MAX_RECENT_REPORTS); + expect(results.personalDetails.length).toBe(_.size(PERSONAL_DETAILS_WITH_CHRONOS) - 2 - MAX_RECENT_REPORTS); expect(results.personalDetails).not.toEqual(expect.arrayContaining([expect.objectContaining({login: 'chronos@expensify.com'})])); // Test by excluding Receipts from the results results = OptionsListUtils.getFilteredOptions(REPORTS_WITH_RECEIPTS, PERSONAL_DETAILS_WITH_RECEIPTS, [], '', [], [CONST.EMAIL.RECEIPTS]); // All the personalDetails should be returned minus the currently logged in user and Concierge - expect(results.personalDetails.length).toBe(Object.values(PERSONAL_DETAILS_WITH_RECEIPTS).length - 2 - MAX_RECENT_REPORTS); + expect(results.personalDetails.length).toBe(_.size(PERSONAL_DETAILS_WITH_RECEIPTS) - 2 - MAX_RECENT_REPORTS); expect(results.personalDetails).not.toEqual(expect.arrayContaining([expect.objectContaining({login: 'receipts@expensify.com'})])); }); @@ -474,7 +448,7 @@ describe('OptionsListUtils', () => { // And we should expect all the personalDetails to show (minus the 5 that are already // showing and the currently logged in user) - expect(results.personalDetails.length).toBe(Object.values(PERSONAL_DETAILS).length - 6); + expect(results.personalDetails.length).toBe(_.size(PERSONAL_DETAILS) - 6); // We should expect personal details sorted alphabetically expect(results.personalDetails[0].text).toBe('Black Widow'); @@ -483,8 +457,8 @@ describe('OptionsListUtils', () => { expect(results.personalDetails[3].text).toBe('The Incredible Hulk'); // And none of our personalDetails should include any of the users with recent reports - const reportLogins = results.recentReports.map((reportOption) => reportOption.login); - const personalDetailsOverlapWithReports = results.personalDetails.every((personalDetailOption) => reportLogins.includes(personalDetailOption.login)); + const reportLogins = _.map(results.recentReports, (reportOption) => reportOption.login); + const personalDetailsOverlapWithReports = _.every(results.personalDetails, (personalDetailOption) => _.contains(reportLogins, personalDetailOption.login)); expect(personalDetailsOverlapWithReports).toBe(false); // When we search for an option that is only in a personalDetail with no existing report @@ -513,15 +487,15 @@ describe('OptionsListUtils', () => { // Then one of our older report options (not in our five most recent) should appear in the personalDetails // but not in recentReports - expect(results.recentReports.every((option) => option.login !== 'peterparker@expensify.com')).toBe(true); - expect(results.personalDetails.every((option) => option.login !== 'peterparker@expensify.com')).toBe(false); + expect(_.every(results.recentReports, (option) => option.login !== 'peterparker@expensify.com')).toBe(true); + expect(_.every(results.personalDetails, (option) => option.login !== 'peterparker@expensify.com')).toBe(false); // When we provide a "selected" option to getFilteredOptions() results = OptionsListUtils.getFilteredOptions(REPORTS, PERSONAL_DETAILS, [], '', [{login: 'peterparker@expensify.com'}]); // Then the option should not appear anywhere in either list - expect(results.recentReports.every((option) => option.login !== 'peterparker@expensify.com')).toBe(true); - expect(results.personalDetails.every((option) => option.login !== 'peterparker@expensify.com')).toBe(true); + expect(_.every(results.recentReports, (option) => option.login !== 'peterparker@expensify.com')).toBe(true); + expect(_.every(results.personalDetails, (option) => option.login !== 'peterparker@expensify.com')).toBe(true); // When we add a search term for which no options exist and the searchValue itself // is not a potential email or phone @@ -557,7 +531,7 @@ describe('OptionsListUtils', () => { expect(results.recentReports.length).toBe(0); expect(results.personalDetails.length).toBe(0); expect(results.userToInvite).not.toBe(null); - expect(results.userToInvite?.login).toBe('+15005550006'); + expect(results.userToInvite.login).toBe('+15005550006'); // When we add a search term for which no options exist and the searchValue itself // is a potential phone number with country code added @@ -568,7 +542,7 @@ describe('OptionsListUtils', () => { expect(results.recentReports.length).toBe(0); expect(results.personalDetails.length).toBe(0); expect(results.userToInvite).not.toBe(null); - expect(results.userToInvite?.login).toBe('+15005550006'); + expect(results.userToInvite.login).toBe('+15005550006'); // When we add a search term for which no options exist and the searchValue itself // is a potential phone number with special characters added @@ -579,7 +553,7 @@ describe('OptionsListUtils', () => { expect(results.recentReports.length).toBe(0); expect(results.personalDetails.length).toBe(0); expect(results.userToInvite).not.toBe(null); - expect(results.userToInvite?.login).toBe('+18003243233'); + expect(results.userToInvite.login).toBe('+18003243233'); // When we use a search term for contact number that contains alphabet characters results = OptionsListUtils.getFilteredOptions(REPORTS, PERSONAL_DETAILS, [], '998243aaaa'); @@ -594,7 +568,7 @@ describe('OptionsListUtils', () => { // Concierge is included in the results by default. We should expect all the personalDetails to show // (minus the 5 that are already showing and the currently logged in user) - expect(results.personalDetails.length).toBe(Object.values(PERSONAL_DETAILS_WITH_CONCIERGE).length - 6); + expect(results.personalDetails.length).toBe(_.size(PERSONAL_DETAILS_WITH_CONCIERGE) - 6); expect(results.recentReports).toEqual(expect.arrayContaining([expect.objectContaining({login: 'concierge@expensify.com'})])); // Test by excluding Concierge from the results @@ -602,7 +576,7 @@ describe('OptionsListUtils', () => { // We should expect all the personalDetails to show (minus the 5 that are already showing, // the currently logged in user and Concierge) - expect(results.personalDetails.length).toBe(Object.values(PERSONAL_DETAILS_WITH_CONCIERGE).length - 7); + expect(results.personalDetails.length).toBe(_.size(PERSONAL_DETAILS_WITH_CONCIERGE) - 7); expect(results.personalDetails).not.toEqual(expect.arrayContaining([expect.objectContaining({login: 'concierge@expensify.com'})])); expect(results.recentReports).not.toEqual(expect.arrayContaining([expect.objectContaining({login: 'concierge@expensify.com'})])); @@ -611,7 +585,7 @@ describe('OptionsListUtils', () => { // We should expect all the personalDetails to show (minus the 5 that are already showing, // the currently logged in user and Concierge) - expect(results.personalDetails.length).toBe(Object.values(PERSONAL_DETAILS_WITH_CHRONOS).length - 7); + expect(results.personalDetails.length).toBe(_.size(PERSONAL_DETAILS_WITH_CHRONOS) - 7); expect(results.personalDetails).not.toEqual(expect.arrayContaining([expect.objectContaining({login: 'chronos@expensify.com'})])); expect(results.recentReports).not.toEqual(expect.arrayContaining([expect.objectContaining({login: 'chronos@expensify.com'})])); @@ -620,27 +594,26 @@ describe('OptionsListUtils', () => { // We should expect all the personalDetails to show (minus the 5 that are already showing, // the currently logged in user and Concierge) - expect(results.personalDetails.length).toBe(Object.values(PERSONAL_DETAILS_WITH_RECEIPTS).length - 7); + expect(results.personalDetails.length).toBe(_.size(PERSONAL_DETAILS_WITH_RECEIPTS) - 7); expect(results.personalDetails).not.toEqual(expect.arrayContaining([expect.objectContaining({login: 'receipts@expensify.com'})])); expect(results.recentReports).not.toEqual(expect.arrayContaining([expect.objectContaining({login: 'receipts@expensify.com'})])); }); it('getShareDestinationsOptions()', () => { // Filter current REPORTS as we do in the component, before getting share destination options - const filteredReports = Object.entries(REPORTS).reduce>>((reports, [reportKey, report]) => { - if (!ReportUtils.canUserPerformWriteAction(report) || ReportUtils.isExpensifyOnlyParticipantInReport(report)) { - return reports; + const filteredReports = {}; + _.keys(REPORTS).forEach((reportKey) => { + if (!ReportUtils.canUserPerformWriteAction(REPORTS[reportKey]) || ReportUtils.isExpensifyOnlyParticipantInReport(REPORTS[reportKey])) { + return; } - // eslint-disable-next-line no-param-reassign - reports[reportKey] = report; - return reports; - }, {}); + filteredReports[reportKey] = REPORTS[reportKey]; + }); // When we pass an empty search value let results = OptionsListUtils.getShareDestinationOptions(filteredReports, PERSONAL_DETAILS, [], ''); // Then we should expect all the recent reports to show but exclude the archived rooms - expect(results.recentReports.length).toBe(Object.values(REPORTS).length - 1); + expect(results.recentReports.length).toBe(_.size(REPORTS) - 1); // When we pass a search value that doesn't match the group chat name results = OptionsListUtils.getShareDestinationOptions(filteredReports, PERSONAL_DETAILS, [], 'mutants'); @@ -655,19 +628,20 @@ describe('OptionsListUtils', () => { expect(results.recentReports.length).toBe(1); // Filter current REPORTS_WITH_WORKSPACE_ROOMS as we do in the component, before getting share destination options - const filteredReportsWithWorkspaceRooms = Object.entries(REPORTS_WITH_WORKSPACE_ROOMS).reduce>>((reports, [reportKey, report]) => { - if (!ReportUtils.canUserPerformWriteAction(report) || ReportUtils.isExpensifyOnlyParticipantInReport(report)) { - return reports; + const filteredReportsWithWorkspaceRooms = {}; + _.keys(REPORTS_WITH_WORKSPACE_ROOMS).forEach((reportKey) => { + if (!ReportUtils.canUserPerformWriteAction(REPORTS_WITH_WORKSPACE_ROOMS[reportKey]) || ReportUtils.isExpensifyOnlyParticipantInReport(REPORTS_WITH_WORKSPACE_ROOMS[reportKey])) { + return; } - return {...reports, [reportKey]: report}; - }, {}); + filteredReportsWithWorkspaceRooms[reportKey] = REPORTS_WITH_WORKSPACE_ROOMS[reportKey]; + }); // When we also have a policy to return rooms in the results results = OptionsListUtils.getShareDestinationOptions(filteredReportsWithWorkspaceRooms, PERSONAL_DETAILS, [], ''); // Then we should expect the DMS, the group chats and the workspace room to show // We should expect all the recent reports to show, excluding the archived rooms - expect(results.recentReports.length).toBe(Object.values(REPORTS_WITH_WORKSPACE_ROOMS).length - 1); + expect(results.recentReports.length).toBe(_.size(REPORTS_WITH_WORKSPACE_ROOMS) - 1); // When we search for a workspace room results = OptionsListUtils.getShareDestinationOptions(filteredReportsWithWorkspaceRooms, PERSONAL_DETAILS, [], 'Avengers Room'); @@ -711,51 +685,31 @@ describe('OptionsListUtils', () => { const emptySearch = ''; const wrongSearch = 'bla bla'; const recentlyUsedCategories = ['Taxi', 'Restaurant']; - const selectedOptions: Array> = [ + const selectedOptions = [ { name: 'Medical', enabled: true, }, ]; - const smallCategoriesList: PolicyCategories = { + const smallCategoriesList = { Taxi: { enabled: false, name: 'Taxi', - unencodedName: 'Taxi', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, Restaurant: { enabled: true, name: 'Restaurant', - unencodedName: 'Restaurant', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, Food: { enabled: true, name: 'Food', - unencodedName: 'Food', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, 'Food: Meat': { enabled: true, name: 'Food: Meat', - unencodedName: 'Food: Meat', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, }; - const smallResultList: OptionsListUtils.CategoryTreeSection[] = [ + const smallResultList = [ { title: '', shouldShow: false, @@ -788,7 +742,7 @@ describe('OptionsListUtils', () => { ], }, ]; - const smallSearchResultList: OptionsListUtils.CategoryTreeSection[] = [ + const smallSearchResultList = [ { title: '', shouldShow: true, @@ -813,7 +767,7 @@ describe('OptionsListUtils', () => { ], }, ]; - const smallWrongSearchResultList: OptionsListUtils.CategoryTreeSection[] = [ + const smallWrongSearchResultList = [ { title: '', shouldShow: true, @@ -821,135 +775,65 @@ describe('OptionsListUtils', () => { data: [], }, ]; - const largeCategoriesList: PolicyCategories = { + const largeCategoriesList = { Taxi: { enabled: false, name: 'Taxi', - unencodedName: 'Taxi', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, Restaurant: { enabled: true, name: 'Restaurant', - unencodedName: 'Restaurant', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, Food: { enabled: true, name: 'Food', - unencodedName: 'Food', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, 'Food: Meat': { enabled: true, name: 'Food: Meat', - unencodedName: 'Food: Meat', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, 'Food: Milk': { enabled: true, name: 'Food: Milk', - unencodedName: 'Food: Milk', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, 'Food: Vegetables': { enabled: false, name: 'Food: Vegetables', - unencodedName: 'Food: Vegetables', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, 'Cars: Audi': { enabled: true, name: 'Cars: Audi', - unencodedName: 'Cars: Audi', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, 'Cars: BMW': { enabled: false, name: 'Cars: BMW', - unencodedName: 'Cars: BMW', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, 'Cars: Mercedes-Benz': { enabled: true, name: 'Cars: Mercedes-Benz', - unencodedName: 'Cars: Mercedes-Benz', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, Medical: { enabled: false, name: 'Medical', - unencodedName: 'Medical', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, 'Travel: Meals': { enabled: true, name: 'Travel: Meals', - unencodedName: 'Travel: Meals', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, 'Travel: Meals: Breakfast': { enabled: true, name: 'Travel: Meals: Breakfast', - unencodedName: 'Travel: Meals: Breakfast', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, 'Travel: Meals: Dinner': { enabled: false, name: 'Travel: Meals: Dinner', - unencodedName: 'Travel: Meals: Dinner', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, 'Travel: Meals: Lunch': { enabled: true, name: 'Travel: Meals: Lunch', - unencodedName: 'Travel: Meals: Lunch', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', }, }; - const largeResultList: OptionsListUtils.CategoryTreeSection[] = [ + const largeResultList = [ { title: '', shouldShow: false, @@ -1076,7 +960,7 @@ describe('OptionsListUtils', () => { ], }, ]; - const largeSearchResultList: OptionsListUtils.CategoryTreeSection[] = [ + const largeSearchResultList = [ { title: '', shouldShow: true, @@ -1109,7 +993,7 @@ describe('OptionsListUtils', () => { ], }, ]; - const largeWrongSearchResultList: OptionsListUtils.CategoryTreeSection[] = [ + const largeWrongSearchResultList = [ { title: '', shouldShow: true, @@ -1118,7 +1002,7 @@ describe('OptionsListUtils', () => { }, ]; const emptyCategoriesList = {}; - const emptySelectedResultList: OptionsListUtils.CategoryTreeSection[] = [ + const emptySelectedResultList = [ { title: '', shouldShow: false, @@ -1205,29 +1089,25 @@ describe('OptionsListUtils', () => { name: 'Medical', }, ]; - const smallTagsList: Record = { + const smallTagsList = { Engineering: { enabled: false, name: 'Engineering', - accountID: null, }, Medical: { enabled: true, name: 'Medical', - accountID: null, }, Accounting: { enabled: true, name: 'Accounting', - accountID: null, }, HR: { enabled: true, name: 'HR', - accountID: null, }, }; - const smallResultList: OptionsListUtils.CategorySection[] = [ + const smallResultList = [ { title: '', shouldShow: false, @@ -1258,7 +1138,7 @@ describe('OptionsListUtils', () => { ], }, ]; - const smallSearchResultList: OptionsListUtils.CategorySection[] = [ + const smallSearchResultList = [ { title: '', shouldShow: true, @@ -1274,7 +1154,7 @@ describe('OptionsListUtils', () => { ], }, ]; - const smallWrongSearchResultList: OptionsListUtils.CategoryTreeSection[] = [ + const smallWrongSearchResultList = [ { title: '', shouldShow: true, @@ -1282,64 +1162,53 @@ describe('OptionsListUtils', () => { data: [], }, ]; - const largeTagsList: Record = { + const largeTagsList = { Engineering: { enabled: false, name: 'Engineering', - accountID: null, }, Medical: { enabled: true, name: 'Medical', - accountID: null, }, Accounting: { enabled: true, name: 'Accounting', - accountID: null, }, HR: { enabled: true, name: 'HR', - accountID: null, }, Food: { enabled: true, name: 'Food', - accountID: null, }, Traveling: { enabled: false, name: 'Traveling', - accountID: null, }, Cleaning: { enabled: true, name: 'Cleaning', - accountID: null, }, Software: { enabled: true, name: 'Software', - accountID: null, }, OfficeSupplies: { enabled: false, name: 'Office Supplies', - accountID: null, }, Taxes: { enabled: true, name: 'Taxes', - accountID: null, }, Benefits: { enabled: true, name: 'Benefits', - accountID: null, }, }; - const largeResultList: OptionsListUtils.CategorySection[] = [ + const largeResultList = [ { title: '', shouldShow: true, @@ -1426,7 +1295,7 @@ describe('OptionsListUtils', () => { ], }, ]; - const largeSearchResultList: OptionsListUtils.CategorySection[] = [ + const largeSearchResultList = [ { title: '', shouldShow: true, @@ -1449,7 +1318,7 @@ describe('OptionsListUtils', () => { ], }, ]; - const largeWrongSearchResultList: OptionsListUtils.CategoryTreeSection[] = [ + const largeWrongSearchResultList = [ { title: '', shouldShow: true, @@ -2194,7 +2063,7 @@ describe('OptionsListUtils', () => { const emptySearch = ''; const wrongSearch = 'bla bla'; - const taxRatesWithDefault: TaxRatesWithDefault = { + const taxRatesWithDefault = { name: 'Tax', defaultExternalID: 'CODE1', defaultValue: '0%', @@ -2203,25 +2072,19 @@ describe('OptionsListUtils', () => { CODE2: { name: 'Tax rate 2', value: '3%', - code: 'CODE2', - modifiedName: 'Tax rate 2 (3%)', }, CODE3: { name: 'Tax option 3', value: '5%', - code: 'CODE3', - modifiedName: 'Tax option 3 (5%)', }, CODE1: { name: 'Tax exempt 1', value: '0%', - code: 'CODE1', - modifiedName: 'Tax exempt 1 (0%) • Default', }, }, }; - const resultList: OptionsListUtils.CategorySection[] = [ + const resultList = [ { title: '', shouldShow: false, @@ -2274,7 +2137,7 @@ describe('OptionsListUtils', () => { }, ]; - const searchResultList: OptionsListUtils.CategorySection[] = [ + const searchResultList = [ { title: '', shouldShow: true, @@ -2298,7 +2161,7 @@ describe('OptionsListUtils', () => { }, ]; - const wrongSearchResultList: OptionsListUtils.CategorySection[] = [ + const wrongSearchResultList = [ { title: '', shouldShow: true, @@ -2319,7 +2182,7 @@ describe('OptionsListUtils', () => { }); it('formatMemberForList()', () => { - const formattedMembers = Object.values(PERSONAL_DETAILS).map((personalDetail) => OptionsListUtils.formatMemberForList(personalDetail)); + const formattedMembers = _.map(PERSONAL_DETAILS, (personalDetail) => OptionsListUtils.formatMemberForList(personalDetail)); // We're only formatting items inside the array, so the order should be the same as the original PERSONAL_DETAILS array expect(formattedMembers[0].text).toBe('Mister Fantastic'); @@ -2330,9 +2193,9 @@ describe('OptionsListUtils', () => { expect(formattedMembers[0].isSelected).toBe(true); // And all the others to be unselected - expect(formattedMembers.slice(1).every((personalDetail) => !personalDetail.isSelected)).toBe(true); + expect(_.every(formattedMembers.slice(1), (personalDetail) => !personalDetail.isSelected)).toBe(true); // `isDisabled` is always false - expect(formattedMembers.every((personalDetail) => !personalDetail.isDisabled)).toBe(true); + expect(_.every(formattedMembers, (personalDetail) => !personalDetail.isDisabled)).toBe(true); }); }); diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.js similarity index 84% rename from tests/unit/ReportUtilsTest.ts rename to tests/unit/ReportUtilsTest.js index 6c76d0bd2eee..7b563d46b7eb 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.js @@ -1,45 +1,42 @@ -/* eslint-disable @typescript-eslint/naming-convention */ -import type {OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; -import * as ReportUtils from '@libs/ReportUtils'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import type {PersonalDetailsList, Policy, Report, ReportAction} from '@src/types/onyx'; -import {toCollectionDataSet} from '@src/types/utils/CollectionDataSet'; +import _ from 'underscore'; +import CONST from '../../src/CONST'; import * as NumberUtils from '../../src/libs/NumberUtils'; +import * as ReportUtils from '../../src/libs/ReportUtils'; +import ONYXKEYS from '../../src/ONYXKEYS'; import * as LHNTestUtils from '../utils/LHNTestUtils'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; // Be sure to include the mocked permissions library or else the beta tests won't work -jest.mock('@libs/Permissions'); +jest.mock('../../src/libs/Permissions'); const currentUserEmail = 'bjorn@vikings.net'; const currentUserAccountID = 5; -const participantsPersonalDetails: PersonalDetailsList = { - '1': { +const participantsPersonalDetails = { + 1: { accountID: 1, displayName: 'Ragnar Lothbrok', firstName: 'Ragnar', login: 'ragnar@vikings.net', }, - '2': { + 2: { accountID: 2, login: 'floki@vikings.net', displayName: 'floki@vikings.net', }, - '3': { + 3: { accountID: 3, displayName: 'Lagertha Lothbrok', firstName: 'Lagertha', login: 'lagertha@vikings.net', pronouns: 'She/her', }, - '4': { + 4: { accountID: 4, login: '+18332403627@expensify.sms', displayName: '(833) 240-3627', }, - '5': { + 5: { accountID: 5, displayName: 'Lagertha Lothbrok', firstName: 'Lagertha', @@ -47,27 +44,20 @@ const participantsPersonalDetails: PersonalDetailsList = { pronouns: 'She/her', }, }; - -const policy: Policy = { - id: '1', +const policy = { + policyID: 1, name: 'Vikings Policy', - role: 'user', - type: 'free', - owner: '', - outputCurrency: '', - isPolicyExpenseChatEnabled: false, }; Onyx.init({keys: ONYXKEYS}); describe('ReportUtils', () => { beforeAll(() => { - const policyCollectionDataSet = toCollectionDataSet(ONYXKEYS.COLLECTION.POLICY, [policy], (current) => current.id); Onyx.multiSet({ [ONYXKEYS.PERSONAL_DETAILS_LIST]: participantsPersonalDetails, [ONYXKEYS.SESSION]: {email: currentUserEmail, accountID: currentUserAccountID}, [ONYXKEYS.COUNTRY_CODE]: 1, - ...policyCollectionDataSet, + [`${ONYXKEYS.COLLECTION.POLICY}${policy.policyID}`]: policy, }); return waitForBatchedUpdates(); }); @@ -117,7 +107,6 @@ describe('ReportUtils', () => { test('with displayName', () => { expect( ReportUtils.getReportName({ - reportID: '', participantAccountIDs: [currentUserAccountID, 1], }), ).toBe('Ragnar Lothbrok'); @@ -126,7 +115,6 @@ describe('ReportUtils', () => { test('no displayName', () => { expect( ReportUtils.getReportName({ - reportID: '', participantAccountIDs: [currentUserAccountID, 2], }), ).toBe('floki@vikings.net'); @@ -135,7 +123,6 @@ describe('ReportUtils', () => { test('SMS', () => { expect( ReportUtils.getReportName({ - reportID: '', participantAccountIDs: [currentUserAccountID, 4], }), ).toBe('(833) 240-3627'); @@ -145,7 +132,6 @@ describe('ReportUtils', () => { test('Group DM', () => { expect( ReportUtils.getReportName({ - reportID: '', participantAccountIDs: [currentUserAccountID, 1, 2, 3, 4], }), ).toBe('Ragnar, floki@vikings.net, Lagertha, (833) 240-3627'); @@ -153,7 +139,6 @@ describe('ReportUtils', () => { describe('Default Policy Room', () => { const baseAdminsRoom = { - reportID: '', chatType: CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, reportName: '#admins', }; @@ -177,7 +162,6 @@ describe('ReportUtils', () => { describe('User-Created Policy Room', () => { const baseUserCreatedRoom = { - reportID: '', chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM, reportName: '#VikingsChat', }; @@ -204,9 +188,8 @@ describe('ReportUtils', () => { test('as member', () => { expect( ReportUtils.getReportName({ - reportID: '', chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, - policyID: policy.id, + policyID: policy.policyID, isOwnPolicyExpenseChat: true, ownerAccountID: 1, }), @@ -216,9 +199,8 @@ describe('ReportUtils', () => { test('as admin', () => { expect( ReportUtils.getReportName({ - reportID: '', chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, - policyID: policy.id, + policyID: policy.policyID, isOwnPolicyExpenseChat: false, ownerAccountID: 1, }), @@ -228,10 +210,9 @@ describe('ReportUtils', () => { describe('Archived', () => { const baseArchivedPolicyExpenseChat = { - reportID: '', chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, ownerAccountID: 1, - policyID: policy.id, + policyID: policy.policyID, oldPolicyName: policy.name, statusNum: CONST.REPORT.STATUS_NUM.CLOSED, stateNum: CONST.REPORT.STATE_NUM.APPROVED, @@ -268,7 +249,7 @@ describe('ReportUtils', () => { describe('requiresAttentionFromCurrentUser', () => { it('returns false when there is no report', () => { - expect(ReportUtils.requiresAttentionFromCurrentUser(null)).toBe(false); + expect(ReportUtils.requiresAttentionFromCurrentUser()).toBe(false); }); it('returns false when the matched IOU report does not have an owner accountID', () => { const report = { @@ -343,7 +324,7 @@ describe('ReportUtils', () => { }); describe('getMoneyRequestOptions', () => { - const participantsAccountIDs = Object.keys(participantsPersonalDetails).map(Number); + const participantsAccountIDs = _.keys(participantsPersonalDetails); beforeAll(() => { Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, { @@ -358,8 +339,8 @@ describe('ReportUtils', () => { describe('return empty iou options if', () => { it('participants aray contains excluded expensify iou emails', () => { - const allEmpty = CONST.EXPENSIFY_ACCOUNT_IDS.every((accountID) => { - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(null, null, [currentUserAccountID, accountID]); + const allEmpty = _.every(CONST.EXPENSIFY_ACCOUNT_IDS, (accountID) => { + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions({}, {}, [currentUserAccountID, accountID]); return moneyRequestOptions.length === 0; }); expect(allEmpty).toBe(true); @@ -370,7 +351,7 @@ describe('ReportUtils', () => { ...LHNTestUtils.getFakeReport(), chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM, }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID]); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID]); expect(moneyRequestOptions.length).toBe(0); }); @@ -380,7 +361,7 @@ describe('ReportUtils', () => { chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, isOwnPolicyExpenseChat: false, }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID]); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID]); expect(moneyRequestOptions.length).toBe(0); }); @@ -390,7 +371,7 @@ describe('ReportUtils', () => { type: CONST.REPORT.TYPE.IOU, statusNum: CONST.REPORT.STATUS_NUM.REIMBURSED, }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID]); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID]); expect(moneyRequestOptions.length).toBe(0); }); @@ -401,7 +382,7 @@ describe('ReportUtils', () => { stateNum: CONST.REPORT.STATE_NUM.APPROVED, statusNum: CONST.REPORT.STATUS_NUM.APPROVED, }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID]); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID]); expect(moneyRequestOptions.length).toBe(0); }); @@ -411,7 +392,7 @@ describe('ReportUtils', () => { type: CONST.REPORT.TYPE.EXPENSE, statusNum: CONST.REPORT.STATUS_NUM.REIMBURSED, }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID]); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID]); expect(moneyRequestOptions.length).toBe(0); }); @@ -425,20 +406,15 @@ describe('ReportUtils', () => { parentReportID: '100', type: CONST.REPORT.TYPE.EXPENSE, }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID]); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID]); expect(moneyRequestOptions.length).toBe(0); }); }); it("it is a submitted report tied to user's own policy expense chat and the policy does not have Instant Submit frequency", () => { - const paidPolicy: Policy = { + const paidPolicy = { id: '3f54cca8', type: CONST.POLICY.TYPE.TEAM, - name: '', - role: 'user', - owner: '', - outputCurrency: '', - isPolicyExpenseChatEnabled: false, }; Promise.all([ Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${paidPolicy.id}`, paidPolicy), @@ -464,19 +440,17 @@ describe('ReportUtils', () => { describe('return only iou split option if', () => { it('it is a chat room with more than one participant', () => { - const onlyHaveSplitOption = [ - CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, - CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE, - CONST.REPORT.CHAT_TYPE.DOMAIN_ALL, - CONST.REPORT.CHAT_TYPE.POLICY_ROOM, - ].every((chatType) => { - const report = { - ...LHNTestUtils.getFakeReport(), - chatType, - }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID, participantsAccountIDs[0]]); - return moneyRequestOptions.length === 1 && moneyRequestOptions.includes(CONST.IOU.TYPE.SPLIT); - }); + const onlyHaveSplitOption = _.every( + [CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE, CONST.REPORT.CHAT_TYPE.DOMAIN_ALL, CONST.REPORT.CHAT_TYPE.POLICY_ROOM], + (chatType) => { + const report = { + ...LHNTestUtils.getFakeReport(), + chatType, + }; + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID, participantsAccountIDs[0]]); + return moneyRequestOptions.length === 1 && moneyRequestOptions.includes(CONST.IOU.TYPE.SPLIT); + }, + ); expect(onlyHaveSplitOption).toBe(true); }); @@ -485,7 +459,7 @@ describe('ReportUtils', () => { ...LHNTestUtils.getFakeReport(), chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM, }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID, ...participantsAccountIDs]); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID, ...participantsAccountIDs]); expect(moneyRequestOptions.length).toBe(1); expect(moneyRequestOptions.includes(CONST.IOU.TYPE.SPLIT)).toBe(true); }); @@ -495,7 +469,7 @@ describe('ReportUtils', () => { ...LHNTestUtils.getFakeReport(), chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM, }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID, ...participantsAccountIDs]); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID, ...participantsAccountIDs]); expect(moneyRequestOptions.length).toBe(1); expect(moneyRequestOptions.includes(CONST.IOU.TYPE.SPLIT)).toBe(true); }); @@ -506,7 +480,7 @@ describe('ReportUtils', () => { type: CONST.REPORT.TYPE.CHAT, participantsAccountIDs: [currentUserAccountID, ...participantsAccountIDs], }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID, ...participantsAccountIDs.map(Number)]); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID, ...participantsAccountIDs]); expect(moneyRequestOptions.length).toBe(1); expect(moneyRequestOptions.includes(CONST.IOU.TYPE.SPLIT)).toBe(true); }); @@ -524,7 +498,7 @@ describe('ReportUtils', () => { parentReportID: '102', type: CONST.REPORT.TYPE.EXPENSE, }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID]); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID]); expect(moneyRequestOptions.length).toBe(1); expect(moneyRequestOptions.includes(CONST.IOU.TYPE.REQUEST)).toBe(true); }); @@ -545,14 +519,8 @@ describe('ReportUtils', () => { }; const paidPolicy = { type: CONST.POLICY.TYPE.TEAM, - id: '', - name: '', - role: 'user', - owner: '', - outputCurrency: '', - isPolicyExpenseChatEnabled: false, - } as const; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, paidPolicy, [currentUserAccountID, participantsAccountIDs[0]]); + }; + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, paidPolicy, [currentUserAccountID, participantsAccountIDs[0]], true); expect(moneyRequestOptions.length).toBe(1); }); }); @@ -564,7 +532,7 @@ describe('ReportUtils', () => { stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID, participantsAccountIDs[0]]); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID, participantsAccountIDs[0]]); expect(moneyRequestOptions.length).toBe(1); expect(moneyRequestOptions.includes(CONST.IOU.TYPE.REQUEST)).toBe(true); }); @@ -576,22 +544,17 @@ describe('ReportUtils', () => { stateNum: CONST.REPORT.STATE_NUM.SUBMITTED, statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID, participantsAccountIDs[0]]); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID, participantsAccountIDs[0]]); expect(moneyRequestOptions.length).toBe(1); expect(moneyRequestOptions.includes(CONST.IOU.TYPE.REQUEST)).toBe(true); }); it("it is a submitted expense report in user's own policyExpenseChat and the policy has Instant Submit frequency", () => { - const paidPolicy: Policy = { + const paidPolicy = { id: 'ef72dfeb', type: CONST.POLICY.TYPE.TEAM, autoReporting: true, autoReportingFrequency: CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT, - name: '', - role: 'user', - owner: '', - outputCurrency: '', - isPolicyExpenseChatEnabled: false, }; Promise.all([ Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${paidPolicy.id}`, paidPolicy), @@ -622,7 +585,7 @@ describe('ReportUtils', () => { chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, isOwnPolicyExpenseChat: true, }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID, ...participantsAccountIDs]); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID, ...participantsAccountIDs]); expect(moneyRequestOptions.length).toBe(2); expect(moneyRequestOptions.includes(CONST.IOU.TYPE.REQUEST)).toBe(true); expect(moneyRequestOptions.includes(CONST.IOU.TYPE.SPLIT)).toBe(true); @@ -633,7 +596,7 @@ describe('ReportUtils', () => { ...LHNTestUtils.getFakeReport(), type: CONST.REPORT.TYPE.CHAT, }; - const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, null, [currentUserAccountID, participantsAccountIDs[0]]); + const moneyRequestOptions = ReportUtils.getMoneyRequestOptions(report, {}, [currentUserAccountID, participantsAccountIDs[0]]); expect(moneyRequestOptions.length).toBe(2); expect(moneyRequestOptions.includes(CONST.IOU.TYPE.REQUEST)).toBe(true); expect(moneyRequestOptions.includes(CONST.IOU.TYPE.SEND)).toBe(true); @@ -659,21 +622,21 @@ describe('ReportUtils', () => { describe('sortReportsByLastRead', () => { it('should filter out report without reportID & lastReadTime and sort lastReadTime in ascending order', () => { - const reports: Array> = [ - {reportID: '1', lastReadTime: '2023-07-08 07:15:44.030'}, - {reportID: '2', lastReadTime: undefined}, - {reportID: '3', lastReadTime: '2023-07-06 07:15:44.030'}, - {reportID: '4', lastReadTime: '2023-07-07 07:15:44.030', type: CONST.REPORT.TYPE.IOU}, - {lastReadTime: '2023-07-09 07:15:44.030'} as Report, - {reportID: '6'}, - null, + const reports = [ + {reportID: 1, lastReadTime: '2023-07-08 07:15:44.030'}, + {reportID: 2, lastReadTime: null}, + {reportID: 3, lastReadTime: '2023-07-06 07:15:44.030'}, + {reportID: 4, lastReadTime: '2023-07-07 07:15:44.030', type: CONST.REPORT.TYPE.IOU}, + {lastReadTime: '2023-07-09 07:15:44.030'}, + {reportID: 6}, + {}, ]; - const sortedReports: Array> = [ - {reportID: '3', lastReadTime: '2023-07-06 07:15:44.030'}, - {reportID: '4', lastReadTime: '2023-07-07 07:15:44.030', type: CONST.REPORT.TYPE.IOU}, - {reportID: '1', lastReadTime: '2023-07-08 07:15:44.030'}, + const sortedReports = [ + {reportID: 3, lastReadTime: '2023-07-06 07:15:44.030'}, + {reportID: 4, lastReadTime: '2023-07-07 07:15:44.030', type: CONST.REPORT.TYPE.IOU}, + {reportID: 1, lastReadTime: '2023-07-08 07:15:44.030'}, ]; - expect(ReportUtils.sortReportsByLastRead(reports, null)).toEqual(sortedReports); + expect(ReportUtils.sortReportsByLastRead(reports)).toEqual(sortedReports); }); }); @@ -693,7 +656,7 @@ describe('ReportUtils', () => { '', [{login: 'email1@test.com'}, {login: 'email2@test.com'}], NumberUtils.rand64(), - ) as ReportAction; + ); expect(ReportUtils.shouldDisableThread(reportAction, reportID)).toBeTruthy(); }); @@ -709,7 +672,7 @@ describe('ReportUtils', () => { }, ], childVisibleActionCount: 1, - } as ReportAction; + }; expect(ReportUtils.shouldDisableThread(reportAction, reportID)).toBeFalsy(); reportAction.childVisibleActionCount = 0; @@ -725,7 +688,7 @@ describe('ReportUtils', () => { .then(() => { const reportAction = { childVisibleActionCount: 1, - } as ReportAction; + }; expect(ReportUtils.shouldDisableThread(reportAction, reportID)).toBeFalsy(); reportAction.childVisibleActionCount = 0; @@ -737,20 +700,20 @@ describe('ReportUtils', () => { const reportAction = { actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIEDEXPENSE, whisperedToAccountIDs: [123456], - } as ReportAction; + }; expect(ReportUtils.shouldDisableThread(reportAction, reportID)).toBeTruthy(); }); it('should disable on thread first chat', () => { const reportAction = { childReportID: reportID, - } as ReportAction; + }; expect(ReportUtils.shouldDisableThread(reportAction, reportID)).toBeTruthy(); }); }); describe('getAllAncestorReportActions', () => { - const reports: Report[] = [ + const reports = [ {reportID: '1', lastReadTime: '2024-02-01 04:56:47.233', reportName: 'Report'}, {reportID: '2', lastReadTime: '2024-02-01 04:56:47.233', parentReportActionID: '1', parentReportID: '1', reportName: 'Report'}, {reportID: '3', lastReadTime: '2024-02-01 04:56:47.233', parentReportActionID: '2', parentReportID: '2', reportName: 'Report'}, @@ -758,23 +721,24 @@ describe('ReportUtils', () => { {reportID: '5', lastReadTime: '2024-02-01 04:56:47.233', parentReportActionID: '4', parentReportID: '4', reportName: 'Report'}, ]; - const reportActions: ReportAction[] = [ - {reportActionID: '1', created: '2024-02-01 04:42:22.965', actionName: 'MARKEDREIMBURSED'}, - {reportActionID: '2', created: '2024-02-01 04:42:28.003', actionName: 'MARKEDREIMBURSED'}, - {reportActionID: '3', created: '2024-02-01 04:42:31.742', actionName: 'MARKEDREIMBURSED'}, - {reportActionID: '4', created: '2024-02-01 04:42:35.619', actionName: 'MARKEDREIMBURSED'}, + const reportActions = [ + {reportActionID: '1', created: '2024-02-01 04:42:22.965'}, + {reportActionID: '2', created: '2024-02-01 04:42:28.003'}, + {reportActionID: '3', created: '2024-02-01 04:42:31.742'}, + {reportActionID: '4', created: '2024-02-01 04:42:35.619'}, ]; beforeAll(() => { - const reportCollectionDataSet = toCollectionDataSet(ONYXKEYS.COLLECTION.REPORT, reports, (report) => report.reportID); - const reportActionCollectionDataSet = toCollectionDataSet( - ONYXKEYS.COLLECTION.REPORT_ACTIONS, - reportActions.map((reportAction) => ({[reportAction.reportActionID]: reportAction})), - (actions) => Object.values(actions)[0].reportActionID, - ); Onyx.multiSet({ - ...reportCollectionDataSet, - ...reportActionCollectionDataSet, + [`${ONYXKEYS.COLLECTION.REPORT}${reports[0].reportID}`]: reports[0], + [`${ONYXKEYS.COLLECTION.REPORT}${reports[1].reportID}`]: reports[1], + [`${ONYXKEYS.COLLECTION.REPORT}${reports[2].reportID}`]: reports[2], + [`${ONYXKEYS.COLLECTION.REPORT}${reports[3].reportID}`]: reports[3], + [`${ONYXKEYS.COLLECTION.REPORT}${reports[4].reportID}`]: reports[4], + [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reports[0].reportID}`]: {[reportActions[0].reportActionID]: reportActions[0]}, + [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reports[1].reportID}`]: {[reportActions[1].reportActionID]: reportActions[1]}, + [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reports[2].reportID}`]: {[reportActions[2].reportActionID]: reportActions[2]}, + [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reports[3].reportID}`]: {[reportActions[3].reportActionID]: reportActions[3]}, }); return waitForBatchedUpdates(); });