@@ -59,6 +59,7 @@ import {
5959 getDisplayNamesWithTooltips ,
6060 getHarvestOriginalReportID ,
6161 getIconsForParticipants ,
62+ getIndicatedMissingPaymentMethod ,
6263 getIOUReportActionDisplayMessage ,
6364 getMoneyReportPreviewName ,
6465 getMostRecentlyVisitedReport ,
@@ -10479,4 +10480,291 @@ describe('ReportUtils', () => {
1047910480 expect ( shouldHideSingleReportField ( reportField ) ) . toBe ( true ) ;
1048010481 } ) ;
1048110482 } ) ;
10483+
10484+ describe ( 'P2P Wallet Activation - GBR and Wallet Indicator' , ( ) => {
10485+ const friendAccountID = 42 ;
10486+
10487+ /**
10488+ * Tests the complete P2P wallet activation scenario:
10489+ * - Friend sends P2P payment to user with SILVER wallet
10490+ * - Backend sets hasOutstandingChildRequest: true (payment pending wallet setup)
10491+ * - GBR shows in LHN
10492+ * - "Enable your wallet" button shows (getIndicatedMissingPaymentMethod returns 'wallet')
10493+ */
10494+ it ( 'should show GBR and wallet indicator for SILVER tier user receiving P2P payment' , async ( ) => {
10495+ await Onyx . clear ( ) ;
10496+
10497+ const iouReportID = '10000' ;
10498+
10499+ // Chat report - hasOutstandingChildRequest set by backend when P2P payment pending wallet
10500+ const chatReport : Report = {
10501+ ...LHNTestUtils . getFakeReport ( [ currentUserAccountID , friendAccountID ] ) ,
10502+ hasOutstandingChildRequest : true ,
10503+ iouReportID,
10504+ } ;
10505+
10506+ // IOU report - P2P payment from friend to current user
10507+ const iouReport : Report = {
10508+ ...LHNTestUtils . getFakeReport ( [ currentUserAccountID , friendAccountID ] ) ,
10509+ reportID : iouReportID ,
10510+ chatReportID : chatReport . reportID ,
10511+ type : CONST . REPORT . TYPE . IOU ,
10512+ ownerAccountID : currentUserAccountID ,
10513+ managerID : friendAccountID ,
10514+ currency : CONST . CURRENCY . USD ,
10515+ total : 10000 ,
10516+ stateNum : CONST . REPORT . STATE_NUM . APPROVED ,
10517+ statusNum : CONST . REPORT . STATUS_NUM . APPROVED ,
10518+ isWaitingOnBankAccount : true ,
10519+ } ;
10520+
10521+ // REIMBURSEMENT_QUEUED with EXPENSIFY payment type = P2P wallet payment
10522+ const reimbursementQueuedAction : ReportAction = {
10523+ ...LHNTestUtils . getFakeReportAction ( ) ,
10524+ actionName : CONST . REPORT . ACTIONS . TYPE . REIMBURSEMENT_QUEUED ,
10525+ originalMessage : {
10526+ paymentType : CONST . IOU . PAYMENT_TYPE . EXPENSIFY ,
10527+ } ,
10528+ } ;
10529+
10530+ await Onyx . merge ( ONYXKEYS . SESSION , { accountID : currentUserAccountID , email : currentUserEmail } ) ;
10531+ await Promise . all ( [
10532+ Onyx . merge ( `${ ONYXKEYS . COLLECTION . REPORT } ${ chatReport . reportID } ` , chatReport ) ,
10533+ Onyx . merge ( `${ ONYXKEYS . COLLECTION . REPORT } ${ iouReportID } ` , iouReport ) ,
10534+ Onyx . merge ( `${ ONYXKEYS . COLLECTION . REPORT_ACTIONS } ${ chatReport . reportID } ` , {
10535+ [ reimbursementQueuedAction . reportActionID ] : reimbursementQueuedAction ,
10536+ } ) ,
10537+ ] ) ;
10538+ await waitForBatchedUpdates ( ) ;
10539+
10540+ // Verify GBR shows in LHN
10541+ const reason = reasonForReportToBeInOptionList ( {
10542+ report : chatReport ,
10543+ chatReport,
10544+ currentReportId : '' ,
10545+ isInFocusMode : false ,
10546+ betas : [ CONST . BETAS . DEFAULT_ROOMS ] ,
10547+ doesReportHaveViolations : false ,
10548+ excludeEmptyChats : false ,
10549+ isReportArchived : false ,
10550+ draftComment : '' ,
10551+ } ) ;
10552+ expect ( reason ) . toBe ( CONST . REPORT_IN_LHN_REASONS . HAS_GBR ) ;
10553+
10554+ // Verify "Enable your wallet" indicator for SILVER tier
10555+ const missingPaymentMethod = getIndicatedMissingPaymentMethod ( CONST . WALLET . TIER_NAME . SILVER , iouReportID , reimbursementQueuedAction , { } ) ;
10556+ expect ( missingPaymentMethod ) . toBe ( 'wallet' ) ;
10557+
10558+ await Onyx . clear ( ) ;
10559+ } ) ;
10560+
10561+ /**
10562+ * Same scenario but user has no wallet tier set (new user)
10563+ */
10564+ it ( 'should show GBR and wallet indicator for user with no wallet tier (undefined)' , async ( ) => {
10565+ await Onyx . clear ( ) ;
10566+
10567+ const iouReportID = '10001' ;
10568+
10569+ const chatReport : Report = {
10570+ ...LHNTestUtils . getFakeReport ( [ currentUserAccountID , friendAccountID ] ) ,
10571+ hasOutstandingChildRequest : true ,
10572+ iouReportID,
10573+ } ;
10574+
10575+ const iouReport : Report = {
10576+ ...LHNTestUtils . getFakeReport ( [ currentUserAccountID , friendAccountID ] ) ,
10577+ reportID : iouReportID ,
10578+ chatReportID : chatReport . reportID ,
10579+ type : CONST . REPORT . TYPE . IOU ,
10580+ ownerAccountID : currentUserAccountID ,
10581+ managerID : friendAccountID ,
10582+ currency : CONST . CURRENCY . USD ,
10583+ total : 5000 ,
10584+ stateNum : CONST . REPORT . STATE_NUM . APPROVED ,
10585+ statusNum : CONST . REPORT . STATUS_NUM . APPROVED ,
10586+ isWaitingOnBankAccount : true ,
10587+ } ;
10588+
10589+ const reimbursementQueuedAction : ReportAction = {
10590+ ...LHNTestUtils . getFakeReportAction ( ) ,
10591+ actionName : CONST . REPORT . ACTIONS . TYPE . REIMBURSEMENT_QUEUED ,
10592+ originalMessage : {
10593+ paymentType : CONST . IOU . PAYMENT_TYPE . EXPENSIFY ,
10594+ } ,
10595+ } ;
10596+
10597+ await Onyx . merge ( ONYXKEYS . SESSION , { accountID : currentUserAccountID , email : currentUserEmail } ) ;
10598+ await Promise . all ( [
10599+ Onyx . merge ( `${ ONYXKEYS . COLLECTION . REPORT } ${ chatReport . reportID } ` , chatReport ) ,
10600+ Onyx . merge ( `${ ONYXKEYS . COLLECTION . REPORT } ${ iouReportID } ` , iouReport ) ,
10601+ Onyx . merge ( `${ ONYXKEYS . COLLECTION . REPORT_ACTIONS } ${ chatReport . reportID } ` , {
10602+ [ reimbursementQueuedAction . reportActionID ] : reimbursementQueuedAction ,
10603+ } ) ,
10604+ ] ) ;
10605+ await waitForBatchedUpdates ( ) ;
10606+
10607+ // Verify GBR shows
10608+ const reason = reasonForReportToBeInOptionList ( {
10609+ report : chatReport ,
10610+ chatReport,
10611+ currentReportId : '' ,
10612+ isInFocusMode : false ,
10613+ betas : [ CONST . BETAS . DEFAULT_ROOMS ] ,
10614+ doesReportHaveViolations : false ,
10615+ excludeEmptyChats : false ,
10616+ isReportArchived : false ,
10617+ draftComment : '' ,
10618+ } ) ;
10619+ expect ( reason ) . toBe ( CONST . REPORT_IN_LHN_REASONS . HAS_GBR ) ;
10620+
10621+ // Verify wallet indicator for undefined tier
10622+ const missingPaymentMethod = getIndicatedMissingPaymentMethod ( undefined , iouReportID , reimbursementQueuedAction , { } ) ;
10623+ expect ( missingPaymentMethod ) . toBe ( 'wallet' ) ;
10624+
10625+ await Onyx . clear ( ) ;
10626+ } ) ;
10627+
10628+ /**
10629+ * When user has GOLD wallet (already enabled):
10630+ * - Payment goes through, no pending state
10631+ * - hasOutstandingChildRequest would be false (set by backend)
10632+ * - No GBR needed, no wallet button needed
10633+ */
10634+ it ( 'should NOT show GBR or wallet indicator when user has GOLD tier (wallet already enabled)' , async ( ) => {
10635+ await Onyx . clear ( ) ;
10636+
10637+ const iouReportID = '10002' ;
10638+
10639+ // No outstanding request - GOLD wallet means payment processes normally
10640+ const chatReport : Report = {
10641+ ...LHNTestUtils . getFakeReport ( [ currentUserAccountID , friendAccountID ] ) ,
10642+ hasOutstandingChildRequest : false ,
10643+ iouReportID,
10644+ } ;
10645+
10646+ const iouReport : Report = {
10647+ ...LHNTestUtils . getFakeReport ( [ currentUserAccountID , friendAccountID ] ) ,
10648+ reportID : iouReportID ,
10649+ chatReportID : chatReport . reportID ,
10650+ type : CONST . REPORT . TYPE . IOU ,
10651+ ownerAccountID : currentUserAccountID ,
10652+ managerID : friendAccountID ,
10653+ currency : CONST . CURRENCY . USD ,
10654+ total : 10000 ,
10655+ stateNum : CONST . REPORT . STATE_NUM . APPROVED ,
10656+ statusNum : CONST . REPORT . STATUS_NUM . APPROVED ,
10657+ isWaitingOnBankAccount : false ,
10658+ } ;
10659+
10660+ const reimbursementQueuedAction : ReportAction = {
10661+ ...LHNTestUtils . getFakeReportAction ( ) ,
10662+ actionName : CONST . REPORT . ACTIONS . TYPE . REIMBURSEMENT_QUEUED ,
10663+ originalMessage : {
10664+ paymentType : CONST . IOU . PAYMENT_TYPE . EXPENSIFY ,
10665+ } ,
10666+ } ;
10667+
10668+ await Onyx . merge ( ONYXKEYS . SESSION , { accountID : currentUserAccountID , email : currentUserEmail } ) ;
10669+ await Promise . all ( [
10670+ Onyx . merge ( `${ ONYXKEYS . COLLECTION . REPORT } ${ chatReport . reportID } ` , chatReport ) ,
10671+ Onyx . merge ( `${ ONYXKEYS . COLLECTION . REPORT } ${ iouReportID } ` , iouReport ) ,
10672+ Onyx . merge ( `${ ONYXKEYS . COLLECTION . REPORT_ACTIONS } ${ chatReport . reportID } ` , {
10673+ [ reimbursementQueuedAction . reportActionID ] : reimbursementQueuedAction ,
10674+ } ) ,
10675+ ] ) ;
10676+ await waitForBatchedUpdates ( ) ;
10677+
10678+ // Verify GBR does NOT show (no outstanding request for GOLD user)
10679+ const reason = reasonForReportToBeInOptionList ( {
10680+ report : chatReport ,
10681+ chatReport,
10682+ currentReportId : '' ,
10683+ isInFocusMode : false ,
10684+ betas : [ CONST . BETAS . DEFAULT_ROOMS ] ,
10685+ doesReportHaveViolations : false ,
10686+ excludeEmptyChats : false ,
10687+ isReportArchived : false ,
10688+ draftComment : '' ,
10689+ } ) ;
10690+ expect ( reason ) . not . toBe ( CONST . REPORT_IN_LHN_REASONS . HAS_GBR ) ;
10691+
10692+ // Verify NO wallet indicator for GOLD tier
10693+ const missingPaymentMethod = getIndicatedMissingPaymentMethod ( CONST . WALLET . TIER_NAME . GOLD , iouReportID , reimbursementQueuedAction , { } ) ;
10694+ expect ( missingPaymentMethod ) . toBeUndefined ( ) ;
10695+
10696+ await Onyx . clear ( ) ;
10697+ } ) ;
10698+
10699+ /**
10700+ * For non-EXPENSIFY payment types (e.g., ELSEWHERE):
10701+ * - This is not a P2P wallet scenario
10702+ * - Wallet indicator should not return 'wallet'
10703+ */
10704+ it ( 'should NOT show wallet indicator for non-EXPENSIFY payment type' , async ( ) => {
10705+ await Onyx . clear ( ) ;
10706+
10707+ const iouReportID = '10003' ;
10708+
10709+ const chatReport : Report = {
10710+ ...LHNTestUtils . getFakeReport ( [ currentUserAccountID , friendAccountID ] ) ,
10711+ hasOutstandingChildRequest : true ,
10712+ iouReportID,
10713+ } ;
10714+
10715+ const iouReport : Report = {
10716+ ...LHNTestUtils . getFakeReport ( [ currentUserAccountID , friendAccountID ] ) ,
10717+ reportID : iouReportID ,
10718+ chatReportID : chatReport . reportID ,
10719+ type : CONST . REPORT . TYPE . IOU ,
10720+ ownerAccountID : currentUserAccountID ,
10721+ managerID : friendAccountID ,
10722+ currency : CONST . CURRENCY . USD ,
10723+ total : 10000 ,
10724+ stateNum : CONST . REPORT . STATE_NUM . APPROVED ,
10725+ statusNum : CONST . REPORT . STATUS_NUM . APPROVED ,
10726+ isWaitingOnBankAccount : true ,
10727+ } ;
10728+
10729+ // Non-P2P payment type (ELSEWHERE = external/manual payment)
10730+ const reimbursementQueuedAction : ReportAction = {
10731+ ...LHNTestUtils . getFakeReportAction ( ) ,
10732+ actionName : CONST . REPORT . ACTIONS . TYPE . REIMBURSEMENT_QUEUED ,
10733+ originalMessage : {
10734+ paymentType : CONST . IOU . PAYMENT_TYPE . ELSEWHERE ,
10735+ } ,
10736+ } ;
10737+
10738+ await Onyx . merge ( ONYXKEYS . SESSION , { accountID : currentUserAccountID , email : currentUserEmail } ) ;
10739+ await Promise . all ( [
10740+ Onyx . merge ( `${ ONYXKEYS . COLLECTION . REPORT } ${ chatReport . reportID } ` , chatReport ) ,
10741+ Onyx . merge ( `${ ONYXKEYS . COLLECTION . REPORT } ${ iouReportID } ` , iouReport ) ,
10742+ Onyx . merge ( `${ ONYXKEYS . COLLECTION . REPORT_ACTIONS } ${ chatReport . reportID } ` , {
10743+ [ reimbursementQueuedAction . reportActionID ] : reimbursementQueuedAction ,
10744+ } ) ,
10745+ ] ) ;
10746+ await waitForBatchedUpdates ( ) ;
10747+
10748+ // GBR may still show (hasOutstandingChildRequest: true) but for different reason
10749+ const reason = reasonForReportToBeInOptionList ( {
10750+ report : chatReport ,
10751+ chatReport,
10752+ currentReportId : '' ,
10753+ isInFocusMode : false ,
10754+ betas : [ CONST . BETAS . DEFAULT_ROOMS ] ,
10755+ doesReportHaveViolations : false ,
10756+ excludeEmptyChats : false ,
10757+ isReportArchived : false ,
10758+ draftComment : '' ,
10759+ } ) ;
10760+ expect ( reason ) . toBe ( CONST . REPORT_IN_LHN_REASONS . HAS_GBR ) ;
10761+
10762+ // But wallet indicator should NOT be 'wallet' for non-EXPENSIFY payment
10763+ // (would be 'bankAccount' or undefined depending on bank account status)
10764+ const missingPaymentMethod = getIndicatedMissingPaymentMethod ( CONST . WALLET . TIER_NAME . SILVER , iouReportID , reimbursementQueuedAction , { } ) ;
10765+ expect ( missingPaymentMethod ) . not . toBe ( 'wallet' ) ;
10766+
10767+ await Onyx . clear ( ) ;
10768+ } ) ;
10769+ } ) ;
1048210770} ) ;
0 commit comments