@ -1,8 +1,9 @@
@@ -1,8 +1,9 @@
using Bit.Billing.Services ;
using Bit.Billing.Services.Implementations ;
using Bit.Billing.Test.Utilities ;
using Bit.Core.AdminConsole.Repositories ;
using Bit.Core.Billing.Caches ;
using Bit.Core.Repositories ;
using Bit.Core.Settings ;
using Microsoft.Extensions.Logging ;
using NSubstitute ;
using Stripe ;
using Xunit ;
@ -11,6 +12,9 @@ namespace Bit.Billing.Test.Services;
@@ -11,6 +12,9 @@ namespace Bit.Billing.Test.Services;
public class StripeEventServiceTests
{
private readonly IOrganizationRepository _ organizationRepository ;
private readonly IProviderRepository _ providerRepository ;
private readonly ISetupIntentCache _ setupIntentCache ;
private readonly IStripeFacade _ stripeFacade ;
private readonly StripeEventService _ stripeEventService ;
@ -20,8 +24,11 @@ public class StripeEventServiceTests
@@ -20,8 +24,11 @@ public class StripeEventServiceTests
var baseServiceUriSettings = new GlobalSettings . BaseServiceUriSettings ( globalSettings ) { CloudRegion = "US" } ;
globalSettings . BaseServiceUri = baseServiceUriSettings ;
_ organizationRepository = Substitute . For < IOrganizationRepository > ( ) ;
_ providerRepository = Substitute . For < IProviderRepository > ( ) ;
_ setupIntentCache = Substitute . For < ISetupIntentCache > ( ) ;
_ stripeFacade = Substitute . For < IStripeFacade > ( ) ;
_ stripeEventService = new StripeEventService ( globalSettings , Substitute . For < ILogger < StripeEventService > > ( ) , _ stripeFacade ) ;
_ stripeEventService = new StripeEventService ( globalSettings , _ organizationRepository , _ providerRepository , _ setupIntentCache , _ stripeFacade ) ;
}
#region GetCharge
@ -29,50 +36,44 @@ public class StripeEventServiceTests
@@ -29,50 +36,44 @@ public class StripeEventServiceTests
public async Task GetCharge_EventNotChargeRelated_ThrowsException ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . InvoiceCreated ) ;
var stripeEvent = CreateMockEvent ( "evt_test" , "invoice.created" , new Invoice { Id = "in_test" } ) ;
// Act
var function = async ( ) = > await _ stripeEventService . GetCharge ( stripeEvent ) ;
// Assert
var exception = await Assert . ThrowsAsync < Exception > ( function ) ;
// Act & Assert
var exception = await Assert . ThrowsAsync < Exception > ( async ( ) = > await _ stripeEventService . GetCharge ( stripeEvent ) ) ;
Assert . Equal ( $"Stripe event with ID '{stripeEvent.Id}' does not have object matching type '{nameof(Charge)}'" , exception . Message ) ;
await _ stripeFacade . DidNotReceiveWithAnyArgs ( ) . GetCharge (
Arg . Any < string > ( ) ,
Arg . Any < ChargeGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Any < ChargeGetOptions > ( ) ) ;
}
[Fact]
public async Task GetCharge_NotFresh_ReturnsEventCharge ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . ChargeSucceeded ) ;
var mockCharge = new Charge { Id = "ch_test" , Amount = 1 0 0 0 } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "charge.succeeded" , mockCharge ) ;
// Act
var charge = await _ stripeEventService . GetCharge ( stripeEvent ) ;
// Assert
Assert . Equivalent ( stripeEvent . Data . Object as Charge , charge , true ) ;
Assert . Equal ( mockCharge . Id , charge . Id ) ;
Assert . Equal ( mockCharge . Amount , charge . Amount ) ;
await _ stripeFacade . DidNotReceiveWithAnyArgs ( ) . GetCharge (
Arg . Any < string > ( ) ,
Arg . Any < ChargeGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Any < ChargeGetOptions > ( ) ) ;
}
[Fact]
public async Task GetCharge_Fresh_Expand_ReturnsAPICharge ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . ChargeSucceeded ) ;
var eventCharge = new Charge { Id = "ch_test" , Amount = 1 0 0 0 } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "charge.succeeded" , eventCharge ) ;
var eventCharge = stripeEvent . Data . Object as Charge ;
var apiCharge = Copy ( eventCharge ) ;
var apiCharge = new Charge { Id = "ch_test" , Amount = 2 0 0 0 } ;
var expand = new List < string > { "customer" } ;
@ -90,9 +91,7 @@ public class StripeEventServiceTests
@@ -90,9 +91,7 @@ public class StripeEventServiceTests
await _ stripeFacade . Received ( ) . GetCharge (
apiCharge . Id ,
Arg . Is < ChargeGetOptions > ( options = > options . Expand = = expand ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Is < ChargeGetOptions > ( options = > options . Expand = = expand ) ) ;
}
# endregion
@ -101,50 +100,44 @@ public class StripeEventServiceTests
@@ -101,50 +100,44 @@ public class StripeEventServiceTests
public async Task GetCustomer_EventNotCustomerRelated_ThrowsException ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . InvoiceCreated ) ;
// Act
var function = async ( ) = > await _ stripeEventService . GetCustomer ( stripeEvent ) ;
var stripeEvent = CreateMockEvent ( "evt_test" , "invoice.created" , new Invoice { Id = "in_test" } ) ;
// Assert
var exception = await Assert . ThrowsAsync < Exception > ( function ) ;
// Act & Assert
var exception = await Assert . ThrowsAsync < Exception > ( async ( ) = > await _ stripeEventService . GetCustomer ( stripeEvent ) ) ;
Assert . Equal ( $"Stripe event with ID '{stripeEvent.Id}' does not have object matching type '{nameof(Customer)}'" , exception . Message ) ;
await _ stripeFacade . DidNotReceiveWithAnyArgs ( ) . GetCustomer (
Arg . Any < string > ( ) ,
Arg . Any < CustomerGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Any < CustomerGetOptions > ( ) ) ;
}
[Fact]
public async Task GetCustomer_NotFresh_ReturnsEventCustomer ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . CustomerUpdated ) ;
var mockCustomer = new Customer { Id = "cus_test" , Email = "test@example.com" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "customer.updated" , mockCustomer ) ;
// Act
var customer = await _ stripeEventService . GetCustomer ( stripeEvent ) ;
// Assert
Assert . Equivalent ( stripeEvent . Data . Object as Customer , customer , true ) ;
Assert . Equal ( mockCustomer . Id , customer . Id ) ;
Assert . Equal ( mockCustomer . Email , customer . Email ) ;
await _ stripeFacade . DidNotReceiveWithAnyArgs ( ) . GetCustomer (
Arg . Any < string > ( ) ,
Arg . Any < CustomerGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Any < CustomerGetOptions > ( ) ) ;
}
[Fact]
public async Task GetCustomer_Fresh_Expand_ReturnsAPICustomer ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . CustomerUpdated ) ;
var eventCustomer = stripeEvent . Data . Object as Customer ;
var eventCustomer = new Customer { Id = "cus_test" , Email = "test@example.com" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "customer.updated" , eventCustomer ) ;
var apiCustomer = Copy ( eventCustomer ) ;
var apiCustomer = new Customer { Id = "cus_test" , Email = "updated@example.com" } ;
var expand = new List < string > { "subscriptions" } ;
@ -162,9 +155,7 @@ public class StripeEventServiceTests
@@ -162,9 +155,7 @@ public class StripeEventServiceTests
await _ stripeFacade . Received ( ) . GetCustomer (
apiCustomer . Id ,
Arg . Is < CustomerGetOptions > ( options = > options . Expand = = expand ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Is < CustomerGetOptions > ( options = > options . Expand = = expand ) ) ;
}
# endregion
@ -173,50 +164,44 @@ public class StripeEventServiceTests
@@ -173,50 +164,44 @@ public class StripeEventServiceTests
public async Task GetInvoice_EventNotInvoiceRelated_ThrowsException ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . CustomerUpdated ) ;
var stripeEvent = CreateMockEvent ( "evt_test" , "customer.updated" , new Customer { Id = "cus_test" } ) ;
// Act
var function = async ( ) = > await _ stripeEventService . GetInvoice ( stripeEvent ) ;
// Assert
var exception = await Assert . ThrowsAsync < Exception > ( function ) ;
// Act & Assert
var exception = await Assert . ThrowsAsync < Exception > ( async ( ) = > await _ stripeEventService . GetInvoice ( stripeEvent ) ) ;
Assert . Equal ( $"Stripe event with ID '{stripeEvent.Id}' does not have object matching type '{nameof(Invoice)}'" , exception . Message ) ;
await _ stripeFacade . DidNotReceiveWithAnyArgs ( ) . GetInvoice (
Arg . Any < string > ( ) ,
Arg . Any < InvoiceGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Any < InvoiceGetOptions > ( ) ) ;
}
[Fact]
public async Task GetInvoice_NotFresh_ReturnsEventInvoice ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . InvoiceCreated ) ;
var mockInvoice = new Invoice { Id = "in_test" , AmountDue = 1 0 0 0 } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "invoice.created" , mockInvoice ) ;
// Act
var invoice = await _ stripeEventService . GetInvoice ( stripeEvent ) ;
// Assert
Assert . Equivalent ( stripeEvent . Data . Object as Invoice , invoice , true ) ;
Assert . Equal ( mockInvoice . Id , invoice . Id ) ;
Assert . Equal ( mockInvoice . AmountDue , invoice . AmountDue ) ;
await _ stripeFacade . DidNotReceiveWithAnyArgs ( ) . GetInvoice (
Arg . Any < string > ( ) ,
Arg . Any < InvoiceGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Any < InvoiceGetOptions > ( ) ) ;
}
[Fact]
public async Task GetInvoice_Fresh_Expand_ReturnsAPIInvoice ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . InvoiceCreated ) ;
var eventInvoice = new Invoice { Id = "in_test" , AmountDue = 1 0 0 0 } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "invoice.created" , eventInvoice ) ;
var eventInvoice = stripeEvent . Data . Object as Invoice ;
var apiInvoice = Copy ( eventInvoice ) ;
var apiInvoice = new Invoice { Id = "in_test" , AmountDue = 2 0 0 0 } ;
var expand = new List < string > { "customer" } ;
@ -234,9 +219,7 @@ public class StripeEventServiceTests
@@ -234,9 +219,7 @@ public class StripeEventServiceTests
await _ stripeFacade . Received ( ) . GetInvoice (
apiInvoice . Id ,
Arg . Is < InvoiceGetOptions > ( options = > options . Expand = = expand ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Is < InvoiceGetOptions > ( options = > options . Expand = = expand ) ) ;
}
# endregion
@ -245,50 +228,44 @@ public class StripeEventServiceTests
@@ -245,50 +228,44 @@ public class StripeEventServiceTests
public async Task GetPaymentMethod_EventNotPaymentMethodRelated_ThrowsException ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . CustomerUpdated ) ;
// Act
var function = async ( ) = > await _ stripeEventService . GetPaymentMethod ( stripeEvent ) ;
var stripeEvent = CreateMockEvent ( "evt_test" , "customer.updated" , new Customer { Id = "cus_test" } ) ;
// Assert
var exception = await Assert . ThrowsAsync < Exception > ( function ) ;
// Act & Assert
var exception = await Assert . ThrowsAsync < Exception > ( async ( ) = > await _ stripeEventService . GetPaymentMethod ( stripeEvent ) ) ;
Assert . Equal ( $"Stripe event with ID '{stripeEvent.Id}' does not have object matching type '{nameof(PaymentMethod)}'" , exception . Message ) ;
await _ stripeFacade . DidNotReceiveWithAnyArgs ( ) . GetPaymentMethod (
Arg . Any < string > ( ) ,
Arg . Any < PaymentMethodGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Any < PaymentMethodGetOptions > ( ) ) ;
}
[Fact]
public async Task GetPaymentMethod_NotFresh_ReturnsEventPaymentMethod ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . PaymentMethodAttached ) ;
var mockPaymentMethod = new PaymentMethod { Id = "pm_test" , Type = "card" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "payment_method.attached" , mockPaymentMethod ) ;
// Act
var paymentMethod = await _ stripeEventService . GetPaymentMethod ( stripeEvent ) ;
// Assert
Assert . Equivalent ( stripeEvent . Data . Object as PaymentMethod , paymentMethod , true ) ;
Assert . Equal ( mockPaymentMethod . Id , paymentMethod . Id ) ;
Assert . Equal ( mockPaymentMethod . Type , paymentMethod . Type ) ;
await _ stripeFacade . DidNotReceiveWithAnyArgs ( ) . GetPaymentMethod (
Arg . Any < string > ( ) ,
Arg . Any < PaymentMethodGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Any < PaymentMethodGetOptions > ( ) ) ;
}
[Fact]
public async Task GetPaymentMethod_Fresh_Expand_ReturnsAPIPaymentMethod ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . PaymentMethodAttached ) ;
var eventPaymentMethod = stripeEvent . Data . Object as PaymentMethod ;
var eventPaymentMethod = new PaymentMethod { Id = "pm_test" , Type = "card" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "payment_method.attached" , eventPaymentMethod ) ;
var apiPaymentMethod = Copy ( eventPaymentMethod ) ;
var apiPaymentMethod = new PaymentMethod { Id = "pm_test" , Type = "card" } ;
var expand = new List < string > { "customer" } ;
@ -306,9 +283,7 @@ public class StripeEventServiceTests
@@ -306,9 +283,7 @@ public class StripeEventServiceTests
await _ stripeFacade . Received ( ) . GetPaymentMethod (
apiPaymentMethod . Id ,
Arg . Is < PaymentMethodGetOptions > ( options = > options . Expand = = expand ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Is < PaymentMethodGetOptions > ( options = > options . Expand = = expand ) ) ;
}
# endregion
@ -317,50 +292,44 @@ public class StripeEventServiceTests
@@ -317,50 +292,44 @@ public class StripeEventServiceTests
public async Task GetSubscription_EventNotSubscriptionRelated_ThrowsException ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . CustomerUpdated ) ;
var stripeEvent = CreateMockEvent ( "evt_test" , "customer.updated" , new Customer { Id = "cus_test" } ) ;
// Act
var function = async ( ) = > await _ stripeEventService . GetSubscription ( stripeEvent ) ;
// Assert
var exception = await Assert . ThrowsAsync < Exception > ( function ) ;
// Act & Assert
var exception = await Assert . ThrowsAsync < Exception > ( async ( ) = > await _ stripeEventService . GetSubscription ( stripeEvent ) ) ;
Assert . Equal ( $"Stripe event with ID '{stripeEvent.Id}' does not have object matching type '{nameof(Subscription)}'" , exception . Message ) ;
await _ stripeFacade . DidNotReceiveWithAnyArgs ( ) . GetSubscription (
Arg . Any < string > ( ) ,
Arg . Any < SubscriptionGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Any < SubscriptionGetOptions > ( ) ) ;
}
[Fact]
public async Task GetSubscription_NotFresh_ReturnsEventSubscription ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . CustomerSubscriptionUpdated ) ;
var mockSubscription = new Subscription { Id = "sub_test" , Status = "active" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "customer.subscription.updated" , mockSubscription ) ;
// Act
var subscription = await _ stripeEventService . GetSubscription ( stripeEvent ) ;
// Assert
Assert . Equivalent ( stripeEvent . Data . Object as Subscription , subscription , true ) ;
Assert . Equal ( mockSubscription . Id , subscription . Id ) ;
Assert . Equal ( mockSubscription . Status , subscription . Status ) ;
await _ stripeFacade . DidNotReceiveWithAnyArgs ( ) . GetSubscription (
Arg . Any < string > ( ) ,
Arg . Any < SubscriptionGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Any < SubscriptionGetOptions > ( ) ) ;
}
[Fact]
public async Task GetSubscription_Fresh_Expand_ReturnsAPISubscription ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . CustomerSubscriptionUpdated ) ;
var eventSubscription = new Subscription { Id = "sub_test" , Status = "active" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "customer.subscription.updated" , eventSubscription ) ;
var eventSubscription = stripeEvent . Data . Object as Subscription ;
var apiSubscription = Copy ( eventSubscription ) ;
var apiSubscription = new Subscription { Id = "sub_test" , Status = "canceled" } ;
var expand = new List < string > { "customer" } ;
@ -378,29 +347,89 @@ public class StripeEventServiceTests
@@ -378,29 +347,89 @@ public class StripeEventServiceTests
await _ stripeFacade . Received ( ) . GetSubscription (
apiSubscription . Id ,
Arg . Is < SubscriptionGetOptions > ( options = > options . Expand = = expand ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
Arg . Is < SubscriptionGetOptions > ( options = > options . Expand = = expand ) ) ;
}
# endregion
#region ValidateCloudRegion
#region GetSetupIntent
[Fact]
public async Task ValidateCloudRegion_SubscriptionUpdated_Success ( )
public async Task GetSetupIntent_EventNotSetupIntentRelated_ThrowsException ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . CustomerSubscriptionUpdated ) ;
var stripeEvent = CreateMockEvent ( "evt_test" , "customer.updated" , new Customer { Id = "cus_test" } ) ;
// Act & Assert
var exception = await Assert . ThrowsAsync < Exception > ( async ( ) = > await _ stripeEventService . GetSetupIntent ( stripeEvent ) ) ;
Assert . Equal ( $"Stripe event with ID '{stripeEvent.Id}' does not have object matching type '{nameof(SetupIntent)}'" , exception . Message ) ;
var subscription = Copy ( stripeEvent . Data . Object as Subscription ) ;
await _ stripeFacade . DidNotReceiveWithAnyArgs ( ) . GetSetupIntent (
Arg . Any < string > ( ) ,
Arg . Any < SetupIntentGetOptions > ( ) ) ;
}
var customer = await GetCustomerAsync ( ) ;
[Fact]
public async Task GetSetupIntent_NotFresh_ReturnsEventSetupIntent ( )
{
// Arrange
var mockSetupIntent = new SetupIntent { Id = "seti_test" , Status = "succeeded" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "setup_intent.succeeded" , mockSetupIntent ) ;
// Act
var setupIntent = await _ stripeEventService . GetSetupIntent ( stripeEvent ) ;
// Assert
Assert . Equal ( mockSetupIntent . Id , setupIntent . Id ) ;
Assert . Equal ( mockSetupIntent . Status , setupIntent . Status ) ;
await _ stripeFacade . DidNotReceiveWithAnyArgs ( ) . GetSetupIntent (
Arg . Any < string > ( ) ,
Arg . Any < SetupIntentGetOptions > ( ) ) ;
}
[Fact]
public async Task GetSetupIntent_Fresh_Expand_ReturnsAPISetupIntent ( )
{
// Arrange
var eventSetupIntent = new SetupIntent { Id = "seti_test" , Status = "succeeded" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "setup_intent.succeeded" , eventSetupIntent ) ;
var apiSetupIntent = new SetupIntent { Id = "seti_test" , Status = "requires_action" } ;
var expand = new List < string > { "customer" } ;
subscription . Customer = customer ;
_ stripeFacade . GetSetupIntent (
apiSetupIntent . Id ,
Arg . Is < SetupIntentGetOptions > ( options = > options . Expand = = expand ) )
. Returns ( apiSetupIntent ) ;
// Act
var setupIntent = await _ stripeEventService . GetSetupIntent ( stripeEvent , true , expand ) ;
// Assert
Assert . Equal ( apiSetupIntent , setupIntent ) ;
Assert . NotSame ( eventSetupIntent , setupIntent ) ;
await _ stripeFacade . Received ( ) . GetSetupIntent (
apiSetupIntent . Id ,
Arg . Is < SetupIntentGetOptions > ( options = > options . Expand = = expand ) ) ;
}
# endregion
#region ValidateCloudRegion
[Fact]
public async Task ValidateCloudRegion_SubscriptionUpdated_Success ( )
{
// Arrange
var mockSubscription = new Subscription { Id = "sub_test" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "customer.subscription.updated" , mockSubscription ) ;
var customer = CreateMockCustomer ( ) ;
mockSubscription . Customer = customer ;
_ stripeFacade . GetSubscription (
subscription . Id ,
mockS ubscription. Id ,
Arg . Any < SubscriptionGetOptions > ( ) )
. Returns ( subscription ) ;
. Returns ( mockS ubscription) ;
// Act
var cloudRegionValid = await _ stripeEventService . ValidateCloudRegion ( stripeEvent ) ;
@ -409,28 +438,24 @@ public class StripeEventServiceTests
@@ -409,28 +438,24 @@ public class StripeEventServiceTests
Assert . True ( cloudRegionValid ) ;
await _ stripeFacade . Received ( 1 ) . GetSubscription (
subscription . Id ,
Arg . Any < SubscriptionGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
mockSubscription . Id ,
Arg . Any < SubscriptionGetOptions > ( ) ) ;
}
[Fact]
public async Task ValidateCloudRegion_ChargeSucceeded_Success ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . ChargeSucceeded ) ;
var charge = Copy ( stripeEvent . Data . Object as Charge ) ;
var customer = await GetCustomerAsync ( ) ;
var mockCharge = new Charge { Id = "ch_test" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "charge.succeeded" , mockCharge ) ;
charge . Customer = customer ;
var customer = CreateMockCustomer ( ) ;
mockCharge . Customer = customer ;
_ stripeFacade . GetCharge (
charge . Id ,
mo ckC harge. Id ,
Arg . Any < ChargeGetOptions > ( ) )
. Returns ( charge ) ;
. Returns ( mo ckC harge) ;
// Act
var cloudRegionValid = await _ stripeEventService . ValidateCloudRegion ( stripeEvent ) ;
@ -439,24 +464,21 @@ public class StripeEventServiceTests
@@ -439,24 +464,21 @@ public class StripeEventServiceTests
Assert . True ( cloudRegionValid ) ;
await _ stripeFacade . Received ( 1 ) . GetCharge (
charge . Id ,
Arg . Any < ChargeGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
mockCharge . Id ,
Arg . Any < ChargeGetOptions > ( ) ) ;
}
[Fact]
public async Task ValidateCloudRegion_UpcomingInvoice_Success ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . InvoiceUpcoming ) ;
var mockInvoice = new Invoice { Id = "in_test" , CustomerId = "cus_test" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "invoice.upcoming" , mockInvoice ) ;
var invoice = Copy ( stripeEvent . Data . Object as Invoice ) ;
var customer = await GetCustomerAsync ( ) ;
var customer = CreateMockCustomer ( ) ;
_ stripeFacade . GetCustomer (
i nvoice. CustomerId ,
mockI nvoice. CustomerId ,
Arg . Any < CustomerGetOptions > ( ) )
. Returns ( customer ) ;
@ -467,28 +489,24 @@ public class StripeEventServiceTests
@@ -467,28 +489,24 @@ public class StripeEventServiceTests
Assert . True ( cloudRegionValid ) ;
await _ stripeFacade . Received ( 1 ) . GetCustomer (
invoice . CustomerId ,
Arg . Any < CustomerGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
mockInvoice . CustomerId ,
Arg . Any < CustomerGetOptions > ( ) ) ;
}
[Fact]
public async Task ValidateCloudRegion_InvoiceCreated_Success ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . InvoiceCreated ) ;
var invoice = Copy ( stripeEvent . Data . Object as Invoice ) ;
var customer = await GetCustomerAsync ( ) ;
var mockInvoice = new Invoice { Id = "in_test" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "invoice.created" , mockInvoice ) ;
invoice . Customer = customer ;
var customer = CreateMockCustomer ( ) ;
mockInvoice . Customer = customer ;
_ stripeFacade . GetInvoice (
i nvoice. Id ,
mockI nvoice. Id ,
Arg . Any < InvoiceGetOptions > ( ) )
. Returns ( i nvoice) ;
. Returns ( mockI nvoice) ;
// Act
var cloudRegionValid = await _ stripeEventService . ValidateCloudRegion ( stripeEvent ) ;
@ -497,28 +515,24 @@ public class StripeEventServiceTests
@@ -497,28 +515,24 @@ public class StripeEventServiceTests
Assert . True ( cloudRegionValid ) ;
await _ stripeFacade . Received ( 1 ) . GetInvoice (
invoice . Id ,
Arg . Any < InvoiceGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
mockInvoice . Id ,
Arg . Any < InvoiceGetOptions > ( ) ) ;
}
[Fact]
public async Task ValidateCloudRegion_PaymentMethodAttached_Success ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . PaymentMethodAttached ) ;
var paymentMethod = Copy ( stripeEvent . Data . Object as PaymentMethod ) ;
var customer = await GetCustomerAsync ( ) ;
var mockPaymentMethod = new PaymentMethod { Id = "pm_test" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "payment_method.attached" , mockPaymentMethod ) ;
paymentMethod . Customer = customer ;
var customer = CreateMockCustomer ( ) ;
mockPaymentMethod . Customer = customer ;
_ stripeFacade . GetPaymentMethod (
p aymentMethod. Id ,
mockP aymentMethod. Id ,
Arg . Any < PaymentMethodGetOptions > ( ) )
. Returns ( p aymentMethod) ;
. Returns ( mockP aymentMethod) ;
// Act
var cloudRegionValid = await _ stripeEventService . ValidateCloudRegion ( stripeEvent ) ;
@ -527,24 +541,21 @@ public class StripeEventServiceTests
@@ -527,24 +541,21 @@ public class StripeEventServiceTests
Assert . True ( cloudRegionValid ) ;
await _ stripeFacade . Received ( 1 ) . GetPaymentMethod (
paymentMethod . Id ,
Arg . Any < PaymentMethodGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
mockPaymentMethod . Id ,
Arg . Any < PaymentMethodGetOptions > ( ) ) ;
}
[Fact]
public async Task ValidateCloudRegion_CustomerUpdated_Success ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . CustomerUpdated ) ;
var customer = Copy ( stripeEvent . Data . Object as Customer ) ;
var mockCustomer = CreateMockCustomer ( ) ;
var stripeEvent = CreateMockEvent ( "evt_test" , "customer.updated" , mockCustomer ) ;
_ stripeFacade . GetCustomer (
customer . Id ,
mo ckC ustomer. Id ,
Arg . Any < CustomerGetOptions > ( ) )
. Returns ( customer ) ;
. Returns ( mo ckC ustomer) ;
// Act
var cloudRegionValid = await _ stripeEventService . ValidateCloudRegion ( stripeEvent ) ;
@ -553,29 +564,24 @@ public class StripeEventServiceTests
@@ -553,29 +564,24 @@ public class StripeEventServiceTests
Assert . True ( cloudRegionValid ) ;
await _ stripeFacade . Received ( 1 ) . GetCustomer (
customer . Id ,
Arg . Any < CustomerGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
mockCustomer . Id ,
Arg . Any < CustomerGetOptions > ( ) ) ;
}
[Fact]
public async Task ValidateCloudRegion_MetadataNull_ReturnsFalse ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . CustomerSubscriptionUpdated ) ;
var subscription = Copy ( stripeEvent . Data . Object as Subscription ) ;
var mockSubscription = new Subscription { Id = "sub_test" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "customer.subscription.updated" , mockSubscription ) ;
var customer = await GetCustomerAsync ( ) ;
customer . Metadata = null ;
subscription . Customer = customer ;
var customer = new Customer { Id = "cus_test" , Metadata = null } ;
mockSubscription . Customer = customer ;
_ stripeFacade . GetSubscription (
s ubscription. Id ,
mockS ubscription. Id ,
Arg . Any < SubscriptionGetOptions > ( ) )
. Returns ( s ubscription) ;
. Returns ( mockS ubscription) ;
// Act
var cloudRegionValid = await _ stripeEventService . ValidateCloudRegion ( stripeEvent ) ;
@ -584,29 +590,54 @@ public class StripeEventServiceTests
@@ -584,29 +590,54 @@ public class StripeEventServiceTests
Assert . False ( cloudRegionValid ) ;
await _ stripeFacade . Received ( 1 ) . GetSubscription (
subscription . Id ,
Arg . Any < SubscriptionGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
mockSubscription . Id ,
Arg . Any < SubscriptionGetOptions > ( ) ) ;
}
[Fact]
public async Task ValidateCloudRegion_MetadataNoRegion_DefaultUS_ReturnsTrue ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . CustomerSubscriptionUpdated ) ;
var mockSubscription = new Subscription { Id = "sub_test" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "customer.subscription.updated" , mockSubscription ) ;
var customer = new Customer { Id = "cus_test" , Metadata = new Dictionary < string , string > ( ) } ;
mockSubscription . Customer = customer ;
_ stripeFacade . GetSubscription (
mockSubscription . Id ,
Arg . Any < SubscriptionGetOptions > ( ) )
. Returns ( mockSubscription ) ;
// Act
var cloudRegionValid = await _ stripeEventService . ValidateCloudRegion ( stripeEvent ) ;
var subscription = Copy ( stripeEvent . Data . Object as Subscription ) ;
// Assert
Assert . True ( cloudRegionValid ) ;
await _ stripeFacade . Received ( 1 ) . GetSubscription (
mockSubscription . Id ,
Arg . Any < SubscriptionGetOptions > ( ) ) ;
}
var customer = await GetCustomerAsync ( ) ;
customer . Metadata = new Dictionary < string , string > ( ) ;
[Fact]
public async Task ValidateCloudRegion_MetadataIncorrectlyCasedRegion_ReturnsTrue ( )
{
// Arrange
var mockSubscription = new Subscription { Id = "sub_test" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "customer.subscription.updated" , mockSubscription ) ;
subscription . Customer = customer ;
var customer = new Customer
{
Id = "cus_test" ,
Metadata = new Dictionary < string , string > { { "Region" , "US" } }
} ;
mockSubscription . Customer = customer ;
_ stripeFacade . GetSubscription (
subscription . Id ,
mockS ubscription. Id ,
Arg . Any < SubscriptionGetOptions > ( ) )
. Returns ( subscription ) ;
. Returns ( mockS ubscription) ;
// Act
var cloudRegionValid = await _ stripeEventService . ValidateCloudRegion ( stripeEvent ) ;
@ -615,32 +646,73 @@ public class StripeEventServiceTests
@@ -615,32 +646,73 @@ public class StripeEventServiceTests
Assert . True ( cloudRegionValid ) ;
await _ stripeFacade . Received ( 1 ) . GetSubscription (
subscription . Id ,
Arg . Any < SubscriptionGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
mockSubscription . Id ,
Arg . Any < SubscriptionGetOptions > ( ) ) ;
}
[Fact]
public async Task ValidateCloudRegion_MetadataMiscasedRegion_ReturnsTrue ( )
public async Task ValidateCloudRegion_SetupIntentSucceeded_OrganizationCustomer_Success ( )
{
// Arrange
var stripeEvent = await StripeTestEvents . GetAsync ( StripeEventType . CustomerSubscriptionUpdated ) ;
var mockSetupIntent = new SetupIntent { Id = "seti_test" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "setup_intent.succeeded" , mockSetupIntent ) ;
var organizationId = Guid . NewGuid ( ) ;
var organizationCustomerId = "cus_org_test" ;
var mockOrganization = new Core . AdminConsole . Entities . Organization
{
Id = organizationId ,
GatewayCustomerId = organizationCustomerId
} ;
var customer = CreateMockCustomer ( ) ;
_ setupIntentCache . GetSubscriberIdForSetupIntent ( mockSetupIntent . Id )
. Returns ( organizationId ) ;
var subscription = Copy ( stripeEvent . Data . Object as Subscription ) ;
_ organizationRepository . GetByIdAsync ( organizationId )
. Returns ( mockOrganization ) ;
var customer = await GetCustomerAsync ( ) ;
customer . Metadata = new Dictionary < string , string >
_ stripeFacade . GetCustomer ( organizationCustomerId )
. Returns ( customer ) ;
// Act
var cloudRegionValid = await _ stripeEventService . ValidateCloudRegion ( stripeEvent ) ;
// Assert
Assert . True ( cloudRegionValid ) ;
await _ setupIntentCache . Received ( 1 ) . GetSubscriberIdForSetupIntent ( mockSetupIntent . Id ) ;
await _ organizationRepository . Received ( 1 ) . GetByIdAsync ( organizationId ) ;
await _ stripeFacade . Received ( 1 ) . GetCustomer ( organizationCustomerId ) ;
}
[Fact]
public async Task ValidateCloudRegion_SetupIntentSucceeded_ProviderCustomer_Success ( )
{
// Arrange
var mockSetupIntent = new SetupIntent { Id = "seti_test" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "setup_intent.succeeded" , mockSetupIntent ) ;
var providerId = Guid . NewGuid ( ) ;
var providerCustomerId = "cus_provider_test" ;
var mockProvider = new Core . AdminConsole . Entities . Provider . Provider
{
{ "Region" , "US" }
Id = providerId ,
GatewayCustomerId = providerCustomerId
} ;
var customer = CreateMockCustomer ( ) ;
subscription . Customer = customer ;
_ setupIntentCache . GetSubscriberIdForSetupIntent ( mockSetupIntent . Id )
. Returns ( providerId ) ;
_ stripeFacade . GetSubscription (
subscription . Id ,
Arg . Any < SubscriptionGetOptions > ( ) )
. Returns ( subscription ) ;
_ organizationRepository . GetByIdAsync ( providerId )
. Returns ( ( Core . AdminConsole . Entities . Organization ? ) null ) ;
_ providerRepository . GetByIdAsync ( providerId )
. Returns ( mockProvider ) ;
_ stripeFacade . GetCustomer ( providerCustomerId )
. Returns ( customer ) ;
// Act
var cloudRegionValid = await _ stripeEventService . ValidateCloudRegion ( stripeEvent ) ;
@ -648,32 +720,135 @@ public class StripeEventServiceTests
@@ -648,32 +720,135 @@ public class StripeEventServiceTests
// Assert
Assert . True ( cloudRegionValid ) ;
await _ stripeFacade . Received ( 1 ) . GetSubscription (
subscription . Id ,
Arg . Any < SubscriptionGetOptions > ( ) ,
Arg . Any < RequestOptions > ( ) ,
Arg . Any < CancellationToken > ( ) ) ;
await _ setupIntentCache . Received ( 1 ) . GetSubscriberIdForSetupIntent ( mockSetupIntent . Id ) ;
await _ organizationRepository . Received ( 1 ) . GetByIdAsync ( providerId ) ;
await _ providerRepository . Received ( 1 ) . GetByIdAsync ( providerId ) ;
await _ stripeFacade . Received ( 1 ) . GetCustomer ( providerCustomerId ) ;
}
# endregion
private static T Copy < T > ( T input )
[Fact]
public async Task ValidateCloudRegion_SetupIntentSucceeded_NoSubscriberIdInCache_ReturnsFalse ( )
{
var copy = ( T ) Activator . CreateInstance ( typeof ( T ) ) ;
// Arrange
var mockSetupIntent = new SetupIntent { Id = "seti_test" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "setup_intent.succeeded" , mockSetupIntent ) ;
var properties = input . GetType ( ) . GetProperties ( ) ;
_ setupIntentCache . GetSubscriberIdForSetupIntent ( mockSetupIntent . Id )
. Returns ( ( Guid ? ) null ) ;
foreach ( var property in properties )
// Act
var cloudRegionValid = await _ stripeEventService . ValidateCloudRegion ( stripeEvent ) ;
// Assert
Assert . False ( cloudRegionValid ) ;
await _ setupIntentCache . Received ( 1 ) . GetSubscriberIdForSetupIntent ( mockSetupIntent . Id ) ;
await _ organizationRepository . DidNotReceiveWithAnyArgs ( ) . GetByIdAsync ( Arg . Any < Guid > ( ) ) ;
await _ providerRepository . DidNotReceiveWithAnyArgs ( ) . GetByIdAsync ( Arg . Any < Guid > ( ) ) ;
await _ stripeFacade . DidNotReceive ( ) . GetCustomer ( Arg . Any < string > ( ) ) ;
}
[Fact]
public async Task ValidateCloudRegion_SetupIntentSucceeded_OrganizationWithoutGatewayCustomerId_ChecksProvider ( )
{
// Arrange
var mockSetupIntent = new SetupIntent { Id = "seti_test" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "setup_intent.succeeded" , mockSetupIntent ) ;
var subscriberId = Guid . NewGuid ( ) ;
var providerCustomerId = "cus_provider_test" ;
var mockOrganizationWithoutCustomerId = new Core . AdminConsole . Entities . Organization
{
var value = property . GetValue ( input ) ;
copy !
. GetType ( )
. GetProperty ( property . Name ) !
. SetValue ( copy , value ) ;
}
Id = subscriberId ,
GatewayCustomerId = null
} ;
return copy ;
var mockProvider = new Core . AdminConsole . Entities . Provider . Provider
{
Id = subscriberId ,
GatewayCustomerId = providerCustomerId
} ;
var customer = CreateMockCustomer ( ) ;
_ setupIntentCache . GetSubscriberIdForSetupIntent ( mockSetupIntent . Id )
. Returns ( subscriberId ) ;
_ organizationRepository . GetByIdAsync ( subscriberId )
. Returns ( mockOrganizationWithoutCustomerId ) ;
_ providerRepository . GetByIdAsync ( subscriberId )
. Returns ( mockProvider ) ;
_ stripeFacade . GetCustomer ( providerCustomerId )
. Returns ( customer ) ;
// Act
var cloudRegionValid = await _ stripeEventService . ValidateCloudRegion ( stripeEvent ) ;
// Assert
Assert . True ( cloudRegionValid ) ;
await _ setupIntentCache . Received ( 1 ) . GetSubscriberIdForSetupIntent ( mockSetupIntent . Id ) ;
await _ organizationRepository . Received ( 1 ) . GetByIdAsync ( subscriberId ) ;
await _ providerRepository . Received ( 1 ) . GetByIdAsync ( subscriberId ) ;
await _ stripeFacade . Received ( 1 ) . GetCustomer ( providerCustomerId ) ;
}
private static async Task < Customer > GetCustomerAsync ( )
= > ( await StripeTestEvents . GetAsync ( StripeEventType . CustomerUpdated ) ) . Data . Object as Customer ;
[Fact]
public async Task ValidateCloudRegion_SetupIntentSucceeded_ProviderWithoutGatewayCustomerId_ReturnsFalse ( )
{
// Arrange
var mockSetupIntent = new SetupIntent { Id = "seti_test" } ;
var stripeEvent = CreateMockEvent ( "evt_test" , "setup_intent.succeeded" , mockSetupIntent ) ;
var subscriberId = Guid . NewGuid ( ) ;
var mockProviderWithoutCustomerId = new Core . AdminConsole . Entities . Provider . Provider
{
Id = subscriberId ,
GatewayCustomerId = null
} ;
_ setupIntentCache . GetSubscriberIdForSetupIntent ( mockSetupIntent . Id )
. Returns ( subscriberId ) ;
_ organizationRepository . GetByIdAsync ( subscriberId )
. Returns ( ( Core . AdminConsole . Entities . Organization ? ) null ) ;
_ providerRepository . GetByIdAsync ( subscriberId )
. Returns ( mockProviderWithoutCustomerId ) ;
// Act
var cloudRegionValid = await _ stripeEventService . ValidateCloudRegion ( stripeEvent ) ;
// Assert
Assert . False ( cloudRegionValid ) ;
await _ setupIntentCache . Received ( 1 ) . GetSubscriberIdForSetupIntent ( mockSetupIntent . Id ) ;
await _ organizationRepository . Received ( 1 ) . GetByIdAsync ( subscriberId ) ;
await _ providerRepository . Received ( 1 ) . GetByIdAsync ( subscriberId ) ;
await _ stripeFacade . DidNotReceive ( ) . GetCustomer ( Arg . Any < string > ( ) ) ;
}
# endregion
private static Event CreateMockEvent < T > ( string id , string type , T dataObject ) where T : IStripeEntity
{
return new Event
{
Id = id ,
Type = type ,
Data = new EventData
{
Object = ( IHasObject ) dataObject
}
} ;
}
private static Customer CreateMockCustomer ( )
{
return new Customer
{
Id = "cus_test" ,
Metadata = new Dictionary < string , string > { { "region" , "US" } }
} ;
}
}