From 1e9cbb9110641449a6115f488c28d077ba6bf472 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Sun, 21 Dec 2025 17:34:45 +0300 Subject: [PATCH 1/2] test: [Create Automated Test] Inbox - GBR: waiting user enable silver wallet receive funds friend p2p flow --- tests/unit/ReportUtilsTest.ts | 284 ++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index 46e6bd82d7b2b..6c37e61b92723 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -59,6 +59,7 @@ import { getDisplayNamesWithTooltips, getHarvestOriginalReportID, getIconsForParticipants, + getIndicatedMissingPaymentMethod, getIOUReportActionDisplayMessage, getMoneyReportPreviewName, getMostRecentlyVisitedReport, @@ -10472,4 +10473,287 @@ describe('ReportUtils', () => { expect(shouldHideSingleReportField(reportField)).toBe(true); }); }); + + describe('P2P Wallet Activation - GBR and Wallet Indicator', () => { + const friendAccountID = 42; + + /** + * Tests the complete P2P wallet activation scenario: + * - Friend sends P2P payment to user with SILVER wallet + * - Backend sets hasOutstandingChildRequest: true (payment pending wallet setup) + * - GBR shows in LHN + * - "Enable your wallet" button shows (getIndicatedMissingPaymentMethod returns 'wallet') + */ + it('should show GBR and wallet indicator for SILVER tier user receiving P2P payment', async () => { + await Onyx.clear(); + + const iouReportID = '10000'; + + // Chat report - hasOutstandingChildRequest set by backend when P2P payment pending wallet + const chatReport: Report = { + ...LHNTestUtils.getFakeReport([currentUserAccountID, friendAccountID]), + hasOutstandingChildRequest: true, + iouReportID, + }; + + // IOU report - P2P payment from friend to current user + const iouReport: Report = { + ...LHNTestUtils.getFakeReport([currentUserAccountID, friendAccountID]), + reportID: iouReportID, + chatReportID: chatReport.reportID, + type: CONST.REPORT.TYPE.IOU, + ownerAccountID: currentUserAccountID, + managerID: friendAccountID, + currency: CONST.CURRENCY.USD, + total: 10000, + stateNum: CONST.REPORT.STATE_NUM.APPROVED, + statusNum: CONST.REPORT.STATUS_NUM.APPROVED, + isWaitingOnBankAccount: true, + }; + + // REIMBURSEMENT_QUEUED with EXPENSIFY payment type = P2P wallet payment + const reimbursementQueuedAction: ReportAction = { + ...LHNTestUtils.getFakeReportAction(), + actionName: CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENT_QUEUED, + originalMessage: { + paymentType: CONST.IOU.PAYMENT_TYPE.EXPENSIFY, + }, + }; + + await Onyx.merge(ONYXKEYS.SESSION, {accountID: currentUserAccountID, email: currentUserEmail}); + await Promise.all([ + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, chatReport), + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, iouReport), + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport.reportID}`, { + [reimbursementQueuedAction.reportActionID]: reimbursementQueuedAction, + }), + ]); + await waitForBatchedUpdates(); + + // Verify GBR shows in LHN + const reason = reasonForReportToBeInOptionList({ + report: chatReport, + currentReportId: '', + isInFocusMode: false, + betas: [CONST.BETAS.DEFAULT_ROOMS], + doesReportHaveViolations: false, + excludeEmptyChats: false, + policies: {}, + isReportArchived: false, + }); + expect(reason).toBe(CONST.REPORT_IN_LHN_REASONS.HAS_GBR); + + // Verify "Enable your wallet" indicator for SILVER tier + const missingPaymentMethod = getIndicatedMissingPaymentMethod(CONST.WALLET.TIER_NAME.SILVER, iouReportID, reimbursementQueuedAction, {}); + expect(missingPaymentMethod).toBe('wallet'); + + await Onyx.clear(); + }); + + /** + * Same scenario but user has no wallet tier set (new user) + */ + it('should show GBR and wallet indicator for user with no wallet tier (undefined)', async () => { + await Onyx.clear(); + + const iouReportID = '10001'; + + const chatReport: Report = { + ...LHNTestUtils.getFakeReport([currentUserAccountID, friendAccountID]), + hasOutstandingChildRequest: true, + iouReportID, + }; + + const iouReport: Report = { + ...LHNTestUtils.getFakeReport([currentUserAccountID, friendAccountID]), + reportID: iouReportID, + chatReportID: chatReport.reportID, + type: CONST.REPORT.TYPE.IOU, + ownerAccountID: currentUserAccountID, + managerID: friendAccountID, + currency: CONST.CURRENCY.USD, + total: 5000, + stateNum: CONST.REPORT.STATE_NUM.APPROVED, + statusNum: CONST.REPORT.STATUS_NUM.APPROVED, + isWaitingOnBankAccount: true, + }; + + const reimbursementQueuedAction: ReportAction = { + ...LHNTestUtils.getFakeReportAction(), + actionName: CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENT_QUEUED, + originalMessage: { + paymentType: CONST.IOU.PAYMENT_TYPE.EXPENSIFY, + }, + }; + + await Onyx.merge(ONYXKEYS.SESSION, {accountID: currentUserAccountID, email: currentUserEmail}); + await Promise.all([ + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, chatReport), + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, iouReport), + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport.reportID}`, { + [reimbursementQueuedAction.reportActionID]: reimbursementQueuedAction, + }), + ]); + await waitForBatchedUpdates(); + + // Verify GBR shows + const reason = reasonForReportToBeInOptionList({ + report: chatReport, + currentReportId: '', + isInFocusMode: false, + betas: [CONST.BETAS.DEFAULT_ROOMS], + doesReportHaveViolations: false, + excludeEmptyChats: false, + policies: {}, + isReportArchived: false, + }); + expect(reason).toBe(CONST.REPORT_IN_LHN_REASONS.HAS_GBR); + + // Verify wallet indicator for undefined tier + const missingPaymentMethod = getIndicatedMissingPaymentMethod(undefined, iouReportID, reimbursementQueuedAction, {}); + expect(missingPaymentMethod).toBe('wallet'); + + await Onyx.clear(); + }); + + /** + * When user has GOLD wallet (already enabled): + * - Payment goes through, no pending state + * - hasOutstandingChildRequest would be false (set by backend) + * - No GBR needed, no wallet button needed + */ + it('should NOT show GBR or wallet indicator when user has GOLD tier (wallet already enabled)', async () => { + await Onyx.clear(); + + const iouReportID = '10002'; + + // No outstanding request - GOLD wallet means payment processes normally + const chatReport: Report = { + ...LHNTestUtils.getFakeReport([currentUserAccountID, friendAccountID]), + hasOutstandingChildRequest: false, + iouReportID, + }; + + const iouReport: Report = { + ...LHNTestUtils.getFakeReport([currentUserAccountID, friendAccountID]), + reportID: iouReportID, + chatReportID: chatReport.reportID, + type: CONST.REPORT.TYPE.IOU, + ownerAccountID: currentUserAccountID, + managerID: friendAccountID, + currency: CONST.CURRENCY.USD, + total: 10000, + stateNum: CONST.REPORT.STATE_NUM.APPROVED, + statusNum: CONST.REPORT.STATUS_NUM.APPROVED, + isWaitingOnBankAccount: false, + }; + + const reimbursementQueuedAction: ReportAction = { + ...LHNTestUtils.getFakeReportAction(), + actionName: CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENT_QUEUED, + originalMessage: { + paymentType: CONST.IOU.PAYMENT_TYPE.EXPENSIFY, + }, + }; + + await Onyx.merge(ONYXKEYS.SESSION, {accountID: currentUserAccountID, email: currentUserEmail}); + await Promise.all([ + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, chatReport), + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, iouReport), + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport.reportID}`, { + [reimbursementQueuedAction.reportActionID]: reimbursementQueuedAction, + }), + ]); + await waitForBatchedUpdates(); + + // Verify GBR does NOT show (no outstanding request for GOLD user) + const reason = reasonForReportToBeInOptionList({ + report: chatReport, + currentReportId: '', + isInFocusMode: false, + betas: [CONST.BETAS.DEFAULT_ROOMS], + doesReportHaveViolations: false, + excludeEmptyChats: false, + policies: {}, + isReportArchived: false, + }); + expect(reason).not.toBe(CONST.REPORT_IN_LHN_REASONS.HAS_GBR); + + // Verify NO wallet indicator for GOLD tier + const missingPaymentMethod = getIndicatedMissingPaymentMethod(CONST.WALLET.TIER_NAME.GOLD, iouReportID, reimbursementQueuedAction, {}); + expect(missingPaymentMethod).toBeUndefined(); + + await Onyx.clear(); + }); + + /** + * For non-EXPENSIFY payment types (e.g., ELSEWHERE): + * - This is not a P2P wallet scenario + * - Wallet indicator should not return 'wallet' + */ + it('should NOT show wallet indicator for non-EXPENSIFY payment type', async () => { + await Onyx.clear(); + + const iouReportID = '10003'; + + const chatReport: Report = { + ...LHNTestUtils.getFakeReport([currentUserAccountID, friendAccountID]), + hasOutstandingChildRequest: true, + iouReportID, + }; + + const iouReport: Report = { + ...LHNTestUtils.getFakeReport([currentUserAccountID, friendAccountID]), + reportID: iouReportID, + chatReportID: chatReport.reportID, + type: CONST.REPORT.TYPE.IOU, + ownerAccountID: currentUserAccountID, + managerID: friendAccountID, + currency: CONST.CURRENCY.USD, + total: 10000, + stateNum: CONST.REPORT.STATE_NUM.APPROVED, + statusNum: CONST.REPORT.STATUS_NUM.APPROVED, + isWaitingOnBankAccount: true, + }; + + // Non-P2P payment type (ELSEWHERE = external/manual payment) + const reimbursementQueuedAction: ReportAction = { + ...LHNTestUtils.getFakeReportAction(), + actionName: CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENT_QUEUED, + originalMessage: { + paymentType: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, + }, + }; + + await Onyx.merge(ONYXKEYS.SESSION, {accountID: currentUserAccountID, email: currentUserEmail}); + await Promise.all([ + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, chatReport), + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, iouReport), + Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport.reportID}`, { + [reimbursementQueuedAction.reportActionID]: reimbursementQueuedAction, + }), + ]); + await waitForBatchedUpdates(); + + // GBR may still show (hasOutstandingChildRequest: true) but for different reason + const reason = reasonForReportToBeInOptionList({ + report: chatReport, + currentReportId: '', + isInFocusMode: false, + betas: [CONST.BETAS.DEFAULT_ROOMS], + doesReportHaveViolations: false, + excludeEmptyChats: false, + policies: {}, + isReportArchived: false, + }); + expect(reason).toBe(CONST.REPORT_IN_LHN_REASONS.HAS_GBR); + + // But wallet indicator should NOT be 'wallet' for non-EXPENSIFY payment + // (would be 'bankAccount' or undefined depending on bank account status) + const missingPaymentMethod = getIndicatedMissingPaymentMethod(CONST.WALLET.TIER_NAME.SILVER, iouReportID, reimbursementQueuedAction, {}); + expect(missingPaymentMethod).not.toBe('wallet'); + + await Onyx.clear(); + }); + }); }); From 6753655674b37c9375e0d01f1f571fd271e9edd8 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Sun, 21 Dec 2025 18:47:16 +0300 Subject: [PATCH 2/2] fix: TypeScript errors in P2P Wallet Activation tests --- tests/unit/ReportUtilsTest.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts index 6c37e61b92723..51ae65d6f75dd 100644 --- a/tests/unit/ReportUtilsTest.ts +++ b/tests/unit/ReportUtilsTest.ts @@ -10533,13 +10533,14 @@ describe('ReportUtils', () => { // Verify GBR shows in LHN const reason = reasonForReportToBeInOptionList({ report: chatReport, + chatReport, currentReportId: '', isInFocusMode: false, betas: [CONST.BETAS.DEFAULT_ROOMS], doesReportHaveViolations: false, excludeEmptyChats: false, - policies: {}, isReportArchived: false, + draftComment: '', }); expect(reason).toBe(CONST.REPORT_IN_LHN_REASONS.HAS_GBR); @@ -10599,13 +10600,14 @@ describe('ReportUtils', () => { // Verify GBR shows const reason = reasonForReportToBeInOptionList({ report: chatReport, + chatReport, currentReportId: '', isInFocusMode: false, betas: [CONST.BETAS.DEFAULT_ROOMS], doesReportHaveViolations: false, excludeEmptyChats: false, - policies: {}, isReportArchived: false, + draftComment: '', }); expect(reason).toBe(CONST.REPORT_IN_LHN_REASONS.HAS_GBR); @@ -10669,13 +10671,14 @@ describe('ReportUtils', () => { // Verify GBR does NOT show (no outstanding request for GOLD user) const reason = reasonForReportToBeInOptionList({ report: chatReport, + chatReport, currentReportId: '', isInFocusMode: false, betas: [CONST.BETAS.DEFAULT_ROOMS], doesReportHaveViolations: false, excludeEmptyChats: false, - policies: {}, isReportArchived: false, + draftComment: '', }); expect(reason).not.toBe(CONST.REPORT_IN_LHN_REASONS.HAS_GBR); @@ -10738,13 +10741,14 @@ describe('ReportUtils', () => { // GBR may still show (hasOutstandingChildRequest: true) but for different reason const reason = reasonForReportToBeInOptionList({ report: chatReport, + chatReport, currentReportId: '', isInFocusMode: false, betas: [CONST.BETAS.DEFAULT_ROOMS], doesReportHaveViolations: false, excludeEmptyChats: false, - policies: {}, isReportArchived: false, + draftComment: '', }); expect(reason).toBe(CONST.REPORT_IN_LHN_REASONS.HAS_GBR);