2023-11-29 09:18:08 +10:00
using Bit.Core.AdminConsole.Entities ;
2024-06-14 15:34:47 -04:00
using Bit.Core.Billing.Enums ;
2025-08-01 14:40:43 -04:00
using Bit.Core.Enums ;
2023-07-24 23:05:05 +01:00
using Bit.Core.Exceptions ;
using Bit.Core.Models.Business ;
2025-08-01 14:40:43 -04:00
using Bit.Core.Models.Data.Organizations.OrganizationUsers ;
2023-07-24 23:05:05 +01:00
using Bit.Core.Models.StaticStore ;
using Bit.Core.OrganizationFeatures.OrganizationSubscriptions ;
using Bit.Core.Repositories ;
using Bit.Core.SecretsManager.Repositories ;
using Bit.Core.Services ;
2023-08-05 07:51:12 +10:00
using Bit.Core.Settings ;
2023-08-22 09:55:39 +10:00
using Bit.Core.Test.AutoFixture.OrganizationFixtures ;
2023-07-24 23:05:05 +01:00
using Bit.Core.Utilities ;
using Bit.Test.Common.AutoFixture ;
using Bit.Test.Common.AutoFixture.Attributes ;
using NSubstitute ;
using Xunit ;
namespace Bit.Core.Test.OrganizationFeatures.OrganizationSubscriptionUpdate ;
[SutProviderCustomize]
2023-08-22 09:55:39 +10:00
[SecretsManagerOrganizationCustomize]
2023-07-24 23:05:05 +01:00
public class UpdateSecretsManagerSubscriptionCommandTests
{
2025-02-27 07:55:46 -05:00
private static TheoryData < Plan > ToPlanTheory ( List < PlanType > types )
{
var theoryData = new TheoryData < Plan > ( ) ;
var plans = types . Select ( StaticStore . GetPlan ) . ToArray ( ) ;
theoryData . AddRange ( plans ) ;
return theoryData ;
}
public static TheoryData < Plan > AllTeamsAndEnterprise
= > ToPlanTheory ( [
PlanType . EnterpriseAnnually2019 ,
PlanType . EnterpriseAnnually2020 ,
PlanType . EnterpriseAnnually ,
PlanType . EnterpriseMonthly2019 ,
PlanType . EnterpriseMonthly2020 ,
PlanType . EnterpriseMonthly ,
PlanType . TeamsMonthly2019 ,
PlanType . TeamsMonthly2020 ,
PlanType . TeamsMonthly ,
PlanType . TeamsAnnually2019 ,
PlanType . TeamsAnnually2020 ,
PlanType . TeamsAnnually ,
PlanType . TeamsStarter
] ) ;
public static TheoryData < Plan > CurrentTeamsAndEnterprise
= > ToPlanTheory ( [
PlanType . EnterpriseAnnually ,
PlanType . EnterpriseMonthly ,
PlanType . TeamsMonthly ,
PlanType . TeamsAnnually ,
PlanType . TeamsStarter
] ) ;
2023-07-24 23:05:05 +01:00
[Theory]
2025-02-27 07:55:46 -05:00
[BitMemberAutoData(nameof(AllTeamsAndEnterprise))]
2023-08-22 09:55:39 +10:00
public async Task UpdateSubscriptionAsync_UpdateEverything_ValidInput_Passes (
2025-02-27 07:55:46 -05:00
Plan plan ,
2023-08-22 09:55:39 +10:00
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2025-02-27 07:55:46 -05:00
organization . PlanType = plan . Type ;
2023-11-03 18:26:47 -04:00
organization . Seats = 400 ;
2023-08-22 09:55:39 +10:00
organization . SmSeats = 10 ;
organization . MaxAutoscaleSmSeats = 20 ;
organization . SmServiceAccounts = 200 ;
organization . MaxAutoscaleSmServiceAccounts = 350 ;
2023-07-24 23:05:05 +01:00
2023-08-22 09:55:39 +10:00
var updateSmSeats = 15 ;
var updateSmServiceAccounts = 300 ;
var updateMaxAutoscaleSmSeats = 16 ;
var updateMaxAutoscaleSmServiceAccounts = 301 ;
2023-08-05 07:51:12 +10:00
2025-02-27 07:55:46 -05:00
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false )
2023-08-22 09:55:39 +10:00
{
SmSeats = updateSmSeats ,
SmServiceAccounts = updateSmServiceAccounts ,
MaxAutoscaleSmSeats = updateMaxAutoscaleSmSeats ,
MaxAutoscaleSmServiceAccounts = updateMaxAutoscaleSmServiceAccounts
} ;
await sutProvider . Sut . UpdateSubscriptionAsync ( update ) ;
await sutProvider . GetDependency < IPaymentService > ( ) . Received ( 1 )
2023-10-23 11:28:13 +01:00
. AdjustSmSeatsAsync ( organization , plan , update . SmSeatsExcludingBase ) ;
2023-08-22 09:55:39 +10:00
await sutProvider . GetDependency < IPaymentService > ( ) . Received ( 1 )
. AdjustServiceAccountsAsync ( organization , plan , update . SmServiceAccountsExcludingBase ) ;
// TODO: call ReferenceEventService - see AC-1481
AssertUpdatedOrganization ( ( ) = > Arg . Is < Organization > ( org = >
org . Id = = organization . Id & &
org . SmSeats = = updateSmSeats & &
org . MaxAutoscaleSmSeats = = updateMaxAutoscaleSmSeats & &
org . SmServiceAccounts = = updateSmServiceAccounts & &
org . MaxAutoscaleSmServiceAccounts = = updateMaxAutoscaleSmServiceAccounts ) ,
sutProvider ) ;
2025-08-01 14:40:43 -04:00
await sutProvider
. GetDependency < IMailService > ( )
. DidNotReceiveWithAnyArgs ( )
. SendSecretsManagerMaxSeatLimitReachedEmailAsync ( default , default , default ) ;
await sutProvider . GetDependency < IMailService > ( )
. DidNotReceiveWithAnyArgs ( )
. SendSecretsManagerMaxServiceAccountLimitReachedEmailAsync ( default , default , default ) ;
2023-07-24 23:05:05 +01:00
}
[Theory]
2025-02-27 07:55:46 -05:00
[BitMemberAutoData(nameof(CurrentTeamsAndEnterprise))]
2023-08-22 09:55:39 +10:00
public async Task UpdateSubscriptionAsync_ValidInput_WithNullMaxAutoscale_Passes (
2025-02-27 07:55:46 -05:00
Plan plan ,
2023-08-22 09:55:39 +10:00
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2025-02-27 07:55:46 -05:00
organization . PlanType = plan . Type ;
2023-11-29 14:57:56 +00:00
organization . Seats = 20 ;
2023-08-22 09:55:39 +10:00
const int updateSmSeats = 15 ;
const int updateSmServiceAccounts = 450 ;
2023-12-04 15:28:41 -05:00
// Ensure that SmSeats is different from the original organization.SmSeats
organization . SmSeats = updateSmSeats + 5 ;
2025-02-27 07:55:46 -05:00
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false )
2023-07-24 23:05:05 +01:00
{
2023-08-22 09:55:39 +10:00
SmSeats = updateSmSeats ,
MaxAutoscaleSmSeats = null ,
SmServiceAccounts = updateSmServiceAccounts ,
MaxAutoscaleSmServiceAccounts = null
2023-07-24 23:05:05 +01:00
} ;
2023-08-22 09:55:39 +10:00
await sutProvider . Sut . UpdateSubscriptionAsync ( update ) ;
await sutProvider . GetDependency < IPaymentService > ( ) . Received ( 1 )
2023-10-23 11:28:13 +01:00
. AdjustSmSeatsAsync ( organization , plan , update . SmSeatsExcludingBase ) ;
2023-08-22 09:55:39 +10:00
await sutProvider . GetDependency < IPaymentService > ( ) . Received ( 1 )
. AdjustServiceAccountsAsync ( organization , plan , update . SmServiceAccountsExcludingBase ) ;
// TODO: call ReferenceEventService - see AC-1481
AssertUpdatedOrganization ( ( ) = > Arg . Is < Organization > ( org = >
org . Id = = organization . Id & &
org . SmSeats = = updateSmSeats & &
org . MaxAutoscaleSmSeats = = null & &
org . SmServiceAccounts = = updateSmServiceAccounts & &
org . MaxAutoscaleSmServiceAccounts = = null ) ,
sutProvider ) ;
await sutProvider . GetDependency < IMailService > ( ) . DidNotReceiveWithAnyArgs ( ) . SendSecretsManagerMaxSeatLimitReachedEmailAsync ( default , default , default ) ;
await sutProvider . GetDependency < IMailService > ( ) . DidNotReceiveWithAnyArgs ( ) . SendSecretsManagerMaxServiceAccountLimitReachedEmailAsync ( default , default , default ) ;
}
[Theory]
[BitAutoData(false, "Cannot update subscription on a self-hosted instance.")]
[BitAutoData(true, "Cannot autoscale on a self-hosted instance.")]
public async Task UpdatingSubscription_WhenSelfHosted_ThrowsBadRequestException (
bool autoscaling ,
string expectedError ,
Organization organization ,
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , autoscaling ) . AdjustSeats ( 2 ) ;
2023-08-22 09:55:39 +10:00
sutProvider . GetDependency < IGlobalSettings > ( ) . SelfHosted . Returns ( true ) ;
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
Assert . Contains ( expectedError , exception . Message ) ;
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
[BitAutoData]
public async Task UpdateSubscriptionAsync_NoSecretsManagerAccess_ThrowsException (
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider ,
Organization organization )
{
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
2023-08-22 09:55:39 +10:00
organization . UseSecretsManager = false ;
2025-02-27 07:55:46 -05:00
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false ) ;
2023-07-24 23:05:05 +01:00
var exception = await Assert . ThrowsAsync < BadRequestException > (
2023-08-22 09:55:39 +10:00
( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2023-08-05 07:51:12 +10:00
2023-07-24 23:05:05 +01:00
Assert . Contains ( "Organization has no access to Secrets Manager." , exception . Message ) ;
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
2023-08-28 08:05:23 +10:00
2023-07-24 23:05:05 +01:00
[Theory]
2025-02-27 07:55:46 -05:00
[BitMemberAutoData(nameof(AllTeamsAndEnterprise))]
2023-08-22 09:55:39 +10:00
public async Task UpdateSubscriptionAsync_PaidPlan_NullGatewayCustomerId_ThrowsException (
2025-02-27 07:55:46 -05:00
Plan plan ,
2023-08-22 09:55:39 +10:00
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2025-02-27 07:55:46 -05:00
organization . PlanType = plan . Type ;
2023-08-22 09:55:39 +10:00
organization . GatewayCustomerId = null ;
2025-02-27 07:55:46 -05:00
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false ) . AdjustSeats ( 1 ) ;
2023-07-24 23:05:05 +01:00
2023-08-22 09:55:39 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
Assert . Contains ( "No payment method found." , exception . Message ) ;
2023-07-24 23:05:05 +01:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
2025-02-27 07:55:46 -05:00
[BitMemberAutoData(nameof(AllTeamsAndEnterprise))]
2023-08-22 09:55:39 +10:00
public async Task UpdateSubscriptionAsync_PaidPlan_NullGatewaySubscriptionId_ThrowsException (
2025-02-27 07:55:46 -05:00
Plan plan ,
2023-08-22 09:55:39 +10:00
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2025-02-27 07:55:46 -05:00
organization . PlanType = plan . Type ;
2023-08-22 09:55:39 +10:00
organization . GatewaySubscriptionId = null ;
2025-02-27 07:55:46 -05:00
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false ) . AdjustSeats ( 1 ) ;
2023-07-24 23:05:05 +01:00
2023-08-22 09:55:39 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
Assert . Contains ( "No subscription found." , exception . Message ) ;
2023-07-24 23:05:05 +01:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
2025-02-27 07:55:46 -05:00
[BitMemberAutoData(nameof(AllTeamsAndEnterprise))]
public async Task AdjustServiceAccountsAsync_WithEnterpriseOrTeamsPlans_Success (
Plan plan ,
Guid organizationId ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2023-10-17 15:56:35 +01:00
var organizationSeats = plan . SecretsManager . BaseSeats + 10 ;
2023-08-22 09:55:39 +10:00
var organizationMaxAutoscaleSeats = 20 ;
2023-10-17 15:56:35 +01:00
var organizationServiceAccounts = plan . SecretsManager . BaseServiceAccount + 10 ;
2023-08-22 09:55:39 +10:00
var organizationMaxAutoscaleServiceAccounts = 300 ;
2023-07-24 23:05:05 +01:00
var organization = new Organization
{
Id = organizationId ,
2025-02-27 07:55:46 -05:00
PlanType = plan . Type ,
2023-08-22 09:55:39 +10:00
GatewayCustomerId = "1" ,
GatewaySubscriptionId = "2" ,
2023-07-24 23:05:05 +01:00
UseSecretsManager = true ,
2023-08-22 09:55:39 +10:00
SmSeats = organizationSeats ,
MaxAutoscaleSmSeats = organizationMaxAutoscaleSeats ,
SmServiceAccounts = organizationServiceAccounts ,
MaxAutoscaleSmServiceAccounts = organizationMaxAutoscaleServiceAccounts
2023-07-24 23:05:05 +01:00
} ;
2023-08-22 09:55:39 +10:00
var smServiceAccountsAdjustment = 10 ;
var expectedSmServiceAccounts = organizationServiceAccounts + smServiceAccountsAdjustment ;
2023-10-17 15:56:35 +01:00
var expectedSmServiceAccountsExcludingBase = expectedSmServiceAccounts - plan . SecretsManager . BaseServiceAccount ;
2023-08-22 09:55:39 +10:00
2025-02-27 07:55:46 -05:00
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false ) . AdjustServiceAccounts ( 10 ) ;
2023-08-22 09:55:39 +10:00
await sutProvider . Sut . UpdateSubscriptionAsync ( update ) ;
await sutProvider . GetDependency < IPaymentService > ( ) . Received ( 1 ) . AdjustServiceAccountsAsync (
Arg . Is < Organization > ( o = > o . Id = = organizationId ) ,
plan ,
expectedSmServiceAccountsExcludingBase ) ;
// TODO: call ReferenceEventService - see AC-1481
AssertUpdatedOrganization ( ( ) = > Arg . Is < Organization > ( o = >
o . Id = = organizationId
& & o . SmSeats = = organizationSeats
& & o . MaxAutoscaleSmSeats = = organizationMaxAutoscaleSeats
& & o . SmServiceAccounts = = expectedSmServiceAccounts
& & o . MaxAutoscaleSmServiceAccounts = = organizationMaxAutoscaleServiceAccounts ) , sutProvider ) ;
2023-07-24 23:05:05 +01:00
}
[Theory]
[BitAutoData]
2025-08-01 14:40:43 -04:00
public async Task UpdateSubscriptionAsync_UpdateSeatCount_AndExistingSeatsDoNotReachAutoscaleLimit_NoEmailSent (
2023-08-22 09:55:39 +10:00
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2025-08-01 14:40:43 -04:00
// Arrange
2023-12-04 15:28:41 -05:00
// Make sure Password Manager seats is greater or equal to Secrets Manager seats
2025-10-22 13:42:56 -04:00
const int initialSeatCount = 9 ;
const int maxSeatCount = 20 ;
// This represents the total number of users allowed in the organization.
organization . Seats = maxSeatCount ;
// This represents the number of Secrets Manager users allowed in the organization.
organization . SmSeats = initialSeatCount ;
// This represents the upper limit of Secrets Manager seats that can be automatically scaled.
organization . MaxAutoscaleSmSeats = maxSeatCount ;
organization . PlanType = PlanType . EnterpriseAnnually ;
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
2023-12-04 15:28:41 -05:00
2025-02-27 07:55:46 -05:00
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false )
2023-07-24 23:05:05 +01:00
{
2025-10-22 13:42:56 -04:00
SmSeats = 8 ,
MaxAutoscaleSmSeats = maxSeatCount
2023-07-24 23:05:05 +01:00
} ;
2025-08-01 14:40:43 -04:00
sutProvider . GetDependency < IOrganizationUserRepository > ( )
. GetOccupiedSmSeatCountByOrganizationIdAsync ( organization . Id )
2025-10-22 13:42:56 -04:00
. Returns ( 5 ) ;
2023-07-24 23:05:05 +01:00
2025-08-01 14:40:43 -04:00
// Act
2023-08-22 09:55:39 +10:00
await sutProvider . Sut . UpdateSubscriptionAsync ( update ) ;
2025-08-01 14:40:43 -04:00
// Assert
// Currently being called once each for different validation methods
await sutProvider . GetDependency < IOrganizationUserRepository > ( )
. Received ( 2 )
. GetOccupiedSmSeatCountByOrganizationIdAsync ( organization . Id ) ;
await sutProvider . GetDependency < IMailService > ( )
. DidNotReceiveWithAnyArgs ( )
. SendSecretsManagerMaxSeatLimitReachedEmailAsync ( Arg . Any < Organization > ( ) , Arg . Any < int > ( ) , Arg . Any < IEnumerable < string > > ( ) ) ;
}
[Theory]
[BitAutoData]
public async Task UpdateSubscriptionAsync_ExistingSeatsReachAutoscaleLimit_EmailOwners (
Organization organization ,
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
// Arrange
2025-10-22 13:42:56 -04:00
const int initialSeatCount = 5 ;
const int maxSeatCount = 10 ;
2025-08-01 14:40:43 -04:00
2025-10-22 13:42:56 -04:00
// This represents the total number of users allowed in the organization.
organization . Seats = maxSeatCount ;
// This represents the number of Secrets Manager users allowed in the organization.
organization . SmSeats = initialSeatCount ;
// This represents the upper limit of Secrets Manager seats that can be automatically scaled.
organization . MaxAutoscaleSmSeats = maxSeatCount ;
var ownerDetailsList = new List < OrganizationUserUserDetails > { new ( ) { Email = "owner@example.com" } } ;
organization . PlanType = PlanType . EnterpriseAnnually ;
2025-08-01 14:40:43 -04:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
2025-10-22 13:42:56 -04:00
2025-08-01 14:40:43 -04:00
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false )
{
2025-10-22 13:42:56 -04:00
SmSeats = maxSeatCount ,
MaxAutoscaleSmSeats = maxSeatCount
2025-08-01 14:40:43 -04:00
} ;
sutProvider . GetDependency < IOrganizationUserRepository > ( )
. GetOccupiedSmSeatCountByOrganizationIdAsync ( organization . Id )
2025-10-22 13:42:56 -04:00
. Returns ( maxSeatCount ) ;
2025-08-01 14:40:43 -04:00
sutProvider . GetDependency < IOrganizationUserRepository > ( )
. GetManyByMinimumRoleAsync ( organization . Id , OrganizationUserType . Owner )
. Returns ( ownerDetailsList ) ;
// Act
await sutProvider . Sut . UpdateSubscriptionAsync ( update ) ;
// Assert
await sutProvider . GetDependency < IOrganizationUserRepository > ( )
2025-10-22 13:42:56 -04:00
. Received ( 1 )
2025-08-01 14:40:43 -04:00
. GetOccupiedSmSeatCountByOrganizationIdAsync ( organization . Id ) ;
await sutProvider . GetDependency < IMailService > ( )
. Received ( 1 )
. SendSecretsManagerMaxSeatLimitReachedEmailAsync ( Arg . Is ( organization ) ,
2025-10-22 13:42:56 -04:00
Arg . Is ( maxSeatCount ) ,
2025-08-01 14:40:43 -04:00
Arg . Is < IEnumerable < string > > ( emails = > emails . Contains ( ownerDetailsList [ 0 ] . Email ) ) ) ;
2023-07-24 23:05:05 +01:00
}
[Theory]
[BitAutoData]
2023-08-05 07:51:12 +10:00
public async Task UpdateSubscriptionAsync_OrgWithNullSmSeatOnSeatsAdjustment_ThrowsException (
2023-08-22 09:55:39 +10:00
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2023-08-22 09:55:39 +10:00
organization . SmSeats = null ;
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false ) . AdjustSeats ( 1 ) ;
2023-07-24 23:05:05 +01:00
var exception = await Assert . ThrowsAsync < BadRequestException > (
2023-08-22 09:55:39 +10:00
( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2023-07-24 23:05:05 +01:00
Assert . Contains ( "Organization has no Secrets Manager seat limit, no need to adjust seats" , exception . Message ) ;
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
2023-08-22 09:55:39 +10:00
[BitAutoData]
public async Task UpdateSubscriptionAsync_SmSeatAutoscaling_Subtracting_ThrowsBadRequestException (
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , true ) . AdjustSeats ( - 2 ) ;
2023-07-24 23:05:05 +01:00
2023-08-22 09:55:39 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
Assert . Contains ( "Cannot use autoscaling to subtract seats." , exception . Message ) ;
2023-07-24 23:05:05 +01:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
[BitAutoData(PlanType.Free)]
2023-08-05 07:51:12 +10:00
public async Task UpdateSubscriptionAsync_WithHasAdditionalSeatsOptionFalse_ThrowsBadRequestException (
2023-07-24 23:05:05 +01:00
PlanType planType ,
2023-08-22 09:55:39 +10:00
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2023-08-22 09:55:39 +10:00
organization . PlanType = planType ;
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false ) . AdjustSeats ( 1 ) ;
2023-07-24 23:05:05 +01:00
2023-08-22 09:55:39 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2023-08-05 07:51:12 +10:00
Assert . Contains ( "You have reached the maximum number of Secrets Manager seats (2) for this plan" ,
exception . Message , StringComparison . InvariantCultureIgnoreCase ) ;
2023-07-24 23:05:05 +01:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
2023-08-22 09:55:39 +10:00
[BitAutoData]
public async Task SmSeatAutoscaling_MaxLimitReached_ThrowsBadRequestException (
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2023-08-22 09:55:39 +10:00
organization . SmSeats = 9 ;
organization . MaxAutoscaleSmSeats = 10 ;
2023-07-24 23:05:05 +01:00
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , true ) . AdjustSeats ( 2 ) ;
2023-08-22 09:55:39 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
Assert . Contains ( "Secrets Manager seat limit has been reached." , exception . Message ) ;
2023-07-24 23:05:05 +01:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
2023-08-22 09:55:39 +10:00
[BitAutoData]
public async Task UpdateSubscriptionAsync_SeatsAdjustmentGreaterThanMaxAutoscaleSeats_ThrowsException (
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false )
2023-07-24 23:05:05 +01:00
{
2023-12-04 15:28:41 -05:00
SmSeats = organization . SmSeats + 10 ,
MaxAutoscaleSmSeats = organization . SmSeats + 5
2023-07-24 23:05:05 +01:00
} ;
2023-08-22 09:55:39 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > (
( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
Assert . Contains ( "Cannot set max seat autoscaling below seat count." , exception . Message ) ;
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
2023-08-05 07:51:12 +10:00
}
2023-07-24 23:05:05 +01:00
2023-08-05 07:51:12 +10:00
[Theory]
2023-08-22 09:55:39 +10:00
[BitAutoData]
public async Task UpdateSubscriptionAsync_ThrowsBadRequestException_WhenSmSeatsLessThanOne (
Organization organization ,
2023-08-05 07:51:12 +10:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false )
2023-07-24 23:05:05 +01:00
{
2023-08-22 09:55:39 +10:00
SmSeats = 0 ,
2023-08-05 07:51:12 +10:00
} ;
2023-07-24 23:05:05 +01:00
2023-08-22 09:55:39 +10:00
sutProvider . GetDependency < IOrganizationUserRepository > ( ) . GetOccupiedSmSeatCountByOrganizationIdAsync ( organization . Id ) . Returns ( 8 ) ;
2023-07-24 23:05:05 +01:00
2023-08-22 09:55:39 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
Assert . Contains ( "You must have at least 1 Secrets Manager seat." , exception . Message ) ;
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
2023-07-24 23:05:05 +01:00
}
[Theory]
[BitAutoData]
2023-08-22 09:55:39 +10:00
public async Task UpdateSubscriptionAsync_ThrowsBadRequestException_WhenOccupiedSeatsExceedNewSeatTotal (
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2023-10-19 01:00:55 +10:00
organization . SmSeats = 8 ;
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false )
2023-07-24 23:05:05 +01:00
{
2023-08-22 09:55:39 +10:00
SmSeats = 7 ,
2023-07-24 23:05:05 +01:00
} ;
2023-08-22 09:55:39 +10:00
sutProvider . GetDependency < IOrganizationUserRepository > ( ) . GetOccupiedSmSeatCountByOrganizationIdAsync ( organization . Id ) . Returns ( 8 ) ;
2023-07-24 23:05:05 +01:00
2023-08-05 07:51:12 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2023-08-28 08:05:23 +10:00
Assert . Contains ( "8 users are currently occupying Secrets Manager seats. You cannot decrease your subscription below your current occupied seat count" , exception . Message ) ;
2023-07-24 23:05:05 +01:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
[BitAutoData]
2025-08-01 14:40:43 -04:00
public async Task UpdateSubscriptionAsync_UpdateServiceAccounts_AndExistingServiceAccountsCountDoesNotReachAutoscaleLimit_NoEmailSent (
Organization organization ,
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
// Arrange
var smServiceAccounts = 300 ;
var existingServiceAccountCount = 299 ;
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false )
{
SmServiceAccounts = smServiceAccounts ,
MaxAutoscaleSmServiceAccounts = smServiceAccounts
} ;
sutProvider . GetDependency < IServiceAccountRepository > ( )
. GetServiceAccountCountByOrganizationIdAsync ( organization . Id )
. Returns ( existingServiceAccountCount ) ;
// Act
await sutProvider . Sut . UpdateSubscriptionAsync ( update ) ;
// Assert
await sutProvider . GetDependency < IServiceAccountRepository > ( )
. Received ( 1 )
. GetServiceAccountCountByOrganizationIdAsync ( organization . Id ) ;
await sutProvider . GetDependency < IMailService > ( )
. DidNotReceiveWithAnyArgs ( )
. SendSecretsManagerMaxServiceAccountLimitReachedEmailAsync (
Arg . Any < Organization > ( ) ,
Arg . Any < int > ( ) ,
Arg . Any < IEnumerable < string > > ( ) ) ;
}
[Theory]
[BitAutoData]
public async Task UpdateSubscriptionAsync_ExistingServiceAccountsReachAutoscaleLimit_EmailOwners (
2023-08-22 09:55:39 +10:00
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2025-08-01 14:40:43 -04:00
var smServiceAccounts = 300 ;
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false )
2023-07-24 23:05:05 +01:00
{
2025-08-01 14:40:43 -04:00
SmServiceAccounts = smServiceAccounts ,
MaxAutoscaleSmServiceAccounts = smServiceAccounts
2023-07-24 23:05:05 +01:00
} ;
2025-08-01 14:40:43 -04:00
var ownerDetailsList = new List < OrganizationUserUserDetails > { new ( ) { Email = "owner@example.com" } } ;
2023-07-24 23:05:05 +01:00
2025-08-01 14:40:43 -04:00
sutProvider . GetDependency < IServiceAccountRepository > ( )
. GetServiceAccountCountByOrganizationIdAsync ( organization . Id )
. Returns ( smServiceAccounts ) ;
sutProvider . GetDependency < IOrganizationUserRepository > ( )
. GetManyByMinimumRoleAsync ( organization . Id , OrganizationUserType . Owner )
. Returns ( ownerDetailsList ) ;
// Act
2023-08-22 09:55:39 +10:00
await sutProvider . Sut . UpdateSubscriptionAsync ( update ) ;
2023-07-24 23:05:05 +01:00
2025-08-01 14:40:43 -04:00
// Assert
await sutProvider . GetDependency < IServiceAccountRepository > ( )
. Received ( 1 )
. GetServiceAccountCountByOrganizationIdAsync ( organization . Id ) ;
await sutProvider . GetDependency < IMailService > ( )
. Received ( 1 )
. SendSecretsManagerMaxServiceAccountLimitReachedEmailAsync ( Arg . Is ( organization ) ,
Arg . Is ( smServiceAccounts ) ,
Arg . Is < IEnumerable < string > > ( emails = > emails . Contains ( ownerDetailsList [ 0 ] . Email ) ) ) ;
2023-07-24 23:05:05 +01:00
}
[Theory]
[BitAutoData]
public async Task AdjustServiceAccountsAsync_ThrowsBadRequestException_WhenSmServiceAccountsIsNull (
2023-08-22 09:55:39 +10:00
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2023-08-22 09:55:39 +10:00
organization . SmServiceAccounts = null ;
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false ) . AdjustServiceAccounts ( 1 ) ;
2023-07-24 23:05:05 +01:00
2023-08-05 07:51:12 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2024-04-05 08:54:36 -04:00
Assert . Contains ( "Organization has no machine accounts limit, no need to adjust machine accounts" , exception . Message ) ;
2023-07-24 23:05:05 +01:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
[BitAutoData]
2023-08-22 09:55:39 +10:00
public async Task UpdateSubscriptionAsync_ServiceAccountAutoscaling_Subtracting_ThrowsBadRequestException (
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , true ) . AdjustServiceAccounts ( - 2 ) ;
2023-07-24 23:05:05 +01:00
2023-08-22 09:55:39 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2024-04-05 08:54:36 -04:00
Assert . Contains ( "Cannot use autoscaling to subtract machine accounts." , exception . Message ) ;
2023-07-24 23:05:05 +01:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
[BitAutoData(PlanType.Free)]
2023-08-22 09:55:39 +10:00
public async Task UpdateSubscriptionAsync_WithHasAdditionalServiceAccountOptionFalse_ThrowsBadRequestException (
2023-07-24 23:05:05 +01:00
PlanType planType ,
2023-08-22 09:55:39 +10:00
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2023-08-22 09:55:39 +10:00
organization . PlanType = planType ;
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false ) . AdjustServiceAccounts ( 1 ) ;
2023-07-24 23:05:05 +01:00
2023-08-22 09:55:39 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2024-04-05 08:54:36 -04:00
Assert . Contains ( "You have reached the maximum number of machine accounts (3) for this plan" ,
2023-08-22 09:55:39 +10:00
exception . Message , StringComparison . InvariantCultureIgnoreCase ) ;
2023-07-24 23:05:05 +01:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
2023-08-22 09:55:39 +10:00
[BitAutoData]
public async Task ServiceAccountAutoscaling_MaxLimitReached_ThrowsBadRequestException (
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2023-08-22 09:55:39 +10:00
organization . SmServiceAccounts = 9 ;
organization . MaxAutoscaleSmServiceAccounts = 10 ;
2023-07-24 23:05:05 +01:00
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , true ) . AdjustServiceAccounts ( 2 ) ;
2023-07-24 23:05:05 +01:00
2023-08-22 09:55:39 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2024-04-05 08:54:36 -04:00
Assert . Contains ( "Secrets Manager machine account limit has been reached." , exception . Message ) ;
2023-07-24 23:05:05 +01:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
2023-08-22 09:55:39 +10:00
[BitAutoData]
public async Task UpdateSubscriptionAsync_ServiceAccountsGreaterThanMaxAutoscaleSeats_ThrowsException (
Organization organization ,
2023-07-24 23:05:05 +01:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2023-12-04 15:28:41 -05:00
const int smServiceAccount = 15 ;
const int maxAutoscaleSmServiceAccounts = 10 ;
organization . SmServiceAccounts = smServiceAccount - 5 ;
organization . MaxAutoscaleSmServiceAccounts = 2 * smServiceAccount ;
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false )
2023-07-24 23:05:05 +01:00
{
2023-12-04 15:28:41 -05:00
SmServiceAccounts = smServiceAccount ,
MaxAutoscaleSmServiceAccounts = maxAutoscaleSmServiceAccounts
2023-07-24 23:05:05 +01:00
} ;
2023-08-22 09:55:39 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > (
( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2024-04-05 08:54:36 -04:00
Assert . Contains ( "Cannot set max machine accounts autoscaling below machine account amount" , exception . Message ) ;
2023-07-24 23:05:05 +01:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
2023-08-05 07:51:12 +10:00
[Theory]
2023-08-22 09:55:39 +10:00
[BitAutoData]
public async Task UpdateSubscriptionAsync_ServiceAccountsLessThanPlanMinimum_ThrowsException (
Organization organization ,
2023-08-05 07:51:12 +10:00
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2024-04-08 14:42:01 -04:00
const int newSmServiceAccounts = 49 ;
2023-12-04 15:28:41 -05:00
organization . SmServiceAccounts = newSmServiceAccounts - 10 ;
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false )
2023-08-05 07:51:12 +10:00
{
2023-12-04 15:28:41 -05:00
SmServiceAccounts = newSmServiceAccounts ,
2023-08-05 07:51:12 +10:00
} ;
2023-08-22 09:55:39 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > (
( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2024-04-08 14:42:01 -04:00
Assert . Contains ( "Plan has a minimum of 50 machine accounts" , exception . Message ) ;
2023-08-22 09:55:39 +10:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
2023-08-05 07:51:12 +10:00
}
[Theory]
2025-02-27 07:55:46 -05:00
[BitMemberAutoData(nameof(AllTeamsAndEnterprise))]
2023-08-22 09:55:39 +10:00
public async Task UpdateSmServiceAccounts_WhenCurrentServiceAccountsIsGreaterThanNew_ThrowsBadRequestException (
2025-02-27 07:55:46 -05:00
Plan plan ,
2023-08-05 07:51:12 +10:00
Organization organization ,
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2023-08-22 09:55:39 +10:00
var currentServiceAccounts = 301 ;
2025-02-27 07:55:46 -05:00
organization . PlanType = plan . Type ;
2023-08-22 09:55:39 +10:00
organization . SmServiceAccounts = currentServiceAccounts ;
2025-02-27 07:55:46 -05:00
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false ) { SmServiceAccounts = 201 } ;
2023-08-05 07:51:12 +10:00
2023-08-22 09:55:39 +10:00
sutProvider . GetDependency < IServiceAccountRepository > ( )
. GetServiceAccountCountByOrganizationIdAsync ( organization . Id )
. Returns ( currentServiceAccounts ) ;
2023-08-05 07:51:12 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2024-04-05 08:54:36 -04:00
Assert . Contains ( "Your organization currently has 301 machine accounts. You cannot decrease your subscription below your current machine account usage" , exception . Message ) ;
2023-08-05 07:51:12 +10:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
2023-08-22 09:55:39 +10:00
[BitAutoData]
public async Task UpdateSubscriptionAsync_ThrowsBadRequestException_WhenMaxAutoscaleSeatsBelowSeatCount (
2023-08-05 07:51:12 +10:00
Organization organization ,
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2023-12-04 15:28:41 -05:00
const int smSeats = 10 ;
const int maxAutoscaleSmSeats = 5 ;
organization . SmSeats = smSeats - 1 ;
organization . MaxAutoscaleSmSeats = smSeats * 2 ;
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false )
2023-08-22 09:55:39 +10:00
{
2023-12-04 15:28:41 -05:00
SmSeats = smSeats ,
MaxAutoscaleSmSeats = maxAutoscaleSmSeats
2023-08-22 09:55:39 +10:00
} ;
2023-08-05 07:51:12 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2023-08-22 09:55:39 +10:00
Assert . Contains ( "Cannot set max seat autoscaling below seat count." , exception . Message ) ;
2023-08-05 07:51:12 +10:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
2023-08-22 09:55:39 +10:00
[BitAutoData(PlanType.Free)]
public async Task UpdateMaxAutoscaleSmSeats_ThrowsBadRequestException_WhenExceedsPlanMaxUsers (
2023-08-05 07:51:12 +10:00
PlanType planType ,
Organization organization ,
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
organization . PlanType = planType ;
2023-08-22 09:55:39 +10:00
organization . SmSeats = 2 ;
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false )
2023-08-22 09:55:39 +10:00
{
MaxAutoscaleSmSeats = 3
} ;
2023-08-05 07:51:12 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2023-08-22 09:55:39 +10:00
Assert . Contains ( "Your plan has a Secrets Manager seat limit of 2, but you have specified a max autoscale count of 3.Reduce your max autoscale count." , exception . Message ) ;
2023-08-05 07:51:12 +10:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
2023-08-22 09:55:39 +10:00
[BitAutoData(PlanType.Free)]
public async Task UpdateMaxAutoscaleSmSeats_ThrowsBadRequestException_WhenPlanDoesNotAllowAutoscale (
2023-08-05 07:51:12 +10:00
PlanType planType ,
Organization organization ,
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
organization . PlanType = planType ;
2023-08-22 09:55:39 +10:00
organization . SmSeats = 2 ;
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false )
2023-08-22 09:55:39 +10:00
{
MaxAutoscaleSmSeats = 2
} ;
2023-08-05 07:51:12 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2023-08-22 09:55:39 +10:00
Assert . Contains ( "Your plan does not allow Secrets Manager seat autoscaling" , exception . Message ) ;
2023-08-05 07:51:12 +10:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
[Theory]
2023-08-22 09:55:39 +10:00
[BitAutoData(PlanType.Free)]
public async Task UpdateMaxAutoscaleSmServiceAccounts_ThrowsBadRequestException_WhenPlanDoesNotAllowAutoscale (
PlanType planType ,
2023-08-05 07:51:12 +10:00
Organization organization ,
SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
2023-08-22 09:55:39 +10:00
organization . PlanType = planType ;
organization . SmServiceAccounts = 3 ;
2023-08-05 07:51:12 +10:00
2025-02-27 07:55:46 -05:00
var plan = StaticStore . GetPlan ( organization . PlanType ) ;
var update = new SecretsManagerSubscriptionUpdate ( organization , plan , false ) { MaxAutoscaleSmServiceAccounts = 3 } ;
2023-08-05 07:51:12 +10:00
var exception = await Assert . ThrowsAsync < BadRequestException > ( ( ) = > sutProvider . Sut . UpdateSubscriptionAsync ( update ) ) ;
2024-04-05 08:54:36 -04:00
Assert . Contains ( "Your plan does not allow machine accounts autoscaling." , exception . Message ) ;
2023-08-05 07:51:12 +10:00
await VerifyDependencyNotCalledAsync ( sutProvider ) ;
}
2023-07-24 23:05:05 +01:00
private static async Task VerifyDependencyNotCalledAsync ( SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
await sutProvider . GetDependency < IPaymentService > ( ) . DidNotReceive ( )
2023-10-23 11:28:13 +01:00
. AdjustSmSeatsAsync ( Arg . Any < Organization > ( ) , Arg . Any < Plan > ( ) , Arg . Any < int > ( ) ) ;
2023-07-24 23:05:05 +01:00
await sutProvider . GetDependency < IPaymentService > ( ) . DidNotReceive ( )
. AdjustServiceAccountsAsync ( Arg . Any < Organization > ( ) , Arg . Any < Plan > ( ) , Arg . Any < int > ( ) ) ;
// TODO: call ReferenceEventService - see AC-1481
await sutProvider . GetDependency < IMailService > ( ) . DidNotReceive ( )
. SendOrganizationMaxSeatLimitReachedEmailAsync ( Arg . Any < Organization > ( ) , Arg . Any < int > ( ) ,
Arg . Any < IEnumerable < string > > ( ) ) ;
2023-08-05 07:51:12 +10:00
2024-08-15 17:14:22 -04:00
await sutProvider . GetDependency < IOrganizationRepository > ( ) . DidNotReceiveWithAnyArgs ( ) . ReplaceAsync ( default ) ;
await sutProvider . GetDependency < IApplicationCacheService > ( ) . DidNotReceiveWithAnyArgs ( ) . UpsertOrganizationAbilityAsync ( default ) ;
2023-08-05 07:51:12 +10:00
}
private void AssertUpdatedOrganization ( Func < Organization > organizationMatcher , SutProvider < UpdateSecretsManagerSubscriptionCommand > sutProvider )
{
sutProvider . GetDependency < IOrganizationRepository > ( ) . Received ( 1 ) . ReplaceAsync ( organizationMatcher ( ) ) ;
sutProvider . GetDependency < IApplicationCacheService > ( ) . Received ( 1 ) . UpsertOrganizationAbilityAsync ( organizationMatcher ( ) ) ;
2023-07-24 23:05:05 +01:00
}
}