diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts
index d56477c3f148..77aeb8e0ecc3 100644
--- a/src/libs/CardUtils.ts
+++ b/src/libs/CardUtils.ts
@@ -135,15 +135,26 @@ function maskCard(lastFour = ''): string {
* Converts given 'X' to '•' for the entire card string.
*
* @param cardName - card name with XXXX in the middle.
+ * @param feed - card feed.
* @returns - The masked card string.
*/
-function maskCardNumber(cardName: string): string {
+function maskCardNumber(cardName: string, feed: string | undefined): string {
if (!cardName || cardName === '') {
return '';
}
const hasSpace = /\s/.test(cardName);
const maskedString = cardName.replace(/X/g, '•');
- return hasSpace ? cardName : maskedString.replace(/(.{4})/g, '$1 ').trim();
+ const isAmexBank = [CONST.COMPANY_CARD.FEED_BANK_NAME.AMEX, CONST.COMPANY_CARD.FEED_BANK_NAME.AMEX_DIRECT].some((value) => value === feed);
+
+ if (hasSpace) {
+ return cardName;
+ }
+
+ if (isAmexBank && maskedString.length === 15) {
+ return maskedString.replace(/(.{4})(.{6})(.{5})/, '$1 $2 $3');
+ }
+
+ return maskedString.replace(/(.{4})/g, '$1 ').trim();
}
/**
diff --git a/src/pages/settings/Wallet/PaymentMethodList.tsx b/src/pages/settings/Wallet/PaymentMethodList.tsx
index 6913b166100e..e9280d494857 100644
--- a/src/pages/settings/Wallet/PaymentMethodList.tsx
+++ b/src/pages/settings/Wallet/PaymentMethodList.tsx
@@ -238,7 +238,7 @@ function PaymentMethodList({
if (!CardUtils.isExpensifyCard(card.cardID)) {
assignedCardsGrouped.push({
key: card.cardID.toString(),
- title: CardUtils.maskCardNumber(card.cardName ?? ''),
+ title: CardUtils.maskCardNumber(card.cardName ?? '', card.bank),
description: getDescriptionForPolicyDomainCard(card.domainName),
shouldShowRightIcon: false,
interactive: false,
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardDetailsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardDetailsPage.tsx
index 9fdfa7bec7b3..bee196031bda 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardDetailsPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardDetailsPage.tsx
@@ -112,7 +112,7 @@ function WorkspaceCompanyCardDetailsPage({route}: WorkspaceCompanyCardDetailsPag
/>
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx
index 9e9e2bf5208f..75b4f44fc843 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx
@@ -60,7 +60,7 @@ function WorkspaceCompanyCardsList({cardsList, policyID}: WorkspaceCompanyCardsL
>
diff --git a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx
index f9e552ac5afe..4b07e7a220b8 100644
--- a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx
@@ -105,7 +105,7 @@ function CardSelectionStep({feed, policyID}: CardSelectionStepProps) {
const cardListOptions = Object.entries(filteredCardList).map(([cardNumber, encryptedCardNumber]) => ({
keyForList: encryptedCardNumber,
value: encryptedCardNumber,
- text: CardUtils.maskCardNumber(cardNumber),
+ text: CardUtils.maskCardNumber(cardNumber, feed),
isSelected: cardSelected === encryptedCardNumber,
leftElement: (
editStep(CONST.COMPANY_CARD.STEP.CARD)}
/>
diff --git a/tests/unit/CardUtilsTest.ts b/tests/unit/CardUtilsTest.ts
index 09a36fcfb562..9d4af5aa3760 100644
--- a/tests/unit/CardUtilsTest.ts
+++ b/tests/unit/CardUtilsTest.ts
@@ -215,4 +215,41 @@ describe('CardUtils', () => {
expect(feedName).toBe(undefined);
});
});
+
+ describe('maskCardNumber', () => {
+ it("Should return the card number divided into chunks of 4, with 'X' replaced by '•' if it's provided in the '480801XXXXXX2554' format", () => {
+ const cardNumber = '480801XXXXXX2554';
+ const maskedCardNumber = CardUtils.maskCardNumber(cardNumber, CONST.COMPANY_CARD.FEED_BANK_NAME.MASTER_CARD);
+ expect(maskedCardNumber).toBe('4808 01•• •••• 2554');
+ });
+
+ it('Should return card number without changes if it has empty space', () => {
+ const cardNumber = 'CREDIT CARD...6607';
+ const maskedCardNumber = CardUtils.maskCardNumber(cardNumber, CONST.COMPANY_CARD.FEED_BANK_NAME.CHASE);
+ expect(maskedCardNumber).toBe(cardNumber);
+ });
+
+ it("Should return the Amex direct feed card number divided into 4/6/5 chunks, with 'X' replaced by '•' if it's provided in '211944XXXXX6557' format", () => {
+ const cardNumber = '211944XXXXX6557';
+ const maskedCardNumber = CardUtils.maskCardNumber(cardNumber, CONST.COMPANY_CARD.FEED_BANK_NAME.AMEX_DIRECT);
+ expect(maskedCardNumber).toBe('2119 44•••• •6557');
+ });
+
+ it("Should return the Amex custom feed card number divided into 4/6/5 chunks, with 'X' replaced by '•' if it's provided in '211944XXXXX6557' format", () => {
+ const cardNumber = '211944XXXXX6557';
+ const maskedCardNumber = CardUtils.maskCardNumber(cardNumber, CONST.COMPANY_CARD.FEED_BANK_NAME.AMEX);
+ expect(maskedCardNumber).toBe('2119 44•••• •6557');
+ });
+
+ it('Should return masked card number even if undefined feed was provided', () => {
+ const cardNumber = '480801XXXXXX2554';
+ const maskedCardNumber = CardUtils.maskCardNumber(cardNumber, undefined);
+ expect(maskedCardNumber).toBe('4808 01•• •••• 2554');
+ });
+
+ it('Should return empty string if invalid card name was provided', () => {
+ const maskedCardNumber = CardUtils.maskCardNumber('', CONST.COMPANY_CARD.FEED_BANK_NAME.MASTER_CARD);
+ expect(maskedCardNumber).toBe('');
+ });
+ });
});