22using Bit . Core . Billing ;
33using Bit . Core . Billing . Enums ;
44using Bit . Core . Billing . Pricing ;
5+ using Bit . Core . Exceptions ;
56using Bit . Core . Services ;
67using Bit . Test . Common . AutoFixture ;
78using Bit . Test . Common . AutoFixture . Attributes ;
@@ -445,6 +446,181 @@ await Assert.ThrowsAsync<BillingException>(() =>
445446
446447 #endregion
447448
449+ #region ListPremiumPlans Tests
450+
451+ [ Fact ]
452+ public async Task ListPremiumPlans_Success_ReturnsPremiumPlans ( )
453+ {
454+ // Arrange
455+ var mockHttp = new MockHttpMessageHandler ( ) ;
456+ var plansJson = $@ "[
457+ { CreatePremiumPlanJson ( "Premium" , true , null , 10M , "price_premium" , 4M , "price_storage" , 1 ) } ,
458+ { CreatePremiumPlanJson ( "Premium Legacy" , false , 2019 , 10M , "price_premium_legacy" , 4M , "price_storage_legacy" , 1 ) }
459+ ]" ;
460+
461+ mockHttp . When ( HttpMethod . Get , "*/plans/premium" )
462+ . Respond ( "application/json" , plansJson ) ;
463+
464+ var featureService = Substitute . For < IFeatureService > ( ) ;
465+ var globalSettings = new GlobalSettings { SelfHosted = false } ;
466+
467+ var httpClient = new HttpClient ( mockHttp )
468+ {
469+ BaseAddress = new Uri ( "https://test.com/" )
470+ } ;
471+
472+ var logger = Substitute . For < ILogger < PricingClient > > ( ) ;
473+ var pricingClient = new PricingClient ( featureService , globalSettings , httpClient , logger ) ;
474+
475+ // Act
476+ var result = await pricingClient . ListPremiumPlans ( ) ;
477+
478+ // Assert
479+ Assert . NotNull ( result ) ;
480+ Assert . Equal ( 2 , result . Count ) ;
481+ Assert . Equal ( "Premium" , result [ 0 ] . Name ) ;
482+ Assert . True ( result [ 0 ] . Available ) ;
483+ Assert . Null ( result [ 0 ] . LegacyYear ) ;
484+ Assert . Equal ( 10M , result [ 0 ] . Seat . Price ) ;
485+ Assert . Equal ( "price_premium" , result [ 0 ] . Seat . StripePriceId ) ;
486+ Assert . Equal ( 4M , result [ 0 ] . Storage . Price ) ;
487+ Assert . Equal ( "price_storage" , result [ 0 ] . Storage . StripePriceId ) ;
488+ Assert . Equal ( 1 , result [ 0 ] . Storage . Provided ) ;
489+ Assert . Equal ( "Premium Legacy" , result [ 1 ] . Name ) ;
490+ Assert . False ( result [ 1 ] . Available ) ;
491+ Assert . Equal ( 2019 , result [ 1 ] . LegacyYear ) ;
492+ }
493+
494+ [ Theory , BitAutoData ]
495+ public async Task ListPremiumPlans_WhenSelfHosted_ReturnsEmptyList (
496+ SutProvider < PricingClient > sutProvider )
497+ {
498+ // Arrange
499+ sutProvider . GetDependency < GlobalSettings > ( ) . SelfHosted = true ;
500+
501+ // Act
502+ var result = await sutProvider . Sut . ListPremiumPlans ( ) ;
503+
504+ // Assert
505+ Assert . NotNull ( result ) ;
506+ Assert . Empty ( result ) ;
507+ }
508+
509+ [ Fact ]
510+ public async Task ListPremiumPlans_WhenPricingServiceReturnsError_ThrowsBillingException ( )
511+ {
512+ // Arrange
513+ var mockHttp = new MockHttpMessageHandler ( ) ;
514+ mockHttp . When ( HttpMethod . Get , "*/plans/premium" )
515+ . Respond ( HttpStatusCode . InternalServerError ) ;
516+
517+ var featureService = Substitute . For < IFeatureService > ( ) ;
518+ var globalSettings = new GlobalSettings { SelfHosted = false } ;
519+
520+ var httpClient = new HttpClient ( mockHttp )
521+ {
522+ BaseAddress = new Uri ( "https://test.com/" )
523+ } ;
524+
525+ var logger = Substitute . For < ILogger < PricingClient > > ( ) ;
526+ var pricingClient = new PricingClient ( featureService , globalSettings , httpClient , logger ) ;
527+
528+ // Act & Assert
529+ await Assert . ThrowsAsync < BillingException > ( ( ) =>
530+ pricingClient . ListPremiumPlans ( ) ) ;
531+ }
532+
533+ #endregion
534+
535+ #region GetAvailablePremiumPlan Tests
536+
537+ [ Fact ]
538+ public async Task GetAvailablePremiumPlan_WithAvailablePlan_ReturnsIt ( )
539+ {
540+ // Arrange
541+ var mockHttp = new MockHttpMessageHandler ( ) ;
542+ var plansJson = $@ "[
543+ { CreatePremiumPlanJson ( "Premium Legacy" , false , 2019 , 10M , "price_legacy" , 4M , "price_storage_legacy" , 1 ) } ,
544+ { CreatePremiumPlanJson ( "Premium" , true , null , 10M , "price_premium" , 4M , "price_storage" , 1 ) }
545+ ]" ;
546+
547+ mockHttp . When ( HttpMethod . Get , "*/plans/premium" )
548+ . Respond ( "application/json" , plansJson ) ;
549+
550+ var featureService = Substitute . For < IFeatureService > ( ) ;
551+ var globalSettings = new GlobalSettings { SelfHosted = false } ;
552+
553+ var httpClient = new HttpClient ( mockHttp )
554+ {
555+ BaseAddress = new Uri ( "https://test.com/" )
556+ } ;
557+
558+ var logger = Substitute . For < ILogger < PricingClient > > ( ) ;
559+ var pricingClient = new PricingClient ( featureService , globalSettings , httpClient , logger ) ;
560+
561+ // Act
562+ var result = await pricingClient . GetAvailablePremiumPlan ( ) ;
563+
564+ // Assert
565+ Assert . NotNull ( result ) ;
566+ Assert . Equal ( "Premium" , result . Name ) ;
567+ Assert . True ( result . Available ) ;
568+ }
569+
570+ [ Fact ]
571+ public async Task GetAvailablePremiumPlan_WithNoAvailablePlan_ThrowsNotFoundException ( )
572+ {
573+ // Arrange
574+ var mockHttp = new MockHttpMessageHandler ( ) ;
575+ var plansJson = $@ "[
576+ { CreatePremiumPlanJson ( "Premium Legacy" , false , 2019 , 10M , "price_legacy" , 4M , "price_storage_legacy" , 1 ) }
577+ ]" ;
578+
579+ mockHttp . When ( HttpMethod . Get , "*/plans/premium" )
580+ . Respond ( "application/json" , plansJson ) ;
581+
582+ var featureService = Substitute . For < IFeatureService > ( ) ;
583+ var globalSettings = new GlobalSettings { SelfHosted = false } ;
584+
585+ var httpClient = new HttpClient ( mockHttp )
586+ {
587+ BaseAddress = new Uri ( "https://test.com/" )
588+ } ;
589+
590+ var logger = Substitute . For < ILogger < PricingClient > > ( ) ;
591+ var pricingClient = new PricingClient ( featureService , globalSettings , httpClient , logger ) ;
592+
593+ // Act & Assert
594+ await Assert . ThrowsAsync < NotFoundException > ( ( ) =>
595+ pricingClient . GetAvailablePremiumPlan ( ) ) ;
596+ }
597+
598+ [ Fact ]
599+ public async Task GetAvailablePremiumPlan_WithEmptyList_ThrowsNotFoundException ( )
600+ {
601+ // Arrange
602+ var mockHttp = new MockHttpMessageHandler ( ) ;
603+ mockHttp . When ( HttpMethod . Get , "*/plans/premium" )
604+ . Respond ( "application/json" , "[]" ) ;
605+
606+ var featureService = Substitute . For < IFeatureService > ( ) ;
607+ var globalSettings = new GlobalSettings { SelfHosted = false } ;
608+
609+ var httpClient = new HttpClient ( mockHttp )
610+ {
611+ BaseAddress = new Uri ( "https://test.com/" )
612+ } ;
613+
614+ var logger = Substitute . For < ILogger < PricingClient > > ( ) ;
615+ var pricingClient = new PricingClient ( featureService , globalSettings , httpClient , logger ) ;
616+
617+ // Act & Assert
618+ await Assert . ThrowsAsync < NotFoundException > ( ( ) =>
619+ pricingClient . GetAvailablePremiumPlan ( ) ) ;
620+ }
621+
622+ #endregion
623+
448624 private static string CreatePlanJson (
449625 string lookupKey ,
450626 string name ,
@@ -471,4 +647,32 @@ private static string CreatePlanJson(
471647 }}
472648 }}" ;
473649 }
650+
651+ private static string CreatePremiumPlanJson (
652+ string name ,
653+ bool available ,
654+ int ? legacyYear ,
655+ decimal seatPrice ,
656+ string seatStripePriceId ,
657+ decimal storagePrice ,
658+ string storageStripePriceId ,
659+ int storageProvided )
660+ {
661+ var legacyYearJson = legacyYear . HasValue ? legacyYear . Value . ToString ( ) : "null" ;
662+ return $@ "{{
663+ ""name"": ""{ name } "",
664+ ""available"": { available . ToString ( ) . ToLower ( ) } ,
665+ ""legacyYear"": { legacyYearJson } ,
666+ ""seat"": {{
667+ ""stripePriceId"": ""{ seatStripePriceId } "",
668+ ""price"": { seatPrice } ,
669+ ""provided"": 0
670+ }},
671+ ""storage"": {{
672+ ""stripePriceId"": ""{ storageStripePriceId } "",
673+ ""price"": { storagePrice } ,
674+ ""provided"": { storageProvided }
675+ }}
676+ }}" ;
677+ }
474678}
0 commit comments