Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions src/libs/OptionsListUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ function getLastMessageTextForReport({
}
}
} else if (isMoneyRequestAction(lastReportAction)) {
const properSchemaForMoneyRequestMessage = getReportPreviewMessage({
const properSchemaForMoneyRequestMessage = getReportPreviewMessage(translate, {
reportOrID: report,
iouReportAction: lastReportAction,
shouldConsiderScanningReceiptOrPendingRoute: true,
Expand All @@ -799,7 +799,7 @@ function getLastMessageTextForReport({
const reportName = reportAttributesDerived?.[iouReport.reportID]?.reportName ?? '';
lastMessageTextFromReport = formatReportLastMessageText(reportName);
} else {
const reportPreviewMessage = getReportPreviewMessage({
const reportPreviewMessage = getReportPreviewMessage(translate, {
reportOrID: !isEmptyObject(iouReport) ? iouReport : null,
iouReportAction: lastIOUMoneyReportAction ?? lastReportAction,
shouldConsiderScanningReceiptOrPendingRoute: true,
Expand Down Expand Up @@ -1072,7 +1072,7 @@ function getLastMessageTextForReport({
lastMessageTextFromReport =
formatReportLastMessageText(
Parser.htmlToText(
getReportPreviewMessage({
getReportPreviewMessage(translate, {
reportOrID: report,
iouReportAction: lastReportAction,
shouldConsiderScanningReceiptOrPendingRoute: true,
Expand Down
301 changes: 266 additions & 35 deletions src/libs/ReportUtils.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/libs/actions/Policy/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4590,7 +4590,7 @@ function createWorkspaceFromIOUPayment(
message: [
{
type: CONST.REPORT.MESSAGE.TYPE.TEXT,
text: ReportUtils.getReportPreviewMessage({reportOrID: expenseReport, policy: newWorkspace}),
text: ReportUtils.getReportPreviewReportActionMessage({reportOrID: expenseReport, policy: newWorkspace}),
},
],
created: DateUtils.getDBTime(),
Expand Down
4 changes: 2 additions & 2 deletions src/libs/actions/Report/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ import {
getReportMetadata,
getReportNotificationPreference,
getReportOrDraftReport,
getReportPreviewMessage,
getReportPreviewReportActionMessage,
getReportTransactions,
hasOutstandingChildRequest,
isAdminRoom,
Expand Down Expand Up @@ -4033,7 +4033,7 @@ function buildNewReportOptimisticData(
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
};

const message = getReportPreviewMessage({reportOrID: optimisticReportData});
const message = getReportPreviewReportActionMessage({reportOrID: optimisticReportData});
const createReportActionMessage = [
{
html: message,
Expand Down
5 changes: 2 additions & 3 deletions src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ import {
getReimbursementDeQueuedOrCanceledActionMessage,
getReimbursementQueuedActionMessage,
getReportOrDraftReport,
getReportPreviewMessage,
getReportPreviewMessageForCopy,
getUnreportedTransactionMessage,
getWorkspaceNameUpdatedMessage,
isExpenseReport,
Expand Down Expand Up @@ -929,10 +929,9 @@ const ContextMenuActions: ContextMenuAction[] = [
const content = selection || messageHtml;
if (isReportPreviewAction) {
const iouReportID = getIOUReportIDFromReportActionPreview(reportAction);
const displayMessage = getReportPreviewMessage({
const displayMessage = getReportPreviewMessageForCopy({
reportOrID: iouReportID,
iouReportAction: reportAction,
isCopyAction: true,
reportAttributes,
});
Clipboard.setString(displayMessage);
Expand Down
4 changes: 2 additions & 2 deletions tests/perf-test/ReportUtils.perf-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
getIcons,
getIconsForParticipants,
getIOUReportActionDisplayMessage,
getReportPreviewMessage,
getReportPreviewReportActionMessage,
getReportRecipientAccountIDs,
getTransactionDetails,
getWorkspaceChats,
Expand Down Expand Up @@ -150,7 +150,7 @@ describe('ReportUtils', () => {

await waitForBatchedUpdates();
await measureFunction(() =>
getReportPreviewMessage({
getReportPreviewReportActionMessage({
reportOrID: report,
iouReportAction: reportAction,
shouldConsiderScanningReceiptOrPendingRoute: shouldConsiderReceiptBeingScanned,
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/OptionsListUtilsTest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ import {
formatReportLastMessageText,
getMovedActionMessage,
getMovedTransactionMessage,
getReportPreviewMessage,
getReportPreviewReportActionMessage,
getReportTransactions,
isCanceledTaskReport,
isExpensifyOnlyParticipantInReport,
Expand Down Expand Up @@ -4471,7 +4471,7 @@ describe('OptionsListUtils', () => {
[iouAction.reportActionID]: iouAction,
});
await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, transaction);
const reportPreviewMessage = getReportPreviewMessage({
const reportPreviewMessage = getReportPreviewReportActionMessage({
reportOrID: iouReport,
iouReportAction: iouAction,
shouldConsiderScanningReceiptOrPendingRoute: true,
Expand Down
82 changes: 70 additions & 12 deletions tests/unit/ReportUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ import {
getReportIDFromLink,
getReportOrDraftReport,
getReportPreviewMessage,
getReportPreviewMessageForCopy,
getReportPreviewReportActionMessage,
getReportStatusTranslation,
getReportSubtitlePrefix,
getTaskAssigneeChatOnyxData,
Expand Down Expand Up @@ -14931,8 +14933,8 @@ describe('ReportUtils', () => {
childMoneyRequestCount: 0,
};

// When we call getReportPreviewMessage
const result = getReportPreviewMessage({reportOrID: report, iouReportAction: reportAction, originalReportAction: reportAction});
// When we call getReportPreviewReportActionMessage
const result = getReportPreviewReportActionMessage({reportOrID: report, iouReportAction: reportAction, originalReportAction: reportAction});

// Then it should return the childReportName instead of "payer owes $0"
expect(result).toBe('Expense Report 2025-01-15');
Expand All @@ -14951,13 +14953,13 @@ describe('ReportUtils', () => {
message: [{html: 'payer owes $100', type: 'COMMENT', text: 'payer owes $100'}],
};

// When we call getReportPreviewMessage
const result = getReportPreviewMessage({reportOrID: report, iouReportAction: reportAction, originalReportAction: reportAction});
// When we call getReportPreviewReportActionMessage
const result = getReportPreviewReportActionMessage({reportOrID: report, iouReportAction: reportAction, originalReportAction: reportAction});

// Then it should return the message from the report action (not the childReportName)
expect(result).toBe('payer owes $100');
});
it('should return expense report name when isCopyAction is true', async () => {
it('getReportPreviewMessageForCopy should return the expense report name', async () => {
const report = LHNTestUtils.getFakeReport();
report.reportName = 'Expense Report 2025-01-15';
const reportAction: ReportAction = {
Expand All @@ -14967,14 +14969,14 @@ describe('ReportUtils', () => {
childMoneyRequestCount: 0,
};

// When we call getReportPreviewMessage with isCopyAction = true
const result = getReportPreviewMessage({reportOrID: report, iouReportAction: reportAction, originalReportAction: reportAction, isCopyAction: true});
// When we call getReportPreviewMessageForCopy
const result = getReportPreviewMessageForCopy({reportOrID: report, iouReportAction: reportAction, originalReportAction: reportAction});

// Then it should return the childReportName instead of "payer owes $0"
expect(result).toBe('Expense Report 2025-01-15');
});

it('should use the report name from the reportAttributes param when isCopyAction is true', async () => {
it('getReportPreviewMessageForCopy should use the report name from the reportAttributes param', async () => {
const report = LHNTestUtils.getFakeReport();
report.reportName = 'Stale Report Name';
const reportAction: ReportAction = {
Expand All @@ -14994,11 +14996,10 @@ describe('ReportUtils', () => {
};

// When called with reportAttributes that provide a report name, it should be preferred over the report's own name
const result = getReportPreviewMessage({
const result = getReportPreviewMessageForCopy({
reportOrID: report,
iouReportAction: reportAction,
originalReportAction: reportAction,
isCopyAction: true,
reportAttributes,
});
expect(result).toBe('Computed Report Name');
Expand Down Expand Up @@ -15045,17 +15046,74 @@ describe('ReportUtils', () => {
originalMessage: {...payOriginalMessage, accountNumber: 'XXXXXX4321'},
};

const result = getReportPreviewMessage({reportOrID: settledReport, iouReportAction: actionWithAccountNumber, originalReportAction: actionWithAccountNumber});
const result = getReportPreviewReportActionMessage({reportOrID: settledReport, iouReportAction: actionWithAccountNumber, originalReportAction: actionWithAccountNumber});

// Then the preview shows the last 4 digits of that account, not the policy default
expect(result).toBe(translate(CONST.LOCALES.EN, 'iou.businessBankAccount', '', '4321'));
});

it('falls back to the policy default bank account when the action has no accountNumber', () => {
const result = getReportPreviewMessage({reportOrID: settledReport, iouReportAction: payReportAction, originalReportAction: payReportAction});
const result = getReportPreviewReportActionMessage({reportOrID: settledReport, iouReportAction: payReportAction, originalReportAction: payReportAction});

expect(result).toBe(translate(CONST.LOCALES.EN, 'iou.businessBankAccount', '', '0000'));
});

it('matches the localized getReportPreviewMessage output when translated to English', () => {
const englishTranslate: LocalizedTranslate = (path, ...parameters) => translate(CONST.LOCALES.EN, path, ...parameters);
const params = {reportOrID: settledReport, iouReportAction: payReportAction, originalReportAction: payReportAction};

// The hardcoded English copy must not drift from the localized function
expect(getReportPreviewReportActionMessage(params)).toBe(getReportPreviewMessage(englishTranslate, params));
});
});

describe('getReportPreviewMessage (localized)', () => {
const expenseReport: Report = {
...LHNTestUtils.getFakeReport(),
reportID: 'preview-localized-report',
type: CONST.REPORT.TYPE.EXPENSE,
currency: CONST.CURRENCY.USD,
stateNum: CONST.REPORT.STATE_NUM.OPEN,
statusNum: CONST.REPORT.STATUS_NUM.OPEN,
};

beforeEach(async () => {
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`, expenseReport);
});

it('uses the injected translate function (not translateLocal) so output follows the passed locale, while getReportPreviewReportActionMessage stays English', async () => {
const params = {reportOrID: expenseReport};
const englishTranslate: LocalizedTranslate = (path, ...parameters) => translate(CONST.LOCALES.EN, path, ...parameters);
const spanishTranslate: LocalizedTranslate = (path, ...parameters) => translate(CONST.LOCALES.ES, path, ...parameters);

await IntlStore.load(CONST.LOCALES.ES).then(waitForBatchedUpdates);

// The localized preview differs between English and Spanish...
expect(getReportPreviewMessage(spanishTranslate, params)).not.toBe(getReportPreviewMessage(englishTranslate, params));
// ...but the report-action-message variant is always the English text, regardless of the loaded locale
expect(getReportPreviewReportActionMessage(params)).toBe(getReportPreviewMessage(englishTranslate, params));
});
});

describe('getReportPreviewReportActionMessage (hardcoded English)', () => {
it('returns the English "owes" message for an expense report and matches en.ts', async () => {
const report: Report = {
...LHNTestUtils.getFakeReport(),
reportID: 'preview-en-owes-report',
type: CONST.REPORT.TYPE.EXPENSE,
currency: CONST.CURRENCY.USD,
stateNum: CONST.REPORT.STATE_NUM.OPEN,
statusNum: CONST.REPORT.STATUS_NUM.OPEN,
};
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, report);

const englishTranslate: LocalizedTranslate = (path, ...parameters) => translate(CONST.LOCALES.EN, path, ...parameters);
const result = getReportPreviewReportActionMessage({reportOrID: report});

// The hardcoded English string must match the en.ts translation produced by the localized function
expect(result).toBe(getReportPreviewMessage(englishTranslate, {reportOrID: report}));
expect(result).toContain('owes');
});
});
});

Expand Down
6 changes: 3 additions & 3 deletions tests/unit/SidebarUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import DateUtils from '@libs/DateUtils';
import {getLastActorDisplayName} from '@libs/OptionsListUtils';
import type * as PolicyUtils from '@libs/PolicyUtils';
import {getOriginalMessage, getReportActionMessageText} from '@libs/ReportActionsUtils';
import {formatReportLastMessageText, generateReportID, getAllReportErrors, getReasonAndReportActionThatRequiresAttention, getReportPreviewMessage} from '@libs/ReportUtils';
import {formatReportLastMessageText, generateReportID, getAllReportErrors, getReasonAndReportActionThatRequiresAttention, getReportPreviewReportActionMessage} from '@libs/ReportUtils';
import SidebarUtils, {_buildSortKey, _categorizeReportsForLHN, _combineReportCategories, _sortCategorizedReports} from '@libs/SidebarUtils';

import initOnyxDerivedValues from '@userActions/OnyxDerived';
Expand Down Expand Up @@ -3445,7 +3445,7 @@ describe('SidebarUtils', () => {
currentUserLogin: CURRENT_USER_LOGIN,
});

const reportPreviewMessage = getReportPreviewMessage({
const reportPreviewMessage = getReportPreviewReportActionMessage({
reportOrID: iouReport,
iouReportAction: iouAction,
shouldConsiderScanningReceiptOrPendingRoute: true,
Expand Down Expand Up @@ -3555,7 +3555,7 @@ describe('SidebarUtils', () => {
currentUserLogin: CURRENT_USER_LOGIN,
});

const reportPreviewMessage = getReportPreviewMessage({
const reportPreviewMessage = getReportPreviewReportActionMessage({
reportOrID: iouReport,
iouReportAction: iouAction,
shouldConsiderScanningReceiptOrPendingRoute: true,
Expand Down
Loading