diff --git a/src/components/DisplayNames/index.native.tsx b/src/components/DisplayNames/index.native.tsx index ceee34586e8b..3ca810aa4d36 100644 --- a/src/components/DisplayNames/index.native.tsx +++ b/src/components/DisplayNames/index.native.tsx @@ -11,6 +11,7 @@ function DisplayNames({accessibilityLabel, fullTitle, textStyles = [], numberOfL accessibilityLabel={accessibilityLabel} style={textStyles} numberOfLines={numberOfLines} + testID={DisplayNames.displayName} > {fullTitle || translate('common.hidden')} {renderAdditionalText?.()} diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index 323e1b0f4974..47520c6b77c8 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -149,6 +149,10 @@ function ReportPreview({ const [invoiceReceiverPolicy] = useOnyx( `${ONYXKEYS.COLLECTION.POLICY}${chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : CONST.DEFAULT_NUMBER_ID}`, ); + const [invoiceReceiverPersonalDetail] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, { + selector: (personalDetails) => + personalDetails?.[chatReport?.invoiceReceiver && 'accountID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.accountID : CONST.DEFAULT_NUMBER_ID], + }); const theme = useTheme(); const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -366,7 +370,7 @@ function ReportPreview({ if (isPolicyExpenseChat) { payerOrApproverName = getPolicyName(chatReport, undefined, policy); } else if (isInvoiceRoom) { - payerOrApproverName = getInvoicePayerName(chatReport, invoiceReceiverPolicy); + payerOrApproverName = getInvoicePayerName(chatReport, invoiceReceiverPolicy, invoiceReceiverPersonalDetail); } else { payerOrApproverName = getDisplayNameForParticipant(managerID, true); } @@ -389,6 +393,7 @@ function ReportPreview({ chatReport, isInvoiceRoom, invoiceReceiverPolicy, + invoiceReceiverPersonalDetail, managerID, isApproved, iouSettled, @@ -549,7 +554,12 @@ function ReportPreview({ - {previewMessage} + + {previewMessage} + {shouldShowRBR && ( , invoiceReceiverPolicy?: OnyxEntry): string { +function getInvoicePayerName(report: OnyxEntry, invoiceReceiverPolicy?: OnyxEntry, invoiceReceiverPersonalDetail?: PersonalDetails): string { const invoiceReceiver = report?.invoiceReceiver; const isIndividual = invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL; if (isIndividual) { - return formatPhoneNumber(getDisplayNameOrDefault(allPersonalDetails?.[invoiceReceiver.accountID])); + return formatPhoneNumber(getDisplayNameOrDefault(invoiceReceiverPersonalDetail ?? allPersonalDetails?.[invoiceReceiver.accountID])); } return getPolicyName(report, false, invoiceReceiverPolicy ?? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${invoiceReceiver?.policyID}`]); @@ -4095,7 +4095,7 @@ function getReportActionMessage(reportAction: OnyxEntry, reportID? /** * Get the title for an invoice room. */ -function getInvoicesChatName(report: OnyxEntry, receiverPolicy: OnyxEntry): string { +function getInvoicesChatName(report: OnyxEntry, receiverPolicy: OnyxEntry, personalDetails?: Partial): string { const invoiceReceiver = report?.invoiceReceiver; const isIndividual = invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL; const invoiceReceiverAccountID = isIndividual ? invoiceReceiver.accountID : CONST.DEFAULT_NUMBER_ID; @@ -4108,7 +4108,7 @@ function getInvoicesChatName(report: OnyxEntry, receiverPolicy: OnyxEntr } if (isIndividual) { - return formatPhoneNumber(getDisplayNameOrDefault(allPersonalDetails?.[invoiceReceiverAccountID])); + return formatPhoneNumber(getDisplayNameOrDefault((personalDetails ?? allPersonalDetails)?.[invoiceReceiverAccountID])); } return getPolicyName(report, false, invoiceReceiverPolicy); @@ -4263,7 +4263,7 @@ function getReportName( } if (isInvoiceRoom(report)) { - formattedName = getInvoicesChatName(report, invoiceReceiverPolicy); + formattedName = getInvoicesChatName(report, invoiceReceiverPolicy, personalDetails); } if (isArchivedNonExpenseReport(report, getReportNameValuePairs(report?.reportID))) { diff --git a/tests/ui/components/HeaderViewTest.tsx b/tests/ui/components/HeaderViewTest.tsx new file mode 100644 index 000000000000..22ae16809345 --- /dev/null +++ b/tests/ui/components/HeaderViewTest.tsx @@ -0,0 +1,71 @@ +import {render, screen} from '@testing-library/react-native'; +import React from 'react'; +import Onyx from 'react-native-onyx'; +import type Navigation from '@libs/Navigation/Navigation'; +import HeaderView from '@pages/home/HeaderView'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import createRandomReport from '../../utils/collections/reports'; +import waitForBatchedUpdates from '../../utils/waitForBatchedUpdates'; + +jest.mock('@react-navigation/native', () => { + const actualNav = jest.requireActual('@react-navigation/native'); + return { + ...actualNav, + useRoute: () => jest.fn(), + }; +}); + +describe('HeaderView', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + beforeAll(() => { + Onyx.init({keys: ONYXKEYS}); + }); + + it('should update invoice room title when the invoice receiver detail is updated', async () => { + // Given an invoice room header + const chatReportID = '1'; + const accountID = 2; + let displayName = 'test'; + const report = { + ...createRandomReport(Number(chatReportID)), + chatType: CONST.REPORT.CHAT_TYPE.INVOICE, + invoiceReceiver: { + accountID, + type: CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL, + }, + }; + await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, { + [accountID]: { + displayName, + }, + }); + + render( + {}} + parentReportAction={null} + reportID={report.reportID} + />, + ); + + await waitForBatchedUpdates(); + + expect(screen.getByTestId('DisplayNames')).toHaveTextContent(displayName); + + // When the invoice receiver display name is updated + displayName = 'test edit'; + await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, { + [accountID]: { + displayName, + }, + }); + + // Then the header title should be updated using the new display name + expect(screen.getByTestId('DisplayNames')).toHaveTextContent(displayName); + }); +}); diff --git a/tests/ui/components/ReportPreviewTest.tsx b/tests/ui/components/ReportPreviewTest.tsx new file mode 100644 index 000000000000..5e5a5e4b5787 --- /dev/null +++ b/tests/ui/components/ReportPreviewTest.tsx @@ -0,0 +1,91 @@ +import {render, screen} from '@testing-library/react-native'; +import React from 'react'; +import Onyx from 'react-native-onyx'; +import {LocaleContextProvider} from '@components/LocaleContextProvider'; +import OnyxProvider from '@components/OnyxProvider'; +import ReportPreview from '@components/ReportActionItem/ReportPreview'; +import {translateLocal} from '@libs/Localize'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import createRandomReportAction from '../../utils/collections/reportActions'; +import createRandomReport from '../../utils/collections/reports'; +import waitForBatchedUpdates from '../../utils/waitForBatchedUpdates'; + +jest.mock('@rnmapbox/maps', () => { + return { + default: jest.fn(), + MarkerView: jest.fn(), + setAccessToken: jest.fn(), + }; +}); + +jest.mock('@react-native-community/geolocation', () => ({ + setRNConfiguration: jest.fn(), +})); + +describe('ReportPreview', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + beforeAll(() => { + Onyx.init({keys: ONYXKEYS}); + }); + + it('should update preview message when the invoice receiver detail is updated', async () => { + // Given an invoice report preview + const chatReportID = '1'; + const iouReportID = '2'; + const accountID = 3; + let displayName = 'test'; + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`, { + ...createRandomReport(Number(chatReportID)), + chatType: CONST.REPORT.CHAT_TYPE.INVOICE, + invoiceReceiver: { + accountID, + type: CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL, + }, + }); + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, { + ...createRandomReport(Number(chatReportID)), + type: CONST.REPORT.TYPE.INVOICE, + isWaitingOnBankAccount: false, + stateNum: CONST.REPORT.STATE_NUM.OPEN, + statusNum: CONST.REPORT.STATUS_NUM.OPEN, + }); + await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, { + [accountID]: { + displayName, + }, + }); + + render( + + + {}} + /> + + , + ); + + await waitForBatchedUpdates(); + + expect(screen.getByTestId('reportPreview-previewMessage')).toHaveTextContent(translateLocal('iou.payerOwes', {payer: displayName})); + + // When the invoice receiver display name is updated + displayName = 'test edit'; + await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, { + [accountID]: { + displayName, + }, + }); + + // Then the report preview's preview message should be updated using the new display name + expect(screen.getByTestId('reportPreview-previewMessage')).toHaveTextContent(translateLocal('iou.payerOwes', {payer: displayName})); + }); +});