@@ -551,5 +551,166 @@ describe('CardFeedErrors Derived Value', () => {
551551 expect ( result . all . shouldShowRBR ) . toBe ( false ) ;
552552 } ) ;
553553 } ) ;
554+
555+ describe ( 'feed selector RBR - per-feed granularity for multi-feed workspaces' , ( ) => {
556+ const SHARED_WORKSPACE_ACCOUNT_ID = 77777777 ;
557+ const AMEX_FEED = {
558+ workspaceAccountID : SHARED_WORKSPACE_ACCOUNT_ID ,
559+ feedName : CONST . COMPANY_CARD . FEED_BANK_NAME . AMEX_DIRECT ,
560+ feedNameWithDomainID : getCardFeedWithDomainID ( CONST . COMPANY_CARD . FEED_BANK_NAME . AMEX_DIRECT , SHARED_WORKSPACE_ACCOUNT_ID ) ,
561+ } ;
562+ const CHASE_FEED = {
563+ workspaceAccountID : SHARED_WORKSPACE_ACCOUNT_ID ,
564+ feedName : CONST . COMPANY_CARD . FEED_BANK_NAME . CHASE ,
565+ feedNameWithDomainID : getCardFeedWithDomainID ( CONST . COMPANY_CARD . FEED_BANK_NAME . CHASE , SHARED_WORKSPACE_ACCOUNT_ID ) ,
566+ } ;
567+
568+ it ( 'should mark only the broken feed when another feed in the same workspace is healthy' , ( ) => {
569+ const brokenCard = createCard ( {
570+ cardID : CARD_IDS . card1 ,
571+ bank : CHASE_FEED . feedName ,
572+ fundID : String ( SHARED_WORKSPACE_ACCOUNT_ID ) ,
573+ lastScrapeResult : 403 ,
574+ } ) ;
575+ const healthyCard = createCard ( {
576+ cardID : CARD_IDS . card2 ,
577+ bank : AMEX_FEED . feedName ,
578+ fundID : String ( SHARED_WORKSPACE_ACCOUNT_ID ) ,
579+ lastScrapeResult : 200 ,
580+ } ) ;
581+
582+ const globalCardList : CardList = {
583+ [ CARD_IDS . card1 ] : brokenCard ,
584+ [ CARD_IDS . card2 ] : healthyCard ,
585+ } ;
586+
587+ const result = cardFeedErrorsConfig . compute ( [ globalCardList , { } , { } ] , DERIVED_VALUE_CONTEXT ) ;
588+
589+ expect ( result . shouldShowRbrForFeedNameWithDomainID [ CHASE_FEED . feedNameWithDomainID ] ) . toBe ( true ) ;
590+ expect ( result . shouldShowRbrForFeedNameWithDomainID [ AMEX_FEED . feedNameWithDomainID ] ) . toBe ( false ) ;
591+ } ) ;
592+
593+ it ( 'should clear RBR for a fixed feed while keeping it for other broken feeds' , ( ) => {
594+ const brokenMockCard = createCard ( {
595+ cardID : CARD_IDS . card1 ,
596+ bank : CHASE_FEED . feedName ,
597+ fundID : String ( SHARED_WORKSPACE_ACCOUNT_ID ) ,
598+ lastScrapeResult : 403 ,
599+ } ) ;
600+ const fixedAmexCard = createCard ( {
601+ cardID : CARD_IDS . card2 ,
602+ bank : AMEX_FEED . feedName ,
603+ fundID : String ( SHARED_WORKSPACE_ACCOUNT_ID ) ,
604+ lastScrapeResult : 200 ,
605+ } ) ;
606+
607+ const globalCardList : CardList = {
608+ [ CARD_IDS . card1 ] : brokenMockCard ,
609+ [ CARD_IDS . card2 ] : fixedAmexCard ,
610+ } ;
611+
612+ const result = cardFeedErrorsConfig . compute ( [ globalCardList , { } , { } ] , DERIVED_VALUE_CONTEXT ) ;
613+
614+ expect ( result . shouldShowRbrForFeedNameWithDomainID [ CHASE_FEED . feedNameWithDomainID ] ) . toBe ( true ) ;
615+ expect ( result . shouldShowRbrForFeedNameWithDomainID [ AMEX_FEED . feedNameWithDomainID ] ) . toBe ( false ) ;
616+ expect ( result . shouldShowRbrForWorkspaceAccountID [ SHARED_WORKSPACE_ACCOUNT_ID ] ) . toBe ( true ) ;
617+ } ) ;
618+
619+ it ( 'should clear all RBR when all feeds in a workspace are healthy' , ( ) => {
620+ const healthyChaseCard = createCard ( {
621+ cardID : CARD_IDS . card1 ,
622+ bank : CHASE_FEED . feedName ,
623+ fundID : String ( SHARED_WORKSPACE_ACCOUNT_ID ) ,
624+ lastScrapeResult : 200 ,
625+ } ) ;
626+ const healthyAmexCard = createCard ( {
627+ cardID : CARD_IDS . card2 ,
628+ bank : AMEX_FEED . feedName ,
629+ fundID : String ( SHARED_WORKSPACE_ACCOUNT_ID ) ,
630+ lastScrapeResult : 200 ,
631+ } ) ;
632+
633+ const globalCardList : CardList = {
634+ [ CARD_IDS . card1 ] : healthyChaseCard ,
635+ [ CARD_IDS . card2 ] : healthyAmexCard ,
636+ } ;
637+
638+ const result = cardFeedErrorsConfig . compute ( [ globalCardList , { } , { } ] , DERIVED_VALUE_CONTEXT ) ;
639+
640+ expect ( result . shouldShowRbrForFeedNameWithDomainID [ CHASE_FEED . feedNameWithDomainID ] ) . toBe ( false ) ;
641+ expect ( result . shouldShowRbrForFeedNameWithDomainID [ AMEX_FEED . feedNameWithDomainID ] ) . toBe ( false ) ;
642+ expect ( result . shouldShowRbrForWorkspaceAccountID [ SHARED_WORKSPACE_ACCOUNT_ID ] ) . toBe ( false ) ;
643+ } ) ;
644+
645+ it ( 'should show RBR on both feeds when both have broken connections' , ( ) => {
646+ const brokenChaseCard = createCard ( {
647+ cardID : CARD_IDS . card1 ,
648+ bank : CHASE_FEED . feedName ,
649+ fundID : String ( SHARED_WORKSPACE_ACCOUNT_ID ) ,
650+ lastScrapeResult : 403 ,
651+ } ) ;
652+ const brokenAmexCard = createCard ( {
653+ cardID : CARD_IDS . card2 ,
654+ bank : AMEX_FEED . feedName ,
655+ fundID : String ( SHARED_WORKSPACE_ACCOUNT_ID ) ,
656+ lastScrapeResult : 401 ,
657+ } ) ;
658+
659+ const globalCardList : CardList = {
660+ [ CARD_IDS . card1 ] : brokenChaseCard ,
661+ [ CARD_IDS . card2 ] : brokenAmexCard ,
662+ } ;
663+
664+ const result = cardFeedErrorsConfig . compute ( [ globalCardList , { } , { } ] , DERIVED_VALUE_CONTEXT ) ;
665+
666+ expect ( result . shouldShowRbrForFeedNameWithDomainID [ CHASE_FEED . feedNameWithDomainID ] ) . toBe ( true ) ;
667+ expect ( result . shouldShowRbrForFeedNameWithDomainID [ AMEX_FEED . feedNameWithDomainID ] ) . toBe ( true ) ;
668+ } ) ;
669+
670+ it ( 'should only mark the feed with errors when mixed feed-level error and broken connection' , ( ) => {
671+ const healthyChaseCard = createCard ( {
672+ cardID : CARD_IDS . card1 ,
673+ bank : CHASE_FEED . feedName ,
674+ fundID : String ( SHARED_WORKSPACE_ACCOUNT_ID ) ,
675+ lastScrapeResult : 200 ,
676+ } ) ;
677+ const healthyAmexCard = createCard ( {
678+ cardID : CARD_IDS . card2 ,
679+ bank : AMEX_FEED . feedName ,
680+ fundID : String ( SHARED_WORKSPACE_ACCOUNT_ID ) ,
681+ lastScrapeResult : 200 ,
682+ } ) ;
683+
684+ const globalCardList : CardList = {
685+ [ CARD_IDS . card1 ] : healthyChaseCard ,
686+ [ CARD_IDS . card2 ] : healthyAmexCard ,
687+ } ;
688+
689+ const cardFeeds : OnyxCollection < CardFeeds > = {
690+ [ `${ ONYXKEYS . COLLECTION . SHARED_NVP_PRIVATE_DOMAIN_MEMBER } ${ SHARED_WORKSPACE_ACCOUNT_ID } ` ] : {
691+ settings : {
692+ companyCards : {
693+ [ AMEX_FEED . feedName ] : {
694+ pending : false ,
695+ errors : { feedError : 'Connection expired' } ,
696+ } ,
697+ [ CHASE_FEED . feedName ] : {
698+ pending : false ,
699+ } ,
700+ } ,
701+ oAuthAccountDetails : {
702+ [ AMEX_FEED . feedName ] : { accountList : [ 'CREDIT CARD...1234' ] , credentials : 'xxxxx' , expiration : 1730998958 } ,
703+ [ CHASE_FEED . feedName ] : { accountList : [ 'CREDIT CARD...5678' ] , credentials : 'xxxxx' , expiration : 1730998958 } ,
704+ } ,
705+ } ,
706+ } ,
707+ } ;
708+
709+ const result = cardFeedErrorsConfig . compute ( [ globalCardList , { } , cardFeeds ] , DERIVED_VALUE_CONTEXT ) ;
710+
711+ expect ( result . shouldShowRbrForFeedNameWithDomainID [ AMEX_FEED . feedNameWithDomainID ] ) . toBe ( true ) ;
712+ expect ( result . shouldShowRbrForFeedNameWithDomainID [ CHASE_FEED . feedNameWithDomainID ] ) . toBe ( false ) ;
713+ } ) ;
714+ } ) ;
554715 } ) ;
555716} ) ;
0 commit comments